1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2bce88370SMarek Vasut /*
3bce88370SMarek Vasut * Freescale i.MX23/i.MX28 SB image generator
4bce88370SMarek Vasut *
5bce88370SMarek Vasut * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de>
6bce88370SMarek Vasut */
7bce88370SMarek Vasut
8bce88370SMarek Vasut #ifdef CONFIG_MXS
9bce88370SMarek Vasut
10bce88370SMarek Vasut #include <errno.h>
11bce88370SMarek Vasut #include <fcntl.h>
12bce88370SMarek Vasut #include <stdio.h>
13bce88370SMarek Vasut #include <string.h>
14bce88370SMarek Vasut #include <unistd.h>
15bce88370SMarek Vasut #include <limits.h>
16bce88370SMarek Vasut
17bce88370SMarek Vasut #include <openssl/evp.h>
18bce88370SMarek Vasut
19f86ed6a8SGuilherme Maciel Ferreira #include "imagetool.h"
20bce88370SMarek Vasut #include "mxsimage.h"
2125308f45SCharles Manning #include "pbl_crc32.h"
22bce88370SMarek Vasut #include <image.h>
23bce88370SMarek Vasut
247bae13b7SMarek Vasut /*
257bae13b7SMarek Vasut * OpenSSL 1.1.0 and newer compatibility functions:
267bae13b7SMarek Vasut * https://wiki.openssl.org/index.php/1.1_API_Changes
277bae13b7SMarek Vasut */
28c5b0bca4SHauke Mehrtens #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
29c5b0bca4SHauke Mehrtens (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
OPENSSL_zalloc(size_t num)307bae13b7SMarek Vasut static void *OPENSSL_zalloc(size_t num)
317bae13b7SMarek Vasut {
327bae13b7SMarek Vasut void *ret = OPENSSL_malloc(num);
337bae13b7SMarek Vasut
347bae13b7SMarek Vasut if (ret != NULL)
357bae13b7SMarek Vasut memset(ret, 0, num);
367bae13b7SMarek Vasut return ret;
377bae13b7SMarek Vasut }
387bae13b7SMarek Vasut
EVP_MD_CTX_new(void)397bae13b7SMarek Vasut EVP_MD_CTX *EVP_MD_CTX_new(void)
407bae13b7SMarek Vasut {
417bae13b7SMarek Vasut return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
427bae13b7SMarek Vasut }
437bae13b7SMarek Vasut
EVP_MD_CTX_free(EVP_MD_CTX * ctx)447bae13b7SMarek Vasut void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
457bae13b7SMarek Vasut {
467bae13b7SMarek Vasut EVP_MD_CTX_cleanup(ctx);
477bae13b7SMarek Vasut OPENSSL_free(ctx);
487bae13b7SMarek Vasut }
497bae13b7SMarek Vasut
EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX * ctx)507bae13b7SMarek Vasut int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
517bae13b7SMarek Vasut {
527bae13b7SMarek Vasut return EVP_CIPHER_CTX_cleanup(ctx);
537bae13b7SMarek Vasut }
547bae13b7SMarek Vasut #endif
55bce88370SMarek Vasut
56bce88370SMarek Vasut /*
57bce88370SMarek Vasut * DCD block
58bce88370SMarek Vasut * |-Write to address command block
59bce88370SMarek Vasut * | 0xf00 == 0xf33d
60bce88370SMarek Vasut * | 0xba2 == 0xb33f
61bce88370SMarek Vasut * |-ORR address with mask command block
62bce88370SMarek Vasut * | 0xf00 |= 0x1337
63bce88370SMarek Vasut * |-Write to address command block
64bce88370SMarek Vasut * | 0xba2 == 0xd00d
65bce88370SMarek Vasut * :
66bce88370SMarek Vasut */
67bce88370SMarek Vasut #define SB_HAB_DCD_WRITE 0xccUL
68bce88370SMarek Vasut #define SB_HAB_DCD_CHECK 0xcfUL
69bce88370SMarek Vasut #define SB_HAB_DCD_NOOP 0xc0UL
70bce88370SMarek Vasut #define SB_HAB_DCD_MASK_BIT (1 << 3)
71bce88370SMarek Vasut #define SB_HAB_DCD_SET_BIT (1 << 4)
72bce88370SMarek Vasut
73bce88370SMarek Vasut /* Addr.n = Value.n */
74bce88370SMarek Vasut #define SB_DCD_WRITE \
75bce88370SMarek Vasut (SB_HAB_DCD_WRITE << 24)
76bce88370SMarek Vasut /* Addr.n &= ~Value.n */
77bce88370SMarek Vasut #define SB_DCD_ANDC \
78bce88370SMarek Vasut ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT)
79bce88370SMarek Vasut /* Addr.n |= Value.n */
80bce88370SMarek Vasut #define SB_DCD_ORR \
81bce88370SMarek Vasut ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT)
82bce88370SMarek Vasut /* (Addr.n & Value.n) == 0 */
83bce88370SMarek Vasut #define SB_DCD_CHK_EQZ \
84bce88370SMarek Vasut (SB_HAB_DCD_CHECK << 24)
85bce88370SMarek Vasut /* (Addr.n & Value.n) == Value.n */
86bce88370SMarek Vasut #define SB_DCD_CHK_EQ \
87bce88370SMarek Vasut ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT)
88bce88370SMarek Vasut /* (Addr.n & Value.n) != Value.n */
89bce88370SMarek Vasut #define SB_DCD_CHK_NEQ \
90bce88370SMarek Vasut ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_MASK_BIT)
91bce88370SMarek Vasut /* (Addr.n & Value.n) != 0 */
92bce88370SMarek Vasut #define SB_DCD_CHK_NEZ \
93bce88370SMarek Vasut ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT)
94bce88370SMarek Vasut /* NOP */
95bce88370SMarek Vasut #define SB_DCD_NOOP \
96bce88370SMarek Vasut (SB_HAB_DCD_NOOP << 24)
97bce88370SMarek Vasut
98bce88370SMarek Vasut struct sb_dcd_ctx {
99bce88370SMarek Vasut struct sb_dcd_ctx *dcd;
100bce88370SMarek Vasut
101bce88370SMarek Vasut uint32_t id;
102bce88370SMarek Vasut
103bce88370SMarek Vasut /* The DCD block. */
104bce88370SMarek Vasut uint32_t *payload;
105bce88370SMarek Vasut /* Size of the whole DCD block. */
106bce88370SMarek Vasut uint32_t size;
107bce88370SMarek Vasut
108bce88370SMarek Vasut /* Pointer to previous DCD command block. */
109bce88370SMarek Vasut uint32_t *prev_dcd_head;
110bce88370SMarek Vasut };
111bce88370SMarek Vasut
112bce88370SMarek Vasut /*
113bce88370SMarek Vasut * IMAGE
114bce88370SMarek Vasut * |-SECTION
115bce88370SMarek Vasut * | |-CMD
116bce88370SMarek Vasut * | |-CMD
117bce88370SMarek Vasut * | `-CMD
118bce88370SMarek Vasut * |-SECTION
119bce88370SMarek Vasut * | |-CMD
120bce88370SMarek Vasut * : :
121bce88370SMarek Vasut */
122bce88370SMarek Vasut struct sb_cmd_list {
123bce88370SMarek Vasut char *cmd;
124bce88370SMarek Vasut size_t len;
125bce88370SMarek Vasut unsigned int lineno;
126bce88370SMarek Vasut };
127bce88370SMarek Vasut
128bce88370SMarek Vasut struct sb_cmd_ctx {
129bce88370SMarek Vasut uint32_t size;
130bce88370SMarek Vasut
131bce88370SMarek Vasut struct sb_cmd_ctx *cmd;
132bce88370SMarek Vasut
133bce88370SMarek Vasut uint8_t *data;
134bce88370SMarek Vasut uint32_t length;
135bce88370SMarek Vasut
136bce88370SMarek Vasut struct sb_command payload;
137bce88370SMarek Vasut struct sb_command c_payload;
138bce88370SMarek Vasut };
139bce88370SMarek Vasut
140bce88370SMarek Vasut struct sb_section_ctx {
141bce88370SMarek Vasut uint32_t size;
142bce88370SMarek Vasut
143bce88370SMarek Vasut /* Section flags */
144bce88370SMarek Vasut unsigned int boot:1;
145bce88370SMarek Vasut
146bce88370SMarek Vasut struct sb_section_ctx *sect;
147bce88370SMarek Vasut
148bce88370SMarek Vasut struct sb_cmd_ctx *cmd_head;
149bce88370SMarek Vasut struct sb_cmd_ctx *cmd_tail;
150bce88370SMarek Vasut
151bce88370SMarek Vasut struct sb_sections_header payload;
152bce88370SMarek Vasut };
153bce88370SMarek Vasut
154bce88370SMarek Vasut struct sb_image_ctx {
155bce88370SMarek Vasut unsigned int in_section:1;
156bce88370SMarek Vasut unsigned int in_dcd:1;
157bce88370SMarek Vasut /* Image configuration */
1587a139959SAlexey Ignatov unsigned int display_progress:1;
159bce88370SMarek Vasut unsigned int silent_dump:1;
160bce88370SMarek Vasut char *input_filename;
161bce88370SMarek Vasut char *output_filename;
162bce88370SMarek Vasut char *cfg_filename;
163bce88370SMarek Vasut uint8_t image_key[16];
164bce88370SMarek Vasut
165bce88370SMarek Vasut /* Number of section in the image */
166bce88370SMarek Vasut unsigned int sect_count;
167bce88370SMarek Vasut /* Bootable section */
168bce88370SMarek Vasut unsigned int sect_boot;
169bce88370SMarek Vasut unsigned int sect_boot_found:1;
170bce88370SMarek Vasut
171bce88370SMarek Vasut struct sb_section_ctx *sect_head;
172bce88370SMarek Vasut struct sb_section_ctx *sect_tail;
173bce88370SMarek Vasut
174bce88370SMarek Vasut struct sb_dcd_ctx *dcd_head;
175bce88370SMarek Vasut struct sb_dcd_ctx *dcd_tail;
176bce88370SMarek Vasut
1777bae13b7SMarek Vasut EVP_CIPHER_CTX *cipher_ctx;
1787bae13b7SMarek Vasut EVP_MD_CTX *md_ctx;
179bce88370SMarek Vasut uint8_t digest[32];
180bce88370SMarek Vasut struct sb_key_dictionary_key sb_dict_key;
181bce88370SMarek Vasut
182bce88370SMarek Vasut struct sb_boot_image_header payload;
183bce88370SMarek Vasut };
184bce88370SMarek Vasut
185bce88370SMarek Vasut /*
186bce88370SMarek Vasut * Instruction semantics:
187bce88370SMarek Vasut * NOOP
188bce88370SMarek Vasut * TAG [LAST]
189bce88370SMarek Vasut * LOAD address file
190bce88370SMarek Vasut * LOAD IVT address IVT_entry_point
191bce88370SMarek Vasut * FILL address pattern length
192bce88370SMarek Vasut * JUMP [HAB] address [r0_arg]
193bce88370SMarek Vasut * CALL [HAB] address [r0_arg]
194bce88370SMarek Vasut * MODE mode
195bce88370SMarek Vasut * For i.MX23, mode = USB/I2C/SPI1_FLASH/SPI2_FLASH/NAND_BCH
196bce88370SMarek Vasut * JTAG/SPI3_EEPROM/SD_SSP0/SD_SSP1
197bce88370SMarek Vasut * For i.MX28, mode = USB/I2C/SPI2_FLASH/SPI3_FLASH/NAND_BCH
198bce88370SMarek Vasut * JTAG/SPI2_EEPROM/SD_SSP0/SD_SSP1
199bce88370SMarek Vasut */
200bce88370SMarek Vasut
201bce88370SMarek Vasut /*
202bce88370SMarek Vasut * AES libcrypto
203bce88370SMarek Vasut */
sb_aes_init(struct sb_image_ctx * ictx,uint8_t * iv,int enc)204bce88370SMarek Vasut static int sb_aes_init(struct sb_image_ctx *ictx, uint8_t *iv, int enc)
205bce88370SMarek Vasut {
2067bae13b7SMarek Vasut EVP_CIPHER_CTX *ctx;
207bce88370SMarek Vasut int ret;
208bce88370SMarek Vasut
209bce88370SMarek Vasut /* If there is no init vector, init vector is all zeroes. */
210bce88370SMarek Vasut if (!iv)
211bce88370SMarek Vasut iv = ictx->image_key;
212bce88370SMarek Vasut
2137bae13b7SMarek Vasut ctx = EVP_CIPHER_CTX_new();
214bce88370SMarek Vasut ret = EVP_CipherInit(ctx, EVP_aes_128_cbc(), ictx->image_key, iv, enc);
2157bae13b7SMarek Vasut if (ret == 1) {
216bce88370SMarek Vasut EVP_CIPHER_CTX_set_padding(ctx, 0);
2177bae13b7SMarek Vasut ictx->cipher_ctx = ctx;
2187bae13b7SMarek Vasut }
219bce88370SMarek Vasut return ret;
220bce88370SMarek Vasut }
221bce88370SMarek Vasut
sb_aes_crypt(struct sb_image_ctx * ictx,uint8_t * in_data,uint8_t * out_data,int in_len)222bce88370SMarek Vasut static int sb_aes_crypt(struct sb_image_ctx *ictx, uint8_t *in_data,
223bce88370SMarek Vasut uint8_t *out_data, int in_len)
224bce88370SMarek Vasut {
2257bae13b7SMarek Vasut EVP_CIPHER_CTX *ctx = ictx->cipher_ctx;
226bce88370SMarek Vasut int ret, outlen;
227bce88370SMarek Vasut uint8_t *outbuf;
228bce88370SMarek Vasut
229bce88370SMarek Vasut outbuf = malloc(in_len);
230bce88370SMarek Vasut if (!outbuf)
231bce88370SMarek Vasut return -ENOMEM;
232bce88370SMarek Vasut memset(outbuf, 0, sizeof(in_len));
233bce88370SMarek Vasut
234bce88370SMarek Vasut ret = EVP_CipherUpdate(ctx, outbuf, &outlen, in_data, in_len);
235bce88370SMarek Vasut if (!ret) {
236bce88370SMarek Vasut ret = -EINVAL;
237bce88370SMarek Vasut goto err;
238bce88370SMarek Vasut }
239bce88370SMarek Vasut
240bce88370SMarek Vasut if (out_data)
241bce88370SMarek Vasut memcpy(out_data, outbuf, outlen);
242bce88370SMarek Vasut
243bce88370SMarek Vasut err:
244bce88370SMarek Vasut free(outbuf);
245bce88370SMarek Vasut return ret;
246bce88370SMarek Vasut }
247bce88370SMarek Vasut
sb_aes_deinit(EVP_CIPHER_CTX * ctx)248bce88370SMarek Vasut static int sb_aes_deinit(EVP_CIPHER_CTX *ctx)
249bce88370SMarek Vasut {
2507bae13b7SMarek Vasut return EVP_CIPHER_CTX_reset(ctx);
251bce88370SMarek Vasut }
252bce88370SMarek Vasut
sb_aes_reinit(struct sb_image_ctx * ictx,int enc)253bce88370SMarek Vasut static int sb_aes_reinit(struct sb_image_ctx *ictx, int enc)
254bce88370SMarek Vasut {
255bce88370SMarek Vasut int ret;
2567bae13b7SMarek Vasut EVP_CIPHER_CTX *ctx = ictx->cipher_ctx;
257bce88370SMarek Vasut struct sb_boot_image_header *sb_header = &ictx->payload;
258bce88370SMarek Vasut uint8_t *iv = sb_header->iv;
259bce88370SMarek Vasut
260bce88370SMarek Vasut ret = sb_aes_deinit(ctx);
261bce88370SMarek Vasut if (!ret)
262bce88370SMarek Vasut return ret;
263bce88370SMarek Vasut return sb_aes_init(ictx, iv, enc);
264bce88370SMarek Vasut }
265bce88370SMarek Vasut
266bce88370SMarek Vasut /*
267bce88370SMarek Vasut * Debug
268bce88370SMarek Vasut */
soprintf(struct sb_image_ctx * ictx,const char * fmt,...)269bce88370SMarek Vasut static void soprintf(struct sb_image_ctx *ictx, const char *fmt, ...)
270bce88370SMarek Vasut {
271bce88370SMarek Vasut va_list ap;
272bce88370SMarek Vasut
273bce88370SMarek Vasut if (ictx->silent_dump)
274bce88370SMarek Vasut return;
275bce88370SMarek Vasut
276bce88370SMarek Vasut va_start(ap, fmt);
277bce88370SMarek Vasut vfprintf(stdout, fmt, ap);
278bce88370SMarek Vasut va_end(ap);
279bce88370SMarek Vasut }
280bce88370SMarek Vasut
281bce88370SMarek Vasut /*
282bce88370SMarek Vasut * Code
283bce88370SMarek Vasut */
sb_get_timestamp(void)284bce88370SMarek Vasut static time_t sb_get_timestamp(void)
285bce88370SMarek Vasut {
286bce88370SMarek Vasut struct tm time_2000 = {
287bce88370SMarek Vasut .tm_yday = 1, /* Jan. 1st */
288bce88370SMarek Vasut .tm_year = 100, /* 2000 */
289bce88370SMarek Vasut };
290bce88370SMarek Vasut time_t seconds_to_2000 = mktime(&time_2000);
291bce88370SMarek Vasut time_t seconds_to_now = time(NULL);
292bce88370SMarek Vasut
293bce88370SMarek Vasut return seconds_to_now - seconds_to_2000;
294bce88370SMarek Vasut }
295bce88370SMarek Vasut
sb_get_time(time_t time,struct tm * tm)296bce88370SMarek Vasut static int sb_get_time(time_t time, struct tm *tm)
297bce88370SMarek Vasut {
298bce88370SMarek Vasut struct tm time_2000 = {
299bce88370SMarek Vasut .tm_yday = 1, /* Jan. 1st */
300bce88370SMarek Vasut .tm_year = 0, /* 1900 */
301bce88370SMarek Vasut };
302bce88370SMarek Vasut const time_t seconds_to_2000 = mktime(&time_2000);
303bce88370SMarek Vasut const time_t seconds_to_now = seconds_to_2000 + time;
304bce88370SMarek Vasut struct tm *ret;
305bce88370SMarek Vasut ret = gmtime_r(&seconds_to_now, tm);
306bce88370SMarek Vasut return ret ? 0 : -EINVAL;
307bce88370SMarek Vasut }
308bce88370SMarek Vasut
sb_encrypt_sb_header(struct sb_image_ctx * ictx)309bce88370SMarek Vasut static void sb_encrypt_sb_header(struct sb_image_ctx *ictx)
310bce88370SMarek Vasut {
3117bae13b7SMarek Vasut EVP_MD_CTX *md_ctx = ictx->md_ctx;
312bce88370SMarek Vasut struct sb_boot_image_header *sb_header = &ictx->payload;
313bce88370SMarek Vasut uint8_t *sb_header_ptr = (uint8_t *)sb_header;
314bce88370SMarek Vasut
315bce88370SMarek Vasut /* Encrypt the header, compute the digest. */
316bce88370SMarek Vasut sb_aes_crypt(ictx, sb_header_ptr, NULL, sizeof(*sb_header));
317bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, sb_header_ptr, sizeof(*sb_header));
318bce88370SMarek Vasut }
319bce88370SMarek Vasut
sb_encrypt_sb_sections_header(struct sb_image_ctx * ictx)320bce88370SMarek Vasut static void sb_encrypt_sb_sections_header(struct sb_image_ctx *ictx)
321bce88370SMarek Vasut {
3227bae13b7SMarek Vasut EVP_MD_CTX *md_ctx = ictx->md_ctx;
323bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head;
324bce88370SMarek Vasut struct sb_sections_header *shdr;
325bce88370SMarek Vasut uint8_t *sb_sections_header_ptr;
326bce88370SMarek Vasut const int size = sizeof(*shdr);
327bce88370SMarek Vasut
328bce88370SMarek Vasut while (sctx) {
329bce88370SMarek Vasut shdr = &sctx->payload;
330bce88370SMarek Vasut sb_sections_header_ptr = (uint8_t *)shdr;
331bce88370SMarek Vasut
332bce88370SMarek Vasut sb_aes_crypt(ictx, sb_sections_header_ptr,
333bce88370SMarek Vasut ictx->sb_dict_key.cbc_mac, size);
334bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, sb_sections_header_ptr, size);
335bce88370SMarek Vasut
336bce88370SMarek Vasut sctx = sctx->sect;
337bce88370SMarek Vasut };
338bce88370SMarek Vasut }
339bce88370SMarek Vasut
sb_encrypt_key_dictionary_key(struct sb_image_ctx * ictx)340bce88370SMarek Vasut static void sb_encrypt_key_dictionary_key(struct sb_image_ctx *ictx)
341bce88370SMarek Vasut {
3427bae13b7SMarek Vasut EVP_MD_CTX *md_ctx = ictx->md_ctx;
343bce88370SMarek Vasut
344bce88370SMarek Vasut sb_aes_crypt(ictx, ictx->image_key, ictx->sb_dict_key.key,
345bce88370SMarek Vasut sizeof(ictx->sb_dict_key.key));
346bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key));
347bce88370SMarek Vasut }
348bce88370SMarek Vasut
sb_decrypt_key_dictionary_key(struct sb_image_ctx * ictx)349bce88370SMarek Vasut static void sb_decrypt_key_dictionary_key(struct sb_image_ctx *ictx)
350bce88370SMarek Vasut {
3517bae13b7SMarek Vasut EVP_MD_CTX *md_ctx = ictx->md_ctx;
352bce88370SMarek Vasut
353bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key));
354bce88370SMarek Vasut sb_aes_crypt(ictx, ictx->sb_dict_key.key, ictx->image_key,
355bce88370SMarek Vasut sizeof(ictx->sb_dict_key.key));
356bce88370SMarek Vasut }
357bce88370SMarek Vasut
sb_encrypt_tag(struct sb_image_ctx * ictx,struct sb_cmd_ctx * cctx)358bce88370SMarek Vasut static void sb_encrypt_tag(struct sb_image_ctx *ictx,
359bce88370SMarek Vasut struct sb_cmd_ctx *cctx)
360bce88370SMarek Vasut {
3617bae13b7SMarek Vasut EVP_MD_CTX *md_ctx = ictx->md_ctx;
362bce88370SMarek Vasut struct sb_command *cmd = &cctx->payload;
363bce88370SMarek Vasut
364bce88370SMarek Vasut sb_aes_crypt(ictx, (uint8_t *)cmd,
365bce88370SMarek Vasut (uint8_t *)&cctx->c_payload, sizeof(*cmd));
366bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd));
367bce88370SMarek Vasut }
368bce88370SMarek Vasut
sb_encrypt_image(struct sb_image_ctx * ictx)369bce88370SMarek Vasut static int sb_encrypt_image(struct sb_image_ctx *ictx)
370bce88370SMarek Vasut {
371bce88370SMarek Vasut /* Start image-wide crypto. */
3727bae13b7SMarek Vasut ictx->md_ctx = EVP_MD_CTX_new();
3737bae13b7SMarek Vasut EVP_DigestInit(ictx->md_ctx, EVP_sha1());
374bce88370SMarek Vasut
375bce88370SMarek Vasut /*
376bce88370SMarek Vasut * SB image header.
377bce88370SMarek Vasut */
378bce88370SMarek Vasut sb_aes_init(ictx, NULL, 1);
379bce88370SMarek Vasut sb_encrypt_sb_header(ictx);
380bce88370SMarek Vasut
381bce88370SMarek Vasut /*
382bce88370SMarek Vasut * SB sections header.
383bce88370SMarek Vasut */
384bce88370SMarek Vasut sb_encrypt_sb_sections_header(ictx);
385bce88370SMarek Vasut
386bce88370SMarek Vasut /*
387bce88370SMarek Vasut * Key dictionary.
388bce88370SMarek Vasut */
389bce88370SMarek Vasut sb_aes_reinit(ictx, 1);
390bce88370SMarek Vasut sb_encrypt_key_dictionary_key(ictx);
391bce88370SMarek Vasut
392bce88370SMarek Vasut /*
393bce88370SMarek Vasut * Section tags.
394bce88370SMarek Vasut */
395bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
396bce88370SMarek Vasut struct sb_command *ccmd;
397bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head;
398bce88370SMarek Vasut
399bce88370SMarek Vasut while (sctx) {
400bce88370SMarek Vasut cctx = sctx->cmd_head;
401bce88370SMarek Vasut
402bce88370SMarek Vasut sb_aes_reinit(ictx, 1);
403bce88370SMarek Vasut
404bce88370SMarek Vasut while (cctx) {
405bce88370SMarek Vasut ccmd = &cctx->payload;
406bce88370SMarek Vasut
407bce88370SMarek Vasut sb_encrypt_tag(ictx, cctx);
408bce88370SMarek Vasut
409bce88370SMarek Vasut if (ccmd->header.tag == ROM_TAG_CMD) {
410bce88370SMarek Vasut sb_aes_reinit(ictx, 1);
411bce88370SMarek Vasut } else if (ccmd->header.tag == ROM_LOAD_CMD) {
412bce88370SMarek Vasut sb_aes_crypt(ictx, cctx->data, cctx->data,
413bce88370SMarek Vasut cctx->length);
4147bae13b7SMarek Vasut EVP_DigestUpdate(ictx->md_ctx, cctx->data,
415bce88370SMarek Vasut cctx->length);
416bce88370SMarek Vasut }
417bce88370SMarek Vasut
418bce88370SMarek Vasut cctx = cctx->cmd;
419bce88370SMarek Vasut }
420bce88370SMarek Vasut
421bce88370SMarek Vasut sctx = sctx->sect;
422bce88370SMarek Vasut };
423bce88370SMarek Vasut
424bce88370SMarek Vasut /*
425bce88370SMarek Vasut * Dump the SHA1 of the whole image.
426bce88370SMarek Vasut */
427bce88370SMarek Vasut sb_aes_reinit(ictx, 1);
428bce88370SMarek Vasut
4297bae13b7SMarek Vasut EVP_DigestFinal(ictx->md_ctx, ictx->digest, NULL);
4307bae13b7SMarek Vasut EVP_MD_CTX_free(ictx->md_ctx);
431bce88370SMarek Vasut sb_aes_crypt(ictx, ictx->digest, ictx->digest, sizeof(ictx->digest));
432bce88370SMarek Vasut
433bce88370SMarek Vasut /* Stop the encryption session. */
4347bae13b7SMarek Vasut sb_aes_deinit(ictx->cipher_ctx);
435bce88370SMarek Vasut
436bce88370SMarek Vasut return 0;
437bce88370SMarek Vasut }
438bce88370SMarek Vasut
sb_load_file(struct sb_cmd_ctx * cctx,char * filename)439bce88370SMarek Vasut static int sb_load_file(struct sb_cmd_ctx *cctx, char *filename)
440bce88370SMarek Vasut {
441bce88370SMarek Vasut long real_size, roundup_size;
442bce88370SMarek Vasut uint8_t *data;
443bce88370SMarek Vasut long ret;
444bce88370SMarek Vasut unsigned long size;
445bce88370SMarek Vasut FILE *fp;
446bce88370SMarek Vasut
447bce88370SMarek Vasut if (!filename) {
448bce88370SMarek Vasut fprintf(stderr, "ERR: Missing filename!\n");
449bce88370SMarek Vasut return -EINVAL;
450bce88370SMarek Vasut }
451bce88370SMarek Vasut
452bce88370SMarek Vasut fp = fopen(filename, "r");
453bce88370SMarek Vasut if (!fp)
454bce88370SMarek Vasut goto err_open;
455bce88370SMarek Vasut
456bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_END);
457bce88370SMarek Vasut if (ret < 0)
458bce88370SMarek Vasut goto err_file;
459bce88370SMarek Vasut
460bce88370SMarek Vasut real_size = ftell(fp);
461bce88370SMarek Vasut if (real_size < 0)
462bce88370SMarek Vasut goto err_file;
463bce88370SMarek Vasut
464bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_SET);
465bce88370SMarek Vasut if (ret < 0)
466bce88370SMarek Vasut goto err_file;
467bce88370SMarek Vasut
468bce88370SMarek Vasut roundup_size = roundup(real_size, SB_BLOCK_SIZE);
469bce88370SMarek Vasut data = calloc(1, roundup_size);
470bce88370SMarek Vasut if (!data)
471bce88370SMarek Vasut goto err_file;
472bce88370SMarek Vasut
473bce88370SMarek Vasut size = fread(data, 1, real_size, fp);
474bce88370SMarek Vasut if (size != (unsigned long)real_size)
475bce88370SMarek Vasut goto err_alloc;
476bce88370SMarek Vasut
477bce88370SMarek Vasut cctx->data = data;
478bce88370SMarek Vasut cctx->length = roundup_size;
479bce88370SMarek Vasut
480bce88370SMarek Vasut fclose(fp);
481bce88370SMarek Vasut return 0;
482bce88370SMarek Vasut
483bce88370SMarek Vasut err_alloc:
484bce88370SMarek Vasut free(data);
485bce88370SMarek Vasut err_file:
486bce88370SMarek Vasut fclose(fp);
487bce88370SMarek Vasut err_open:
488bce88370SMarek Vasut fprintf(stderr, "ERR: Failed to load file \"%s\"\n", filename);
489bce88370SMarek Vasut return -EINVAL;
490bce88370SMarek Vasut }
491bce88370SMarek Vasut
sb_command_checksum(struct sb_command * inst)492bce88370SMarek Vasut static uint8_t sb_command_checksum(struct sb_command *inst)
493bce88370SMarek Vasut {
494bce88370SMarek Vasut uint8_t *inst_ptr = (uint8_t *)inst;
495bce88370SMarek Vasut uint8_t csum = 0;
496bce88370SMarek Vasut unsigned int i;
497bce88370SMarek Vasut
498bce88370SMarek Vasut for (i = 0; i < sizeof(struct sb_command); i++)
499bce88370SMarek Vasut csum += inst_ptr[i];
500bce88370SMarek Vasut
501bce88370SMarek Vasut return csum;
502bce88370SMarek Vasut }
503bce88370SMarek Vasut
sb_token_to_long(char * tok,uint32_t * rid)504bce88370SMarek Vasut static int sb_token_to_long(char *tok, uint32_t *rid)
505bce88370SMarek Vasut {
506bce88370SMarek Vasut char *endptr;
507bce88370SMarek Vasut unsigned long id;
508bce88370SMarek Vasut
509bce88370SMarek Vasut if (tok[0] != '0' || tok[1] != 'x') {
510bce88370SMarek Vasut fprintf(stderr, "ERR: Invalid hexadecimal number!\n");
511bce88370SMarek Vasut return -EINVAL;
512bce88370SMarek Vasut }
513bce88370SMarek Vasut
514bce88370SMarek Vasut tok += 2;
515bce88370SMarek Vasut
5165b5a82ebSMarek Vasut errno = 0;
517bce88370SMarek Vasut id = strtoul(tok, &endptr, 16);
518bce88370SMarek Vasut if ((errno == ERANGE && id == ULONG_MAX) || (errno != 0 && id == 0)) {
519bce88370SMarek Vasut fprintf(stderr, "ERR: Value can't be decoded!\n");
520bce88370SMarek Vasut return -EINVAL;
521bce88370SMarek Vasut }
522bce88370SMarek Vasut
523bce88370SMarek Vasut /* Check for 32-bit overflow. */
524bce88370SMarek Vasut if (id > 0xffffffff) {
525bce88370SMarek Vasut fprintf(stderr, "ERR: Value too big!\n");
526bce88370SMarek Vasut return -EINVAL;
527bce88370SMarek Vasut }
528bce88370SMarek Vasut
529bce88370SMarek Vasut if (endptr == tok) {
530bce88370SMarek Vasut fprintf(stderr, "ERR: Deformed value!\n");
531bce88370SMarek Vasut return -EINVAL;
532bce88370SMarek Vasut }
533bce88370SMarek Vasut
534bce88370SMarek Vasut *rid = (uint32_t)id;
535bce88370SMarek Vasut return 0;
536bce88370SMarek Vasut }
537bce88370SMarek Vasut
sb_grow_dcd(struct sb_dcd_ctx * dctx,unsigned int inc_size)538bce88370SMarek Vasut static int sb_grow_dcd(struct sb_dcd_ctx *dctx, unsigned int inc_size)
539bce88370SMarek Vasut {
540bce88370SMarek Vasut uint32_t *tmp;
541bce88370SMarek Vasut
542bce88370SMarek Vasut if (!inc_size)
543bce88370SMarek Vasut return 0;
544bce88370SMarek Vasut
545bce88370SMarek Vasut dctx->size += inc_size;
546bce88370SMarek Vasut tmp = realloc(dctx->payload, dctx->size);
547bce88370SMarek Vasut if (!tmp)
548bce88370SMarek Vasut return -ENOMEM;
549bce88370SMarek Vasut
550bce88370SMarek Vasut dctx->payload = tmp;
551bce88370SMarek Vasut
552bce88370SMarek Vasut /* Assemble and update the HAB DCD header. */
553bce88370SMarek Vasut dctx->payload[0] = htonl((SB_HAB_DCD_TAG << 24) |
554bce88370SMarek Vasut (dctx->size << 8) |
555bce88370SMarek Vasut SB_HAB_VERSION);
556bce88370SMarek Vasut
557bce88370SMarek Vasut return 0;
558bce88370SMarek Vasut }
559bce88370SMarek Vasut
sb_build_dcd(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)560bce88370SMarek Vasut static int sb_build_dcd(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
561bce88370SMarek Vasut {
562bce88370SMarek Vasut struct sb_dcd_ctx *dctx;
563bce88370SMarek Vasut
564bce88370SMarek Vasut char *tok;
565bce88370SMarek Vasut uint32_t id;
566bce88370SMarek Vasut int ret;
567bce88370SMarek Vasut
568bce88370SMarek Vasut dctx = calloc(1, sizeof(*dctx));
569bce88370SMarek Vasut if (!dctx)
570bce88370SMarek Vasut return -ENOMEM;
571bce88370SMarek Vasut
572bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 4);
573bce88370SMarek Vasut if (ret)
574bce88370SMarek Vasut goto err_dcd;
575bce88370SMarek Vasut
576bce88370SMarek Vasut /* Read DCD block number. */
577bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
578bce88370SMarek Vasut if (!tok) {
579bce88370SMarek Vasut fprintf(stderr, "#%i ERR: DCD block without number!\n",
580bce88370SMarek Vasut cmd->lineno);
581bce88370SMarek Vasut ret = -EINVAL;
582bce88370SMarek Vasut goto err_dcd;
583bce88370SMarek Vasut }
584bce88370SMarek Vasut
585bce88370SMarek Vasut /* Parse the DCD block number. */
586bce88370SMarek Vasut ret = sb_token_to_long(tok, &id);
587bce88370SMarek Vasut if (ret) {
588bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Malformed DCD block number!\n",
589bce88370SMarek Vasut cmd->lineno);
590bce88370SMarek Vasut goto err_dcd;
591bce88370SMarek Vasut }
592bce88370SMarek Vasut
593bce88370SMarek Vasut dctx->id = id;
594bce88370SMarek Vasut
595bce88370SMarek Vasut /*
596bce88370SMarek Vasut * The DCD block is now constructed. Append it to the list.
597bce88370SMarek Vasut * WARNING: The DCD size is still not computed and will be
598bce88370SMarek Vasut * updated while parsing it's commands.
599bce88370SMarek Vasut */
600bce88370SMarek Vasut if (!ictx->dcd_head) {
601bce88370SMarek Vasut ictx->dcd_head = dctx;
602bce88370SMarek Vasut ictx->dcd_tail = dctx;
603bce88370SMarek Vasut } else {
604bce88370SMarek Vasut ictx->dcd_tail->dcd = dctx;
605bce88370SMarek Vasut ictx->dcd_tail = dctx;
606bce88370SMarek Vasut }
607bce88370SMarek Vasut
608bce88370SMarek Vasut return 0;
609bce88370SMarek Vasut
610bce88370SMarek Vasut err_dcd:
611bce88370SMarek Vasut free(dctx->payload);
612bce88370SMarek Vasut free(dctx);
613bce88370SMarek Vasut return ret;
614bce88370SMarek Vasut }
615bce88370SMarek Vasut
sb_build_dcd_block(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd,uint32_t type)616bce88370SMarek Vasut static int sb_build_dcd_block(struct sb_image_ctx *ictx,
617bce88370SMarek Vasut struct sb_cmd_list *cmd,
618bce88370SMarek Vasut uint32_t type)
619bce88370SMarek Vasut {
620bce88370SMarek Vasut char *tok;
621bce88370SMarek Vasut uint32_t address, value, length;
622bce88370SMarek Vasut int ret;
623bce88370SMarek Vasut
624bce88370SMarek Vasut struct sb_dcd_ctx *dctx = ictx->dcd_tail;
625bce88370SMarek Vasut uint32_t *dcd;
626bce88370SMarek Vasut
627bce88370SMarek Vasut if (dctx->prev_dcd_head && (type != SB_DCD_NOOP) &&
628bce88370SMarek Vasut ((dctx->prev_dcd_head[0] & 0xff0000ff) == type)) {
629bce88370SMarek Vasut /* Same instruction as before, just append it. */
630bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 8);
631bce88370SMarek Vasut if (ret)
632bce88370SMarek Vasut return ret;
633bce88370SMarek Vasut } else if (type == SB_DCD_NOOP) {
634bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 4);
635bce88370SMarek Vasut if (ret)
636bce88370SMarek Vasut return ret;
637bce88370SMarek Vasut
638bce88370SMarek Vasut /* Update DCD command block pointer. */
639bce88370SMarek Vasut dctx->prev_dcd_head = dctx->payload +
640bce88370SMarek Vasut dctx->size / sizeof(*dctx->payload) - 1;
641bce88370SMarek Vasut
642bce88370SMarek Vasut /* NOOP has only 4 bytes and no payload. */
643bce88370SMarek Vasut goto noop;
644bce88370SMarek Vasut } else {
645bce88370SMarek Vasut /*
646bce88370SMarek Vasut * Either a different instruction block started now
647bce88370SMarek Vasut * or this is the first instruction block.
648bce88370SMarek Vasut */
649bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 12);
650bce88370SMarek Vasut if (ret)
651bce88370SMarek Vasut return ret;
652bce88370SMarek Vasut
653bce88370SMarek Vasut /* Update DCD command block pointer. */
654bce88370SMarek Vasut dctx->prev_dcd_head = dctx->payload +
655bce88370SMarek Vasut dctx->size / sizeof(*dctx->payload) - 3;
656bce88370SMarek Vasut }
657bce88370SMarek Vasut
658bce88370SMarek Vasut dcd = dctx->payload + dctx->size / sizeof(*dctx->payload) - 2;
659bce88370SMarek Vasut
660bce88370SMarek Vasut /*
661bce88370SMarek Vasut * Prepare the command.
662bce88370SMarek Vasut */
663bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
664bce88370SMarek Vasut if (!tok) {
665bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing DCD address!\n",
666bce88370SMarek Vasut cmd->lineno);
667bce88370SMarek Vasut ret = -EINVAL;
668bce88370SMarek Vasut goto err;
669bce88370SMarek Vasut }
670bce88370SMarek Vasut
671bce88370SMarek Vasut /* Read DCD destination address. */
672bce88370SMarek Vasut ret = sb_token_to_long(tok, &address);
673bce88370SMarek Vasut if (ret) {
674bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect DCD address!\n",
675bce88370SMarek Vasut cmd->lineno);
676bce88370SMarek Vasut goto err;
677bce88370SMarek Vasut }
678bce88370SMarek Vasut
679bce88370SMarek Vasut tok = strtok(NULL, " ");
680bce88370SMarek Vasut if (!tok) {
681bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing DCD value!\n",
682bce88370SMarek Vasut cmd->lineno);
683bce88370SMarek Vasut ret = -EINVAL;
684bce88370SMarek Vasut goto err;
685bce88370SMarek Vasut }
686bce88370SMarek Vasut
687bce88370SMarek Vasut /* Read DCD operation value. */
688bce88370SMarek Vasut ret = sb_token_to_long(tok, &value);
689bce88370SMarek Vasut if (ret) {
690bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect DCD value!\n",
691bce88370SMarek Vasut cmd->lineno);
692bce88370SMarek Vasut goto err;
693bce88370SMarek Vasut }
694bce88370SMarek Vasut
695bce88370SMarek Vasut /* Fill in the new DCD entry. */
696bce88370SMarek Vasut dcd[0] = htonl(address);
697bce88370SMarek Vasut dcd[1] = htonl(value);
698bce88370SMarek Vasut
699bce88370SMarek Vasut noop:
700bce88370SMarek Vasut /* Update the DCD command block. */
701bce88370SMarek Vasut length = dctx->size -
702bce88370SMarek Vasut ((dctx->prev_dcd_head - dctx->payload) *
703bce88370SMarek Vasut sizeof(*dctx->payload));
704bce88370SMarek Vasut dctx->prev_dcd_head[0] = htonl(type | (length << 8));
705bce88370SMarek Vasut
706bce88370SMarek Vasut err:
707bce88370SMarek Vasut return ret;
708bce88370SMarek Vasut }
709bce88370SMarek Vasut
sb_build_section(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)710bce88370SMarek Vasut static int sb_build_section(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
711bce88370SMarek Vasut {
712bce88370SMarek Vasut struct sb_section_ctx *sctx;
713bce88370SMarek Vasut struct sb_sections_header *shdr;
714bce88370SMarek Vasut char *tok;
715bce88370SMarek Vasut uint32_t bootable = 0;
716bce88370SMarek Vasut uint32_t id;
717bce88370SMarek Vasut int ret;
718bce88370SMarek Vasut
719bce88370SMarek Vasut sctx = calloc(1, sizeof(*sctx));
720bce88370SMarek Vasut if (!sctx)
721bce88370SMarek Vasut return -ENOMEM;
722bce88370SMarek Vasut
723bce88370SMarek Vasut /* Read section number. */
724bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
725bce88370SMarek Vasut if (!tok) {
726bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Section without number!\n",
727bce88370SMarek Vasut cmd->lineno);
728bce88370SMarek Vasut ret = -EINVAL;
729bce88370SMarek Vasut goto err_sect;
730bce88370SMarek Vasut }
731bce88370SMarek Vasut
732bce88370SMarek Vasut /* Parse the section number. */
733bce88370SMarek Vasut ret = sb_token_to_long(tok, &id);
734bce88370SMarek Vasut if (ret) {
735bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Malformed section number!\n",
736bce88370SMarek Vasut cmd->lineno);
737bce88370SMarek Vasut goto err_sect;
738bce88370SMarek Vasut }
739bce88370SMarek Vasut
740bce88370SMarek Vasut /* Read section's BOOTABLE flag. */
741bce88370SMarek Vasut tok = strtok(NULL, " ");
742bce88370SMarek Vasut if (tok && (strlen(tok) == 8) && !strncmp(tok, "BOOTABLE", 8))
743bce88370SMarek Vasut bootable = SB_SECTION_FLAG_BOOTABLE;
744bce88370SMarek Vasut
745bce88370SMarek Vasut sctx->boot = bootable;
746bce88370SMarek Vasut
747bce88370SMarek Vasut shdr = &sctx->payload;
748bce88370SMarek Vasut shdr->section_number = id;
749bce88370SMarek Vasut shdr->section_flags = bootable;
750bce88370SMarek Vasut
751bce88370SMarek Vasut /*
752bce88370SMarek Vasut * The section is now constructed. Append it to the list.
753bce88370SMarek Vasut * WARNING: The section size is still not computed and will
754bce88370SMarek Vasut * be updated while parsing it's commands.
755bce88370SMarek Vasut */
756bce88370SMarek Vasut ictx->sect_count++;
757bce88370SMarek Vasut
758bce88370SMarek Vasut /* Mark that this section is bootable one. */
759bce88370SMarek Vasut if (bootable) {
760bce88370SMarek Vasut if (ictx->sect_boot_found) {
761bce88370SMarek Vasut fprintf(stderr,
762bce88370SMarek Vasut "#%i WARN: Multiple bootable section!\n",
763bce88370SMarek Vasut cmd->lineno);
764bce88370SMarek Vasut } else {
765bce88370SMarek Vasut ictx->sect_boot = id;
766bce88370SMarek Vasut ictx->sect_boot_found = 1;
767bce88370SMarek Vasut }
768bce88370SMarek Vasut }
769bce88370SMarek Vasut
770bce88370SMarek Vasut if (!ictx->sect_head) {
771bce88370SMarek Vasut ictx->sect_head = sctx;
772bce88370SMarek Vasut ictx->sect_tail = sctx;
773bce88370SMarek Vasut } else {
774bce88370SMarek Vasut ictx->sect_tail->sect = sctx;
775bce88370SMarek Vasut ictx->sect_tail = sctx;
776bce88370SMarek Vasut }
777bce88370SMarek Vasut
778bce88370SMarek Vasut return 0;
779bce88370SMarek Vasut
780bce88370SMarek Vasut err_sect:
781bce88370SMarek Vasut free(sctx);
782bce88370SMarek Vasut return ret;
783bce88370SMarek Vasut }
784bce88370SMarek Vasut
sb_build_command_nop(struct sb_image_ctx * ictx)785bce88370SMarek Vasut static int sb_build_command_nop(struct sb_image_ctx *ictx)
786bce88370SMarek Vasut {
787bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail;
788bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
789bce88370SMarek Vasut struct sb_command *ccmd;
790bce88370SMarek Vasut
791bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
792bce88370SMarek Vasut if (!cctx)
793bce88370SMarek Vasut return -ENOMEM;
794bce88370SMarek Vasut
795bce88370SMarek Vasut ccmd = &cctx->payload;
796bce88370SMarek Vasut
797bce88370SMarek Vasut /*
798bce88370SMarek Vasut * Construct the command.
799bce88370SMarek Vasut */
800bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
801bce88370SMarek Vasut ccmd->header.tag = ROM_NOP_CMD;
802bce88370SMarek Vasut
803bce88370SMarek Vasut cctx->size = sizeof(*ccmd);
804bce88370SMarek Vasut
805bce88370SMarek Vasut /*
806bce88370SMarek Vasut * Append the command to the last section.
807bce88370SMarek Vasut */
808bce88370SMarek Vasut if (!sctx->cmd_head) {
809bce88370SMarek Vasut sctx->cmd_head = cctx;
810bce88370SMarek Vasut sctx->cmd_tail = cctx;
811bce88370SMarek Vasut } else {
812bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
813bce88370SMarek Vasut sctx->cmd_tail = cctx;
814bce88370SMarek Vasut }
815bce88370SMarek Vasut
816bce88370SMarek Vasut return 0;
817bce88370SMarek Vasut }
818bce88370SMarek Vasut
sb_build_command_tag(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)819bce88370SMarek Vasut static int sb_build_command_tag(struct sb_image_ctx *ictx,
820bce88370SMarek Vasut struct sb_cmd_list *cmd)
821bce88370SMarek Vasut {
822bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail;
823bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
824bce88370SMarek Vasut struct sb_command *ccmd;
825bce88370SMarek Vasut char *tok;
826bce88370SMarek Vasut
827bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
828bce88370SMarek Vasut if (!cctx)
829bce88370SMarek Vasut return -ENOMEM;
830bce88370SMarek Vasut
831bce88370SMarek Vasut ccmd = &cctx->payload;
832bce88370SMarek Vasut
833bce88370SMarek Vasut /*
834bce88370SMarek Vasut * Prepare the command.
835bce88370SMarek Vasut */
836bce88370SMarek Vasut /* Check for the LAST keyword. */
837bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
838bce88370SMarek Vasut if (tok && !strcmp(tok, "LAST"))
839bce88370SMarek Vasut ccmd->header.flags = ROM_TAG_CMD_FLAG_ROM_LAST_TAG;
840bce88370SMarek Vasut
841bce88370SMarek Vasut /*
842bce88370SMarek Vasut * Construct the command.
843bce88370SMarek Vasut */
844bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
845bce88370SMarek Vasut ccmd->header.tag = ROM_TAG_CMD;
846bce88370SMarek Vasut
847bce88370SMarek Vasut cctx->size = sizeof(*ccmd);
848bce88370SMarek Vasut
849bce88370SMarek Vasut /*
850bce88370SMarek Vasut * Append the command to the last section.
851bce88370SMarek Vasut */
852bce88370SMarek Vasut if (!sctx->cmd_head) {
853bce88370SMarek Vasut sctx->cmd_head = cctx;
854bce88370SMarek Vasut sctx->cmd_tail = cctx;
855bce88370SMarek Vasut } else {
856bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
857bce88370SMarek Vasut sctx->cmd_tail = cctx;
858bce88370SMarek Vasut }
859bce88370SMarek Vasut
860bce88370SMarek Vasut return 0;
861bce88370SMarek Vasut }
862bce88370SMarek Vasut
sb_build_command_load(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)863bce88370SMarek Vasut static int sb_build_command_load(struct sb_image_ctx *ictx,
864bce88370SMarek Vasut struct sb_cmd_list *cmd)
865bce88370SMarek Vasut {
866bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail;
867bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
868bce88370SMarek Vasut struct sb_command *ccmd;
869bce88370SMarek Vasut char *tok;
870bce88370SMarek Vasut int ret, is_ivt = 0, is_dcd = 0;
871bce88370SMarek Vasut uint32_t dest, dcd = 0;
872bce88370SMarek Vasut
873bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
874bce88370SMarek Vasut if (!cctx)
875bce88370SMarek Vasut return -ENOMEM;
876bce88370SMarek Vasut
877bce88370SMarek Vasut ccmd = &cctx->payload;
878bce88370SMarek Vasut
879bce88370SMarek Vasut /*
880bce88370SMarek Vasut * Prepare the command.
881bce88370SMarek Vasut */
882bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
883bce88370SMarek Vasut if (!tok) {
884bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing LOAD address or 'IVT'!\n",
885bce88370SMarek Vasut cmd->lineno);
886bce88370SMarek Vasut ret = -EINVAL;
887bce88370SMarek Vasut goto err;
888bce88370SMarek Vasut }
889bce88370SMarek Vasut
890bce88370SMarek Vasut /* Check for "IVT" flag. */
891bce88370SMarek Vasut if (!strcmp(tok, "IVT"))
892bce88370SMarek Vasut is_ivt = 1;
893bce88370SMarek Vasut if (!strcmp(tok, "DCD"))
894bce88370SMarek Vasut is_dcd = 1;
895bce88370SMarek Vasut if (is_ivt || is_dcd) {
896bce88370SMarek Vasut tok = strtok(NULL, " ");
897bce88370SMarek Vasut if (!tok) {
898bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing LOAD address!\n",
899bce88370SMarek Vasut cmd->lineno);
900bce88370SMarek Vasut ret = -EINVAL;
901bce88370SMarek Vasut goto err;
902bce88370SMarek Vasut }
903bce88370SMarek Vasut }
904bce88370SMarek Vasut
905bce88370SMarek Vasut /* Read load destination address. */
906bce88370SMarek Vasut ret = sb_token_to_long(tok, &dest);
907bce88370SMarek Vasut if (ret) {
908bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect LOAD address!\n",
909bce88370SMarek Vasut cmd->lineno);
910bce88370SMarek Vasut goto err;
911bce88370SMarek Vasut }
912bce88370SMarek Vasut
913bce88370SMarek Vasut /* Read filename or IVT entrypoint or DCD block ID. */
914bce88370SMarek Vasut tok = strtok(NULL, " ");
915bce88370SMarek Vasut if (!tok) {
916bce88370SMarek Vasut fprintf(stderr,
917bce88370SMarek Vasut "#%i ERR: Missing LOAD filename or IVT ep or DCD block ID!\n",
918bce88370SMarek Vasut cmd->lineno);
919bce88370SMarek Vasut ret = -EINVAL;
920bce88370SMarek Vasut goto err;
921bce88370SMarek Vasut }
922bce88370SMarek Vasut
923bce88370SMarek Vasut if (is_ivt) {
924bce88370SMarek Vasut /* Handle IVT. */
925bce88370SMarek Vasut struct sb_ivt_header *ivt;
926bce88370SMarek Vasut uint32_t ivtep;
927bce88370SMarek Vasut ret = sb_token_to_long(tok, &ivtep);
928bce88370SMarek Vasut
929bce88370SMarek Vasut if (ret) {
930bce88370SMarek Vasut fprintf(stderr,
931bce88370SMarek Vasut "#%i ERR: Incorrect IVT entry point!\n",
932bce88370SMarek Vasut cmd->lineno);
933bce88370SMarek Vasut goto err;
934bce88370SMarek Vasut }
935bce88370SMarek Vasut
936bce88370SMarek Vasut ivt = calloc(1, sizeof(*ivt));
937bce88370SMarek Vasut if (!ivt) {
938bce88370SMarek Vasut ret = -ENOMEM;
939bce88370SMarek Vasut goto err;
940bce88370SMarek Vasut }
941bce88370SMarek Vasut
942bce88370SMarek Vasut ivt->header = sb_hab_ivt_header();
943bce88370SMarek Vasut ivt->entry = ivtep;
944bce88370SMarek Vasut ivt->self = dest;
945bce88370SMarek Vasut
946bce88370SMarek Vasut cctx->data = (uint8_t *)ivt;
947bce88370SMarek Vasut cctx->length = sizeof(*ivt);
948bce88370SMarek Vasut } else if (is_dcd) {
949bce88370SMarek Vasut struct sb_dcd_ctx *dctx = ictx->dcd_head;
950bce88370SMarek Vasut uint32_t dcdid;
951bce88370SMarek Vasut uint8_t *payload;
952bce88370SMarek Vasut uint32_t asize;
953bce88370SMarek Vasut ret = sb_token_to_long(tok, &dcdid);
954bce88370SMarek Vasut
955bce88370SMarek Vasut if (ret) {
956bce88370SMarek Vasut fprintf(stderr,
957bce88370SMarek Vasut "#%i ERR: Incorrect DCD block ID!\n",
958bce88370SMarek Vasut cmd->lineno);
959bce88370SMarek Vasut goto err;
960bce88370SMarek Vasut }
961bce88370SMarek Vasut
962bce88370SMarek Vasut while (dctx) {
963bce88370SMarek Vasut if (dctx->id == dcdid)
964bce88370SMarek Vasut break;
965bce88370SMarek Vasut dctx = dctx->dcd;
966bce88370SMarek Vasut }
967bce88370SMarek Vasut
968bce88370SMarek Vasut if (!dctx) {
969bce88370SMarek Vasut fprintf(stderr, "#%i ERR: DCD block %08x not found!\n",
970bce88370SMarek Vasut cmd->lineno, dcdid);
971bce88370SMarek Vasut goto err;
972bce88370SMarek Vasut }
973bce88370SMarek Vasut
974bce88370SMarek Vasut asize = roundup(dctx->size, SB_BLOCK_SIZE);
975bce88370SMarek Vasut payload = calloc(1, asize);
976bce88370SMarek Vasut if (!payload) {
977bce88370SMarek Vasut ret = -ENOMEM;
978bce88370SMarek Vasut goto err;
979bce88370SMarek Vasut }
980bce88370SMarek Vasut
981bce88370SMarek Vasut memcpy(payload, dctx->payload, dctx->size);
982bce88370SMarek Vasut
983bce88370SMarek Vasut cctx->data = payload;
984bce88370SMarek Vasut cctx->length = asize;
985bce88370SMarek Vasut
986bce88370SMarek Vasut /* Set the Load DCD flag. */
987bce88370SMarek Vasut dcd = ROM_LOAD_CMD_FLAG_DCD_LOAD;
988bce88370SMarek Vasut } else {
989bce88370SMarek Vasut /* Regular LOAD of a file. */
990bce88370SMarek Vasut ret = sb_load_file(cctx, tok);
991bce88370SMarek Vasut if (ret) {
992bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Cannot load '%s'!\n",
993bce88370SMarek Vasut cmd->lineno, tok);
994bce88370SMarek Vasut goto err;
995bce88370SMarek Vasut }
996bce88370SMarek Vasut }
997bce88370SMarek Vasut
998bce88370SMarek Vasut if (cctx->length & (SB_BLOCK_SIZE - 1)) {
999bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Unaligned payload!\n",
1000bce88370SMarek Vasut cmd->lineno);
1001bce88370SMarek Vasut }
1002bce88370SMarek Vasut
1003bce88370SMarek Vasut /*
1004bce88370SMarek Vasut * Construct the command.
1005bce88370SMarek Vasut */
1006bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
1007bce88370SMarek Vasut ccmd->header.tag = ROM_LOAD_CMD;
1008bce88370SMarek Vasut ccmd->header.flags = dcd;
1009bce88370SMarek Vasut
1010bce88370SMarek Vasut ccmd->load.address = dest;
1011bce88370SMarek Vasut ccmd->load.count = cctx->length;
101225308f45SCharles Manning ccmd->load.crc32 = pbl_crc32(0,
101325308f45SCharles Manning (const char *)cctx->data,
101425308f45SCharles Manning cctx->length);
1015bce88370SMarek Vasut
1016bce88370SMarek Vasut cctx->size = sizeof(*ccmd) + cctx->length;
1017bce88370SMarek Vasut
1018bce88370SMarek Vasut /*
1019bce88370SMarek Vasut * Append the command to the last section.
1020bce88370SMarek Vasut */
1021bce88370SMarek Vasut if (!sctx->cmd_head) {
1022bce88370SMarek Vasut sctx->cmd_head = cctx;
1023bce88370SMarek Vasut sctx->cmd_tail = cctx;
1024bce88370SMarek Vasut } else {
1025bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
1026bce88370SMarek Vasut sctx->cmd_tail = cctx;
1027bce88370SMarek Vasut }
1028bce88370SMarek Vasut
1029bce88370SMarek Vasut return 0;
1030bce88370SMarek Vasut
1031bce88370SMarek Vasut err:
1032bce88370SMarek Vasut free(cctx);
1033bce88370SMarek Vasut return ret;
1034bce88370SMarek Vasut }
1035bce88370SMarek Vasut
sb_build_command_fill(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)1036bce88370SMarek Vasut static int sb_build_command_fill(struct sb_image_ctx *ictx,
1037bce88370SMarek Vasut struct sb_cmd_list *cmd)
1038bce88370SMarek Vasut {
1039bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail;
1040bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
1041bce88370SMarek Vasut struct sb_command *ccmd;
1042bce88370SMarek Vasut char *tok;
1043bce88370SMarek Vasut uint32_t address, pattern, length;
1044bce88370SMarek Vasut int ret;
1045bce88370SMarek Vasut
1046bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
1047bce88370SMarek Vasut if (!cctx)
1048bce88370SMarek Vasut return -ENOMEM;
1049bce88370SMarek Vasut
1050bce88370SMarek Vasut ccmd = &cctx->payload;
1051bce88370SMarek Vasut
1052bce88370SMarek Vasut /*
1053bce88370SMarek Vasut * Prepare the command.
1054bce88370SMarek Vasut */
1055bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
1056bce88370SMarek Vasut if (!tok) {
1057bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing FILL address!\n",
1058bce88370SMarek Vasut cmd->lineno);
1059bce88370SMarek Vasut ret = -EINVAL;
1060bce88370SMarek Vasut goto err;
1061bce88370SMarek Vasut }
1062bce88370SMarek Vasut
1063bce88370SMarek Vasut /* Read fill destination address. */
1064bce88370SMarek Vasut ret = sb_token_to_long(tok, &address);
1065bce88370SMarek Vasut if (ret) {
1066bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect FILL address!\n",
1067bce88370SMarek Vasut cmd->lineno);
1068bce88370SMarek Vasut goto err;
1069bce88370SMarek Vasut }
1070bce88370SMarek Vasut
1071bce88370SMarek Vasut tok = strtok(NULL, " ");
1072bce88370SMarek Vasut if (!tok) {
1073bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing FILL pattern!\n",
1074bce88370SMarek Vasut cmd->lineno);
1075bce88370SMarek Vasut ret = -EINVAL;
1076bce88370SMarek Vasut goto err;
1077bce88370SMarek Vasut }
1078bce88370SMarek Vasut
1079bce88370SMarek Vasut /* Read fill pattern address. */
1080bce88370SMarek Vasut ret = sb_token_to_long(tok, &pattern);
1081bce88370SMarek Vasut if (ret) {
1082bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect FILL pattern!\n",
1083bce88370SMarek Vasut cmd->lineno);
1084bce88370SMarek Vasut goto err;
1085bce88370SMarek Vasut }
1086bce88370SMarek Vasut
1087bce88370SMarek Vasut tok = strtok(NULL, " ");
1088bce88370SMarek Vasut if (!tok) {
1089bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing FILL length!\n",
1090bce88370SMarek Vasut cmd->lineno);
1091bce88370SMarek Vasut ret = -EINVAL;
1092bce88370SMarek Vasut goto err;
1093bce88370SMarek Vasut }
1094bce88370SMarek Vasut
1095bce88370SMarek Vasut /* Read fill pattern address. */
1096bce88370SMarek Vasut ret = sb_token_to_long(tok, &length);
1097bce88370SMarek Vasut if (ret) {
1098bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect FILL length!\n",
1099bce88370SMarek Vasut cmd->lineno);
1100bce88370SMarek Vasut goto err;
1101bce88370SMarek Vasut }
1102bce88370SMarek Vasut
1103bce88370SMarek Vasut /*
1104bce88370SMarek Vasut * Construct the command.
1105bce88370SMarek Vasut */
1106bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
1107bce88370SMarek Vasut ccmd->header.tag = ROM_FILL_CMD;
1108bce88370SMarek Vasut
1109bce88370SMarek Vasut ccmd->fill.address = address;
1110bce88370SMarek Vasut ccmd->fill.count = length;
1111bce88370SMarek Vasut ccmd->fill.pattern = pattern;
1112bce88370SMarek Vasut
1113bce88370SMarek Vasut cctx->size = sizeof(*ccmd);
1114bce88370SMarek Vasut
1115bce88370SMarek Vasut /*
1116bce88370SMarek Vasut * Append the command to the last section.
1117bce88370SMarek Vasut */
1118bce88370SMarek Vasut if (!sctx->cmd_head) {
1119bce88370SMarek Vasut sctx->cmd_head = cctx;
1120bce88370SMarek Vasut sctx->cmd_tail = cctx;
1121bce88370SMarek Vasut } else {
1122bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
1123bce88370SMarek Vasut sctx->cmd_tail = cctx;
1124bce88370SMarek Vasut }
1125bce88370SMarek Vasut
1126bce88370SMarek Vasut return 0;
1127bce88370SMarek Vasut
1128bce88370SMarek Vasut err:
1129bce88370SMarek Vasut free(cctx);
1130bce88370SMarek Vasut return ret;
1131bce88370SMarek Vasut }
1132bce88370SMarek Vasut
sb_build_command_jump_call(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd,unsigned int is_call)1133bce88370SMarek Vasut static int sb_build_command_jump_call(struct sb_image_ctx *ictx,
1134bce88370SMarek Vasut struct sb_cmd_list *cmd,
1135bce88370SMarek Vasut unsigned int is_call)
1136bce88370SMarek Vasut {
1137bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail;
1138bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
1139bce88370SMarek Vasut struct sb_command *ccmd;
1140bce88370SMarek Vasut char *tok;
1141bce88370SMarek Vasut uint32_t dest, arg = 0x0;
1142bce88370SMarek Vasut uint32_t hab = 0;
1143bce88370SMarek Vasut int ret;
1144bce88370SMarek Vasut const char *cmdname = is_call ? "CALL" : "JUMP";
1145bce88370SMarek Vasut
1146bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
1147bce88370SMarek Vasut if (!cctx)
1148bce88370SMarek Vasut return -ENOMEM;
1149bce88370SMarek Vasut
1150bce88370SMarek Vasut ccmd = &cctx->payload;
1151bce88370SMarek Vasut
1152bce88370SMarek Vasut /*
1153bce88370SMarek Vasut * Prepare the command.
1154bce88370SMarek Vasut */
1155bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
1156bce88370SMarek Vasut if (!tok) {
1157bce88370SMarek Vasut fprintf(stderr,
1158bce88370SMarek Vasut "#%i ERR: Missing %s address or 'HAB'!\n",
1159bce88370SMarek Vasut cmd->lineno, cmdname);
1160bce88370SMarek Vasut ret = -EINVAL;
1161bce88370SMarek Vasut goto err;
1162bce88370SMarek Vasut }
1163bce88370SMarek Vasut
1164bce88370SMarek Vasut /* Check for "HAB" flag. */
1165bce88370SMarek Vasut if (!strcmp(tok, "HAB")) {
1166bce88370SMarek Vasut hab = is_call ? ROM_CALL_CMD_FLAG_HAB : ROM_JUMP_CMD_FLAG_HAB;
1167bce88370SMarek Vasut tok = strtok(NULL, " ");
1168bce88370SMarek Vasut if (!tok) {
1169bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing %s address!\n",
1170bce88370SMarek Vasut cmd->lineno, cmdname);
1171bce88370SMarek Vasut ret = -EINVAL;
1172bce88370SMarek Vasut goto err;
1173bce88370SMarek Vasut }
1174bce88370SMarek Vasut }
1175bce88370SMarek Vasut /* Read load destination address. */
1176bce88370SMarek Vasut ret = sb_token_to_long(tok, &dest);
1177bce88370SMarek Vasut if (ret) {
1178bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect %s address!\n",
1179bce88370SMarek Vasut cmd->lineno, cmdname);
1180bce88370SMarek Vasut goto err;
1181bce88370SMarek Vasut }
1182bce88370SMarek Vasut
1183bce88370SMarek Vasut tok = strtok(NULL, " ");
1184bce88370SMarek Vasut if (tok) {
1185bce88370SMarek Vasut ret = sb_token_to_long(tok, &arg);
1186bce88370SMarek Vasut if (ret) {
1187bce88370SMarek Vasut fprintf(stderr,
1188bce88370SMarek Vasut "#%i ERR: Incorrect %s argument!\n",
1189bce88370SMarek Vasut cmd->lineno, cmdname);
1190bce88370SMarek Vasut goto err;
1191bce88370SMarek Vasut }
1192bce88370SMarek Vasut }
1193bce88370SMarek Vasut
1194bce88370SMarek Vasut /*
1195bce88370SMarek Vasut * Construct the command.
1196bce88370SMarek Vasut */
1197bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
1198bce88370SMarek Vasut ccmd->header.tag = is_call ? ROM_CALL_CMD : ROM_JUMP_CMD;
1199bce88370SMarek Vasut ccmd->header.flags = hab;
1200bce88370SMarek Vasut
1201bce88370SMarek Vasut ccmd->call.address = dest;
1202bce88370SMarek Vasut ccmd->call.argument = arg;
1203bce88370SMarek Vasut
1204bce88370SMarek Vasut cctx->size = sizeof(*ccmd);
1205bce88370SMarek Vasut
1206bce88370SMarek Vasut /*
1207bce88370SMarek Vasut * Append the command to the last section.
1208bce88370SMarek Vasut */
1209bce88370SMarek Vasut if (!sctx->cmd_head) {
1210bce88370SMarek Vasut sctx->cmd_head = cctx;
1211bce88370SMarek Vasut sctx->cmd_tail = cctx;
1212bce88370SMarek Vasut } else {
1213bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
1214bce88370SMarek Vasut sctx->cmd_tail = cctx;
1215bce88370SMarek Vasut }
1216bce88370SMarek Vasut
1217bce88370SMarek Vasut return 0;
1218bce88370SMarek Vasut
1219bce88370SMarek Vasut err:
1220bce88370SMarek Vasut free(cctx);
1221bce88370SMarek Vasut return ret;
1222bce88370SMarek Vasut }
1223bce88370SMarek Vasut
sb_build_command_jump(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)1224bce88370SMarek Vasut static int sb_build_command_jump(struct sb_image_ctx *ictx,
1225bce88370SMarek Vasut struct sb_cmd_list *cmd)
1226bce88370SMarek Vasut {
1227bce88370SMarek Vasut return sb_build_command_jump_call(ictx, cmd, 0);
1228bce88370SMarek Vasut }
1229bce88370SMarek Vasut
sb_build_command_call(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)1230bce88370SMarek Vasut static int sb_build_command_call(struct sb_image_ctx *ictx,
1231bce88370SMarek Vasut struct sb_cmd_list *cmd)
1232bce88370SMarek Vasut {
1233bce88370SMarek Vasut return sb_build_command_jump_call(ictx, cmd, 1);
1234bce88370SMarek Vasut }
1235bce88370SMarek Vasut
sb_build_command_mode(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)1236bce88370SMarek Vasut static int sb_build_command_mode(struct sb_image_ctx *ictx,
1237bce88370SMarek Vasut struct sb_cmd_list *cmd)
1238bce88370SMarek Vasut {
1239bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail;
1240bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
1241bce88370SMarek Vasut struct sb_command *ccmd;
1242bce88370SMarek Vasut char *tok;
1243bce88370SMarek Vasut int ret;
1244bce88370SMarek Vasut unsigned int i;
1245bce88370SMarek Vasut uint32_t mode = 0xffffffff;
1246bce88370SMarek Vasut
1247bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
1248bce88370SMarek Vasut if (!cctx)
1249bce88370SMarek Vasut return -ENOMEM;
1250bce88370SMarek Vasut
1251bce88370SMarek Vasut ccmd = &cctx->payload;
1252bce88370SMarek Vasut
1253bce88370SMarek Vasut /*
1254bce88370SMarek Vasut * Prepare the command.
1255bce88370SMarek Vasut */
1256bce88370SMarek Vasut tok = strtok(cmd->cmd, " ");
1257bce88370SMarek Vasut if (!tok) {
1258bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing MODE boot mode argument!\n",
1259bce88370SMarek Vasut cmd->lineno);
1260bce88370SMarek Vasut ret = -EINVAL;
1261bce88370SMarek Vasut goto err;
1262bce88370SMarek Vasut }
1263bce88370SMarek Vasut
1264bce88370SMarek Vasut for (i = 0; i < ARRAY_SIZE(modetable); i++) {
1265bce88370SMarek Vasut if (!strcmp(tok, modetable[i].name)) {
1266bce88370SMarek Vasut mode = modetable[i].mode;
1267bce88370SMarek Vasut break;
1268bce88370SMarek Vasut }
1269bce88370SMarek Vasut
1270bce88370SMarek Vasut if (!modetable[i].altname)
1271bce88370SMarek Vasut continue;
1272bce88370SMarek Vasut
1273bce88370SMarek Vasut if (!strcmp(tok, modetable[i].altname)) {
1274bce88370SMarek Vasut mode = modetable[i].mode;
1275bce88370SMarek Vasut break;
1276bce88370SMarek Vasut }
1277bce88370SMarek Vasut }
1278bce88370SMarek Vasut
1279bce88370SMarek Vasut if (mode == 0xffffffff) {
1280bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid MODE boot mode argument!\n",
1281bce88370SMarek Vasut cmd->lineno);
1282bce88370SMarek Vasut ret = -EINVAL;
1283bce88370SMarek Vasut goto err;
1284bce88370SMarek Vasut }
1285bce88370SMarek Vasut
1286bce88370SMarek Vasut /*
1287bce88370SMarek Vasut * Construct the command.
1288bce88370SMarek Vasut */
1289bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
1290bce88370SMarek Vasut ccmd->header.tag = ROM_MODE_CMD;
1291bce88370SMarek Vasut
1292bce88370SMarek Vasut ccmd->mode.mode = mode;
1293bce88370SMarek Vasut
1294bce88370SMarek Vasut cctx->size = sizeof(*ccmd);
1295bce88370SMarek Vasut
1296bce88370SMarek Vasut /*
1297bce88370SMarek Vasut * Append the command to the last section.
1298bce88370SMarek Vasut */
1299bce88370SMarek Vasut if (!sctx->cmd_head) {
1300bce88370SMarek Vasut sctx->cmd_head = cctx;
1301bce88370SMarek Vasut sctx->cmd_tail = cctx;
1302bce88370SMarek Vasut } else {
1303bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
1304bce88370SMarek Vasut sctx->cmd_tail = cctx;
1305bce88370SMarek Vasut }
1306bce88370SMarek Vasut
1307bce88370SMarek Vasut return 0;
1308bce88370SMarek Vasut
1309bce88370SMarek Vasut err:
1310bce88370SMarek Vasut free(cctx);
1311bce88370SMarek Vasut return ret;
1312bce88370SMarek Vasut }
1313bce88370SMarek Vasut
sb_prefill_image_header(struct sb_image_ctx * ictx)1314bce88370SMarek Vasut static int sb_prefill_image_header(struct sb_image_ctx *ictx)
1315bce88370SMarek Vasut {
1316bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload;
1317bce88370SMarek Vasut
1318bce88370SMarek Vasut /* Fill signatures */
1319bce88370SMarek Vasut memcpy(hdr->signature1, "STMP", 4);
1320bce88370SMarek Vasut memcpy(hdr->signature2, "sgtl", 4);
1321bce88370SMarek Vasut
1322bce88370SMarek Vasut /* SB Image version 1.1 */
1323bce88370SMarek Vasut hdr->major_version = SB_VERSION_MAJOR;
1324bce88370SMarek Vasut hdr->minor_version = SB_VERSION_MINOR;
1325bce88370SMarek Vasut
1326bce88370SMarek Vasut /* Boot image major version */
1327bce88370SMarek Vasut hdr->product_version.major = htons(0x999);
1328bce88370SMarek Vasut hdr->product_version.minor = htons(0x999);
1329bce88370SMarek Vasut hdr->product_version.revision = htons(0x999);
1330bce88370SMarek Vasut /* Boot image major version */
1331bce88370SMarek Vasut hdr->component_version.major = htons(0x999);
1332bce88370SMarek Vasut hdr->component_version.minor = htons(0x999);
1333bce88370SMarek Vasut hdr->component_version.revision = htons(0x999);
1334bce88370SMarek Vasut
1335bce88370SMarek Vasut /* Drive tag must be 0x0 for i.MX23 */
1336bce88370SMarek Vasut hdr->drive_tag = 0;
1337bce88370SMarek Vasut
1338bce88370SMarek Vasut hdr->header_blocks =
1339bce88370SMarek Vasut sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE;
1340bce88370SMarek Vasut hdr->section_header_size =
1341bce88370SMarek Vasut sizeof(struct sb_sections_header) / SB_BLOCK_SIZE;
1342bce88370SMarek Vasut hdr->timestamp_us = sb_get_timestamp() * 1000000;
1343bce88370SMarek Vasut
13447a139959SAlexey Ignatov hdr->flags = ictx->display_progress ?
13457a139959SAlexey Ignatov SB_IMAGE_FLAG_DISPLAY_PROGRESS : 0;
1346bce88370SMarek Vasut
1347bce88370SMarek Vasut /* FIXME -- We support only default key */
1348bce88370SMarek Vasut hdr->key_count = 1;
1349bce88370SMarek Vasut
1350bce88370SMarek Vasut return 0;
1351bce88370SMarek Vasut }
1352bce88370SMarek Vasut
sb_postfill_image_header(struct sb_image_ctx * ictx)1353bce88370SMarek Vasut static int sb_postfill_image_header(struct sb_image_ctx *ictx)
1354bce88370SMarek Vasut {
1355bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload;
1356bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head;
1357bce88370SMarek Vasut uint32_t kd_size, sections_blocks;
13587bae13b7SMarek Vasut EVP_MD_CTX *md_ctx;
1359bce88370SMarek Vasut
1360bce88370SMarek Vasut /* The main SB header size in blocks. */
1361bce88370SMarek Vasut hdr->image_blocks = hdr->header_blocks;
1362bce88370SMarek Vasut
1363bce88370SMarek Vasut /* Size of the key dictionary, which has single zero entry. */
1364bce88370SMarek Vasut kd_size = hdr->key_count * sizeof(struct sb_key_dictionary_key);
1365bce88370SMarek Vasut hdr->image_blocks += kd_size / SB_BLOCK_SIZE;
1366bce88370SMarek Vasut
1367bce88370SMarek Vasut /* Now count the payloads. */
1368bce88370SMarek Vasut hdr->section_count = ictx->sect_count;
1369bce88370SMarek Vasut while (sctx) {
1370bce88370SMarek Vasut hdr->image_blocks += sctx->size / SB_BLOCK_SIZE;
1371bce88370SMarek Vasut sctx = sctx->sect;
1372bce88370SMarek Vasut }
1373bce88370SMarek Vasut
1374bce88370SMarek Vasut if (!ictx->sect_boot_found) {
1375bce88370SMarek Vasut fprintf(stderr, "ERR: No bootable section selected!\n");
1376bce88370SMarek Vasut return -EINVAL;
1377bce88370SMarek Vasut }
1378bce88370SMarek Vasut hdr->first_boot_section_id = ictx->sect_boot;
1379bce88370SMarek Vasut
1380bce88370SMarek Vasut /* The n * SB section size in blocks. */
1381bce88370SMarek Vasut sections_blocks = hdr->section_count * hdr->section_header_size;
1382bce88370SMarek Vasut hdr->image_blocks += sections_blocks;
1383bce88370SMarek Vasut
1384bce88370SMarek Vasut /* Key dictionary offset. */
1385bce88370SMarek Vasut hdr->key_dictionary_block = hdr->header_blocks + sections_blocks;
1386bce88370SMarek Vasut
1387bce88370SMarek Vasut /* Digest of the whole image. */
1388bce88370SMarek Vasut hdr->image_blocks += 2;
1389bce88370SMarek Vasut
1390bce88370SMarek Vasut /* Pointer past the dictionary. */
1391bce88370SMarek Vasut hdr->first_boot_tag_block =
1392bce88370SMarek Vasut hdr->key_dictionary_block + kd_size / SB_BLOCK_SIZE;
1393bce88370SMarek Vasut
1394bce88370SMarek Vasut /* Compute header digest. */
13957bae13b7SMarek Vasut md_ctx = EVP_MD_CTX_new();
1396bce88370SMarek Vasut
13977bae13b7SMarek Vasut EVP_DigestInit(md_ctx, EVP_sha1());
13987bae13b7SMarek Vasut EVP_DigestUpdate(md_ctx, hdr->signature1,
1399bce88370SMarek Vasut sizeof(struct sb_boot_image_header) -
1400bce88370SMarek Vasut sizeof(hdr->digest));
14017bae13b7SMarek Vasut EVP_DigestFinal(md_ctx, hdr->digest, NULL);
14027bae13b7SMarek Vasut EVP_MD_CTX_free(md_ctx);
1403bce88370SMarek Vasut
1404bce88370SMarek Vasut return 0;
1405bce88370SMarek Vasut }
1406bce88370SMarek Vasut
sb_fixup_sections_and_tags(struct sb_image_ctx * ictx)1407bce88370SMarek Vasut static int sb_fixup_sections_and_tags(struct sb_image_ctx *ictx)
1408bce88370SMarek Vasut {
1409bce88370SMarek Vasut /* Fixup the placement of sections. */
1410bce88370SMarek Vasut struct sb_boot_image_header *ihdr = &ictx->payload;
1411bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head;
1412bce88370SMarek Vasut struct sb_sections_header *shdr;
1413bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
1414bce88370SMarek Vasut struct sb_command *ccmd;
1415bce88370SMarek Vasut uint32_t offset = ihdr->first_boot_tag_block;
1416bce88370SMarek Vasut
1417bce88370SMarek Vasut while (sctx) {
1418bce88370SMarek Vasut shdr = &sctx->payload;
1419bce88370SMarek Vasut
1420bce88370SMarek Vasut /* Fill in the section TAG offset. */
1421bce88370SMarek Vasut shdr->section_offset = offset + 1;
1422bce88370SMarek Vasut offset += shdr->section_size;
1423bce88370SMarek Vasut
1424bce88370SMarek Vasut /* Section length is measured from the TAG block. */
1425bce88370SMarek Vasut shdr->section_size--;
1426bce88370SMarek Vasut
1427bce88370SMarek Vasut /* Fixup the TAG command. */
1428bce88370SMarek Vasut cctx = sctx->cmd_head;
1429bce88370SMarek Vasut while (cctx) {
1430bce88370SMarek Vasut ccmd = &cctx->payload;
1431bce88370SMarek Vasut if (ccmd->header.tag == ROM_TAG_CMD) {
1432bce88370SMarek Vasut ccmd->tag.section_number = shdr->section_number;
1433bce88370SMarek Vasut ccmd->tag.section_length = shdr->section_size;
1434bce88370SMarek Vasut ccmd->tag.section_flags = shdr->section_flags;
1435bce88370SMarek Vasut }
1436bce88370SMarek Vasut
1437bce88370SMarek Vasut /* Update the command checksum. */
1438bce88370SMarek Vasut ccmd->header.checksum = sb_command_checksum(ccmd);
1439bce88370SMarek Vasut
1440bce88370SMarek Vasut cctx = cctx->cmd;
1441bce88370SMarek Vasut }
1442bce88370SMarek Vasut
1443bce88370SMarek Vasut sctx = sctx->sect;
1444bce88370SMarek Vasut }
1445bce88370SMarek Vasut
1446bce88370SMarek Vasut return 0;
1447bce88370SMarek Vasut }
1448bce88370SMarek Vasut
sb_parse_line(struct sb_image_ctx * ictx,struct sb_cmd_list * cmd)1449bce88370SMarek Vasut static int sb_parse_line(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
1450bce88370SMarek Vasut {
1451bce88370SMarek Vasut char *tok;
1452bce88370SMarek Vasut char *line = cmd->cmd;
14533cb4b713SAlbert ARIBAUD char *rptr = NULL;
1454bce88370SMarek Vasut int ret;
1455bce88370SMarek Vasut
1456bce88370SMarek Vasut /* Analyze the identifier on this line first. */
1457bce88370SMarek Vasut tok = strtok_r(line, " ", &rptr);
1458bce88370SMarek Vasut if (!tok || (strlen(tok) == 0)) {
1459bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid line!\n", cmd->lineno);
1460bce88370SMarek Vasut return -EINVAL;
1461bce88370SMarek Vasut }
1462bce88370SMarek Vasut
1463bce88370SMarek Vasut cmd->cmd = rptr;
1464bce88370SMarek Vasut
14657a139959SAlexey Ignatov /* set DISPLAY_PROGRESS flag */
14667a139959SAlexey Ignatov if (!strcmp(tok, "DISPLAYPROGRESS")) {
14677a139959SAlexey Ignatov ictx->display_progress = 1;
14687a139959SAlexey Ignatov return 0;
14697a139959SAlexey Ignatov }
14707a139959SAlexey Ignatov
1471bce88370SMarek Vasut /* DCD */
1472bce88370SMarek Vasut if (!strcmp(tok, "DCD")) {
1473bce88370SMarek Vasut ictx->in_section = 0;
1474bce88370SMarek Vasut ictx->in_dcd = 1;
1475bce88370SMarek Vasut sb_build_dcd(ictx, cmd);
1476bce88370SMarek Vasut return 0;
1477bce88370SMarek Vasut }
1478bce88370SMarek Vasut
1479bce88370SMarek Vasut /* Section */
1480bce88370SMarek Vasut if (!strcmp(tok, "SECTION")) {
1481bce88370SMarek Vasut ictx->in_section = 1;
1482bce88370SMarek Vasut ictx->in_dcd = 0;
1483bce88370SMarek Vasut sb_build_section(ictx, cmd);
1484bce88370SMarek Vasut return 0;
1485bce88370SMarek Vasut }
1486bce88370SMarek Vasut
1487bce88370SMarek Vasut if (!ictx->in_section && !ictx->in_dcd) {
1488bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Data outside of a section!\n",
1489bce88370SMarek Vasut cmd->lineno);
1490bce88370SMarek Vasut return -EINVAL;
1491bce88370SMarek Vasut }
1492bce88370SMarek Vasut
1493bce88370SMarek Vasut if (ictx->in_section) {
1494bce88370SMarek Vasut /* Section commands */
1495bce88370SMarek Vasut if (!strcmp(tok, "NOP")) {
1496bce88370SMarek Vasut ret = sb_build_command_nop(ictx);
1497bce88370SMarek Vasut } else if (!strcmp(tok, "TAG")) {
1498bce88370SMarek Vasut ret = sb_build_command_tag(ictx, cmd);
1499bce88370SMarek Vasut } else if (!strcmp(tok, "LOAD")) {
1500bce88370SMarek Vasut ret = sb_build_command_load(ictx, cmd);
1501bce88370SMarek Vasut } else if (!strcmp(tok, "FILL")) {
1502bce88370SMarek Vasut ret = sb_build_command_fill(ictx, cmd);
1503bce88370SMarek Vasut } else if (!strcmp(tok, "JUMP")) {
1504bce88370SMarek Vasut ret = sb_build_command_jump(ictx, cmd);
1505bce88370SMarek Vasut } else if (!strcmp(tok, "CALL")) {
1506bce88370SMarek Vasut ret = sb_build_command_call(ictx, cmd);
1507bce88370SMarek Vasut } else if (!strcmp(tok, "MODE")) {
1508bce88370SMarek Vasut ret = sb_build_command_mode(ictx, cmd);
1509bce88370SMarek Vasut } else {
1510bce88370SMarek Vasut fprintf(stderr,
1511bce88370SMarek Vasut "#%i ERR: Unsupported instruction '%s'!\n",
1512bce88370SMarek Vasut cmd->lineno, tok);
1513bce88370SMarek Vasut return -ENOTSUP;
1514bce88370SMarek Vasut }
1515bce88370SMarek Vasut } else if (ictx->in_dcd) {
1516bce88370SMarek Vasut char *lptr;
1517bce88370SMarek Vasut uint32_t ilen = '1';
1518bce88370SMarek Vasut
1519bce88370SMarek Vasut tok = strtok_r(tok, ".", &lptr);
1520bce88370SMarek Vasut if (!tok || (strlen(tok) == 0) || (lptr && strlen(lptr) != 1)) {
1521bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid line!\n",
1522bce88370SMarek Vasut cmd->lineno);
1523bce88370SMarek Vasut return -EINVAL;
1524bce88370SMarek Vasut }
1525bce88370SMarek Vasut
1526bce88370SMarek Vasut if (lptr &&
1527bce88370SMarek Vasut (lptr[0] != '1' && lptr[0] != '2' && lptr[0] != '4')) {
1528bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid instruction width!\n",
1529bce88370SMarek Vasut cmd->lineno);
1530bce88370SMarek Vasut return -EINVAL;
1531bce88370SMarek Vasut }
1532bce88370SMarek Vasut
1533bce88370SMarek Vasut if (lptr)
1534bce88370SMarek Vasut ilen = lptr[0] - '1';
1535bce88370SMarek Vasut
1536bce88370SMarek Vasut /* DCD commands */
1537bce88370SMarek Vasut if (!strcmp(tok, "WRITE")) {
1538bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1539bce88370SMarek Vasut SB_DCD_WRITE | ilen);
1540bce88370SMarek Vasut } else if (!strcmp(tok, "ANDC")) {
1541bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1542bce88370SMarek Vasut SB_DCD_ANDC | ilen);
1543bce88370SMarek Vasut } else if (!strcmp(tok, "ORR")) {
1544bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1545bce88370SMarek Vasut SB_DCD_ORR | ilen);
1546bce88370SMarek Vasut } else if (!strcmp(tok, "EQZ")) {
1547bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1548bce88370SMarek Vasut SB_DCD_CHK_EQZ | ilen);
1549bce88370SMarek Vasut } else if (!strcmp(tok, "EQ")) {
1550bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1551bce88370SMarek Vasut SB_DCD_CHK_EQ | ilen);
1552bce88370SMarek Vasut } else if (!strcmp(tok, "NEQ")) {
1553bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1554bce88370SMarek Vasut SB_DCD_CHK_NEQ | ilen);
1555bce88370SMarek Vasut } else if (!strcmp(tok, "NEZ")) {
1556bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd,
1557bce88370SMarek Vasut SB_DCD_CHK_NEZ | ilen);
1558bce88370SMarek Vasut } else if (!strcmp(tok, "NOOP")) {
1559bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, SB_DCD_NOOP);
1560bce88370SMarek Vasut } else {
1561bce88370SMarek Vasut fprintf(stderr,
1562bce88370SMarek Vasut "#%i ERR: Unsupported instruction '%s'!\n",
1563bce88370SMarek Vasut cmd->lineno, tok);
1564bce88370SMarek Vasut return -ENOTSUP;
1565bce88370SMarek Vasut }
1566bce88370SMarek Vasut } else {
1567bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Unsupported instruction '%s'!\n",
1568bce88370SMarek Vasut cmd->lineno, tok);
1569bce88370SMarek Vasut return -ENOTSUP;
1570bce88370SMarek Vasut }
1571bce88370SMarek Vasut
1572bce88370SMarek Vasut /*
1573bce88370SMarek Vasut * Here we have at least one section with one command, otherwise we
1574bce88370SMarek Vasut * would have failed already higher above.
1575bce88370SMarek Vasut *
1576bce88370SMarek Vasut * FIXME -- should the updating happen here ?
1577bce88370SMarek Vasut */
1578bce88370SMarek Vasut if (ictx->in_section && !ret) {
1579bce88370SMarek Vasut ictx->sect_tail->size += ictx->sect_tail->cmd_tail->size;
1580bce88370SMarek Vasut ictx->sect_tail->payload.section_size =
1581bce88370SMarek Vasut ictx->sect_tail->size / SB_BLOCK_SIZE;
1582bce88370SMarek Vasut }
1583bce88370SMarek Vasut
1584bce88370SMarek Vasut return ret;
1585bce88370SMarek Vasut }
1586bce88370SMarek Vasut
sb_load_cmdfile(struct sb_image_ctx * ictx)1587bce88370SMarek Vasut static int sb_load_cmdfile(struct sb_image_ctx *ictx)
1588bce88370SMarek Vasut {
1589bce88370SMarek Vasut struct sb_cmd_list cmd;
1590bce88370SMarek Vasut int lineno = 1;
1591bce88370SMarek Vasut FILE *fp;
1592bce88370SMarek Vasut char *line = NULL;
1593bce88370SMarek Vasut ssize_t rlen;
1594bce88370SMarek Vasut size_t len;
1595bce88370SMarek Vasut
1596bce88370SMarek Vasut fp = fopen(ictx->cfg_filename, "r");
1597bce88370SMarek Vasut if (!fp)
1598bce88370SMarek Vasut goto err_file;
1599bce88370SMarek Vasut
1600bce88370SMarek Vasut while ((rlen = getline(&line, &len, fp)) > 0) {
1601bce88370SMarek Vasut memset(&cmd, 0, sizeof(cmd));
1602bce88370SMarek Vasut
1603bce88370SMarek Vasut /* Strip the trailing newline. */
1604bce88370SMarek Vasut line[rlen - 1] = '\0';
1605bce88370SMarek Vasut
1606bce88370SMarek Vasut cmd.cmd = line;
1607bce88370SMarek Vasut cmd.len = rlen;
1608bce88370SMarek Vasut cmd.lineno = lineno++;
1609bce88370SMarek Vasut
1610bce88370SMarek Vasut sb_parse_line(ictx, &cmd);
1611bce88370SMarek Vasut }
1612bce88370SMarek Vasut
1613bce88370SMarek Vasut free(line);
1614bce88370SMarek Vasut
1615bce88370SMarek Vasut fclose(fp);
1616bce88370SMarek Vasut
1617bce88370SMarek Vasut return 0;
1618bce88370SMarek Vasut
1619bce88370SMarek Vasut err_file:
1620bce88370SMarek Vasut fclose(fp);
1621bce88370SMarek Vasut fprintf(stderr, "ERR: Failed to load file \"%s\"\n",
1622bce88370SMarek Vasut ictx->cfg_filename);
1623bce88370SMarek Vasut return -EINVAL;
1624bce88370SMarek Vasut }
1625bce88370SMarek Vasut
sb_build_tree_from_cfg(struct sb_image_ctx * ictx)1626bce88370SMarek Vasut static int sb_build_tree_from_cfg(struct sb_image_ctx *ictx)
1627bce88370SMarek Vasut {
1628bce88370SMarek Vasut int ret;
1629bce88370SMarek Vasut
1630bce88370SMarek Vasut ret = sb_load_cmdfile(ictx);
1631bce88370SMarek Vasut if (ret)
1632bce88370SMarek Vasut return ret;
1633bce88370SMarek Vasut
1634bce88370SMarek Vasut ret = sb_prefill_image_header(ictx);
1635bce88370SMarek Vasut if (ret)
1636bce88370SMarek Vasut return ret;
1637bce88370SMarek Vasut
1638bce88370SMarek Vasut ret = sb_postfill_image_header(ictx);
1639bce88370SMarek Vasut if (ret)
1640bce88370SMarek Vasut return ret;
1641bce88370SMarek Vasut
1642bce88370SMarek Vasut ret = sb_fixup_sections_and_tags(ictx);
1643bce88370SMarek Vasut if (ret)
1644bce88370SMarek Vasut return ret;
1645bce88370SMarek Vasut
1646bce88370SMarek Vasut return 0;
1647bce88370SMarek Vasut }
1648bce88370SMarek Vasut
sb_verify_image_header(struct sb_image_ctx * ictx,FILE * fp,long fsize)1649bce88370SMarek Vasut static int sb_verify_image_header(struct sb_image_ctx *ictx,
1650bce88370SMarek Vasut FILE *fp, long fsize)
1651bce88370SMarek Vasut {
1652bce88370SMarek Vasut /* Verify static fields in the image header. */
1653bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload;
1654bce88370SMarek Vasut const char *stat[2] = { "[PASS]", "[FAIL]" };
1655bce88370SMarek Vasut struct tm tm;
1656bce88370SMarek Vasut int sz, ret = 0;
1657bce88370SMarek Vasut unsigned char digest[20];
16587bae13b7SMarek Vasut EVP_MD_CTX *md_ctx;
1659bce88370SMarek Vasut unsigned long size;
1660bce88370SMarek Vasut
1661bce88370SMarek Vasut /* Start image-wide crypto. */
16627bae13b7SMarek Vasut ictx->md_ctx = EVP_MD_CTX_new();
16637bae13b7SMarek Vasut EVP_DigestInit(ictx->md_ctx, EVP_sha1());
1664bce88370SMarek Vasut
1665bce88370SMarek Vasut soprintf(ictx, "---------- Verifying SB Image Header ----------\n");
1666bce88370SMarek Vasut
1667bce88370SMarek Vasut size = fread(&ictx->payload, 1, sizeof(ictx->payload), fp);
1668bce88370SMarek Vasut if (size != sizeof(ictx->payload)) {
1669bce88370SMarek Vasut fprintf(stderr, "ERR: SB image header too short!\n");
1670bce88370SMarek Vasut return -EINVAL;
1671bce88370SMarek Vasut }
1672bce88370SMarek Vasut
1673bce88370SMarek Vasut /* Compute header digest. */
16747bae13b7SMarek Vasut md_ctx = EVP_MD_CTX_new();
16757bae13b7SMarek Vasut EVP_DigestInit(md_ctx, EVP_sha1());
16767bae13b7SMarek Vasut EVP_DigestUpdate(md_ctx, hdr->signature1,
1677bce88370SMarek Vasut sizeof(struct sb_boot_image_header) -
1678bce88370SMarek Vasut sizeof(hdr->digest));
16797bae13b7SMarek Vasut EVP_DigestFinal(md_ctx, digest, NULL);
16807bae13b7SMarek Vasut EVP_MD_CTX_free(md_ctx);
1681bce88370SMarek Vasut
1682bce88370SMarek Vasut sb_aes_init(ictx, NULL, 1);
1683bce88370SMarek Vasut sb_encrypt_sb_header(ictx);
1684bce88370SMarek Vasut
1685bce88370SMarek Vasut if (memcmp(digest, hdr->digest, 20))
1686bce88370SMarek Vasut ret = -EINVAL;
1687bce88370SMarek Vasut soprintf(ictx, "%s Image header checksum: %s\n", stat[!!ret],
1688bce88370SMarek Vasut ret ? "BAD" : "OK");
1689bce88370SMarek Vasut if (ret)
1690bce88370SMarek Vasut return ret;
1691bce88370SMarek Vasut
1692bce88370SMarek Vasut if (memcmp(hdr->signature1, "STMP", 4) ||
1693bce88370SMarek Vasut memcmp(hdr->signature2, "sgtl", 4))
1694bce88370SMarek Vasut ret = -EINVAL;
1695bce88370SMarek Vasut soprintf(ictx, "%s Signatures: '%.4s' '%.4s'\n",
1696bce88370SMarek Vasut stat[!!ret], hdr->signature1, hdr->signature2);
1697bce88370SMarek Vasut if (ret)
1698bce88370SMarek Vasut return ret;
1699bce88370SMarek Vasut
1700bce88370SMarek Vasut if ((hdr->major_version != SB_VERSION_MAJOR) ||
1701bce88370SMarek Vasut ((hdr->minor_version != 1) && (hdr->minor_version != 2)))
1702bce88370SMarek Vasut ret = -EINVAL;
1703bce88370SMarek Vasut soprintf(ictx, "%s Image version: v%i.%i\n", stat[!!ret],
1704bce88370SMarek Vasut hdr->major_version, hdr->minor_version);
1705bce88370SMarek Vasut if (ret)
1706bce88370SMarek Vasut return ret;
1707bce88370SMarek Vasut
1708bce88370SMarek Vasut ret = sb_get_time(hdr->timestamp_us / 1000000, &tm);
1709bce88370SMarek Vasut soprintf(ictx,
1710bce88370SMarek Vasut "%s Creation time: %02i:%02i:%02i %02i/%02i/%04i\n",
1711bce88370SMarek Vasut stat[!!ret], tm.tm_hour, tm.tm_min, tm.tm_sec,
1712bce88370SMarek Vasut tm.tm_mday, tm.tm_mon, tm.tm_year + 2000);
1713bce88370SMarek Vasut if (ret)
1714bce88370SMarek Vasut return ret;
1715bce88370SMarek Vasut
1716bce88370SMarek Vasut soprintf(ictx, "%s Product version: %x.%x.%x\n", stat[0],
1717bce88370SMarek Vasut ntohs(hdr->product_version.major),
1718bce88370SMarek Vasut ntohs(hdr->product_version.minor),
1719bce88370SMarek Vasut ntohs(hdr->product_version.revision));
1720bce88370SMarek Vasut soprintf(ictx, "%s Component version: %x.%x.%x\n", stat[0],
1721bce88370SMarek Vasut ntohs(hdr->component_version.major),
1722bce88370SMarek Vasut ntohs(hdr->component_version.minor),
1723bce88370SMarek Vasut ntohs(hdr->component_version.revision));
1724bce88370SMarek Vasut
17257a139959SAlexey Ignatov if (hdr->flags & ~SB_IMAGE_FLAGS_MASK)
1726bce88370SMarek Vasut ret = -EINVAL;
1727bce88370SMarek Vasut soprintf(ictx, "%s Image flags: %s\n", stat[!!ret],
17287a139959SAlexey Ignatov hdr->flags & SB_IMAGE_FLAG_DISPLAY_PROGRESS ?
17297a139959SAlexey Ignatov "Display_progress" : "");
1730bce88370SMarek Vasut if (ret)
1731bce88370SMarek Vasut return ret;
1732bce88370SMarek Vasut
1733bce88370SMarek Vasut if (hdr->drive_tag != 0)
1734bce88370SMarek Vasut ret = -EINVAL;
1735bce88370SMarek Vasut soprintf(ictx, "%s Drive tag: %i\n", stat[!!ret],
1736bce88370SMarek Vasut hdr->drive_tag);
1737bce88370SMarek Vasut if (ret)
1738bce88370SMarek Vasut return ret;
1739bce88370SMarek Vasut
1740bce88370SMarek Vasut sz = sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE;
1741bce88370SMarek Vasut if (hdr->header_blocks != sz)
1742bce88370SMarek Vasut ret = -EINVAL;
1743bce88370SMarek Vasut soprintf(ictx, "%s Image header size (blocks): %i\n", stat[!!ret],
1744bce88370SMarek Vasut hdr->header_blocks);
1745bce88370SMarek Vasut if (ret)
1746bce88370SMarek Vasut return ret;
1747bce88370SMarek Vasut
1748bce88370SMarek Vasut sz = sizeof(struct sb_sections_header) / SB_BLOCK_SIZE;
1749bce88370SMarek Vasut if (hdr->section_header_size != sz)
1750bce88370SMarek Vasut ret = -EINVAL;
1751bce88370SMarek Vasut soprintf(ictx, "%s Section header size (blocks): %i\n", stat[!!ret],
1752bce88370SMarek Vasut hdr->section_header_size);
1753bce88370SMarek Vasut if (ret)
1754bce88370SMarek Vasut return ret;
1755bce88370SMarek Vasut
1756bce88370SMarek Vasut soprintf(ictx, "%s Sections count: %i\n", stat[!!ret],
1757bce88370SMarek Vasut hdr->section_count);
1758bce88370SMarek Vasut soprintf(ictx, "%s First bootable section %i\n", stat[!!ret],
1759bce88370SMarek Vasut hdr->first_boot_section_id);
1760bce88370SMarek Vasut
1761bce88370SMarek Vasut if (hdr->image_blocks != fsize / SB_BLOCK_SIZE)
1762bce88370SMarek Vasut ret = -EINVAL;
1763bce88370SMarek Vasut soprintf(ictx, "%s Image size (blocks): %i\n", stat[!!ret],
1764bce88370SMarek Vasut hdr->image_blocks);
1765bce88370SMarek Vasut if (ret)
1766bce88370SMarek Vasut return ret;
1767bce88370SMarek Vasut
1768bce88370SMarek Vasut sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count;
1769bce88370SMarek Vasut if (hdr->key_dictionary_block != sz)
1770bce88370SMarek Vasut ret = -EINVAL;
1771bce88370SMarek Vasut soprintf(ictx, "%s Key dict offset (blocks): %i\n", stat[!!ret],
1772bce88370SMarek Vasut hdr->key_dictionary_block);
1773bce88370SMarek Vasut if (ret)
1774bce88370SMarek Vasut return ret;
1775bce88370SMarek Vasut
1776bce88370SMarek Vasut if (hdr->key_count != 1)
1777bce88370SMarek Vasut ret = -EINVAL;
1778bce88370SMarek Vasut soprintf(ictx, "%s Number of encryption keys: %i\n", stat[!!ret],
1779bce88370SMarek Vasut hdr->key_count);
1780bce88370SMarek Vasut if (ret)
1781bce88370SMarek Vasut return ret;
1782bce88370SMarek Vasut
1783bce88370SMarek Vasut sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count;
1784bce88370SMarek Vasut sz += hdr->key_count *
1785bce88370SMarek Vasut sizeof(struct sb_key_dictionary_key) / SB_BLOCK_SIZE;
1786bce88370SMarek Vasut if (hdr->first_boot_tag_block != (unsigned)sz)
1787bce88370SMarek Vasut ret = -EINVAL;
1788bce88370SMarek Vasut soprintf(ictx, "%s First TAG block (blocks): %i\n", stat[!!ret],
1789bce88370SMarek Vasut hdr->first_boot_tag_block);
1790bce88370SMarek Vasut if (ret)
1791bce88370SMarek Vasut return ret;
1792bce88370SMarek Vasut
1793bce88370SMarek Vasut return 0;
1794bce88370SMarek Vasut }
1795bce88370SMarek Vasut
sb_decrypt_tag(struct sb_image_ctx * ictx,struct sb_cmd_ctx * cctx)1796bce88370SMarek Vasut static void sb_decrypt_tag(struct sb_image_ctx *ictx,
1797bce88370SMarek Vasut struct sb_cmd_ctx *cctx)
1798bce88370SMarek Vasut {
17997bae13b7SMarek Vasut EVP_MD_CTX *md_ctx = ictx->md_ctx;
1800bce88370SMarek Vasut struct sb_command *cmd = &cctx->payload;
1801bce88370SMarek Vasut
1802bce88370SMarek Vasut sb_aes_crypt(ictx, (uint8_t *)&cctx->c_payload,
1803bce88370SMarek Vasut (uint8_t *)&cctx->payload, sizeof(*cmd));
1804bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd));
1805bce88370SMarek Vasut }
1806bce88370SMarek Vasut
sb_verify_command(struct sb_image_ctx * ictx,struct sb_cmd_ctx * cctx,FILE * fp,unsigned long * tsize)1807bce88370SMarek Vasut static int sb_verify_command(struct sb_image_ctx *ictx,
1808bce88370SMarek Vasut struct sb_cmd_ctx *cctx, FILE *fp,
1809bce88370SMarek Vasut unsigned long *tsize)
1810bce88370SMarek Vasut {
1811bce88370SMarek Vasut struct sb_command *ccmd = &cctx->payload;
1812bce88370SMarek Vasut unsigned long size, asize;
1813bce88370SMarek Vasut char *csum, *flag = "";
1814bce88370SMarek Vasut int ret;
1815bce88370SMarek Vasut unsigned int i;
1816bce88370SMarek Vasut uint8_t csn, csc = ccmd->header.checksum;
1817bce88370SMarek Vasut ccmd->header.checksum = 0x5a;
1818bce88370SMarek Vasut csn = sb_command_checksum(ccmd);
1819bce88370SMarek Vasut ccmd->header.checksum = csc;
1820bce88370SMarek Vasut
1821bce88370SMarek Vasut if (csc == csn)
1822bce88370SMarek Vasut ret = 0;
1823bce88370SMarek Vasut else
1824bce88370SMarek Vasut ret = -EINVAL;
1825bce88370SMarek Vasut csum = ret ? "checksum BAD" : "checksum OK";
1826bce88370SMarek Vasut
1827bce88370SMarek Vasut switch (ccmd->header.tag) {
1828bce88370SMarek Vasut case ROM_NOP_CMD:
1829bce88370SMarek Vasut soprintf(ictx, " NOOP # %s\n", csum);
1830bce88370SMarek Vasut return ret;
1831bce88370SMarek Vasut case ROM_TAG_CMD:
1832bce88370SMarek Vasut if (ccmd->header.flags & ROM_TAG_CMD_FLAG_ROM_LAST_TAG)
1833bce88370SMarek Vasut flag = "LAST";
1834bce88370SMarek Vasut soprintf(ictx, " TAG %s # %s\n", flag, csum);
1835bce88370SMarek Vasut sb_aes_reinit(ictx, 0);
1836bce88370SMarek Vasut return ret;
1837bce88370SMarek Vasut case ROM_LOAD_CMD:
1838bce88370SMarek Vasut soprintf(ictx, " LOAD addr=0x%08x length=0x%08x # %s\n",
1839bce88370SMarek Vasut ccmd->load.address, ccmd->load.count, csum);
1840bce88370SMarek Vasut
1841bce88370SMarek Vasut cctx->length = ccmd->load.count;
1842bce88370SMarek Vasut asize = roundup(cctx->length, SB_BLOCK_SIZE);
1843bce88370SMarek Vasut cctx->data = malloc(asize);
1844bce88370SMarek Vasut if (!cctx->data)
1845bce88370SMarek Vasut return -ENOMEM;
1846bce88370SMarek Vasut
1847bce88370SMarek Vasut size = fread(cctx->data, 1, asize, fp);
1848bce88370SMarek Vasut if (size != asize) {
1849bce88370SMarek Vasut fprintf(stderr,
1850bce88370SMarek Vasut "ERR: SB LOAD command payload too short!\n");
1851bce88370SMarek Vasut return -EINVAL;
1852bce88370SMarek Vasut }
1853bce88370SMarek Vasut
1854bce88370SMarek Vasut *tsize += size;
1855bce88370SMarek Vasut
18567bae13b7SMarek Vasut EVP_DigestUpdate(ictx->md_ctx, cctx->data, asize);
1857bce88370SMarek Vasut sb_aes_crypt(ictx, cctx->data, cctx->data, asize);
1858bce88370SMarek Vasut
185925308f45SCharles Manning if (ccmd->load.crc32 != pbl_crc32(0,
186025308f45SCharles Manning (const char *)cctx->data,
186125308f45SCharles Manning asize)) {
1862bce88370SMarek Vasut fprintf(stderr,
1863bce88370SMarek Vasut "ERR: SB LOAD command payload CRC32 invalid!\n");
1864bce88370SMarek Vasut return -EINVAL;
1865bce88370SMarek Vasut }
1866bce88370SMarek Vasut return 0;
1867bce88370SMarek Vasut case ROM_FILL_CMD:
1868bce88370SMarek Vasut soprintf(ictx,
1869bce88370SMarek Vasut " FILL addr=0x%08x length=0x%08x pattern=0x%08x # %s\n",
1870bce88370SMarek Vasut ccmd->fill.address, ccmd->fill.count,
1871bce88370SMarek Vasut ccmd->fill.pattern, csum);
1872bce88370SMarek Vasut return 0;
1873bce88370SMarek Vasut case ROM_JUMP_CMD:
1874bce88370SMarek Vasut if (ccmd->header.flags & ROM_JUMP_CMD_FLAG_HAB)
1875bce88370SMarek Vasut flag = " HAB";
1876bce88370SMarek Vasut soprintf(ictx,
1877bce88370SMarek Vasut " JUMP%s addr=0x%08x r0_arg=0x%08x # %s\n",
1878bce88370SMarek Vasut flag, ccmd->fill.address, ccmd->jump.argument, csum);
1879bce88370SMarek Vasut return 0;
1880bce88370SMarek Vasut case ROM_CALL_CMD:
1881bce88370SMarek Vasut if (ccmd->header.flags & ROM_CALL_CMD_FLAG_HAB)
1882bce88370SMarek Vasut flag = " HAB";
1883bce88370SMarek Vasut soprintf(ictx,
1884bce88370SMarek Vasut " CALL%s addr=0x%08x r0_arg=0x%08x # %s\n",
1885bce88370SMarek Vasut flag, ccmd->fill.address, ccmd->jump.argument, csum);
1886bce88370SMarek Vasut return 0;
1887bce88370SMarek Vasut case ROM_MODE_CMD:
1888bce88370SMarek Vasut for (i = 0; i < ARRAY_SIZE(modetable); i++) {
1889bce88370SMarek Vasut if (ccmd->mode.mode == modetable[i].mode) {
1890bce88370SMarek Vasut soprintf(ictx, " MODE %s # %s\n",
1891bce88370SMarek Vasut modetable[i].name, csum);
1892bce88370SMarek Vasut break;
1893bce88370SMarek Vasut }
1894bce88370SMarek Vasut }
1895bce88370SMarek Vasut fprintf(stderr, " MODE !INVALID! # %s\n", csum);
1896bce88370SMarek Vasut return 0;
1897bce88370SMarek Vasut }
1898bce88370SMarek Vasut
1899bce88370SMarek Vasut return ret;
1900bce88370SMarek Vasut }
1901bce88370SMarek Vasut
sb_verify_commands(struct sb_image_ctx * ictx,struct sb_section_ctx * sctx,FILE * fp)1902bce88370SMarek Vasut static int sb_verify_commands(struct sb_image_ctx *ictx,
1903bce88370SMarek Vasut struct sb_section_ctx *sctx, FILE *fp)
1904bce88370SMarek Vasut {
1905bce88370SMarek Vasut unsigned long size, tsize = 0;
1906bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
1907bce88370SMarek Vasut int ret;
1908bce88370SMarek Vasut
1909bce88370SMarek Vasut sb_aes_reinit(ictx, 0);
1910bce88370SMarek Vasut
1911bce88370SMarek Vasut while (tsize < sctx->size) {
1912bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx));
1913bce88370SMarek Vasut if (!cctx)
1914bce88370SMarek Vasut return -ENOMEM;
1915bce88370SMarek Vasut if (!sctx->cmd_head) {
1916bce88370SMarek Vasut sctx->cmd_head = cctx;
1917bce88370SMarek Vasut sctx->cmd_tail = cctx;
1918bce88370SMarek Vasut } else {
1919bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx;
1920bce88370SMarek Vasut sctx->cmd_tail = cctx;
1921bce88370SMarek Vasut }
1922bce88370SMarek Vasut
1923bce88370SMarek Vasut size = fread(&cctx->c_payload, 1, sizeof(cctx->c_payload), fp);
1924bce88370SMarek Vasut if (size != sizeof(cctx->c_payload)) {
1925bce88370SMarek Vasut fprintf(stderr, "ERR: SB command header too short!\n");
1926bce88370SMarek Vasut return -EINVAL;
1927bce88370SMarek Vasut }
1928bce88370SMarek Vasut
1929bce88370SMarek Vasut tsize += size;
1930bce88370SMarek Vasut
1931bce88370SMarek Vasut sb_decrypt_tag(ictx, cctx);
1932bce88370SMarek Vasut
1933bce88370SMarek Vasut ret = sb_verify_command(ictx, cctx, fp, &tsize);
1934bce88370SMarek Vasut if (ret)
1935bce88370SMarek Vasut return -EINVAL;
1936bce88370SMarek Vasut }
1937bce88370SMarek Vasut
1938bce88370SMarek Vasut return 0;
1939bce88370SMarek Vasut }
1940bce88370SMarek Vasut
sb_verify_sections_cmds(struct sb_image_ctx * ictx,FILE * fp)1941bce88370SMarek Vasut static int sb_verify_sections_cmds(struct sb_image_ctx *ictx, FILE *fp)
1942bce88370SMarek Vasut {
1943bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload;
1944bce88370SMarek Vasut struct sb_sections_header *shdr;
1945bce88370SMarek Vasut unsigned int i;
1946bce88370SMarek Vasut int ret;
1947bce88370SMarek Vasut struct sb_section_ctx *sctx;
1948bce88370SMarek Vasut unsigned long size;
1949bce88370SMarek Vasut char *bootable = "";
1950bce88370SMarek Vasut
1951bce88370SMarek Vasut soprintf(ictx, "----- Verifying SB Sections and Commands -----\n");
1952bce88370SMarek Vasut
1953bce88370SMarek Vasut for (i = 0; i < hdr->section_count; i++) {
1954bce88370SMarek Vasut sctx = calloc(1, sizeof(*sctx));
1955bce88370SMarek Vasut if (!sctx)
1956bce88370SMarek Vasut return -ENOMEM;
1957bce88370SMarek Vasut if (!ictx->sect_head) {
1958bce88370SMarek Vasut ictx->sect_head = sctx;
1959bce88370SMarek Vasut ictx->sect_tail = sctx;
1960bce88370SMarek Vasut } else {
1961bce88370SMarek Vasut ictx->sect_tail->sect = sctx;
1962bce88370SMarek Vasut ictx->sect_tail = sctx;
1963bce88370SMarek Vasut }
1964bce88370SMarek Vasut
1965bce88370SMarek Vasut size = fread(&sctx->payload, 1, sizeof(sctx->payload), fp);
1966bce88370SMarek Vasut if (size != sizeof(sctx->payload)) {
1967bce88370SMarek Vasut fprintf(stderr, "ERR: SB section header too short!\n");
1968bce88370SMarek Vasut return -EINVAL;
1969bce88370SMarek Vasut }
1970bce88370SMarek Vasut }
1971bce88370SMarek Vasut
1972bce88370SMarek Vasut size = fread(&ictx->sb_dict_key, 1, sizeof(ictx->sb_dict_key), fp);
1973bce88370SMarek Vasut if (size != sizeof(ictx->sb_dict_key)) {
1974bce88370SMarek Vasut fprintf(stderr, "ERR: SB key dictionary too short!\n");
1975bce88370SMarek Vasut return -EINVAL;
1976bce88370SMarek Vasut }
1977bce88370SMarek Vasut
1978bce88370SMarek Vasut sb_encrypt_sb_sections_header(ictx);
1979bce88370SMarek Vasut sb_aes_reinit(ictx, 0);
1980bce88370SMarek Vasut sb_decrypt_key_dictionary_key(ictx);
1981bce88370SMarek Vasut
1982bce88370SMarek Vasut sb_aes_reinit(ictx, 0);
1983bce88370SMarek Vasut
1984bce88370SMarek Vasut sctx = ictx->sect_head;
1985bce88370SMarek Vasut while (sctx) {
1986bce88370SMarek Vasut shdr = &sctx->payload;
1987bce88370SMarek Vasut
1988bce88370SMarek Vasut if (shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) {
1989bce88370SMarek Vasut sctx->boot = 1;
1990bce88370SMarek Vasut bootable = " BOOTABLE";
1991bce88370SMarek Vasut }
1992bce88370SMarek Vasut
1993bce88370SMarek Vasut sctx->size = (shdr->section_size * SB_BLOCK_SIZE) +
1994bce88370SMarek Vasut sizeof(struct sb_command);
1995bce88370SMarek Vasut soprintf(ictx, "SECTION 0x%x%s # size = %i bytes\n",
1996bce88370SMarek Vasut shdr->section_number, bootable, sctx->size);
1997bce88370SMarek Vasut
1998bce88370SMarek Vasut if (shdr->section_flags & ~SB_SECTION_FLAG_BOOTABLE)
1999bce88370SMarek Vasut fprintf(stderr, " WARN: Unknown section flag(s) %08x\n",
2000bce88370SMarek Vasut shdr->section_flags);
2001bce88370SMarek Vasut
2002bce88370SMarek Vasut if ((shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) &&
2003bce88370SMarek Vasut (hdr->first_boot_section_id != shdr->section_number)) {
2004bce88370SMarek Vasut fprintf(stderr,
2005bce88370SMarek Vasut " WARN: Bootable section does ID not match image header ID!\n");
2006bce88370SMarek Vasut }
2007bce88370SMarek Vasut
2008bce88370SMarek Vasut ret = sb_verify_commands(ictx, sctx, fp);
2009bce88370SMarek Vasut if (ret)
2010bce88370SMarek Vasut return ret;
2011bce88370SMarek Vasut
2012bce88370SMarek Vasut sctx = sctx->sect;
2013bce88370SMarek Vasut }
2014bce88370SMarek Vasut
2015bce88370SMarek Vasut /*
2016bce88370SMarek Vasut * FIXME IDEA:
2017bce88370SMarek Vasut * check if the first TAG command is at sctx->section_offset
2018bce88370SMarek Vasut */
2019bce88370SMarek Vasut return 0;
2020bce88370SMarek Vasut }
2021bce88370SMarek Vasut
sb_verify_image_end(struct sb_image_ctx * ictx,FILE * fp,off_t filesz)2022bce88370SMarek Vasut static int sb_verify_image_end(struct sb_image_ctx *ictx,
2023bce88370SMarek Vasut FILE *fp, off_t filesz)
2024bce88370SMarek Vasut {
2025bce88370SMarek Vasut uint8_t digest[32];
2026bce88370SMarek Vasut unsigned long size;
2027bce88370SMarek Vasut off_t pos;
2028bce88370SMarek Vasut int ret;
2029bce88370SMarek Vasut
2030bce88370SMarek Vasut soprintf(ictx, "------------- Verifying image end -------------\n");
2031bce88370SMarek Vasut
2032bce88370SMarek Vasut size = fread(digest, 1, sizeof(digest), fp);
2033bce88370SMarek Vasut if (size != sizeof(digest)) {
2034bce88370SMarek Vasut fprintf(stderr, "ERR: SB key dictionary too short!\n");
2035bce88370SMarek Vasut return -EINVAL;
2036bce88370SMarek Vasut }
2037bce88370SMarek Vasut
2038bce88370SMarek Vasut pos = ftell(fp);
2039bce88370SMarek Vasut if (pos != filesz) {
2040bce88370SMarek Vasut fprintf(stderr, "ERR: Trailing data past the image!\n");
2041bce88370SMarek Vasut return -EINVAL;
2042bce88370SMarek Vasut }
2043bce88370SMarek Vasut
2044bce88370SMarek Vasut /* Check the image digest. */
20457bae13b7SMarek Vasut EVP_DigestFinal(ictx->md_ctx, ictx->digest, NULL);
20467bae13b7SMarek Vasut EVP_MD_CTX_free(ictx->md_ctx);
2047bce88370SMarek Vasut
2048bce88370SMarek Vasut /* Decrypt the image digest from the input image. */
2049bce88370SMarek Vasut sb_aes_reinit(ictx, 0);
2050bce88370SMarek Vasut sb_aes_crypt(ictx, digest, digest, sizeof(digest));
2051bce88370SMarek Vasut
2052bce88370SMarek Vasut /* Check all of 20 bytes of the SHA1 hash. */
2053bce88370SMarek Vasut ret = memcmp(digest, ictx->digest, 20) ? -EINVAL : 0;
2054bce88370SMarek Vasut
2055bce88370SMarek Vasut if (ret)
2056bce88370SMarek Vasut soprintf(ictx, "[FAIL] Full-image checksum: BAD\n");
2057bce88370SMarek Vasut else
2058bce88370SMarek Vasut soprintf(ictx, "[PASS] Full-image checksum: OK\n");
2059bce88370SMarek Vasut
2060bce88370SMarek Vasut return ret;
2061bce88370SMarek Vasut }
2062bce88370SMarek Vasut
2063bce88370SMarek Vasut
sb_build_tree_from_img(struct sb_image_ctx * ictx)2064bce88370SMarek Vasut static int sb_build_tree_from_img(struct sb_image_ctx *ictx)
2065bce88370SMarek Vasut {
2066bce88370SMarek Vasut long filesize;
2067bce88370SMarek Vasut int ret;
2068bce88370SMarek Vasut FILE *fp;
2069bce88370SMarek Vasut
2070bce88370SMarek Vasut if (!ictx->input_filename) {
2071bce88370SMarek Vasut fprintf(stderr, "ERR: Missing filename!\n");
2072bce88370SMarek Vasut return -EINVAL;
2073bce88370SMarek Vasut }
2074bce88370SMarek Vasut
2075bce88370SMarek Vasut fp = fopen(ictx->input_filename, "r");
2076bce88370SMarek Vasut if (!fp)
2077bce88370SMarek Vasut goto err_open;
2078bce88370SMarek Vasut
2079bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_END);
2080bce88370SMarek Vasut if (ret < 0)
2081bce88370SMarek Vasut goto err_file;
2082bce88370SMarek Vasut
2083bce88370SMarek Vasut filesize = ftell(fp);
2084bce88370SMarek Vasut if (filesize < 0)
2085bce88370SMarek Vasut goto err_file;
2086bce88370SMarek Vasut
2087bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_SET);
2088bce88370SMarek Vasut if (ret < 0)
2089bce88370SMarek Vasut goto err_file;
2090bce88370SMarek Vasut
2091bce88370SMarek Vasut if (filesize < (signed)sizeof(ictx->payload)) {
2092bce88370SMarek Vasut fprintf(stderr, "ERR: File too short!\n");
2093bce88370SMarek Vasut goto err_file;
2094bce88370SMarek Vasut }
2095bce88370SMarek Vasut
2096bce88370SMarek Vasut if (filesize & (SB_BLOCK_SIZE - 1)) {
2097bce88370SMarek Vasut fprintf(stderr, "ERR: The file is not aligned!\n");
2098bce88370SMarek Vasut goto err_file;
2099bce88370SMarek Vasut }
2100bce88370SMarek Vasut
2101bce88370SMarek Vasut /* Load and verify image header */
2102bce88370SMarek Vasut ret = sb_verify_image_header(ictx, fp, filesize);
2103bce88370SMarek Vasut if (ret)
2104bce88370SMarek Vasut goto err_verify;
2105bce88370SMarek Vasut
2106bce88370SMarek Vasut /* Load and verify sections and commands */
2107bce88370SMarek Vasut ret = sb_verify_sections_cmds(ictx, fp);
2108bce88370SMarek Vasut if (ret)
2109bce88370SMarek Vasut goto err_verify;
2110bce88370SMarek Vasut
2111bce88370SMarek Vasut ret = sb_verify_image_end(ictx, fp, filesize);
2112bce88370SMarek Vasut if (ret)
2113bce88370SMarek Vasut goto err_verify;
2114bce88370SMarek Vasut
2115bce88370SMarek Vasut ret = 0;
2116bce88370SMarek Vasut
2117bce88370SMarek Vasut err_verify:
2118bce88370SMarek Vasut soprintf(ictx, "-------------------- Result -------------------\n");
2119bce88370SMarek Vasut soprintf(ictx, "Verification %s\n", ret ? "FAILED" : "PASSED");
2120bce88370SMarek Vasut
2121bce88370SMarek Vasut /* Stop the encryption session. */
21227bae13b7SMarek Vasut sb_aes_deinit(ictx->cipher_ctx);
2123bce88370SMarek Vasut
2124bce88370SMarek Vasut fclose(fp);
2125bce88370SMarek Vasut return ret;
2126bce88370SMarek Vasut
2127bce88370SMarek Vasut err_file:
2128bce88370SMarek Vasut fclose(fp);
2129bce88370SMarek Vasut err_open:
2130bce88370SMarek Vasut fprintf(stderr, "ERR: Failed to load file \"%s\"\n",
2131bce88370SMarek Vasut ictx->input_filename);
2132bce88370SMarek Vasut return -EINVAL;
2133bce88370SMarek Vasut }
2134bce88370SMarek Vasut
sb_free_image(struct sb_image_ctx * ictx)2135bce88370SMarek Vasut static void sb_free_image(struct sb_image_ctx *ictx)
2136bce88370SMarek Vasut {
2137bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head, *s_head;
2138bce88370SMarek Vasut struct sb_dcd_ctx *dctx = ictx->dcd_head, *d_head;
2139bce88370SMarek Vasut struct sb_cmd_ctx *cctx, *c_head;
2140bce88370SMarek Vasut
2141bce88370SMarek Vasut while (sctx) {
2142bce88370SMarek Vasut s_head = sctx;
2143bce88370SMarek Vasut c_head = sctx->cmd_head;
2144bce88370SMarek Vasut
2145bce88370SMarek Vasut while (c_head) {
2146bce88370SMarek Vasut cctx = c_head;
2147bce88370SMarek Vasut c_head = c_head->cmd;
2148bce88370SMarek Vasut if (cctx->data)
2149bce88370SMarek Vasut free(cctx->data);
2150bce88370SMarek Vasut free(cctx);
2151bce88370SMarek Vasut }
2152bce88370SMarek Vasut
2153bce88370SMarek Vasut sctx = sctx->sect;
2154bce88370SMarek Vasut free(s_head);
2155bce88370SMarek Vasut }
2156bce88370SMarek Vasut
2157bce88370SMarek Vasut while (dctx) {
2158bce88370SMarek Vasut d_head = dctx;
2159bce88370SMarek Vasut dctx = dctx->dcd;
2160bce88370SMarek Vasut free(d_head->payload);
2161bce88370SMarek Vasut free(d_head);
2162bce88370SMarek Vasut }
2163bce88370SMarek Vasut }
2164bce88370SMarek Vasut
2165bce88370SMarek Vasut /*
2166bce88370SMarek Vasut * MXSSB-MKIMAGE glue code.
2167bce88370SMarek Vasut */
mxsimage_check_image_types(uint8_t type)2168bce88370SMarek Vasut static int mxsimage_check_image_types(uint8_t type)
2169bce88370SMarek Vasut {
2170bce88370SMarek Vasut if (type == IH_TYPE_MXSIMAGE)
2171bce88370SMarek Vasut return EXIT_SUCCESS;
2172bce88370SMarek Vasut else
2173bce88370SMarek Vasut return EXIT_FAILURE;
2174bce88370SMarek Vasut }
2175bce88370SMarek Vasut
mxsimage_set_header(void * ptr,struct stat * sbuf,int ifd,struct image_tool_params * params)2176bce88370SMarek Vasut static void mxsimage_set_header(void *ptr, struct stat *sbuf, int ifd,
2177f86ed6a8SGuilherme Maciel Ferreira struct image_tool_params *params)
2178bce88370SMarek Vasut {
2179bce88370SMarek Vasut }
2180bce88370SMarek Vasut
mxsimage_check_params(struct image_tool_params * params)2181f86ed6a8SGuilherme Maciel Ferreira int mxsimage_check_params(struct image_tool_params *params)
2182bce88370SMarek Vasut {
2183bce88370SMarek Vasut if (!params)
2184bce88370SMarek Vasut return -1;
2185bce88370SMarek Vasut if (!strlen(params->imagename)) {
2186bce88370SMarek Vasut fprintf(stderr,
2187bce88370SMarek Vasut "Error: %s - Configuration file not specified, it is needed for mxsimage generation\n",
2188bce88370SMarek Vasut params->cmdname);
2189bce88370SMarek Vasut return -1;
2190bce88370SMarek Vasut }
2191bce88370SMarek Vasut
2192bce88370SMarek Vasut /*
2193bce88370SMarek Vasut * Check parameters:
2194bce88370SMarek Vasut * XIP is not allowed and verify that incompatible
2195bce88370SMarek Vasut * parameters are not sent at the same time
2196bce88370SMarek Vasut * For example, if list is required a data image must not be provided
2197bce88370SMarek Vasut */
2198bce88370SMarek Vasut return (params->dflag && (params->fflag || params->lflag)) ||
2199bce88370SMarek Vasut (params->fflag && (params->dflag || params->lflag)) ||
2200bce88370SMarek Vasut (params->lflag && (params->dflag || params->fflag)) ||
2201bce88370SMarek Vasut (params->xflag) || !(strlen(params->imagename));
2202bce88370SMarek Vasut }
2203bce88370SMarek Vasut
mxsimage_verify_print_header(char * file,int silent)2204bce88370SMarek Vasut static int mxsimage_verify_print_header(char *file, int silent)
2205bce88370SMarek Vasut {
2206bce88370SMarek Vasut int ret;
2207bce88370SMarek Vasut struct sb_image_ctx ctx;
2208bce88370SMarek Vasut
2209bce88370SMarek Vasut memset(&ctx, 0, sizeof(ctx));
2210bce88370SMarek Vasut
2211bce88370SMarek Vasut ctx.input_filename = file;
2212bce88370SMarek Vasut ctx.silent_dump = silent;
2213bce88370SMarek Vasut
2214bce88370SMarek Vasut ret = sb_build_tree_from_img(&ctx);
2215bce88370SMarek Vasut sb_free_image(&ctx);
2216bce88370SMarek Vasut
2217bce88370SMarek Vasut return ret;
2218bce88370SMarek Vasut }
2219bce88370SMarek Vasut
2220bce88370SMarek Vasut char *imagefile;
mxsimage_verify_header(unsigned char * ptr,int image_size,struct image_tool_params * params)2221bce88370SMarek Vasut static int mxsimage_verify_header(unsigned char *ptr, int image_size,
2222f86ed6a8SGuilherme Maciel Ferreira struct image_tool_params *params)
2223bce88370SMarek Vasut {
2224bce88370SMarek Vasut struct sb_boot_image_header *hdr;
2225bce88370SMarek Vasut
2226bce88370SMarek Vasut if (!ptr)
2227bce88370SMarek Vasut return -EINVAL;
2228bce88370SMarek Vasut
2229bce88370SMarek Vasut hdr = (struct sb_boot_image_header *)ptr;
2230bce88370SMarek Vasut
2231bce88370SMarek Vasut /*
2232bce88370SMarek Vasut * Check if the header contains the MXS image signatures,
2233bce88370SMarek Vasut * if so, do a full-image verification.
2234bce88370SMarek Vasut */
2235bce88370SMarek Vasut if (memcmp(hdr->signature1, "STMP", 4) ||
2236bce88370SMarek Vasut memcmp(hdr->signature2, "sgtl", 4))
2237bce88370SMarek Vasut return -EINVAL;
2238bce88370SMarek Vasut
2239bce88370SMarek Vasut imagefile = params->imagefile;
2240bce88370SMarek Vasut
2241bce88370SMarek Vasut return mxsimage_verify_print_header(params->imagefile, 1);
2242bce88370SMarek Vasut }
2243bce88370SMarek Vasut
mxsimage_print_header(const void * hdr)2244bce88370SMarek Vasut static void mxsimage_print_header(const void *hdr)
2245bce88370SMarek Vasut {
2246bce88370SMarek Vasut if (imagefile)
2247bce88370SMarek Vasut mxsimage_verify_print_header(imagefile, 0);
2248bce88370SMarek Vasut }
2249bce88370SMarek Vasut
sb_build_image(struct sb_image_ctx * ictx,struct image_type_params * tparams)2250bce88370SMarek Vasut static int sb_build_image(struct sb_image_ctx *ictx,
2251bce88370SMarek Vasut struct image_type_params *tparams)
2252bce88370SMarek Vasut {
2253bce88370SMarek Vasut struct sb_boot_image_header *sb_header = &ictx->payload;
2254bce88370SMarek Vasut struct sb_section_ctx *sctx;
2255bce88370SMarek Vasut struct sb_cmd_ctx *cctx;
2256bce88370SMarek Vasut struct sb_command *ccmd;
2257bce88370SMarek Vasut struct sb_key_dictionary_key *sb_dict_key = &ictx->sb_dict_key;
2258bce88370SMarek Vasut
2259bce88370SMarek Vasut uint8_t *image, *iptr;
2260bce88370SMarek Vasut
2261bce88370SMarek Vasut /* Calculate image size. */
2262bce88370SMarek Vasut uint32_t size = sizeof(*sb_header) +
2263bce88370SMarek Vasut ictx->sect_count * sizeof(struct sb_sections_header) +
2264bce88370SMarek Vasut sizeof(*sb_dict_key) + sizeof(ictx->digest);
2265bce88370SMarek Vasut
2266bce88370SMarek Vasut sctx = ictx->sect_head;
2267bce88370SMarek Vasut while (sctx) {
2268bce88370SMarek Vasut size += sctx->size;
2269bce88370SMarek Vasut sctx = sctx->sect;
2270bce88370SMarek Vasut };
2271bce88370SMarek Vasut
2272bce88370SMarek Vasut image = malloc(size);
2273bce88370SMarek Vasut if (!image)
2274bce88370SMarek Vasut return -ENOMEM;
2275bce88370SMarek Vasut iptr = image;
2276bce88370SMarek Vasut
2277bce88370SMarek Vasut memcpy(iptr, sb_header, sizeof(*sb_header));
2278bce88370SMarek Vasut iptr += sizeof(*sb_header);
2279bce88370SMarek Vasut
2280bce88370SMarek Vasut sctx = ictx->sect_head;
2281bce88370SMarek Vasut while (sctx) {
2282bce88370SMarek Vasut memcpy(iptr, &sctx->payload, sizeof(struct sb_sections_header));
2283bce88370SMarek Vasut iptr += sizeof(struct sb_sections_header);
2284bce88370SMarek Vasut sctx = sctx->sect;
2285bce88370SMarek Vasut };
2286bce88370SMarek Vasut
2287bce88370SMarek Vasut memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key));
2288bce88370SMarek Vasut iptr += sizeof(*sb_dict_key);
2289bce88370SMarek Vasut
2290bce88370SMarek Vasut sctx = ictx->sect_head;
2291bce88370SMarek Vasut while (sctx) {
2292bce88370SMarek Vasut cctx = sctx->cmd_head;
2293bce88370SMarek Vasut while (cctx) {
2294bce88370SMarek Vasut ccmd = &cctx->payload;
2295bce88370SMarek Vasut
2296bce88370SMarek Vasut memcpy(iptr, &cctx->c_payload, sizeof(cctx->payload));
2297bce88370SMarek Vasut iptr += sizeof(cctx->payload);
2298bce88370SMarek Vasut
2299bce88370SMarek Vasut if (ccmd->header.tag == ROM_LOAD_CMD) {
2300bce88370SMarek Vasut memcpy(iptr, cctx->data, cctx->length);
2301bce88370SMarek Vasut iptr += cctx->length;
2302bce88370SMarek Vasut }
2303bce88370SMarek Vasut
2304bce88370SMarek Vasut cctx = cctx->cmd;
2305bce88370SMarek Vasut }
2306bce88370SMarek Vasut
2307bce88370SMarek Vasut sctx = sctx->sect;
2308bce88370SMarek Vasut };
2309bce88370SMarek Vasut
2310bce88370SMarek Vasut memcpy(iptr, ictx->digest, sizeof(ictx->digest));
2311bce88370SMarek Vasut iptr += sizeof(ictx->digest);
2312bce88370SMarek Vasut
2313bce88370SMarek Vasut /* Configure the mkimage */
2314bce88370SMarek Vasut tparams->hdr = image;
2315bce88370SMarek Vasut tparams->header_size = size;
2316bce88370SMarek Vasut
2317bce88370SMarek Vasut return 0;
2318bce88370SMarek Vasut }
2319bce88370SMarek Vasut
mxsimage_generate(struct image_tool_params * params,struct image_type_params * tparams)2320f86ed6a8SGuilherme Maciel Ferreira static int mxsimage_generate(struct image_tool_params *params,
2321bce88370SMarek Vasut struct image_type_params *tparams)
2322bce88370SMarek Vasut {
2323bce88370SMarek Vasut int ret;
2324bce88370SMarek Vasut struct sb_image_ctx ctx;
2325bce88370SMarek Vasut
2326bce88370SMarek Vasut /* Do not copy the U-Boot image! */
2327bce88370SMarek Vasut params->skipcpy = 1;
2328bce88370SMarek Vasut
2329bce88370SMarek Vasut memset(&ctx, 0, sizeof(ctx));
2330bce88370SMarek Vasut
2331bce88370SMarek Vasut ctx.cfg_filename = params->imagename;
2332bce88370SMarek Vasut ctx.output_filename = params->imagefile;
2333bce88370SMarek Vasut
2334bce88370SMarek Vasut ret = sb_build_tree_from_cfg(&ctx);
2335bce88370SMarek Vasut if (ret)
2336bce88370SMarek Vasut goto fail;
2337bce88370SMarek Vasut
2338bce88370SMarek Vasut ret = sb_encrypt_image(&ctx);
2339bce88370SMarek Vasut if (!ret)
2340bce88370SMarek Vasut ret = sb_build_image(&ctx, tparams);
2341bce88370SMarek Vasut
2342bce88370SMarek Vasut fail:
2343bce88370SMarek Vasut sb_free_image(&ctx);
2344bce88370SMarek Vasut
2345bce88370SMarek Vasut return ret;
2346bce88370SMarek Vasut }
2347bce88370SMarek Vasut
2348bce88370SMarek Vasut /*
2349bce88370SMarek Vasut * mxsimage parameters
2350bce88370SMarek Vasut */
2351a93648d1SGuilherme Maciel Ferreira U_BOOT_IMAGE_TYPE(
2352a93648d1SGuilherme Maciel Ferreira mxsimage,
2353a93648d1SGuilherme Maciel Ferreira "Freescale MXS Boot Image support",
2354a93648d1SGuilherme Maciel Ferreira 0,
2355a93648d1SGuilherme Maciel Ferreira NULL,
2356a93648d1SGuilherme Maciel Ferreira mxsimage_check_params,
2357a93648d1SGuilherme Maciel Ferreira mxsimage_verify_header,
2358a93648d1SGuilherme Maciel Ferreira mxsimage_print_header,
2359a93648d1SGuilherme Maciel Ferreira mxsimage_set_header,
2360a93648d1SGuilherme Maciel Ferreira NULL,
2361a93648d1SGuilherme Maciel Ferreira mxsimage_check_image_types,
2362a93648d1SGuilherme Maciel Ferreira NULL,
2363a93648d1SGuilherme Maciel Ferreira mxsimage_generate
2364a93648d1SGuilherme Maciel Ferreira );
2365bce88370SMarek Vasut #endif
2366