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