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