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