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