xref: /openbmc/u-boot/tools/kwbimage.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2aa0c7a86SPrafulla Wadaskar /*
34acd2d24SStefan Roese  * Image manipulator for Marvell SoCs
4a1b6b0a9SMario Six  *  supports Kirkwood, Dove, Armada 370, Armada XP, and Armada 38x
54acd2d24SStefan Roese  *
64acd2d24SStefan Roese  * (C) Copyright 2013 Thomas Petazzoni
74acd2d24SStefan Roese  * <thomas.petazzoni@free-electrons.com>
8aa0c7a86SPrafulla Wadaskar  *
9a1b6b0a9SMario Six  * Not implemented: support for the register headers in v1 images
10aa0c7a86SPrafulla Wadaskar  */
11aa0c7a86SPrafulla Wadaskar 
12f86ed6a8SGuilherme Maciel Ferreira #include "imagetool.h"
13e5f1a586SAndreas Bießmann #include <limits.h>
14aa0c7a86SPrafulla Wadaskar #include <image.h>
15a1b6b0a9SMario Six #include <stdarg.h>
164acd2d24SStefan Roese #include <stdint.h>
17aa0c7a86SPrafulla Wadaskar #include "kwbimage.h"
18aa0c7a86SPrafulla Wadaskar 
19a1b6b0a9SMario Six #ifdef CONFIG_KWB_SECURE
20e15843b1SJelle van der Waa #include <openssl/bn.h>
21a1b6b0a9SMario Six #include <openssl/rsa.h>
22a1b6b0a9SMario Six #include <openssl/pem.h>
23a1b6b0a9SMario Six #include <openssl/err.h>
24a1b6b0a9SMario Six #include <openssl/evp.h>
25e15843b1SJelle van der Waa 
26a2d5efd7SJonathan Gray #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
27a2d5efd7SJonathan Gray     (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
RSA_get0_key(const RSA * r,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)28e15843b1SJelle van der Waa static void RSA_get0_key(const RSA *r,
29e15843b1SJelle van der Waa                  const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
30e15843b1SJelle van der Waa {
31e15843b1SJelle van der Waa    if (n != NULL)
32e15843b1SJelle van der Waa        *n = r->n;
33e15843b1SJelle van der Waa    if (e != NULL)
34e15843b1SJelle van der Waa        *e = r->e;
35e15843b1SJelle van der Waa    if (d != NULL)
36e15843b1SJelle van der Waa        *d = r->d;
37e15843b1SJelle van der Waa }
38e15843b1SJelle van der Waa 
39a2d5efd7SJonathan Gray #elif !defined(LIBRESSL_VERSION_NUMBER)
EVP_MD_CTX_cleanup(EVP_MD_CTX * ctx)40e15843b1SJelle van der Waa void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
41e15843b1SJelle van der Waa {
42e15843b1SJelle van der Waa 	EVP_MD_CTX_reset(ctx);
43e15843b1SJelle van der Waa }
44e15843b1SJelle van der Waa #endif
45a1b6b0a9SMario Six #endif
46a1b6b0a9SMario Six 
474acd2d24SStefan Roese static struct image_cfg_element *image_cfg;
484acd2d24SStefan Roese static int cfgn;
49a1b6b0a9SMario Six #ifdef CONFIG_KWB_SECURE
50a1b6b0a9SMario Six static int verbose_mode;
51a1b6b0a9SMario Six #endif
524acd2d24SStefan Roese 
534acd2d24SStefan Roese struct boot_mode {
544acd2d24SStefan Roese 	unsigned int id;
554acd2d24SStefan Roese 	const char *name;
56aa0c7a86SPrafulla Wadaskar };
57aa0c7a86SPrafulla Wadaskar 
58a1b6b0a9SMario Six /*
59a1b6b0a9SMario Six  * SHA2-256 hash
60a1b6b0a9SMario Six  */
61a1b6b0a9SMario Six struct hash_v1 {
62a1b6b0a9SMario Six 	uint8_t hash[32];
63a1b6b0a9SMario Six };
64a1b6b0a9SMario Six 
654acd2d24SStefan Roese struct boot_mode boot_modes[] = {
664acd2d24SStefan Roese 	{ 0x4D, "i2c"  },
674acd2d24SStefan Roese 	{ 0x5A, "spi"  },
684acd2d24SStefan Roese 	{ 0x8B, "nand" },
694acd2d24SStefan Roese 	{ 0x78, "sata" },
704acd2d24SStefan Roese 	{ 0x9C, "pex"  },
714acd2d24SStefan Roese 	{ 0x69, "uart" },
721bbe63c3SStefan Roese 	{ 0xAE, "sdio" },
734acd2d24SStefan Roese 	{},
744acd2d24SStefan Roese };
754acd2d24SStefan Roese 
764acd2d24SStefan Roese struct nand_ecc_mode {
774acd2d24SStefan Roese 	unsigned int id;
784acd2d24SStefan Roese 	const char *name;
794acd2d24SStefan Roese };
804acd2d24SStefan Roese 
814acd2d24SStefan Roese struct nand_ecc_mode nand_ecc_modes[] = {
824acd2d24SStefan Roese 	{ 0x00, "default" },
834acd2d24SStefan Roese 	{ 0x01, "hamming" },
844acd2d24SStefan Roese 	{ 0x02, "rs" },
854acd2d24SStefan Roese 	{ 0x03, "disabled" },
864acd2d24SStefan Roese 	{},
874acd2d24SStefan Roese };
884acd2d24SStefan Roese 
894acd2d24SStefan Roese /* Used to identify an undefined execution or destination address */
904acd2d24SStefan Roese #define ADDR_INVALID ((uint32_t)-1)
914acd2d24SStefan Roese 
924acd2d24SStefan Roese #define BINARY_MAX_ARGS 8
934acd2d24SStefan Roese 
944acd2d24SStefan Roese /* In-memory representation of a line of the configuration file */
954991b4f7SMario Six 
964991b4f7SMario Six enum image_cfg_type {
974acd2d24SStefan Roese 	IMAGE_CFG_VERSION = 0x1,
984acd2d24SStefan Roese 	IMAGE_CFG_BOOT_FROM,
994acd2d24SStefan Roese 	IMAGE_CFG_DEST_ADDR,
1004acd2d24SStefan Roese 	IMAGE_CFG_EXEC_ADDR,
1014acd2d24SStefan Roese 	IMAGE_CFG_NAND_BLKSZ,
1024acd2d24SStefan Roese 	IMAGE_CFG_NAND_BADBLK_LOCATION,
1034acd2d24SStefan Roese 	IMAGE_CFG_NAND_ECC_MODE,
1044acd2d24SStefan Roese 	IMAGE_CFG_NAND_PAGESZ,
1054acd2d24SStefan Roese 	IMAGE_CFG_BINARY,
1064acd2d24SStefan Roese 	IMAGE_CFG_PAYLOAD,
1074acd2d24SStefan Roese 	IMAGE_CFG_DATA,
1084bdb5479SChris Packham 	IMAGE_CFG_BAUDRATE,
1092611c05eSChris Packham 	IMAGE_CFG_DEBUG,
110a1b6b0a9SMario Six 	IMAGE_CFG_KAK,
111a1b6b0a9SMario Six 	IMAGE_CFG_CSK,
112a1b6b0a9SMario Six 	IMAGE_CFG_CSK_INDEX,
113a1b6b0a9SMario Six 	IMAGE_CFG_JTAG_DELAY,
114a1b6b0a9SMario Six 	IMAGE_CFG_BOX_ID,
115a1b6b0a9SMario Six 	IMAGE_CFG_FLASH_ID,
116a1b6b0a9SMario Six 	IMAGE_CFG_SEC_COMMON_IMG,
117a1b6b0a9SMario Six 	IMAGE_CFG_SEC_SPECIALIZED_IMG,
118a1b6b0a9SMario Six 	IMAGE_CFG_SEC_BOOT_DEV,
119a1b6b0a9SMario Six 	IMAGE_CFG_SEC_FUSE_DUMP,
1204991b4f7SMario Six 
1214991b4f7SMario Six 	IMAGE_CFG_COUNT
1224acd2d24SStefan Roese } type;
1234991b4f7SMario Six 
1244991b4f7SMario Six static const char * const id_strs[] = {
1254991b4f7SMario Six 	[IMAGE_CFG_VERSION] = "VERSION",
1264991b4f7SMario Six 	[IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
1274991b4f7SMario Six 	[IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
1284991b4f7SMario Six 	[IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
1294991b4f7SMario Six 	[IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
1304991b4f7SMario Six 	[IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
1314991b4f7SMario Six 	[IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
1324991b4f7SMario Six 	[IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
1334991b4f7SMario Six 	[IMAGE_CFG_BINARY] = "BINARY",
1344991b4f7SMario Six 	[IMAGE_CFG_PAYLOAD] = "PAYLOAD",
1354991b4f7SMario Six 	[IMAGE_CFG_DATA] = "DATA",
1364991b4f7SMario Six 	[IMAGE_CFG_BAUDRATE] = "BAUDRATE",
1374991b4f7SMario Six 	[IMAGE_CFG_DEBUG] = "DEBUG",
138a1b6b0a9SMario Six 	[IMAGE_CFG_KAK] = "KAK",
139a1b6b0a9SMario Six 	[IMAGE_CFG_CSK] = "CSK",
140a1b6b0a9SMario Six 	[IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
141a1b6b0a9SMario Six 	[IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
142a1b6b0a9SMario Six 	[IMAGE_CFG_BOX_ID] = "BOX_ID",
143a1b6b0a9SMario Six 	[IMAGE_CFG_FLASH_ID] = "FLASH_ID",
144a1b6b0a9SMario Six 	[IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
145a1b6b0a9SMario Six 	[IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
146a1b6b0a9SMario Six 	[IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
147a1b6b0a9SMario Six 	[IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
1484991b4f7SMario Six };
1494991b4f7SMario Six 
1504991b4f7SMario Six struct image_cfg_element {
1514991b4f7SMario Six 	enum image_cfg_type type;
1524acd2d24SStefan Roese 	union {
1534acd2d24SStefan Roese 		unsigned int version;
1544acd2d24SStefan Roese 		unsigned int bootfrom;
1554acd2d24SStefan Roese 		struct {
1564acd2d24SStefan Roese 			const char *file;
1574acd2d24SStefan Roese 			unsigned int args[BINARY_MAX_ARGS];
1584acd2d24SStefan Roese 			unsigned int nargs;
1594acd2d24SStefan Roese 		} binary;
1604acd2d24SStefan Roese 		const char *payload;
1614acd2d24SStefan Roese 		unsigned int dstaddr;
1624acd2d24SStefan Roese 		unsigned int execaddr;
1634acd2d24SStefan Roese 		unsigned int nandblksz;
1644acd2d24SStefan Roese 		unsigned int nandbadblklocation;
1654acd2d24SStefan Roese 		unsigned int nandeccmode;
1664acd2d24SStefan Roese 		unsigned int nandpagesz;
1674acd2d24SStefan Roese 		struct ext_hdr_v0_reg regdata;
1684bdb5479SChris Packham 		unsigned int baudrate;
1692611c05eSChris Packham 		unsigned int debug;
170a1b6b0a9SMario Six 		const char *key_name;
171a1b6b0a9SMario Six 		int csk_idx;
172a1b6b0a9SMario Six 		uint8_t jtag_delay;
173a1b6b0a9SMario Six 		uint32_t boxid;
174a1b6b0a9SMario Six 		uint32_t flashid;
175a1b6b0a9SMario Six 		bool sec_specialized_img;
176a1b6b0a9SMario Six 		unsigned int sec_boot_dev;
177a1b6b0a9SMario Six 		const char *name;
1784acd2d24SStefan Roese 	};
1794acd2d24SStefan Roese };
1804acd2d24SStefan Roese 
1814acd2d24SStefan Roese #define IMAGE_CFG_ELEMENT_MAX 256
182aa0c7a86SPrafulla Wadaskar 
183aa0c7a86SPrafulla Wadaskar /*
1844acd2d24SStefan Roese  * Utility functions to manipulate boot mode and ecc modes (convert
1854acd2d24SStefan Roese  * them back and forth between description strings and the
1864acd2d24SStefan Roese  * corresponding numerical identifiers).
187aa0c7a86SPrafulla Wadaskar  */
1884acd2d24SStefan Roese 
image_boot_mode_name(unsigned int id)1894acd2d24SStefan Roese static const char *image_boot_mode_name(unsigned int id)
190aa0c7a86SPrafulla Wadaskar {
1914acd2d24SStefan Roese 	int i;
19294490a4aSMario Six 
1934acd2d24SStefan Roese 	for (i = 0; boot_modes[i].name; i++)
1944acd2d24SStefan Roese 		if (boot_modes[i].id == id)
1954acd2d24SStefan Roese 			return boot_modes[i].name;
1964acd2d24SStefan Roese 	return NULL;
1974acd2d24SStefan Roese }
1984acd2d24SStefan Roese 
image_boot_mode_id(const char * boot_mode_name)1994acd2d24SStefan Roese int image_boot_mode_id(const char *boot_mode_name)
2004acd2d24SStefan Roese {
2014acd2d24SStefan Roese 	int i;
20294490a4aSMario Six 
2034acd2d24SStefan Roese 	for (i = 0; boot_modes[i].name; i++)
2044acd2d24SStefan Roese 		if (!strcmp(boot_modes[i].name, boot_mode_name))
2054acd2d24SStefan Roese 			return boot_modes[i].id;
2064acd2d24SStefan Roese 
2074acd2d24SStefan Roese 	return -1;
2084acd2d24SStefan Roese }
2094acd2d24SStefan Roese 
image_nand_ecc_mode_id(const char * nand_ecc_mode_name)2104acd2d24SStefan Roese int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
2114acd2d24SStefan Roese {
2124acd2d24SStefan Roese 	int i;
21394490a4aSMario Six 
2144acd2d24SStefan Roese 	for (i = 0; nand_ecc_modes[i].name; i++)
2154acd2d24SStefan Roese 		if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
2164acd2d24SStefan Roese 			return nand_ecc_modes[i].id;
2174acd2d24SStefan Roese 	return -1;
2184acd2d24SStefan Roese }
2194acd2d24SStefan Roese 
2204acd2d24SStefan Roese static struct image_cfg_element *
image_find_option(unsigned int optiontype)2214acd2d24SStefan Roese image_find_option(unsigned int optiontype)
2224acd2d24SStefan Roese {
2234acd2d24SStefan Roese 	int i;
2244acd2d24SStefan Roese 
2254acd2d24SStefan Roese 	for (i = 0; i < cfgn; i++) {
2264acd2d24SStefan Roese 		if (image_cfg[i].type == optiontype)
2274acd2d24SStefan Roese 			return &image_cfg[i];
2284acd2d24SStefan Roese 	}
2294acd2d24SStefan Roese 
2304acd2d24SStefan Roese 	return NULL;
2314acd2d24SStefan Roese }
2324acd2d24SStefan Roese 
2334acd2d24SStefan Roese static unsigned int
image_count_options(unsigned int optiontype)2344acd2d24SStefan Roese image_count_options(unsigned int optiontype)
2354acd2d24SStefan Roese {
2364acd2d24SStefan Roese 	int i;
2374acd2d24SStefan Roese 	unsigned int count = 0;
2384acd2d24SStefan Roese 
2394acd2d24SStefan Roese 	for (i = 0; i < cfgn; i++)
2404acd2d24SStefan Roese 		if (image_cfg[i].type == optiontype)
2414acd2d24SStefan Roese 			count++;
2424acd2d24SStefan Roese 
2434acd2d24SStefan Roese 	return count;
2444acd2d24SStefan Roese }
2454acd2d24SStefan Roese 
246a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
247a1b6b0a9SMario Six 
image_get_csk_index(void)248a1b6b0a9SMario Six static int image_get_csk_index(void)
249a1b6b0a9SMario Six {
250a1b6b0a9SMario Six 	struct image_cfg_element *e;
251a1b6b0a9SMario Six 
252a1b6b0a9SMario Six 	e = image_find_option(IMAGE_CFG_CSK_INDEX);
253a1b6b0a9SMario Six 	if (!e)
254a1b6b0a9SMario Six 		return -1;
255a1b6b0a9SMario Six 
256a1b6b0a9SMario Six 	return e->csk_idx;
257a1b6b0a9SMario Six }
258a1b6b0a9SMario Six 
image_get_spezialized_img(void)259a1b6b0a9SMario Six static bool image_get_spezialized_img(void)
260a1b6b0a9SMario Six {
261a1b6b0a9SMario Six 	struct image_cfg_element *e;
262a1b6b0a9SMario Six 
263a1b6b0a9SMario Six 	e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
264a1b6b0a9SMario Six 	if (!e)
265a1b6b0a9SMario Six 		return false;
266a1b6b0a9SMario Six 
267a1b6b0a9SMario Six 	return e->sec_specialized_img;
268a1b6b0a9SMario Six }
269a1b6b0a9SMario Six 
270a1b6b0a9SMario Six #endif
271a1b6b0a9SMario Six 
2724acd2d24SStefan Roese /*
2734acd2d24SStefan Roese  * Compute a 8-bit checksum of a memory area. This algorithm follows
2744acd2d24SStefan Roese  * the requirements of the Marvell SoC BootROM specifications.
2754acd2d24SStefan Roese  */
image_checksum8(void * start,uint32_t len)2764acd2d24SStefan Roese static uint8_t image_checksum8(void *start, uint32_t len)
2774acd2d24SStefan Roese {
2784acd2d24SStefan Roese 	uint8_t csum = 0;
2794acd2d24SStefan Roese 	uint8_t *p = start;
280aa0c7a86SPrafulla Wadaskar 
281aa0c7a86SPrafulla Wadaskar 	/* check len and return zero checksum if invalid */
282aa0c7a86SPrafulla Wadaskar 	if (!len)
283aa0c7a86SPrafulla Wadaskar 		return 0;
284aa0c7a86SPrafulla Wadaskar 
285aa0c7a86SPrafulla Wadaskar 	do {
2864acd2d24SStefan Roese 		csum += *p;
287aa0c7a86SPrafulla Wadaskar 		p++;
288aa0c7a86SPrafulla Wadaskar 	} while (--len);
2894acd2d24SStefan Roese 
2904acd2d24SStefan Roese 	return csum;
291aa0c7a86SPrafulla Wadaskar }
292aa0c7a86SPrafulla Wadaskar 
kwbimage_header_size(unsigned char * ptr)293db7cd4edSBaruch Siach size_t kwbimage_header_size(unsigned char *ptr)
294db7cd4edSBaruch Siach {
295db7cd4edSBaruch Siach 	if (image_version((void *)ptr) == 0)
296db7cd4edSBaruch Siach 		return sizeof(struct main_hdr_v0);
297db7cd4edSBaruch Siach 	else
298db7cd4edSBaruch Siach 		return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr);
299db7cd4edSBaruch Siach }
300db7cd4edSBaruch Siach 
301db7cd4edSBaruch Siach /*
302db7cd4edSBaruch Siach  * Verify checksum over a complete header that includes the checksum field.
303db7cd4edSBaruch Siach  * Return 1 when OK, otherwise 0.
304db7cd4edSBaruch Siach  */
main_hdr_checksum_ok(void * hdr)305db7cd4edSBaruch Siach static int main_hdr_checksum_ok(void *hdr)
306db7cd4edSBaruch Siach {
307db7cd4edSBaruch Siach 	/* Offsets of checksum in v0 and v1 headers are the same */
308db7cd4edSBaruch Siach 	struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
309db7cd4edSBaruch Siach 	uint8_t checksum;
310db7cd4edSBaruch Siach 
311db7cd4edSBaruch Siach 	checksum = image_checksum8(hdr, kwbimage_header_size(hdr));
312db7cd4edSBaruch Siach 	/* Calculated checksum includes the header checksum field. Compensate
313db7cd4edSBaruch Siach 	 * for that.
314db7cd4edSBaruch Siach 	 */
315db7cd4edSBaruch Siach 	checksum -= main_hdr->checksum;
316db7cd4edSBaruch Siach 
317db7cd4edSBaruch Siach 	return checksum == main_hdr->checksum;
318db7cd4edSBaruch Siach }
319db7cd4edSBaruch Siach 
image_checksum32(void * start,uint32_t len)3204acd2d24SStefan Roese static uint32_t image_checksum32(void *start, uint32_t len)
321aa0c7a86SPrafulla Wadaskar {
3224acd2d24SStefan Roese 	uint32_t csum = 0;
3234acd2d24SStefan Roese 	uint32_t *p = start;
324aa0c7a86SPrafulla Wadaskar 
325aa0c7a86SPrafulla Wadaskar 	/* check len and return zero checksum if invalid */
326aa0c7a86SPrafulla Wadaskar 	if (!len)
327aa0c7a86SPrafulla Wadaskar 		return 0;
328aa0c7a86SPrafulla Wadaskar 
329aa0c7a86SPrafulla Wadaskar 	if (len % sizeof(uint32_t)) {
3304acd2d24SStefan Roese 		fprintf(stderr, "Length %d is not in multiple of %zu\n",
3314acd2d24SStefan Roese 			len, sizeof(uint32_t));
332aa0c7a86SPrafulla Wadaskar 		return 0;
333aa0c7a86SPrafulla Wadaskar 	}
334aa0c7a86SPrafulla Wadaskar 
335aa0c7a86SPrafulla Wadaskar 	do {
3364acd2d24SStefan Roese 		csum += *p;
337aa0c7a86SPrafulla Wadaskar 		p++;
338aa0c7a86SPrafulla Wadaskar 		len -= sizeof(uint32_t);
339aa0c7a86SPrafulla Wadaskar 	} while (len > 0);
3404acd2d24SStefan Roese 
3414acd2d24SStefan Roese 	return csum;
342aa0c7a86SPrafulla Wadaskar }
343aa0c7a86SPrafulla Wadaskar 
baudrate_to_option(unsigned int baudrate)3444bdb5479SChris Packham static uint8_t baudrate_to_option(unsigned int baudrate)
3454bdb5479SChris Packham {
3464bdb5479SChris Packham 	switch (baudrate) {
3474bdb5479SChris Packham 	case 2400:
3484bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_2400;
3494bdb5479SChris Packham 	case 4800:
3504bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_4800;
3514bdb5479SChris Packham 	case 9600:
3524bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_9600;
3534bdb5479SChris Packham 	case 19200:
3544bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_19200;
3554bdb5479SChris Packham 	case 38400:
3564bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_38400;
3574bdb5479SChris Packham 	case 57600:
3584bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_57600;
3594bdb5479SChris Packham 	case 115200:
3604bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_115200;
3614bdb5479SChris Packham 	default:
3624bdb5479SChris Packham 		return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
3634bdb5479SChris Packham 	}
3644bdb5479SChris Packham }
3654bdb5479SChris Packham 
366a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
kwb_msg(const char * fmt,...)367a1b6b0a9SMario Six static void kwb_msg(const char *fmt, ...)
368a1b6b0a9SMario Six {
369a1b6b0a9SMario Six 	if (verbose_mode) {
370a1b6b0a9SMario Six 		va_list ap;
371a1b6b0a9SMario Six 
372a1b6b0a9SMario Six 		va_start(ap, fmt);
373a1b6b0a9SMario Six 		vfprintf(stdout, fmt, ap);
374a1b6b0a9SMario Six 		va_end(ap);
375a1b6b0a9SMario Six 	}
376a1b6b0a9SMario Six }
377a1b6b0a9SMario Six 
openssl_err(const char * msg)378a1b6b0a9SMario Six static int openssl_err(const char *msg)
379a1b6b0a9SMario Six {
380a1b6b0a9SMario Six 	unsigned long ssl_err = ERR_get_error();
381a1b6b0a9SMario Six 
382a1b6b0a9SMario Six 	fprintf(stderr, "%s", msg);
383a1b6b0a9SMario Six 	fprintf(stderr, ": %s\n",
384a1b6b0a9SMario Six 		ERR_error_string(ssl_err, 0));
385a1b6b0a9SMario Six 
386a1b6b0a9SMario Six 	return -1;
387a1b6b0a9SMario Six }
388a1b6b0a9SMario Six 
kwb_load_rsa_key(const char * keydir,const char * name,RSA ** p_rsa)389a1b6b0a9SMario Six static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
390a1b6b0a9SMario Six {
391a1b6b0a9SMario Six 	char path[PATH_MAX];
392a1b6b0a9SMario Six 	RSA *rsa;
393a1b6b0a9SMario Six 	FILE *f;
394a1b6b0a9SMario Six 
395a1b6b0a9SMario Six 	if (!keydir)
396a1b6b0a9SMario Six 		keydir = ".";
397a1b6b0a9SMario Six 
398a1b6b0a9SMario Six 	snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
399a1b6b0a9SMario Six 	f = fopen(path, "r");
400a1b6b0a9SMario Six 	if (!f) {
401a1b6b0a9SMario Six 		fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
402a1b6b0a9SMario Six 			path, strerror(errno));
403a1b6b0a9SMario Six 		return -ENOENT;
404a1b6b0a9SMario Six 	}
405a1b6b0a9SMario Six 
406a1b6b0a9SMario Six 	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
407a1b6b0a9SMario Six 	if (!rsa) {
408a1b6b0a9SMario Six 		openssl_err("Failure reading private key");
409a1b6b0a9SMario Six 		fclose(f);
410a1b6b0a9SMario Six 		return -EPROTO;
411a1b6b0a9SMario Six 	}
412a1b6b0a9SMario Six 	fclose(f);
413a1b6b0a9SMario Six 	*p_rsa = rsa;
414a1b6b0a9SMario Six 
415a1b6b0a9SMario Six 	return 0;
416a1b6b0a9SMario Six }
417a1b6b0a9SMario Six 
kwb_load_cfg_key(struct image_tool_params * params,unsigned int cfg_option,const char * key_name,RSA ** p_key)418a1b6b0a9SMario Six static int kwb_load_cfg_key(struct image_tool_params *params,
419a1b6b0a9SMario Six 			    unsigned int cfg_option, const char *key_name,
420a1b6b0a9SMario Six 			    RSA **p_key)
421a1b6b0a9SMario Six {
422a1b6b0a9SMario Six 	struct image_cfg_element *e_key;
423a1b6b0a9SMario Six 	RSA *key;
424a1b6b0a9SMario Six 	int res;
425a1b6b0a9SMario Six 
426a1b6b0a9SMario Six 	*p_key = NULL;
427a1b6b0a9SMario Six 
428a1b6b0a9SMario Six 	e_key = image_find_option(cfg_option);
429a1b6b0a9SMario Six 	if (!e_key) {
430a1b6b0a9SMario Six 		fprintf(stderr, "%s not configured\n", key_name);
431a1b6b0a9SMario Six 		return -ENOENT;
432a1b6b0a9SMario Six 	}
433a1b6b0a9SMario Six 
434a1b6b0a9SMario Six 	res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
435a1b6b0a9SMario Six 	if (res < 0) {
436a1b6b0a9SMario Six 		fprintf(stderr, "Failed to load %s\n", key_name);
437a1b6b0a9SMario Six 		return -ENOENT;
438a1b6b0a9SMario Six 	}
439a1b6b0a9SMario Six 
440a1b6b0a9SMario Six 	*p_key = key;
441a1b6b0a9SMario Six 
442a1b6b0a9SMario Six 	return 0;
443a1b6b0a9SMario Six }
444a1b6b0a9SMario Six 
kwb_load_kak(struct image_tool_params * params,RSA ** p_kak)445a1b6b0a9SMario Six static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
446a1b6b0a9SMario Six {
447a1b6b0a9SMario Six 	return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
448a1b6b0a9SMario Six }
449a1b6b0a9SMario Six 
kwb_load_csk(struct image_tool_params * params,RSA ** p_csk)450a1b6b0a9SMario Six static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
451a1b6b0a9SMario Six {
452a1b6b0a9SMario Six 	return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
453a1b6b0a9SMario Six }
454a1b6b0a9SMario Six 
kwb_compute_pubkey_hash(struct pubkey_der_v1 * pk,struct hash_v1 * hash)455a1b6b0a9SMario Six static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
456a1b6b0a9SMario Six 				   struct hash_v1 *hash)
457a1b6b0a9SMario Six {
458a1b6b0a9SMario Six 	EVP_MD_CTX *ctx;
459a1b6b0a9SMario Six 	unsigned int key_size;
460a1b6b0a9SMario Six 	unsigned int hash_size;
461a1b6b0a9SMario Six 	int ret = 0;
462a1b6b0a9SMario Six 
463a1b6b0a9SMario Six 	if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
464a1b6b0a9SMario Six 		return -EINVAL;
465a1b6b0a9SMario Six 
466a1b6b0a9SMario Six 	key_size = (pk->key[2] << 8) + pk->key[3] + 4;
467a1b6b0a9SMario Six 
468a1b6b0a9SMario Six 	ctx = EVP_MD_CTX_create();
469a1b6b0a9SMario Six 	if (!ctx)
470a1b6b0a9SMario Six 		return openssl_err("EVP context creation failed");
471a1b6b0a9SMario Six 
472a1b6b0a9SMario Six 	EVP_MD_CTX_init(ctx);
473a1b6b0a9SMario Six 	if (!EVP_DigestInit(ctx, EVP_sha256())) {
474a1b6b0a9SMario Six 		ret = openssl_err("Digest setup failed");
475a1b6b0a9SMario Six 		goto hash_err_ctx;
476a1b6b0a9SMario Six 	}
477a1b6b0a9SMario Six 
478a1b6b0a9SMario Six 	if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
479a1b6b0a9SMario Six 		ret = openssl_err("Hashing data failed");
480a1b6b0a9SMario Six 		goto hash_err_ctx;
481a1b6b0a9SMario Six 	}
482a1b6b0a9SMario Six 
483a1b6b0a9SMario Six 	if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
484a1b6b0a9SMario Six 		ret = openssl_err("Could not obtain hash");
485a1b6b0a9SMario Six 		goto hash_err_ctx;
486a1b6b0a9SMario Six 	}
487a1b6b0a9SMario Six 
488a1b6b0a9SMario Six 	EVP_MD_CTX_cleanup(ctx);
489a1b6b0a9SMario Six 
490a1b6b0a9SMario Six hash_err_ctx:
491a1b6b0a9SMario Six 	EVP_MD_CTX_destroy(ctx);
492a1b6b0a9SMario Six 	return ret;
493a1b6b0a9SMario Six }
494a1b6b0a9SMario Six 
kwb_import_pubkey(RSA ** key,struct pubkey_der_v1 * src,char * keyname)495a1b6b0a9SMario Six static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
496a1b6b0a9SMario Six {
497a1b6b0a9SMario Six 	RSA *rsa;
498a1b6b0a9SMario Six 	const unsigned char *ptr;
499a1b6b0a9SMario Six 
500a1b6b0a9SMario Six 	if (!key || !src)
501a1b6b0a9SMario Six 		goto fail;
502a1b6b0a9SMario Six 
503a1b6b0a9SMario Six 	ptr = src->key;
504a1b6b0a9SMario Six 	rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
505a1b6b0a9SMario Six 	if (!rsa) {
506a1b6b0a9SMario Six 		openssl_err("error decoding public key");
507a1b6b0a9SMario Six 		goto fail;
508a1b6b0a9SMario Six 	}
509a1b6b0a9SMario Six 
510a1b6b0a9SMario Six 	return 0;
511a1b6b0a9SMario Six fail:
512a1b6b0a9SMario Six 	fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
513a1b6b0a9SMario Six 	return -EINVAL;
514a1b6b0a9SMario Six }
515a1b6b0a9SMario Six 
kwb_export_pubkey(RSA * key,struct pubkey_der_v1 * dst,FILE * hashf,char * keyname)516a1b6b0a9SMario Six static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
517a1b6b0a9SMario Six 			     char *keyname)
518a1b6b0a9SMario Six {
519a1b6b0a9SMario Six 	int size_exp, size_mod, size_seq;
520e15843b1SJelle van der Waa 	const BIGNUM *key_e, *key_n;
521a1b6b0a9SMario Six 	uint8_t *cur;
522a1b6b0a9SMario Six 	char *errmsg = "Failed to encode %s\n";
523a1b6b0a9SMario Six 
524e15843b1SJelle van der Waa 	RSA_get0_key(key, NULL, &key_e, NULL);
525e15843b1SJelle van der Waa 	RSA_get0_key(key, &key_n, NULL, NULL);
526e15843b1SJelle van der Waa 
527e15843b1SJelle van der Waa 	if (!key || !key_e || !key_n || !dst) {
528a1b6b0a9SMario Six 		fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
529e15843b1SJelle van der Waa 			key, key_e, key_n, dst);
530a1b6b0a9SMario Six 		fprintf(stderr, errmsg, keyname);
531a1b6b0a9SMario Six 		return -EINVAL;
532a1b6b0a9SMario Six 	}
533a1b6b0a9SMario Six 
534a1b6b0a9SMario Six 	/*
535a1b6b0a9SMario Six 	 * According to the specs, the key should be PKCS#1 DER encoded.
536a1b6b0a9SMario Six 	 * But unfortunately the really required encoding seems to be different;
537a1b6b0a9SMario Six 	 * it violates DER...! (But it still conformes to BER.)
538a1b6b0a9SMario Six 	 * (Length always in long form w/ 2 byte length code; no leading zero
539a1b6b0a9SMario Six 	 * when MSB of first byte is set...)
540a1b6b0a9SMario Six 	 * So we cannot use the encoding func provided by OpenSSL and have to
541a1b6b0a9SMario Six 	 * do the encoding manually.
542a1b6b0a9SMario Six 	 */
543a1b6b0a9SMario Six 
544e15843b1SJelle van der Waa 	size_exp = BN_num_bytes(key_e);
545e15843b1SJelle van der Waa 	size_mod = BN_num_bytes(key_n);
546a1b6b0a9SMario Six 	size_seq = 4 + size_mod + 4 + size_exp;
547a1b6b0a9SMario Six 
548a1b6b0a9SMario Six 	if (size_mod > 256) {
549a1b6b0a9SMario Six 		fprintf(stderr, "export pk failed: wrong mod size: %d\n",
550a1b6b0a9SMario Six 			size_mod);
551a1b6b0a9SMario Six 		fprintf(stderr, errmsg, keyname);
552a1b6b0a9SMario Six 		return -EINVAL;
553a1b6b0a9SMario Six 	}
554a1b6b0a9SMario Six 
555a1b6b0a9SMario Six 	if (4 + size_seq > sizeof(dst->key)) {
556a1b6b0a9SMario Six 		fprintf(stderr, "export pk failed: seq too large (%d, %lu)\n",
557a1b6b0a9SMario Six 			4 + size_seq, sizeof(dst->key));
558a1b6b0a9SMario Six 		fprintf(stderr, errmsg, keyname);
559a1b6b0a9SMario Six 		return -ENOBUFS;
560a1b6b0a9SMario Six 	}
561a1b6b0a9SMario Six 
562a1b6b0a9SMario Six 	cur = dst->key;
563a1b6b0a9SMario Six 
564a1b6b0a9SMario Six 	/* PKCS#1 (RFC3447) RSAPublicKey structure */
565a1b6b0a9SMario Six 	*cur++ = 0x30;		/* SEQUENCE */
566a1b6b0a9SMario Six 	*cur++ = 0x82;
567a1b6b0a9SMario Six 	*cur++ = (size_seq >> 8) & 0xFF;
568a1b6b0a9SMario Six 	*cur++ = size_seq & 0xFF;
569a1b6b0a9SMario Six 	/* Modulus */
570a1b6b0a9SMario Six 	*cur++ = 0x02;		/* INTEGER */
571a1b6b0a9SMario Six 	*cur++ = 0x82;
572a1b6b0a9SMario Six 	*cur++ = (size_mod >> 8) & 0xFF;
573a1b6b0a9SMario Six 	*cur++ = size_mod & 0xFF;
574e15843b1SJelle van der Waa 	BN_bn2bin(key_n, cur);
575a1b6b0a9SMario Six 	cur += size_mod;
576a1b6b0a9SMario Six 	/* Exponent */
577a1b6b0a9SMario Six 	*cur++ = 0x02;		/* INTEGER */
578a1b6b0a9SMario Six 	*cur++ = 0x82;
579a1b6b0a9SMario Six 	*cur++ = (size_exp >> 8) & 0xFF;
580a1b6b0a9SMario Six 	*cur++ = size_exp & 0xFF;
581e15843b1SJelle van der Waa 	BN_bn2bin(key_e, cur);
582a1b6b0a9SMario Six 
583a1b6b0a9SMario Six 	if (hashf) {
584a1b6b0a9SMario Six 		struct hash_v1 pk_hash;
585a1b6b0a9SMario Six 		int i;
586a1b6b0a9SMario Six 		int ret = 0;
587a1b6b0a9SMario Six 
588a1b6b0a9SMario Six 		ret = kwb_compute_pubkey_hash(dst, &pk_hash);
589a1b6b0a9SMario Six 		if (ret < 0) {
590a1b6b0a9SMario Six 			fprintf(stderr, errmsg, keyname);
591a1b6b0a9SMario Six 			return ret;
592a1b6b0a9SMario Six 		}
593a1b6b0a9SMario Six 
594a1b6b0a9SMario Six 		fprintf(hashf, "SHA256 = ");
595a1b6b0a9SMario Six 		for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
596a1b6b0a9SMario Six 			fprintf(hashf, "%02X", pk_hash.hash[i]);
597a1b6b0a9SMario Six 		fprintf(hashf, "\n");
598a1b6b0a9SMario Six 	}
599a1b6b0a9SMario Six 
600a1b6b0a9SMario Six 	return 0;
601a1b6b0a9SMario Six }
602a1b6b0a9SMario Six 
kwb_sign(RSA * key,void * data,int datasz,struct sig_v1 * sig,char * signame)603a1b6b0a9SMario Six int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
604a1b6b0a9SMario Six {
605a1b6b0a9SMario Six 	EVP_PKEY *evp_key;
606a1b6b0a9SMario Six 	EVP_MD_CTX *ctx;
607a1b6b0a9SMario Six 	unsigned int sig_size;
608a1b6b0a9SMario Six 	int size;
609a1b6b0a9SMario Six 	int ret = 0;
610a1b6b0a9SMario Six 
611a1b6b0a9SMario Six 	evp_key = EVP_PKEY_new();
612a1b6b0a9SMario Six 	if (!evp_key)
613a1b6b0a9SMario Six 		return openssl_err("EVP_PKEY object creation failed");
614a1b6b0a9SMario Six 
615a1b6b0a9SMario Six 	if (!EVP_PKEY_set1_RSA(evp_key, key)) {
616a1b6b0a9SMario Six 		ret = openssl_err("EVP key setup failed");
617a1b6b0a9SMario Six 		goto err_key;
618a1b6b0a9SMario Six 	}
619a1b6b0a9SMario Six 
620a1b6b0a9SMario Six 	size = EVP_PKEY_size(evp_key);
621a1b6b0a9SMario Six 	if (size > sizeof(sig->sig)) {
622a1b6b0a9SMario Six 		fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
623a1b6b0a9SMario Six 			size);
624a1b6b0a9SMario Six 		ret = -ENOBUFS;
625a1b6b0a9SMario Six 		goto err_key;
626a1b6b0a9SMario Six 	}
627a1b6b0a9SMario Six 
628a1b6b0a9SMario Six 	ctx = EVP_MD_CTX_create();
629a1b6b0a9SMario Six 	if (!ctx) {
630a1b6b0a9SMario Six 		ret = openssl_err("EVP context creation failed");
631a1b6b0a9SMario Six 		goto err_key;
632a1b6b0a9SMario Six 	}
633a1b6b0a9SMario Six 	EVP_MD_CTX_init(ctx);
634a1b6b0a9SMario Six 	if (!EVP_SignInit(ctx, EVP_sha256())) {
635a1b6b0a9SMario Six 		ret = openssl_err("Signer setup failed");
636a1b6b0a9SMario Six 		goto err_ctx;
637a1b6b0a9SMario Six 	}
638a1b6b0a9SMario Six 
639a1b6b0a9SMario Six 	if (!EVP_SignUpdate(ctx, data, datasz)) {
640a1b6b0a9SMario Six 		ret = openssl_err("Signing data failed");
641a1b6b0a9SMario Six 		goto err_ctx;
642a1b6b0a9SMario Six 	}
643a1b6b0a9SMario Six 
644a1b6b0a9SMario Six 	if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
645a1b6b0a9SMario Six 		ret = openssl_err("Could not obtain signature");
646a1b6b0a9SMario Six 		goto err_ctx;
647a1b6b0a9SMario Six 	}
648a1b6b0a9SMario Six 
649a1b6b0a9SMario Six 	EVP_MD_CTX_cleanup(ctx);
650a1b6b0a9SMario Six 	EVP_MD_CTX_destroy(ctx);
651a1b6b0a9SMario Six 	EVP_PKEY_free(evp_key);
652a1b6b0a9SMario Six 
653a1b6b0a9SMario Six 	return 0;
654a1b6b0a9SMario Six 
655a1b6b0a9SMario Six err_ctx:
656a1b6b0a9SMario Six 	EVP_MD_CTX_destroy(ctx);
657a1b6b0a9SMario Six err_key:
658a1b6b0a9SMario Six 	EVP_PKEY_free(evp_key);
659a1b6b0a9SMario Six 	fprintf(stderr, "Failed to create %s signature\n", signame);
660a1b6b0a9SMario Six 	return ret;
661a1b6b0a9SMario Six }
662a1b6b0a9SMario Six 
kwb_verify(RSA * key,void * data,int datasz,struct sig_v1 * sig,char * signame)663a1b6b0a9SMario Six int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
664a1b6b0a9SMario Six 	       char *signame)
665a1b6b0a9SMario Six {
666a1b6b0a9SMario Six 	EVP_PKEY *evp_key;
667a1b6b0a9SMario Six 	EVP_MD_CTX *ctx;
668a1b6b0a9SMario Six 	int size;
669a1b6b0a9SMario Six 	int ret = 0;
670a1b6b0a9SMario Six 
671a1b6b0a9SMario Six 	evp_key = EVP_PKEY_new();
672a1b6b0a9SMario Six 	if (!evp_key)
673a1b6b0a9SMario Six 		return openssl_err("EVP_PKEY object creation failed");
674a1b6b0a9SMario Six 
675a1b6b0a9SMario Six 	if (!EVP_PKEY_set1_RSA(evp_key, key)) {
676a1b6b0a9SMario Six 		ret = openssl_err("EVP key setup failed");
677a1b6b0a9SMario Six 		goto err_key;
678a1b6b0a9SMario Six 	}
679a1b6b0a9SMario Six 
680a1b6b0a9SMario Six 	size = EVP_PKEY_size(evp_key);
681a1b6b0a9SMario Six 	if (size > sizeof(sig->sig)) {
682a1b6b0a9SMario Six 		fprintf(stderr, "Invalid signature size (%d bytes)\n",
683a1b6b0a9SMario Six 			size);
684a1b6b0a9SMario Six 		ret = -EINVAL;
685a1b6b0a9SMario Six 		goto err_key;
686a1b6b0a9SMario Six 	}
687a1b6b0a9SMario Six 
688a1b6b0a9SMario Six 	ctx = EVP_MD_CTX_create();
689a1b6b0a9SMario Six 	if (!ctx) {
690a1b6b0a9SMario Six 		ret = openssl_err("EVP context creation failed");
691a1b6b0a9SMario Six 		goto err_key;
692a1b6b0a9SMario Six 	}
693a1b6b0a9SMario Six 	EVP_MD_CTX_init(ctx);
694a1b6b0a9SMario Six 	if (!EVP_VerifyInit(ctx, EVP_sha256())) {
695a1b6b0a9SMario Six 		ret = openssl_err("Verifier setup failed");
696a1b6b0a9SMario Six 		goto err_ctx;
697a1b6b0a9SMario Six 	}
698a1b6b0a9SMario Six 
699a1b6b0a9SMario Six 	if (!EVP_VerifyUpdate(ctx, data, datasz)) {
700a1b6b0a9SMario Six 		ret = openssl_err("Hashing data failed");
701a1b6b0a9SMario Six 		goto err_ctx;
702a1b6b0a9SMario Six 	}
703a1b6b0a9SMario Six 
704a1b6b0a9SMario Six 	if (!EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key)) {
705a1b6b0a9SMario Six 		ret = openssl_err("Could not verify signature");
706a1b6b0a9SMario Six 		goto err_ctx;
707a1b6b0a9SMario Six 	}
708a1b6b0a9SMario Six 
709a1b6b0a9SMario Six 	EVP_MD_CTX_cleanup(ctx);
710a1b6b0a9SMario Six 	EVP_MD_CTX_destroy(ctx);
711a1b6b0a9SMario Six 	EVP_PKEY_free(evp_key);
712a1b6b0a9SMario Six 
713a1b6b0a9SMario Six 	return 0;
714a1b6b0a9SMario Six 
715a1b6b0a9SMario Six err_ctx:
716a1b6b0a9SMario Six 	EVP_MD_CTX_destroy(ctx);
717a1b6b0a9SMario Six err_key:
718a1b6b0a9SMario Six 	EVP_PKEY_free(evp_key);
719a1b6b0a9SMario Six 	fprintf(stderr, "Failed to verify %s signature\n", signame);
720a1b6b0a9SMario Six 	return ret;
721a1b6b0a9SMario Six }
722a1b6b0a9SMario Six 
kwb_sign_and_verify(RSA * key,void * data,int datasz,struct sig_v1 * sig,char * signame)723a1b6b0a9SMario Six int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
724a1b6b0a9SMario Six 			char *signame)
725a1b6b0a9SMario Six {
726a1b6b0a9SMario Six 	if (kwb_sign(key, data, datasz, sig, signame) < 0)
727a1b6b0a9SMario Six 		return -1;
728a1b6b0a9SMario Six 
729a1b6b0a9SMario Six 	if (kwb_verify(key, data, datasz, sig, signame) < 0)
730a1b6b0a9SMario Six 		return -1;
731a1b6b0a9SMario Six 
732a1b6b0a9SMario Six 	return 0;
733a1b6b0a9SMario Six }
734a1b6b0a9SMario Six 
735a1b6b0a9SMario Six 
kwb_dump_fuse_cmds_38x(FILE * out,struct secure_hdr_v1 * sec_hdr)736a1b6b0a9SMario Six int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
737a1b6b0a9SMario Six {
738a1b6b0a9SMario Six 	struct hash_v1 kak_pub_hash;
739a1b6b0a9SMario Six 	struct image_cfg_element *e;
740a1b6b0a9SMario Six 	unsigned int fuse_line;
741a1b6b0a9SMario Six 	int i, idx;
742a1b6b0a9SMario Six 	uint8_t *ptr;
743a1b6b0a9SMario Six 	uint32_t val;
744a1b6b0a9SMario Six 	int ret = 0;
745a1b6b0a9SMario Six 
746a1b6b0a9SMario Six 	if (!out || !sec_hdr)
747a1b6b0a9SMario Six 		return -EINVAL;
748a1b6b0a9SMario Six 
749a1b6b0a9SMario Six 	ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
750a1b6b0a9SMario Six 	if (ret < 0)
751a1b6b0a9SMario Six 		goto done;
752a1b6b0a9SMario Six 
753a1b6b0a9SMario Six 	fprintf(out, "# burn KAK pub key hash\n");
754a1b6b0a9SMario Six 	ptr = kak_pub_hash.hash;
755a1b6b0a9SMario Six 	for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
756a1b6b0a9SMario Six 		fprintf(out, "fuse prog -y %u 0 ", fuse_line);
757a1b6b0a9SMario Six 
758a1b6b0a9SMario Six 		for (i = 4; i-- > 0;)
759a1b6b0a9SMario Six 			fprintf(out, "%02hx", (ushort)ptr[i]);
760a1b6b0a9SMario Six 		ptr += 4;
761a1b6b0a9SMario Six 		fprintf(out, " 00");
762a1b6b0a9SMario Six 
763a1b6b0a9SMario Six 		if (fuse_line < 30) {
764a1b6b0a9SMario Six 			for (i = 3; i-- > 0;)
765a1b6b0a9SMario Six 				fprintf(out, "%02hx", (ushort)ptr[i]);
766a1b6b0a9SMario Six 			ptr += 3;
767a1b6b0a9SMario Six 		} else {
768a1b6b0a9SMario Six 			fprintf(out, "000000");
769a1b6b0a9SMario Six 		}
770a1b6b0a9SMario Six 
771a1b6b0a9SMario Six 		fprintf(out, " 1\n");
772a1b6b0a9SMario Six 	}
773a1b6b0a9SMario Six 
774a1b6b0a9SMario Six 	fprintf(out, "# burn CSK selection\n");
775a1b6b0a9SMario Six 
776a1b6b0a9SMario Six 	idx = image_get_csk_index();
777a1b6b0a9SMario Six 	if (idx < 0 || idx > 15) {
778a1b6b0a9SMario Six 		ret = -EINVAL;
779a1b6b0a9SMario Six 		goto done;
780a1b6b0a9SMario Six 	}
781a1b6b0a9SMario Six 	if (idx > 0) {
782a1b6b0a9SMario Six 		for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
783a1b6b0a9SMario Six 			fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
784a1b6b0a9SMario Six 				fuse_line);
785a1b6b0a9SMario Six 	} else {
786a1b6b0a9SMario Six 		fprintf(out, "# CSK index is 0; no mods needed\n");
787a1b6b0a9SMario Six 	}
788a1b6b0a9SMario Six 
789a1b6b0a9SMario Six 	e = image_find_option(IMAGE_CFG_BOX_ID);
790a1b6b0a9SMario Six 	if (e) {
791a1b6b0a9SMario Six 		fprintf(out, "# set box ID\n");
792a1b6b0a9SMario Six 		fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
793a1b6b0a9SMario Six 	}
794a1b6b0a9SMario Six 
795a1b6b0a9SMario Six 	e = image_find_option(IMAGE_CFG_FLASH_ID);
796a1b6b0a9SMario Six 	if (e) {
797a1b6b0a9SMario Six 		fprintf(out, "# set flash ID\n");
798a1b6b0a9SMario Six 		fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
799a1b6b0a9SMario Six 	}
800a1b6b0a9SMario Six 
801a1b6b0a9SMario Six 	fprintf(out, "# enable secure mode ");
802a1b6b0a9SMario Six 	fprintf(out, "(must be the last fuse line written)\n");
803a1b6b0a9SMario Six 
804a1b6b0a9SMario Six 	val = 1;
805a1b6b0a9SMario Six 	e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
806a1b6b0a9SMario Six 	if (!e) {
807a1b6b0a9SMario Six 		fprintf(stderr, "ERROR: secured mode boot device not given\n");
808a1b6b0a9SMario Six 		ret = -EINVAL;
809a1b6b0a9SMario Six 		goto done;
810a1b6b0a9SMario Six 	}
811a1b6b0a9SMario Six 
812a1b6b0a9SMario Six 	if (e->sec_boot_dev > 0xff) {
813a1b6b0a9SMario Six 		fprintf(stderr, "ERROR: secured mode boot device invalid\n");
814a1b6b0a9SMario Six 		ret = -EINVAL;
815a1b6b0a9SMario Six 		goto done;
816a1b6b0a9SMario Six 	}
817a1b6b0a9SMario Six 
818a1b6b0a9SMario Six 	val |= (e->sec_boot_dev << 8);
819a1b6b0a9SMario Six 
820a1b6b0a9SMario Six 	fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
821a1b6b0a9SMario Six 
822a1b6b0a9SMario Six 	fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
823a1b6b0a9SMario Six 	for (fuse_line = 0; fuse_line < 24; ++fuse_line)
824a1b6b0a9SMario Six 		fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
825a1b6b0a9SMario Six 
826a1b6b0a9SMario Six 	fprintf(out, "# OK, that's all :-)\n");
827a1b6b0a9SMario Six 
828a1b6b0a9SMario Six done:
829a1b6b0a9SMario Six 	return ret;
830a1b6b0a9SMario Six }
831a1b6b0a9SMario Six 
kwb_dump_fuse_cmds(struct secure_hdr_v1 * sec_hdr)832a1b6b0a9SMario Six static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
833a1b6b0a9SMario Six {
834a1b6b0a9SMario Six 	int ret = 0;
835a1b6b0a9SMario Six 	struct image_cfg_element *e;
836a1b6b0a9SMario Six 
837a1b6b0a9SMario Six 	e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
838a1b6b0a9SMario Six 	if (!e)
839a1b6b0a9SMario Six 		return 0;
840a1b6b0a9SMario Six 
841a1b6b0a9SMario Six 	if (!strcmp(e->name, "a38x")) {
842a1b6b0a9SMario Six 		FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
843a1b6b0a9SMario Six 
844a1b6b0a9SMario Six 		kwb_dump_fuse_cmds_38x(out, sec_hdr);
845a1b6b0a9SMario Six 		fclose(out);
846a1b6b0a9SMario Six 		goto done;
847a1b6b0a9SMario Six 	}
848a1b6b0a9SMario Six 
849a1b6b0a9SMario Six 	ret = -ENOSYS;
850a1b6b0a9SMario Six 
851a1b6b0a9SMario Six done:
852a1b6b0a9SMario Six 	return ret;
853a1b6b0a9SMario Six }
854a1b6b0a9SMario Six 
855a1b6b0a9SMario Six #endif
856a1b6b0a9SMario Six 
image_create_v0(size_t * imagesz,struct image_tool_params * params,int payloadsz)8574acd2d24SStefan Roese static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
8584acd2d24SStefan Roese 			     int payloadsz)
859aa0c7a86SPrafulla Wadaskar {
8604acd2d24SStefan Roese 	struct image_cfg_element *e;
8614acd2d24SStefan Roese 	size_t headersz;
8624acd2d24SStefan Roese 	struct main_hdr_v0 *main_hdr;
863885fba15SMario Six 	uint8_t *image;
8644acd2d24SStefan Roese 	int has_ext = 0;
865aa0c7a86SPrafulla Wadaskar 
866aa0c7a86SPrafulla Wadaskar 	/*
8674acd2d24SStefan Roese 	 * Calculate the size of the header and the size of the
8684acd2d24SStefan Roese 	 * payload
869aa0c7a86SPrafulla Wadaskar 	 */
8704acd2d24SStefan Roese 	headersz  = sizeof(struct main_hdr_v0);
871aa0c7a86SPrafulla Wadaskar 
8724acd2d24SStefan Roese 	if (image_count_options(IMAGE_CFG_DATA) > 0) {
8734acd2d24SStefan Roese 		has_ext = 1;
8744acd2d24SStefan Roese 		headersz += sizeof(struct ext_hdr_v0);
875aa0c7a86SPrafulla Wadaskar 	}
876aa0c7a86SPrafulla Wadaskar 
8774acd2d24SStefan Roese 	if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
8784acd2d24SStefan Roese 		fprintf(stderr, "More than one payload, not possible\n");
8794acd2d24SStefan Roese 		return NULL;
8804acd2d24SStefan Roese 	}
8814acd2d24SStefan Roese 
8824acd2d24SStefan Roese 	image = malloc(headersz);
8834acd2d24SStefan Roese 	if (!image) {
8844acd2d24SStefan Roese 		fprintf(stderr, "Cannot allocate memory for image\n");
8854acd2d24SStefan Roese 		return NULL;
8864acd2d24SStefan Roese 	}
8874acd2d24SStefan Roese 
8884acd2d24SStefan Roese 	memset(image, 0, headersz);
8894acd2d24SStefan Roese 
890885fba15SMario Six 	main_hdr = (struct main_hdr_v0 *)image;
8914acd2d24SStefan Roese 
8924acd2d24SStefan Roese 	/* Fill in the main header */
893a8840dceSReinhard Pfau 	main_hdr->blocksize =
894a8840dceSReinhard Pfau 		cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz);
895a8840dceSReinhard Pfau 	main_hdr->srcaddr   = cpu_to_le32(headersz);
8964acd2d24SStefan Roese 	main_hdr->ext       = has_ext;
897a8840dceSReinhard Pfau 	main_hdr->destaddr  = cpu_to_le32(params->addr);
898a8840dceSReinhard Pfau 	main_hdr->execaddr  = cpu_to_le32(params->ep);
8994acd2d24SStefan Roese 
9004acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_BOOT_FROM);
9014acd2d24SStefan Roese 	if (e)
9024acd2d24SStefan Roese 		main_hdr->blockid = e->bootfrom;
9034acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
9044acd2d24SStefan Roese 	if (e)
9054acd2d24SStefan Roese 		main_hdr->nandeccmode = e->nandeccmode;
9064acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
9074acd2d24SStefan Roese 	if (e)
908a8840dceSReinhard Pfau 		main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
9094acd2d24SStefan Roese 	main_hdr->checksum = image_checksum8(image,
9104acd2d24SStefan Roese 					     sizeof(struct main_hdr_v0));
9114acd2d24SStefan Roese 
9124acd2d24SStefan Roese 	/* Generate the ext header */
9134acd2d24SStefan Roese 	if (has_ext) {
914e89016c4SMario Six 		struct ext_hdr_v0 *ext_hdr;
9154acd2d24SStefan Roese 		int cfgi, datai;
9164acd2d24SStefan Roese 
917885fba15SMario Six 		ext_hdr = (struct ext_hdr_v0 *)
918885fba15SMario Six 				(image + sizeof(struct main_hdr_v0));
919a8840dceSReinhard Pfau 		ext_hdr->offset = cpu_to_le32(0x40);
9204acd2d24SStefan Roese 
9214acd2d24SStefan Roese 		for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
9224acd2d24SStefan Roese 			e = &image_cfg[cfgi];
9234acd2d24SStefan Roese 			if (e->type != IMAGE_CFG_DATA)
924aa0c7a86SPrafulla Wadaskar 				continue;
925aa0c7a86SPrafulla Wadaskar 
926a8840dceSReinhard Pfau 			ext_hdr->rcfg[datai].raddr =
927a8840dceSReinhard Pfau 				cpu_to_le32(e->regdata.raddr);
928a8840dceSReinhard Pfau 			ext_hdr->rcfg[datai].rdata =
929a8840dceSReinhard Pfau 				cpu_to_le32(e->regdata.rdata);
9304acd2d24SStefan Roese 			datai++;
931aa0c7a86SPrafulla Wadaskar 		}
932aa0c7a86SPrafulla Wadaskar 
9334acd2d24SStefan Roese 		ext_hdr->checksum = image_checksum8(ext_hdr,
9344acd2d24SStefan Roese 						    sizeof(struct ext_hdr_v0));
9354acd2d24SStefan Roese 	}
9364acd2d24SStefan Roese 
9374acd2d24SStefan Roese 	*imagesz = headersz;
9384acd2d24SStefan Roese 	return image;
9394acd2d24SStefan Roese }
9404acd2d24SStefan Roese 
image_headersz_v1(int * hasext)941e93cf53fSMario Six static size_t image_headersz_v1(int *hasext)
9424acd2d24SStefan Roese {
9434acd2d24SStefan Roese 	struct image_cfg_element *binarye;
9444acd2d24SStefan Roese 	size_t headersz;
945aa0c7a86SPrafulla Wadaskar 
946aa0c7a86SPrafulla Wadaskar 	/*
9474acd2d24SStefan Roese 	 * Calculate the size of the header and the size of the
9484acd2d24SStefan Roese 	 * payload
949aa0c7a86SPrafulla Wadaskar 	 */
9504acd2d24SStefan Roese 	headersz = sizeof(struct main_hdr_v1);
9514acd2d24SStefan Roese 
9524acd2d24SStefan Roese 	if (image_count_options(IMAGE_CFG_BINARY) > 1) {
9534acd2d24SStefan Roese 		fprintf(stderr, "More than one binary blob, not supported\n");
9544acd2d24SStefan Roese 		return 0;
9554acd2d24SStefan Roese 	}
9564acd2d24SStefan Roese 
9574acd2d24SStefan Roese 	if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
9584acd2d24SStefan Roese 		fprintf(stderr, "More than one payload, not possible\n");
9594acd2d24SStefan Roese 		return 0;
9604acd2d24SStefan Roese 	}
9614acd2d24SStefan Roese 
9624acd2d24SStefan Roese 	binarye = image_find_option(IMAGE_CFG_BINARY);
9634acd2d24SStefan Roese 	if (binarye) {
964e89016c4SMario Six 		int ret;
9654acd2d24SStefan Roese 		struct stat s;
9664acd2d24SStefan Roese 
9674acd2d24SStefan Roese 		ret = stat(binarye->binary.file, &s);
9684acd2d24SStefan Roese 		if (ret < 0) {
969e5f1a586SAndreas Bießmann 			char cwd[PATH_MAX];
970e5f1a586SAndreas Bießmann 			char *dir = cwd;
971e5f1a586SAndreas Bießmann 
972e5f1a586SAndreas Bießmann 			memset(cwd, 0, sizeof(cwd));
973e5f1a586SAndreas Bießmann 			if (!getcwd(cwd, sizeof(cwd))) {
974e5f1a586SAndreas Bießmann 				dir = "current working directory";
975e5f1a586SAndreas Bießmann 				perror("getcwd() failed");
976e5f1a586SAndreas Bießmann 			}
977e5f1a586SAndreas Bießmann 
9784acd2d24SStefan Roese 			fprintf(stderr,
9794acd2d24SStefan Roese 				"Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
9804acd2d24SStefan Roese 				"This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
9814acd2d24SStefan Roese 				"image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
982e5f1a586SAndreas Bießmann 				binarye->binary.file, dir);
9834acd2d24SStefan Roese 			return 0;
9844acd2d24SStefan Roese 		}
9854acd2d24SStefan Roese 
98676b391cdSReinhard Pfau 		headersz += sizeof(struct opt_hdr_v1) +
98776b391cdSReinhard Pfau 			s.st_size +
98876b391cdSReinhard Pfau 			(binarye->binary.nargs + 2) * sizeof(uint32_t);
9894acd2d24SStefan Roese 		if (hasext)
9904acd2d24SStefan Roese 			*hasext = 1;
9914acd2d24SStefan Roese 	}
9924acd2d24SStefan Roese 
993a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
994a1b6b0a9SMario Six 	if (image_get_csk_index() >= 0) {
995a1b6b0a9SMario Six 		headersz += sizeof(struct secure_hdr_v1);
996a1b6b0a9SMario Six 		if (hasext)
997a1b6b0a9SMario Six 			*hasext = 1;
998a1b6b0a9SMario Six 	}
999a1b6b0a9SMario Six #endif
1000a1b6b0a9SMario Six 
10017ddf8cfbSStefan Roese #if defined(CONFIG_SYS_U_BOOT_OFFS)
10027ddf8cfbSStefan Roese 	if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
100394490a4aSMario Six 		fprintf(stderr,
100494490a4aSMario Six 			"Error: Image header (incl. SPL image) too big!\n");
10057ddf8cfbSStefan Roese 		fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
10067ddf8cfbSStefan Roese 			(int)headersz, CONFIG_SYS_U_BOOT_OFFS);
10077ddf8cfbSStefan Roese 		fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
1008a0aad123SKevin Smith 		return 0;
1009a0aad123SKevin Smith 	}
101079066ef8SMario Six 
101194490a4aSMario Six 	headersz = CONFIG_SYS_U_BOOT_OFFS;
1012a0aad123SKevin Smith #endif
1013a0aad123SKevin Smith 
10144acd2d24SStefan Roese 	/*
10154acd2d24SStefan Roese 	 * The payload should be aligned on some reasonable
10164acd2d24SStefan Roese 	 * boundary
10174acd2d24SStefan Roese 	 */
10184acd2d24SStefan Roese 	return ALIGN_SUP(headersz, 4096);
10194acd2d24SStefan Roese }
10204acd2d24SStefan Roese 
add_binary_header_v1(uint8_t * cur)102179066ef8SMario Six int add_binary_header_v1(uint8_t *cur)
102279066ef8SMario Six {
102379066ef8SMario Six 	struct image_cfg_element *binarye;
102479066ef8SMario Six 	struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
102579066ef8SMario Six 	uint32_t *args;
102679066ef8SMario Six 	size_t binhdrsz;
102779066ef8SMario Six 	struct stat s;
102879066ef8SMario Six 	int argi;
102979066ef8SMario Six 	FILE *bin;
103079066ef8SMario Six 	int ret;
103179066ef8SMario Six 
103279066ef8SMario Six 	binarye = image_find_option(IMAGE_CFG_BINARY);
103379066ef8SMario Six 
103479066ef8SMario Six 	if (!binarye)
103579066ef8SMario Six 		return 0;
103679066ef8SMario Six 
103779066ef8SMario Six 	hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
103879066ef8SMario Six 
103979066ef8SMario Six 	bin = fopen(binarye->binary.file, "r");
104079066ef8SMario Six 	if (!bin) {
104179066ef8SMario Six 		fprintf(stderr, "Cannot open binary file %s\n",
104279066ef8SMario Six 			binarye->binary.file);
104379066ef8SMario Six 		return -1;
104479066ef8SMario Six 	}
104579066ef8SMario Six 
10461f6c8a57SMario Six 	if (fstat(fileno(bin), &s)) {
10471f6c8a57SMario Six 		fprintf(stderr, "Cannot stat binary file %s\n",
10481f6c8a57SMario Six 			binarye->binary.file);
10491f6c8a57SMario Six 		goto err_close;
10501f6c8a57SMario Six 	}
105179066ef8SMario Six 
105279066ef8SMario Six 	binhdrsz = sizeof(struct opt_hdr_v1) +
105379066ef8SMario Six 		(binarye->binary.nargs + 2) * sizeof(uint32_t) +
105479066ef8SMario Six 		s.st_size;
105579066ef8SMario Six 
105679066ef8SMario Six 	/*
105779066ef8SMario Six 	 * The size includes the binary image size, rounded
105879066ef8SMario Six 	 * up to a 4-byte boundary. Plus 4 bytes for the
105979066ef8SMario Six 	 * next-header byte and 3-byte alignment at the end.
106079066ef8SMario Six 	 */
106179066ef8SMario Six 	binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
106279066ef8SMario Six 	hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
106379066ef8SMario Six 	hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
106479066ef8SMario Six 
106579066ef8SMario Six 	cur += sizeof(struct opt_hdr_v1);
106679066ef8SMario Six 
106779066ef8SMario Six 	args = (uint32_t *)cur;
106879066ef8SMario Six 	*args = cpu_to_le32(binarye->binary.nargs);
106979066ef8SMario Six 	args++;
107079066ef8SMario Six 	for (argi = 0; argi < binarye->binary.nargs; argi++)
107179066ef8SMario Six 		args[argi] = cpu_to_le32(binarye->binary.args[argi]);
107279066ef8SMario Six 
107379066ef8SMario Six 	cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
107479066ef8SMario Six 
107579066ef8SMario Six 	ret = fread(cur, s.st_size, 1, bin);
107679066ef8SMario Six 	if (ret != 1) {
107779066ef8SMario Six 		fprintf(stderr,
107879066ef8SMario Six 			"Could not read binary image %s\n",
107979066ef8SMario Six 			binarye->binary.file);
10801f6c8a57SMario Six 		goto err_close;
108179066ef8SMario Six 	}
108279066ef8SMario Six 
108379066ef8SMario Six 	fclose(bin);
108479066ef8SMario Six 
108579066ef8SMario Six 	cur += ALIGN_SUP(s.st_size, 4);
108679066ef8SMario Six 
108779066ef8SMario Six 	/*
108879066ef8SMario Six 	 * For now, we don't support more than one binary
108979066ef8SMario Six 	 * header, and no other header types are
109079066ef8SMario Six 	 * supported. So, the binary header is necessarily the
109179066ef8SMario Six 	 * last one
109279066ef8SMario Six 	 */
109379066ef8SMario Six 	*((uint32_t *)cur) = 0x00000000;
109479066ef8SMario Six 
109579066ef8SMario Six 	cur += sizeof(uint32_t);
109679066ef8SMario Six 
109779066ef8SMario Six 	return 0;
10981f6c8a57SMario Six 
10991f6c8a57SMario Six err_close:
11001f6c8a57SMario Six 	fclose(bin);
11011f6c8a57SMario Six 
11021f6c8a57SMario Six 	return -1;
110379066ef8SMario Six }
110479066ef8SMario Six 
1105a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
1106a1b6b0a9SMario Six 
export_pub_kak_hash(RSA * kak,struct secure_hdr_v1 * secure_hdr)1107a1b6b0a9SMario Six int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
1108a1b6b0a9SMario Six {
1109a1b6b0a9SMario Six 	FILE *hashf;
1110a1b6b0a9SMario Six 	int res;
1111a1b6b0a9SMario Six 
1112a1b6b0a9SMario Six 	hashf = fopen("pub_kak_hash.txt", "w");
1113a1b6b0a9SMario Six 
1114a1b6b0a9SMario Six 	res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1115a1b6b0a9SMario Six 
1116a1b6b0a9SMario Six 	fclose(hashf);
1117a1b6b0a9SMario Six 
1118a1b6b0a9SMario Six 	return res < 0 ? 1 : 0;
1119a1b6b0a9SMario Six }
1120a1b6b0a9SMario Six 
kwb_sign_csk_with_kak(struct image_tool_params * params,struct secure_hdr_v1 * secure_hdr,RSA * csk)1121a1b6b0a9SMario Six int kwb_sign_csk_with_kak(struct image_tool_params *params,
1122a1b6b0a9SMario Six 			  struct secure_hdr_v1 *secure_hdr, RSA *csk)
1123a1b6b0a9SMario Six {
1124a1b6b0a9SMario Six 	RSA *kak = NULL;
1125a1b6b0a9SMario Six 	RSA *kak_pub = NULL;
1126a1b6b0a9SMario Six 	int csk_idx = image_get_csk_index();
1127a1b6b0a9SMario Six 	struct sig_v1 tmp_sig;
1128a1b6b0a9SMario Six 
1129a1b6b0a9SMario Six 	if (csk_idx >= 16) {
1130a1b6b0a9SMario Six 		fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1131a1b6b0a9SMario Six 		return 1;
1132a1b6b0a9SMario Six 	}
1133a1b6b0a9SMario Six 
1134a1b6b0a9SMario Six 	if (kwb_load_kak(params, &kak) < 0)
1135a1b6b0a9SMario Six 		return 1;
1136a1b6b0a9SMario Six 
1137a1b6b0a9SMario Six 	if (export_pub_kak_hash(kak, secure_hdr))
1138a1b6b0a9SMario Six 		return 1;
1139a1b6b0a9SMario Six 
1140a1b6b0a9SMario Six 	if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1141a1b6b0a9SMario Six 		return 1;
1142a1b6b0a9SMario Six 
1143a1b6b0a9SMario Six 	if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1144a1b6b0a9SMario Six 		return 1;
1145a1b6b0a9SMario Six 
1146a1b6b0a9SMario Six 	if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1147a1b6b0a9SMario Six 				sizeof(secure_hdr->csk) +
1148a1b6b0a9SMario Six 				sizeof(secure_hdr->csksig),
1149a1b6b0a9SMario Six 				&tmp_sig, "CSK") < 0)
1150a1b6b0a9SMario Six 		return 1;
1151a1b6b0a9SMario Six 
1152a1b6b0a9SMario Six 	if (kwb_verify(kak_pub, &secure_hdr->csk,
1153a1b6b0a9SMario Six 		       sizeof(secure_hdr->csk) +
1154a1b6b0a9SMario Six 		       sizeof(secure_hdr->csksig),
1155a1b6b0a9SMario Six 		       &tmp_sig, "CSK (2)") < 0)
1156a1b6b0a9SMario Six 		return 1;
1157a1b6b0a9SMario Six 
1158a1b6b0a9SMario Six 	secure_hdr->csksig = tmp_sig;
1159a1b6b0a9SMario Six 
1160a1b6b0a9SMario Six 	return 0;
1161a1b6b0a9SMario Six }
1162a1b6b0a9SMario Six 
add_secure_header_v1(struct image_tool_params * params,uint8_t * ptr,int payloadsz,size_t headersz,uint8_t * image,struct secure_hdr_v1 * secure_hdr)1163a1b6b0a9SMario Six int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1164a1b6b0a9SMario Six 			 int payloadsz, size_t headersz, uint8_t *image,
1165a1b6b0a9SMario Six 			 struct secure_hdr_v1 *secure_hdr)
1166a1b6b0a9SMario Six {
1167a1b6b0a9SMario Six 	struct image_cfg_element *e_jtagdelay;
1168a1b6b0a9SMario Six 	struct image_cfg_element *e_boxid;
1169a1b6b0a9SMario Six 	struct image_cfg_element *e_flashid;
1170a1b6b0a9SMario Six 	RSA *csk = NULL;
1171a1b6b0a9SMario Six 	unsigned char *image_ptr;
1172a1b6b0a9SMario Six 	size_t image_size;
1173a1b6b0a9SMario Six 	struct sig_v1 tmp_sig;
1174a1b6b0a9SMario Six 	bool specialized_img = image_get_spezialized_img();
1175a1b6b0a9SMario Six 
1176a1b6b0a9SMario Six 	kwb_msg("Create secure header content\n");
1177a1b6b0a9SMario Six 
1178a1b6b0a9SMario Six 	e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1179a1b6b0a9SMario Six 	e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1180a1b6b0a9SMario Six 	e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1181a1b6b0a9SMario Six 
1182a1b6b0a9SMario Six 	if (kwb_load_csk(params, &csk) < 0)
1183a1b6b0a9SMario Six 		return 1;
1184a1b6b0a9SMario Six 
1185a1b6b0a9SMario Six 	secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1186a1b6b0a9SMario Six 	secure_hdr->headersz_msb = 0;
1187a1b6b0a9SMario Six 	secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1188a1b6b0a9SMario Six 	if (e_jtagdelay)
1189a1b6b0a9SMario Six 		secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1190a1b6b0a9SMario Six 	if (e_boxid && specialized_img)
1191a1b6b0a9SMario Six 		secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1192a1b6b0a9SMario Six 	if (e_flashid && specialized_img)
1193a1b6b0a9SMario Six 		secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1194a1b6b0a9SMario Six 
1195a1b6b0a9SMario Six 	if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1196a1b6b0a9SMario Six 		return 1;
1197a1b6b0a9SMario Six 
1198a1b6b0a9SMario Six 	image_ptr = ptr + headersz;
1199a1b6b0a9SMario Six 	image_size = payloadsz - headersz;
1200a1b6b0a9SMario Six 
1201a1b6b0a9SMario Six 	if (kwb_sign_and_verify(csk, image_ptr, image_size,
1202a1b6b0a9SMario Six 				&secure_hdr->imgsig, "image") < 0)
1203a1b6b0a9SMario Six 		return 1;
1204a1b6b0a9SMario Six 
1205a1b6b0a9SMario Six 	if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1206a1b6b0a9SMario Six 		return 1;
1207a1b6b0a9SMario Six 
1208a1b6b0a9SMario Six 	secure_hdr->hdrsig = tmp_sig;
1209a1b6b0a9SMario Six 
1210a1b6b0a9SMario Six 	kwb_dump_fuse_cmds(secure_hdr);
1211a1b6b0a9SMario Six 
1212a1b6b0a9SMario Six 	return 0;
1213a1b6b0a9SMario Six }
1214a1b6b0a9SMario Six #endif
1215a1b6b0a9SMario Six 
image_create_v1(size_t * imagesz,struct image_tool_params * params,uint8_t * ptr,int payloadsz)12164acd2d24SStefan Roese static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
1217a1b6b0a9SMario Six 			     uint8_t *ptr, int payloadsz)
12184acd2d24SStefan Roese {
121979066ef8SMario Six 	struct image_cfg_element *e;
12204acd2d24SStefan Roese 	struct main_hdr_v1 *main_hdr;
1221a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
1222a1b6b0a9SMario Six 	struct secure_hdr_v1 *secure_hdr = NULL;
1223a1b6b0a9SMario Six #endif
12244acd2d24SStefan Roese 	size_t headersz;
1225885fba15SMario Six 	uint8_t *image, *cur;
12264acd2d24SStefan Roese 	int hasext = 0;
1227a1b6b0a9SMario Six 	uint8_t *next_ext = NULL;
12284acd2d24SStefan Roese 
12294acd2d24SStefan Roese 	/*
12304acd2d24SStefan Roese 	 * Calculate the size of the header and the size of the
12314acd2d24SStefan Roese 	 * payload
12324acd2d24SStefan Roese 	 */
1233e93cf53fSMario Six 	headersz = image_headersz_v1(&hasext);
12344acd2d24SStefan Roese 	if (headersz == 0)
12354acd2d24SStefan Roese 		return NULL;
12364acd2d24SStefan Roese 
12374acd2d24SStefan Roese 	image = malloc(headersz);
12384acd2d24SStefan Roese 	if (!image) {
12394acd2d24SStefan Roese 		fprintf(stderr, "Cannot allocate memory for image\n");
12404acd2d24SStefan Roese 		return NULL;
12414acd2d24SStefan Roese 	}
12424acd2d24SStefan Roese 
12434acd2d24SStefan Roese 	memset(image, 0, headersz);
12444acd2d24SStefan Roese 
1245885fba15SMario Six 	main_hdr = (struct main_hdr_v1 *)image;
1246a1b6b0a9SMario Six 	cur = image;
1247a1b6b0a9SMario Six 	cur += sizeof(struct main_hdr_v1);
1248a1b6b0a9SMario Six 	next_ext = &main_hdr->ext;
12494acd2d24SStefan Roese 
12504acd2d24SStefan Roese 	/* Fill the main header */
1251a8840dceSReinhard Pfau 	main_hdr->blocksize    =
1252a8840dceSReinhard Pfau 		cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
1253a8840dceSReinhard Pfau 	main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
12544acd2d24SStefan Roese 	main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
125594084eeaSMario Six 	main_hdr->destaddr     = cpu_to_le32(params->addr)
125694084eeaSMario Six 				 - sizeof(image_header_t);
1257a8840dceSReinhard Pfau 	main_hdr->execaddr     = cpu_to_le32(params->ep);
1258a8840dceSReinhard Pfau 	main_hdr->srcaddr      = cpu_to_le32(headersz);
12594acd2d24SStefan Roese 	main_hdr->ext          = hasext;
12604acd2d24SStefan Roese 	main_hdr->version      = 1;
12614acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_BOOT_FROM);
12624acd2d24SStefan Roese 	if (e)
12634acd2d24SStefan Roese 		main_hdr->blockid = e->bootfrom;
12644acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
12654acd2d24SStefan Roese 	if (e)
12664acd2d24SStefan Roese 		main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
12674acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
12684acd2d24SStefan Roese 	if (e)
12694acd2d24SStefan Roese 		main_hdr->nandbadblklocation = e->nandbadblklocation;
12704bdb5479SChris Packham 	e = image_find_option(IMAGE_CFG_BAUDRATE);
12714bdb5479SChris Packham 	if (e)
12724bdb5479SChris Packham 		main_hdr->options = baudrate_to_option(e->baudrate);
12732611c05eSChris Packham 	e = image_find_option(IMAGE_CFG_DEBUG);
12742611c05eSChris Packham 	if (e)
12752611c05eSChris Packham 		main_hdr->flags = e->debug ? 0x1 : 0;
12764acd2d24SStefan Roese 
1277a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
1278a1b6b0a9SMario Six 	if (image_get_csk_index() >= 0) {
1279a1b6b0a9SMario Six 		/*
1280a1b6b0a9SMario Six 		 * only reserve the space here; we fill the header later since
1281a1b6b0a9SMario Six 		 * we need the header to be complete to compute the signatures
1282a1b6b0a9SMario Six 		 */
1283a1b6b0a9SMario Six 		secure_hdr = (struct secure_hdr_v1 *)cur;
1284a1b6b0a9SMario Six 		cur += sizeof(struct secure_hdr_v1);
1285a1b6b0a9SMario Six 		next_ext = &secure_hdr->next;
1286a1b6b0a9SMario Six 	}
1287a1b6b0a9SMario Six #endif
1288a1b6b0a9SMario Six 	*next_ext = 1;
1289a1b6b0a9SMario Six 
129079066ef8SMario Six 	if (add_binary_header_v1(cur))
12914acd2d24SStefan Roese 		return NULL;
12924acd2d24SStefan Roese 
1293a1b6b0a9SMario Six #if defined(CONFIG_KWB_SECURE)
1294a1b6b0a9SMario Six 	if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
1295a1b6b0a9SMario Six 					       headersz, image, secure_hdr))
1296a1b6b0a9SMario Six 		return NULL;
1297a1b6b0a9SMario Six #endif
1298a1b6b0a9SMario Six 
12994acd2d24SStefan Roese 	/* Calculate and set the header checksum */
13004acd2d24SStefan Roese 	main_hdr->checksum = image_checksum8(main_hdr, headersz);
13014acd2d24SStefan Roese 
13024acd2d24SStefan Roese 	*imagesz = headersz;
13034acd2d24SStefan Roese 	return image;
13044acd2d24SStefan Roese }
13054acd2d24SStefan Roese 
recognize_keyword(char * keyword)13064991b4f7SMario Six int recognize_keyword(char *keyword)
13074991b4f7SMario Six {
13084991b4f7SMario Six 	int kw_id;
13094991b4f7SMario Six 
13104991b4f7SMario Six 	for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
13114991b4f7SMario Six 		if (!strcmp(keyword, id_strs[kw_id]))
13124991b4f7SMario Six 			return kw_id;
13134991b4f7SMario Six 
13144991b4f7SMario Six 	return 0;
13154991b4f7SMario Six }
13164991b4f7SMario Six 
image_create_config_parse_oneline(char * line,struct image_cfg_element * el)13174acd2d24SStefan Roese static int image_create_config_parse_oneline(char *line,
13184acd2d24SStefan Roese 					     struct image_cfg_element *el)
13194acd2d24SStefan Roese {
13204991b4f7SMario Six 	char *keyword, *saveptr, *value1, *value2;
13214991b4f7SMario Six 	char delimiters[] = " \t";
13224991b4f7SMario Six 	int keyword_id, ret, argi;
13234991b4f7SMario Six 	char *unknown_msg = "Ignoring unknown line '%s'\n";
13244acd2d24SStefan Roese 
13254991b4f7SMario Six 	keyword = strtok_r(line, delimiters, &saveptr);
13264991b4f7SMario Six 	keyword_id = recognize_keyword(keyword);
132794490a4aSMario Six 
13284991b4f7SMario Six 	if (!keyword_id) {
13294991b4f7SMario Six 		fprintf(stderr, unknown_msg, line);
13304991b4f7SMario Six 		return 0;
13314991b4f7SMario Six 	}
133294490a4aSMario Six 
13334991b4f7SMario Six 	el->type = keyword_id;
13344991b4f7SMario Six 
13354991b4f7SMario Six 	value1 = strtok_r(NULL, delimiters, &saveptr);
13364991b4f7SMario Six 
13374991b4f7SMario Six 	if (!value1) {
13384991b4f7SMario Six 		fprintf(stderr, "Parameter missing in line '%s'\n", line);
13394acd2d24SStefan Roese 		return -1;
13404acd2d24SStefan Roese 	}
13414991b4f7SMario Six 
13424991b4f7SMario Six 	switch (keyword_id) {
13434991b4f7SMario Six 	case IMAGE_CFG_VERSION:
13444991b4f7SMario Six 		el->version = atoi(value1);
13454991b4f7SMario Six 		break;
13464991b4f7SMario Six 	case IMAGE_CFG_BOOT_FROM:
13474991b4f7SMario Six 		ret = image_boot_mode_id(value1);
13484991b4f7SMario Six 
13494991b4f7SMario Six 		if (ret < 0) {
13504991b4f7SMario Six 			fprintf(stderr, "Invalid boot media '%s'\n", value1);
13514991b4f7SMario Six 			return -1;
13524991b4f7SMario Six 		}
1353f411b8f2SAndreas Bießmann 		el->bootfrom = ret;
13544991b4f7SMario Six 		break;
13554991b4f7SMario Six 	case IMAGE_CFG_NAND_BLKSZ:
13564991b4f7SMario Six 		el->nandblksz = strtoul(value1, NULL, 16);
13574991b4f7SMario Six 		break;
13584991b4f7SMario Six 	case IMAGE_CFG_NAND_BADBLK_LOCATION:
13594991b4f7SMario Six 		el->nandbadblklocation = strtoul(value1, NULL, 16);
13604991b4f7SMario Six 		break;
13614991b4f7SMario Six 	case IMAGE_CFG_NAND_ECC_MODE:
13624991b4f7SMario Six 		ret = image_nand_ecc_mode_id(value1);
136394490a4aSMario Six 
1364f411b8f2SAndreas Bießmann 		if (ret < 0) {
13654991b4f7SMario Six 			fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
13664acd2d24SStefan Roese 			return -1;
13674acd2d24SStefan Roese 		}
1368f411b8f2SAndreas Bießmann 		el->nandeccmode = ret;
13694991b4f7SMario Six 		break;
13704991b4f7SMario Six 	case IMAGE_CFG_NAND_PAGESZ:
13714991b4f7SMario Six 		el->nandpagesz = strtoul(value1, NULL, 16);
13724991b4f7SMario Six 		break;
13734991b4f7SMario Six 	case IMAGE_CFG_BINARY:
13744991b4f7SMario Six 		argi = 0;
137594490a4aSMario Six 
13764991b4f7SMario Six 		el->binary.file = strdup(value1);
13774acd2d24SStefan Roese 		while (1) {
13784991b4f7SMario Six 			char *value = strtok_r(NULL, delimiters, &saveptr);
13794991b4f7SMario Six 
13804acd2d24SStefan Roese 			if (!value)
13814acd2d24SStefan Roese 				break;
13824acd2d24SStefan Roese 			el->binary.args[argi] = strtoul(value, NULL, 16);
13834acd2d24SStefan Roese 			argi++;
13844acd2d24SStefan Roese 			if (argi >= BINARY_MAX_ARGS) {
13854acd2d24SStefan Roese 				fprintf(stderr,
13864991b4f7SMario Six 					"Too many arguments for BINARY\n");
13874acd2d24SStefan Roese 				return -1;
13884acd2d24SStefan Roese 			}
13894acd2d24SStefan Roese 		}
13904acd2d24SStefan Roese 		el->binary.nargs = argi;
13914991b4f7SMario Six 		break;
13924991b4f7SMario Six 	case IMAGE_CFG_DATA:
13934991b4f7SMario Six 		value2 = strtok_r(NULL, delimiters, &saveptr);
13944acd2d24SStefan Roese 
13954acd2d24SStefan Roese 		if (!value1 || !value2) {
13964acd2d24SStefan Roese 			fprintf(stderr,
13974acd2d24SStefan Roese 				"Invalid number of arguments for DATA\n");
13984acd2d24SStefan Roese 			return -1;
13994acd2d24SStefan Roese 		}
14004acd2d24SStefan Roese 
14014acd2d24SStefan Roese 		el->regdata.raddr = strtoul(value1, NULL, 16);
14024acd2d24SStefan Roese 		el->regdata.rdata = strtoul(value2, NULL, 16);
14034991b4f7SMario Six 		break;
14044991b4f7SMario Six 	case IMAGE_CFG_BAUDRATE:
14054991b4f7SMario Six 		el->baudrate = strtoul(value1, NULL, 10);
14064991b4f7SMario Six 		break;
14074991b4f7SMario Six 	case IMAGE_CFG_DEBUG:
14084991b4f7SMario Six 		el->debug = strtoul(value1, NULL, 10);
14094991b4f7SMario Six 		break;
1410a1b6b0a9SMario Six 	case IMAGE_CFG_KAK:
1411a1b6b0a9SMario Six 		el->key_name = strdup(value1);
1412a1b6b0a9SMario Six 		break;
1413a1b6b0a9SMario Six 	case IMAGE_CFG_CSK:
1414a1b6b0a9SMario Six 		el->key_name = strdup(value1);
1415a1b6b0a9SMario Six 		break;
1416a1b6b0a9SMario Six 	case IMAGE_CFG_CSK_INDEX:
1417a1b6b0a9SMario Six 		el->csk_idx = strtol(value1, NULL, 0);
1418a1b6b0a9SMario Six 		break;
1419a1b6b0a9SMario Six 	case IMAGE_CFG_JTAG_DELAY:
1420a1b6b0a9SMario Six 		el->jtag_delay = strtoul(value1, NULL, 0);
1421a1b6b0a9SMario Six 		break;
1422a1b6b0a9SMario Six 	case IMAGE_CFG_BOX_ID:
1423a1b6b0a9SMario Six 		el->boxid = strtoul(value1, NULL, 0);
1424a1b6b0a9SMario Six 		break;
1425a1b6b0a9SMario Six 	case IMAGE_CFG_FLASH_ID:
1426a1b6b0a9SMario Six 		el->flashid = strtoul(value1, NULL, 0);
1427a1b6b0a9SMario Six 		break;
1428a1b6b0a9SMario Six 	case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1429a1b6b0a9SMario Six 		el->sec_specialized_img = true;
1430a1b6b0a9SMario Six 		break;
1431a1b6b0a9SMario Six 	case IMAGE_CFG_SEC_COMMON_IMG:
1432a1b6b0a9SMario Six 		el->sec_specialized_img = false;
1433a1b6b0a9SMario Six 		break;
1434a1b6b0a9SMario Six 	case IMAGE_CFG_SEC_BOOT_DEV:
1435a1b6b0a9SMario Six 		el->sec_boot_dev = strtoul(value1, NULL, 0);
1436a1b6b0a9SMario Six 		break;
1437a1b6b0a9SMario Six 	case IMAGE_CFG_SEC_FUSE_DUMP:
1438a1b6b0a9SMario Six 		el->name = strdup(value1);
1439a1b6b0a9SMario Six 		break;
14404991b4f7SMario Six 	default:
14414991b4f7SMario Six 		fprintf(stderr, unknown_msg, line);
14424acd2d24SStefan Roese 	}
14434acd2d24SStefan Roese 
14444acd2d24SStefan Roese 	return 0;
14454acd2d24SStefan Roese }
14464acd2d24SStefan Roese 
14474acd2d24SStefan Roese /*
14484acd2d24SStefan Roese  * Parse the configuration file 'fcfg' into the array of configuration
14494acd2d24SStefan Roese  * elements 'image_cfg', and return the number of configuration
14504acd2d24SStefan Roese  * elements in 'cfgn'.
14514acd2d24SStefan Roese  */
image_create_config_parse(FILE * fcfg)14524acd2d24SStefan Roese static int image_create_config_parse(FILE *fcfg)
14534acd2d24SStefan Roese {
14544acd2d24SStefan Roese 	int ret;
14554acd2d24SStefan Roese 	int cfgi = 0;
14564acd2d24SStefan Roese 
14574acd2d24SStefan Roese 	/* Parse the configuration file */
14584acd2d24SStefan Roese 	while (!feof(fcfg)) {
14594acd2d24SStefan Roese 		char *line;
14604acd2d24SStefan Roese 		char buf[256];
14614acd2d24SStefan Roese 
14624acd2d24SStefan Roese 		/* Read the current line */
14634acd2d24SStefan Roese 		memset(buf, 0, sizeof(buf));
14644acd2d24SStefan Roese 		line = fgets(buf, sizeof(buf), fcfg);
14654acd2d24SStefan Roese 		if (!line)
14664acd2d24SStefan Roese 			break;
14674acd2d24SStefan Roese 
14684acd2d24SStefan Roese 		/* Ignore useless lines */
14694acd2d24SStefan Roese 		if (line[0] == '\n' || line[0] == '#')
14704acd2d24SStefan Roese 			continue;
14714acd2d24SStefan Roese 
14724acd2d24SStefan Roese 		/* Strip final newline */
14734acd2d24SStefan Roese 		if (line[strlen(line) - 1] == '\n')
14744acd2d24SStefan Roese 			line[strlen(line) - 1] = 0;
14754acd2d24SStefan Roese 
14764acd2d24SStefan Roese 		/* Parse the current line */
14774acd2d24SStefan Roese 		ret = image_create_config_parse_oneline(line,
14784acd2d24SStefan Roese 							&image_cfg[cfgi]);
14794acd2d24SStefan Roese 		if (ret)
14804acd2d24SStefan Roese 			return ret;
14814acd2d24SStefan Roese 
14824acd2d24SStefan Roese 		cfgi++;
14834acd2d24SStefan Roese 
14844acd2d24SStefan Roese 		if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
14854acd2d24SStefan Roese 			fprintf(stderr,
14864acd2d24SStefan Roese 				"Too many configuration elements in .cfg file\n");
14874acd2d24SStefan Roese 			return -1;
14884acd2d24SStefan Roese 		}
14894acd2d24SStefan Roese 	}
14904acd2d24SStefan Roese 
14914acd2d24SStefan Roese 	cfgn = cfgi;
14924acd2d24SStefan Roese 	return 0;
14934acd2d24SStefan Roese }
14944acd2d24SStefan Roese 
image_get_version(void)14954acd2d24SStefan Roese static int image_get_version(void)
14964acd2d24SStefan Roese {
14974acd2d24SStefan Roese 	struct image_cfg_element *e;
14984acd2d24SStefan Roese 
14994acd2d24SStefan Roese 	e = image_find_option(IMAGE_CFG_VERSION);
15004acd2d24SStefan Roese 	if (!e)
15014acd2d24SStefan Roese 		return -1;
15024acd2d24SStefan Roese 
15034acd2d24SStefan Roese 	return e->version;
15044acd2d24SStefan Roese }
15054acd2d24SStefan Roese 
kwbimage_set_header(void * ptr,struct stat * sbuf,int ifd,struct image_tool_params * params)1506aa0c7a86SPrafulla Wadaskar static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
1507f86ed6a8SGuilherme Maciel Ferreira 				struct image_tool_params *params)
1508aa0c7a86SPrafulla Wadaskar {
15094acd2d24SStefan Roese 	FILE *fcfg;
15104acd2d24SStefan Roese 	void *image = NULL;
15114acd2d24SStefan Roese 	int version;
151293e9371fSŁukasz Majewski 	size_t headersz = 0;
1513aa0c7a86SPrafulla Wadaskar 	uint32_t checksum;
15144acd2d24SStefan Roese 	int ret;
1515aa0c7a86SPrafulla Wadaskar 	int size;
1516aa0c7a86SPrafulla Wadaskar 
15174acd2d24SStefan Roese 	fcfg = fopen(params->imagename, "r");
15184acd2d24SStefan Roese 	if (!fcfg) {
15194acd2d24SStefan Roese 		fprintf(stderr, "Could not open input file %s\n",
15204acd2d24SStefan Roese 			params->imagename);
15214acd2d24SStefan Roese 		exit(EXIT_FAILURE);
15224acd2d24SStefan Roese 	}
1523aa0c7a86SPrafulla Wadaskar 
15244acd2d24SStefan Roese 	image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
15254acd2d24SStefan Roese 			   sizeof(struct image_cfg_element));
15264acd2d24SStefan Roese 	if (!image_cfg) {
15274acd2d24SStefan Roese 		fprintf(stderr, "Cannot allocate memory\n");
15284acd2d24SStefan Roese 		fclose(fcfg);
15294acd2d24SStefan Roese 		exit(EXIT_FAILURE);
15304acd2d24SStefan Roese 	}
15314acd2d24SStefan Roese 
15324acd2d24SStefan Roese 	memset(image_cfg, 0,
15334acd2d24SStefan Roese 	       IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
15344acd2d24SStefan Roese 	rewind(fcfg);
15354acd2d24SStefan Roese 
15364acd2d24SStefan Roese 	ret = image_create_config_parse(fcfg);
15374acd2d24SStefan Roese 	fclose(fcfg);
15384acd2d24SStefan Roese 	if (ret) {
15394acd2d24SStefan Roese 		free(image_cfg);
15404acd2d24SStefan Roese 		exit(EXIT_FAILURE);
15414acd2d24SStefan Roese 	}
15424acd2d24SStefan Roese 
15439b163d8cSStefan Roese 	/* The MVEBU BootROM does not allow non word aligned payloads */
15449b163d8cSStefan Roese 	sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4);
15459b163d8cSStefan Roese 
15464acd2d24SStefan Roese 	version = image_get_version();
1547934a529fSStefan Roese 	switch (version) {
1548934a529fSStefan Roese 		/*
1549934a529fSStefan Roese 		 * Fallback to version 0 if no version is provided in the
1550934a529fSStefan Roese 		 * cfg file
1551934a529fSStefan Roese 		 */
1552934a529fSStefan Roese 	case -1:
1553934a529fSStefan Roese 	case 0:
15544acd2d24SStefan Roese 		image = image_create_v0(&headersz, params, sbuf->st_size);
1555934a529fSStefan Roese 		break;
1556934a529fSStefan Roese 
1557934a529fSStefan Roese 	case 1:
1558a1b6b0a9SMario Six 		image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
1559934a529fSStefan Roese 		break;
1560934a529fSStefan Roese 
1561934a529fSStefan Roese 	default:
1562934a529fSStefan Roese 		fprintf(stderr, "Unsupported version %d\n", version);
1563934a529fSStefan Roese 		free(image_cfg);
1564934a529fSStefan Roese 		exit(EXIT_FAILURE);
1565934a529fSStefan Roese 	}
15664acd2d24SStefan Roese 
15674acd2d24SStefan Roese 	if (!image) {
15684acd2d24SStefan Roese 		fprintf(stderr, "Could not create image\n");
15694acd2d24SStefan Roese 		free(image_cfg);
15704acd2d24SStefan Roese 		exit(EXIT_FAILURE);
15714acd2d24SStefan Roese 	}
15724acd2d24SStefan Roese 
15734acd2d24SStefan Roese 	free(image_cfg);
15744acd2d24SStefan Roese 
15754acd2d24SStefan Roese 	/* Build and add image checksum header */
1576a8840dceSReinhard Pfau 	checksum =
1577a8840dceSReinhard Pfau 		cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size));
1578aa0c7a86SPrafulla Wadaskar 	size = write(ifd, &checksum, sizeof(uint32_t));
1579aa0c7a86SPrafulla Wadaskar 	if (size != sizeof(uint32_t)) {
15804acd2d24SStefan Roese 		fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
1581aa0c7a86SPrafulla Wadaskar 			params->cmdname, size, params->imagefile);
1582aa0c7a86SPrafulla Wadaskar 		exit(EXIT_FAILURE);
1583aa0c7a86SPrafulla Wadaskar 	}
1584aa0c7a86SPrafulla Wadaskar 
1585aa0c7a86SPrafulla Wadaskar 	sbuf->st_size += sizeof(uint32_t);
1586aa0c7a86SPrafulla Wadaskar 
15874acd2d24SStefan Roese 	/* Finally copy the header into the image area */
15884acd2d24SStefan Roese 	memcpy(ptr, image, headersz);
1589aa0c7a86SPrafulla Wadaskar 
15904acd2d24SStefan Roese 	free(image);
1591aa0c7a86SPrafulla Wadaskar }
1592aa0c7a86SPrafulla Wadaskar 
kwbimage_print_header(const void * ptr)1593aa0c7a86SPrafulla Wadaskar static void kwbimage_print_header(const void *ptr)
1594aa0c7a86SPrafulla Wadaskar {
15954acd2d24SStefan Roese 	struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
1596aa0c7a86SPrafulla Wadaskar 
15974acd2d24SStefan Roese 	printf("Image Type:   MVEBU Boot from %s Image\n",
15984acd2d24SStefan Roese 	       image_boot_mode_name(mhdr->blockid));
15994acd2d24SStefan Roese 	printf("Image version:%d\n", image_version((void *)ptr));
160026f195c7SGerald Kerma 	printf("Data Size:    ");
1601aa0c7a86SPrafulla Wadaskar 	genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1602aa0c7a86SPrafulla Wadaskar 	printf("Load Address: %08x\n", mhdr->destaddr);
1603aa0c7a86SPrafulla Wadaskar 	printf("Entry Point:  %08x\n", mhdr->execaddr);
1604aa0c7a86SPrafulla Wadaskar }
1605aa0c7a86SPrafulla Wadaskar 
kwbimage_check_image_types(uint8_t type)1606aa0c7a86SPrafulla Wadaskar static int kwbimage_check_image_types(uint8_t type)
1607aa0c7a86SPrafulla Wadaskar {
1608aa0c7a86SPrafulla Wadaskar 	if (type == IH_TYPE_KWBIMAGE)
1609aa0c7a86SPrafulla Wadaskar 		return EXIT_SUCCESS;
161094490a4aSMario Six 
1611aa0c7a86SPrafulla Wadaskar 	return EXIT_FAILURE;
1612aa0c7a86SPrafulla Wadaskar }
1613aa0c7a86SPrafulla Wadaskar 
kwbimage_verify_header(unsigned char * ptr,int image_size,struct image_tool_params * params)16144acd2d24SStefan Roese static int kwbimage_verify_header(unsigned char *ptr, int image_size,
16154acd2d24SStefan Roese 				  struct image_tool_params *params)
16164acd2d24SStefan Roese {
16174acd2d24SStefan Roese 	uint8_t checksum;
16186cd5678cSAlexander Graf 	size_t header_size = kwbimage_header_size(ptr);
16196cd5678cSAlexander Graf 
16206cd5678cSAlexander Graf 	if (header_size > image_size)
16216cd5678cSAlexander Graf 		return -FDT_ERR_BADSTRUCTURE;
16224acd2d24SStefan Roese 
1623db7cd4edSBaruch Siach 	if (!main_hdr_checksum_ok(ptr))
16244acd2d24SStefan Roese 		return -FDT_ERR_BADSTRUCTURE;
16254acd2d24SStefan Roese 
16264acd2d24SStefan Roese 	/* Only version 0 extended header has checksum */
16274acd2d24SStefan Roese 	if (image_version((void *)ptr) == 0) {
1628e89016c4SMario Six 		struct ext_hdr_v0 *ext_hdr;
1629e89016c4SMario Six 
1630885fba15SMario Six 		ext_hdr = (struct ext_hdr_v0 *)
1631885fba15SMario Six 				(ptr + sizeof(struct main_hdr_v0));
16324acd2d24SStefan Roese 		checksum = image_checksum8(ext_hdr,
163326f195c7SGerald Kerma 					   sizeof(struct ext_hdr_v0)
163426f195c7SGerald Kerma 					   - sizeof(uint8_t));
16354acd2d24SStefan Roese 		if (checksum != ext_hdr->checksum)
16364acd2d24SStefan Roese 			return -FDT_ERR_BADSTRUCTURE;
16374acd2d24SStefan Roese 	}
16384acd2d24SStefan Roese 
16394acd2d24SStefan Roese 	return 0;
16404acd2d24SStefan Roese }
16414acd2d24SStefan Roese 
kwbimage_generate(struct image_tool_params * params,struct image_type_params * tparams)16424acd2d24SStefan Roese static int kwbimage_generate(struct image_tool_params *params,
16434acd2d24SStefan Roese 			     struct image_type_params *tparams)
16444acd2d24SStefan Roese {
16456cbf7edaSPatrick Wildt 	FILE *fcfg;
16464acd2d24SStefan Roese 	int alloc_len;
16476cbf7edaSPatrick Wildt 	int version;
16484acd2d24SStefan Roese 	void *hdr;
16496cbf7edaSPatrick Wildt 	int ret;
16504acd2d24SStefan Roese 
16516cbf7edaSPatrick Wildt 	fcfg = fopen(params->imagename, "r");
16526cbf7edaSPatrick Wildt 	if (!fcfg) {
16536cbf7edaSPatrick Wildt 		fprintf(stderr, "Could not open input file %s\n",
16546cbf7edaSPatrick Wildt 			params->imagename);
16556cbf7edaSPatrick Wildt 		exit(EXIT_FAILURE);
16566cbf7edaSPatrick Wildt 	}
16576cbf7edaSPatrick Wildt 
16586cbf7edaSPatrick Wildt 	image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
16596cbf7edaSPatrick Wildt 			   sizeof(struct image_cfg_element));
16606cbf7edaSPatrick Wildt 	if (!image_cfg) {
16616cbf7edaSPatrick Wildt 		fprintf(stderr, "Cannot allocate memory\n");
16626cbf7edaSPatrick Wildt 		fclose(fcfg);
16636cbf7edaSPatrick Wildt 		exit(EXIT_FAILURE);
16646cbf7edaSPatrick Wildt 	}
16656cbf7edaSPatrick Wildt 
16666cbf7edaSPatrick Wildt 	memset(image_cfg, 0,
16676cbf7edaSPatrick Wildt 	       IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
16686cbf7edaSPatrick Wildt 	rewind(fcfg);
16696cbf7edaSPatrick Wildt 
16706cbf7edaSPatrick Wildt 	ret = image_create_config_parse(fcfg);
16716cbf7edaSPatrick Wildt 	fclose(fcfg);
16726cbf7edaSPatrick Wildt 	if (ret) {
16736cbf7edaSPatrick Wildt 		free(image_cfg);
16746cbf7edaSPatrick Wildt 		exit(EXIT_FAILURE);
16756cbf7edaSPatrick Wildt 	}
16766cbf7edaSPatrick Wildt 
16776cbf7edaSPatrick Wildt 	version = image_get_version();
16786cbf7edaSPatrick Wildt 	switch (version) {
16796cbf7edaSPatrick Wildt 		/*
16806cbf7edaSPatrick Wildt 		 * Fallback to version 0 if no version is provided in the
16816cbf7edaSPatrick Wildt 		 * cfg file
16826cbf7edaSPatrick Wildt 		 */
16836cbf7edaSPatrick Wildt 	case -1:
16846cbf7edaSPatrick Wildt 	case 0:
16854acd2d24SStefan Roese 		alloc_len = sizeof(struct main_hdr_v0) +
16864acd2d24SStefan Roese 			sizeof(struct ext_hdr_v0);
16876cbf7edaSPatrick Wildt 		break;
16886cbf7edaSPatrick Wildt 
16896cbf7edaSPatrick Wildt 	case 1:
1690e93cf53fSMario Six 		alloc_len = image_headersz_v1(NULL);
16916cbf7edaSPatrick Wildt 		break;
16926cbf7edaSPatrick Wildt 
16936cbf7edaSPatrick Wildt 	default:
16946cbf7edaSPatrick Wildt 		fprintf(stderr, "Unsupported version %d\n", version);
16956cbf7edaSPatrick Wildt 		free(image_cfg);
16966cbf7edaSPatrick Wildt 		exit(EXIT_FAILURE);
16974acd2d24SStefan Roese 	}
16984acd2d24SStefan Roese 
16996cbf7edaSPatrick Wildt 	free(image_cfg);
17006cbf7edaSPatrick Wildt 
17014acd2d24SStefan Roese 	hdr = malloc(alloc_len);
17024acd2d24SStefan Roese 	if (!hdr) {
17034acd2d24SStefan Roese 		fprintf(stderr, "%s: malloc return failure: %s\n",
17044acd2d24SStefan Roese 			params->cmdname, strerror(errno));
17054acd2d24SStefan Roese 		exit(EXIT_FAILURE);
17064acd2d24SStefan Roese 	}
17074acd2d24SStefan Roese 
17084acd2d24SStefan Roese 	memset(hdr, 0, alloc_len);
17094acd2d24SStefan Roese 	tparams->header_size = alloc_len;
17104acd2d24SStefan Roese 	tparams->hdr = hdr;
17114acd2d24SStefan Roese 
171277720859SStefan Roese 	/*
171377720859SStefan Roese 	 * The resulting image needs to be 4-byte aligned. At least
171477720859SStefan Roese 	 * the Marvell hdrparser tool complains if its unaligned.
171577720859SStefan Roese 	 * By returning 1 here in this function, called via
171677720859SStefan Roese 	 * tparams->vrec_header() in mkimage.c, mkimage will
171777720859SStefan Roese 	 * automatically pad the the resulting image to a 4-byte
171877720859SStefan Roese 	 * size if necessary.
171977720859SStefan Roese 	 */
172077720859SStefan Roese 	return 1;
17214acd2d24SStefan Roese }
17224acd2d24SStefan Roese 
17234acd2d24SStefan Roese /*
17244acd2d24SStefan Roese  * Report Error if xflag is set in addition to default
17254acd2d24SStefan Roese  */
kwbimage_check_params(struct image_tool_params * params)17264acd2d24SStefan Roese static int kwbimage_check_params(struct image_tool_params *params)
17274acd2d24SStefan Roese {
17284acd2d24SStefan Roese 	if (!strlen(params->imagename)) {
172994490a4aSMario Six 		char *msg = "Configuration file for kwbimage creation omitted";
173094490a4aSMario Six 
173194490a4aSMario Six 		fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
17324acd2d24SStefan Roese 		return CFG_INVALID;
17334acd2d24SStefan Roese 	}
17344acd2d24SStefan Roese 
17354acd2d24SStefan Roese 	return (params->dflag && (params->fflag || params->lflag)) ||
17364acd2d24SStefan Roese 		(params->fflag && (params->dflag || params->lflag)) ||
17374acd2d24SStefan Roese 		(params->lflag && (params->dflag || params->fflag)) ||
17384acd2d24SStefan Roese 		(params->xflag) || !(strlen(params->imagename));
17394acd2d24SStefan Roese }
17404acd2d24SStefan Roese 
1741aa0c7a86SPrafulla Wadaskar /*
1742aa0c7a86SPrafulla Wadaskar  * kwbimage type parameters definition
1743aa0c7a86SPrafulla Wadaskar  */
1744a93648d1SGuilherme Maciel Ferreira U_BOOT_IMAGE_TYPE(
1745a93648d1SGuilherme Maciel Ferreira 	kwbimage,
1746a93648d1SGuilherme Maciel Ferreira 	"Marvell MVEBU Boot Image support",
1747a93648d1SGuilherme Maciel Ferreira 	0,
1748a93648d1SGuilherme Maciel Ferreira 	NULL,
1749a93648d1SGuilherme Maciel Ferreira 	kwbimage_check_params,
1750a93648d1SGuilherme Maciel Ferreira 	kwbimage_verify_header,
1751a93648d1SGuilherme Maciel Ferreira 	kwbimage_print_header,
1752a93648d1SGuilherme Maciel Ferreira 	kwbimage_set_header,
1753a93648d1SGuilherme Maciel Ferreira 	NULL,
1754a93648d1SGuilherme Maciel Ferreira 	kwbimage_check_image_types,
1755a93648d1SGuilherme Maciel Ferreira 	NULL,
1756a93648d1SGuilherme Maciel Ferreira 	kwbimage_generate
1757a93648d1SGuilherme Maciel Ferreira );
1758