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