1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Image manipulator for Marvell SoCs
3*4882a593Smuzhiyun * supports Kirkwood, Dove, Armada 370, Armada XP, and Armada 38x
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright 2013 Thomas Petazzoni
6*4882a593Smuzhiyun * <thomas.petazzoni@free-electrons.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Not implemented: support for the register headers in v1 images
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include "imagetool.h"
14*4882a593Smuzhiyun #include <limits.h>
15*4882a593Smuzhiyun #include <image.h>
16*4882a593Smuzhiyun #include <stdarg.h>
17*4882a593Smuzhiyun #include <stdint.h>
18*4882a593Smuzhiyun #include "kwbimage.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #ifdef CONFIG_KWB_SECURE
21*4882a593Smuzhiyun #include <openssl/bn.h>
22*4882a593Smuzhiyun #include <openssl/rsa.h>
23*4882a593Smuzhiyun #include <openssl/pem.h>
24*4882a593Smuzhiyun #include <openssl/err.h>
25*4882a593Smuzhiyun #include <openssl/evp.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
RSA_get0_key(const RSA * r,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)28*4882a593Smuzhiyun static void RSA_get0_key(const RSA *r,
29*4882a593Smuzhiyun const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun if (n != NULL)
32*4882a593Smuzhiyun *n = r->n;
33*4882a593Smuzhiyun if (e != NULL)
34*4882a593Smuzhiyun *e = r->e;
35*4882a593Smuzhiyun if (d != NULL)
36*4882a593Smuzhiyun *d = r->d;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #else
EVP_MD_CTX_cleanup(EVP_MD_CTX * ctx)40*4882a593Smuzhiyun void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun EVP_MD_CTX_reset(ctx);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun #endif
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static struct image_cfg_element *image_cfg;
48*4882a593Smuzhiyun static int cfgn;
49*4882a593Smuzhiyun #ifdef CONFIG_KWB_SECURE
50*4882a593Smuzhiyun static int verbose_mode;
51*4882a593Smuzhiyun #endif
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun struct boot_mode {
54*4882a593Smuzhiyun unsigned int id;
55*4882a593Smuzhiyun const char *name;
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /*
59*4882a593Smuzhiyun * SHA2-256 hash
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun struct hash_v1 {
62*4882a593Smuzhiyun uint8_t hash[32];
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun struct boot_mode boot_modes[] = {
66*4882a593Smuzhiyun { 0x4D, "i2c" },
67*4882a593Smuzhiyun { 0x5A, "spi" },
68*4882a593Smuzhiyun { 0x8B, "nand" },
69*4882a593Smuzhiyun { 0x78, "sata" },
70*4882a593Smuzhiyun { 0x9C, "pex" },
71*4882a593Smuzhiyun { 0x69, "uart" },
72*4882a593Smuzhiyun { 0xAE, "sdio" },
73*4882a593Smuzhiyun {},
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun struct nand_ecc_mode {
77*4882a593Smuzhiyun unsigned int id;
78*4882a593Smuzhiyun const char *name;
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun struct nand_ecc_mode nand_ecc_modes[] = {
82*4882a593Smuzhiyun { 0x00, "default" },
83*4882a593Smuzhiyun { 0x01, "hamming" },
84*4882a593Smuzhiyun { 0x02, "rs" },
85*4882a593Smuzhiyun { 0x03, "disabled" },
86*4882a593Smuzhiyun {},
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* Used to identify an undefined execution or destination address */
90*4882a593Smuzhiyun #define ADDR_INVALID ((uint32_t)-1)
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun #define BINARY_MAX_ARGS 8
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /* In-memory representation of a line of the configuration file */
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun enum image_cfg_type {
97*4882a593Smuzhiyun IMAGE_CFG_VERSION = 0x1,
98*4882a593Smuzhiyun IMAGE_CFG_BOOT_FROM,
99*4882a593Smuzhiyun IMAGE_CFG_DEST_ADDR,
100*4882a593Smuzhiyun IMAGE_CFG_EXEC_ADDR,
101*4882a593Smuzhiyun IMAGE_CFG_NAND_BLKSZ,
102*4882a593Smuzhiyun IMAGE_CFG_NAND_BADBLK_LOCATION,
103*4882a593Smuzhiyun IMAGE_CFG_NAND_ECC_MODE,
104*4882a593Smuzhiyun IMAGE_CFG_NAND_PAGESZ,
105*4882a593Smuzhiyun IMAGE_CFG_BINARY,
106*4882a593Smuzhiyun IMAGE_CFG_PAYLOAD,
107*4882a593Smuzhiyun IMAGE_CFG_DATA,
108*4882a593Smuzhiyun IMAGE_CFG_BAUDRATE,
109*4882a593Smuzhiyun IMAGE_CFG_DEBUG,
110*4882a593Smuzhiyun IMAGE_CFG_KAK,
111*4882a593Smuzhiyun IMAGE_CFG_CSK,
112*4882a593Smuzhiyun IMAGE_CFG_CSK_INDEX,
113*4882a593Smuzhiyun IMAGE_CFG_JTAG_DELAY,
114*4882a593Smuzhiyun IMAGE_CFG_BOX_ID,
115*4882a593Smuzhiyun IMAGE_CFG_FLASH_ID,
116*4882a593Smuzhiyun IMAGE_CFG_SEC_COMMON_IMG,
117*4882a593Smuzhiyun IMAGE_CFG_SEC_SPECIALIZED_IMG,
118*4882a593Smuzhiyun IMAGE_CFG_SEC_BOOT_DEV,
119*4882a593Smuzhiyun IMAGE_CFG_SEC_FUSE_DUMP,
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun IMAGE_CFG_COUNT
122*4882a593Smuzhiyun } type;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun static const char * const id_strs[] = {
125*4882a593Smuzhiyun [IMAGE_CFG_VERSION] = "VERSION",
126*4882a593Smuzhiyun [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
127*4882a593Smuzhiyun [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
128*4882a593Smuzhiyun [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
129*4882a593Smuzhiyun [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
130*4882a593Smuzhiyun [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
131*4882a593Smuzhiyun [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
132*4882a593Smuzhiyun [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
133*4882a593Smuzhiyun [IMAGE_CFG_BINARY] = "BINARY",
134*4882a593Smuzhiyun [IMAGE_CFG_PAYLOAD] = "PAYLOAD",
135*4882a593Smuzhiyun [IMAGE_CFG_DATA] = "DATA",
136*4882a593Smuzhiyun [IMAGE_CFG_BAUDRATE] = "BAUDRATE",
137*4882a593Smuzhiyun [IMAGE_CFG_DEBUG] = "DEBUG",
138*4882a593Smuzhiyun [IMAGE_CFG_KAK] = "KAK",
139*4882a593Smuzhiyun [IMAGE_CFG_CSK] = "CSK",
140*4882a593Smuzhiyun [IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
141*4882a593Smuzhiyun [IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
142*4882a593Smuzhiyun [IMAGE_CFG_BOX_ID] = "BOX_ID",
143*4882a593Smuzhiyun [IMAGE_CFG_FLASH_ID] = "FLASH_ID",
144*4882a593Smuzhiyun [IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
145*4882a593Smuzhiyun [IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
146*4882a593Smuzhiyun [IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
147*4882a593Smuzhiyun [IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
148*4882a593Smuzhiyun };
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun struct image_cfg_element {
151*4882a593Smuzhiyun enum image_cfg_type type;
152*4882a593Smuzhiyun union {
153*4882a593Smuzhiyun unsigned int version;
154*4882a593Smuzhiyun unsigned int bootfrom;
155*4882a593Smuzhiyun struct {
156*4882a593Smuzhiyun const char *file;
157*4882a593Smuzhiyun unsigned int args[BINARY_MAX_ARGS];
158*4882a593Smuzhiyun unsigned int nargs;
159*4882a593Smuzhiyun } binary;
160*4882a593Smuzhiyun const char *payload;
161*4882a593Smuzhiyun unsigned int dstaddr;
162*4882a593Smuzhiyun unsigned int execaddr;
163*4882a593Smuzhiyun unsigned int nandblksz;
164*4882a593Smuzhiyun unsigned int nandbadblklocation;
165*4882a593Smuzhiyun unsigned int nandeccmode;
166*4882a593Smuzhiyun unsigned int nandpagesz;
167*4882a593Smuzhiyun struct ext_hdr_v0_reg regdata;
168*4882a593Smuzhiyun unsigned int baudrate;
169*4882a593Smuzhiyun unsigned int debug;
170*4882a593Smuzhiyun const char *key_name;
171*4882a593Smuzhiyun int csk_idx;
172*4882a593Smuzhiyun uint8_t jtag_delay;
173*4882a593Smuzhiyun uint32_t boxid;
174*4882a593Smuzhiyun uint32_t flashid;
175*4882a593Smuzhiyun bool sec_specialized_img;
176*4882a593Smuzhiyun unsigned int sec_boot_dev;
177*4882a593Smuzhiyun const char *name;
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun };
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun #define IMAGE_CFG_ELEMENT_MAX 256
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /*
184*4882a593Smuzhiyun * Utility functions to manipulate boot mode and ecc modes (convert
185*4882a593Smuzhiyun * them back and forth between description strings and the
186*4882a593Smuzhiyun * corresponding numerical identifiers).
187*4882a593Smuzhiyun */
188*4882a593Smuzhiyun
image_boot_mode_name(unsigned int id)189*4882a593Smuzhiyun static const char *image_boot_mode_name(unsigned int id)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun int i;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun for (i = 0; boot_modes[i].name; i++)
194*4882a593Smuzhiyun if (boot_modes[i].id == id)
195*4882a593Smuzhiyun return boot_modes[i].name;
196*4882a593Smuzhiyun return NULL;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
image_boot_mode_id(const char * boot_mode_name)199*4882a593Smuzhiyun int image_boot_mode_id(const char *boot_mode_name)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun int i;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun for (i = 0; boot_modes[i].name; i++)
204*4882a593Smuzhiyun if (!strcmp(boot_modes[i].name, boot_mode_name))
205*4882a593Smuzhiyun return boot_modes[i].id;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun return -1;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
image_nand_ecc_mode_id(const char * nand_ecc_mode_name)210*4882a593Smuzhiyun int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun int i;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun for (i = 0; nand_ecc_modes[i].name; i++)
215*4882a593Smuzhiyun if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
216*4882a593Smuzhiyun return nand_ecc_modes[i].id;
217*4882a593Smuzhiyun return -1;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun static struct image_cfg_element *
image_find_option(unsigned int optiontype)221*4882a593Smuzhiyun image_find_option(unsigned int optiontype)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun int i;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun for (i = 0; i < cfgn; i++) {
226*4882a593Smuzhiyun if (image_cfg[i].type == optiontype)
227*4882a593Smuzhiyun return &image_cfg[i];
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun return NULL;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun static unsigned int
image_count_options(unsigned int optiontype)234*4882a593Smuzhiyun image_count_options(unsigned int optiontype)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun int i;
237*4882a593Smuzhiyun unsigned int count = 0;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun for (i = 0; i < cfgn; i++)
240*4882a593Smuzhiyun if (image_cfg[i].type == optiontype)
241*4882a593Smuzhiyun count++;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun return count;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
247*4882a593Smuzhiyun
image_get_csk_index(void)248*4882a593Smuzhiyun static int image_get_csk_index(void)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun struct image_cfg_element *e;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_CSK_INDEX);
253*4882a593Smuzhiyun if (!e)
254*4882a593Smuzhiyun return -1;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun return e->csk_idx;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
image_get_spezialized_img(void)259*4882a593Smuzhiyun static bool image_get_spezialized_img(void)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun struct image_cfg_element *e;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
264*4882a593Smuzhiyun if (!e)
265*4882a593Smuzhiyun return false;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun return e->sec_specialized_img;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun #endif
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /*
273*4882a593Smuzhiyun * Compute a 8-bit checksum of a memory area. This algorithm follows
274*4882a593Smuzhiyun * the requirements of the Marvell SoC BootROM specifications.
275*4882a593Smuzhiyun */
image_checksum8(void * start,uint32_t len)276*4882a593Smuzhiyun static uint8_t image_checksum8(void *start, uint32_t len)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun uint8_t csum = 0;
279*4882a593Smuzhiyun uint8_t *p = start;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /* check len and return zero checksum if invalid */
282*4882a593Smuzhiyun if (!len)
283*4882a593Smuzhiyun return 0;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun do {
286*4882a593Smuzhiyun csum += *p;
287*4882a593Smuzhiyun p++;
288*4882a593Smuzhiyun } while (--len);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return csum;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
kwbimage_header_size(unsigned char * ptr)293*4882a593Smuzhiyun size_t kwbimage_header_size(unsigned char *ptr)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun if (image_version((void *)ptr) == 0)
296*4882a593Smuzhiyun return sizeof(struct main_hdr_v0);
297*4882a593Smuzhiyun else
298*4882a593Smuzhiyun return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /*
302*4882a593Smuzhiyun * Verify checksum over a complete header that includes the checksum field.
303*4882a593Smuzhiyun * Return 1 when OK, otherwise 0.
304*4882a593Smuzhiyun */
main_hdr_checksum_ok(void * hdr)305*4882a593Smuzhiyun static int main_hdr_checksum_ok(void *hdr)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun /* Offsets of checksum in v0 and v1 headers are the same */
308*4882a593Smuzhiyun struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
309*4882a593Smuzhiyun uint8_t checksum;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun checksum = image_checksum8(hdr, kwbimage_header_size(hdr));
312*4882a593Smuzhiyun /* Calculated checksum includes the header checksum field. Compensate
313*4882a593Smuzhiyun * for that.
314*4882a593Smuzhiyun */
315*4882a593Smuzhiyun checksum -= main_hdr->checksum;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun return checksum == main_hdr->checksum;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
image_checksum32(void * start,uint32_t len)320*4882a593Smuzhiyun static uint32_t image_checksum32(void *start, uint32_t len)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun uint32_t csum = 0;
323*4882a593Smuzhiyun uint32_t *p = start;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun /* check len and return zero checksum if invalid */
326*4882a593Smuzhiyun if (!len)
327*4882a593Smuzhiyun return 0;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun if (len % sizeof(uint32_t)) {
330*4882a593Smuzhiyun fprintf(stderr, "Length %d is not in multiple of %zu\n",
331*4882a593Smuzhiyun len, sizeof(uint32_t));
332*4882a593Smuzhiyun return 0;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun do {
336*4882a593Smuzhiyun csum += *p;
337*4882a593Smuzhiyun p++;
338*4882a593Smuzhiyun len -= sizeof(uint32_t);
339*4882a593Smuzhiyun } while (len > 0);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun return csum;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
baudrate_to_option(unsigned int baudrate)344*4882a593Smuzhiyun static uint8_t baudrate_to_option(unsigned int baudrate)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun switch (baudrate) {
347*4882a593Smuzhiyun case 2400:
348*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_2400;
349*4882a593Smuzhiyun case 4800:
350*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_4800;
351*4882a593Smuzhiyun case 9600:
352*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_9600;
353*4882a593Smuzhiyun case 19200:
354*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_19200;
355*4882a593Smuzhiyun case 38400:
356*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_38400;
357*4882a593Smuzhiyun case 57600:
358*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_57600;
359*4882a593Smuzhiyun case 115200:
360*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_115200;
361*4882a593Smuzhiyun default:
362*4882a593Smuzhiyun return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
kwb_msg(const char * fmt,...)367*4882a593Smuzhiyun static void kwb_msg(const char *fmt, ...)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun if (verbose_mode) {
370*4882a593Smuzhiyun va_list ap;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun va_start(ap, fmt);
373*4882a593Smuzhiyun vfprintf(stdout, fmt, ap);
374*4882a593Smuzhiyun va_end(ap);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
openssl_err(const char * msg)378*4882a593Smuzhiyun static int openssl_err(const char *msg)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun unsigned long ssl_err = ERR_get_error();
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun fprintf(stderr, "%s", msg);
383*4882a593Smuzhiyun fprintf(stderr, ": %s\n",
384*4882a593Smuzhiyun ERR_error_string(ssl_err, 0));
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun return -1;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
kwb_load_rsa_key(const char * keydir,const char * name,RSA ** p_rsa)389*4882a593Smuzhiyun static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun char path[PATH_MAX];
392*4882a593Smuzhiyun RSA *rsa;
393*4882a593Smuzhiyun FILE *f;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun if (!keydir)
396*4882a593Smuzhiyun keydir = ".";
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
399*4882a593Smuzhiyun f = fopen(path, "r");
400*4882a593Smuzhiyun if (!f) {
401*4882a593Smuzhiyun fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
402*4882a593Smuzhiyun path, strerror(errno));
403*4882a593Smuzhiyun return -ENOENT;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
407*4882a593Smuzhiyun if (!rsa) {
408*4882a593Smuzhiyun openssl_err("Failure reading private key");
409*4882a593Smuzhiyun fclose(f);
410*4882a593Smuzhiyun return -EPROTO;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun fclose(f);
413*4882a593Smuzhiyun *p_rsa = rsa;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun return 0;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
kwb_load_cfg_key(struct image_tool_params * params,unsigned int cfg_option,const char * key_name,RSA ** p_key)418*4882a593Smuzhiyun static int kwb_load_cfg_key(struct image_tool_params *params,
419*4882a593Smuzhiyun unsigned int cfg_option, const char *key_name,
420*4882a593Smuzhiyun RSA **p_key)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct image_cfg_element *e_key;
423*4882a593Smuzhiyun RSA *key;
424*4882a593Smuzhiyun int res;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun *p_key = NULL;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun e_key = image_find_option(cfg_option);
429*4882a593Smuzhiyun if (!e_key) {
430*4882a593Smuzhiyun fprintf(stderr, "%s not configured\n", key_name);
431*4882a593Smuzhiyun return -ENOENT;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
435*4882a593Smuzhiyun if (res < 0) {
436*4882a593Smuzhiyun fprintf(stderr, "Failed to load %s\n", key_name);
437*4882a593Smuzhiyun return -ENOENT;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun *p_key = key;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun return 0;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
kwb_load_kak(struct image_tool_params * params,RSA ** p_kak)445*4882a593Smuzhiyun static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
kwb_load_csk(struct image_tool_params * params,RSA ** p_csk)450*4882a593Smuzhiyun static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
kwb_compute_pubkey_hash(struct pubkey_der_v1 * pk,struct hash_v1 * hash)455*4882a593Smuzhiyun static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
456*4882a593Smuzhiyun struct hash_v1 *hash)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun EVP_MD_CTX *ctx;
459*4882a593Smuzhiyun unsigned int key_size;
460*4882a593Smuzhiyun unsigned int hash_size;
461*4882a593Smuzhiyun int ret = 0;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
464*4882a593Smuzhiyun return -EINVAL;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun key_size = (pk->key[2] << 8) + pk->key[3] + 4;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun ctx = EVP_MD_CTX_create();
469*4882a593Smuzhiyun if (!ctx)
470*4882a593Smuzhiyun return openssl_err("EVP context creation failed");
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun EVP_MD_CTX_init(ctx);
473*4882a593Smuzhiyun if (!EVP_DigestInit(ctx, EVP_sha256())) {
474*4882a593Smuzhiyun ret = openssl_err("Digest setup failed");
475*4882a593Smuzhiyun goto hash_err_ctx;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
479*4882a593Smuzhiyun ret = openssl_err("Hashing data failed");
480*4882a593Smuzhiyun goto hash_err_ctx;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
484*4882a593Smuzhiyun ret = openssl_err("Could not obtain hash");
485*4882a593Smuzhiyun goto hash_err_ctx;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun EVP_MD_CTX_cleanup(ctx);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun hash_err_ctx:
491*4882a593Smuzhiyun EVP_MD_CTX_destroy(ctx);
492*4882a593Smuzhiyun return ret;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
kwb_import_pubkey(RSA ** key,struct pubkey_der_v1 * src,char * keyname)495*4882a593Smuzhiyun static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun RSA *rsa;
498*4882a593Smuzhiyun const unsigned char *ptr;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun if (!key || !src)
501*4882a593Smuzhiyun goto fail;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun ptr = src->key;
504*4882a593Smuzhiyun rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
505*4882a593Smuzhiyun if (!rsa) {
506*4882a593Smuzhiyun openssl_err("error decoding public key");
507*4882a593Smuzhiyun goto fail;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun return 0;
511*4882a593Smuzhiyun fail:
512*4882a593Smuzhiyun fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
513*4882a593Smuzhiyun return -EINVAL;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun
kwb_export_pubkey(RSA * key,struct pubkey_der_v1 * dst,FILE * hashf,char * keyname)516*4882a593Smuzhiyun static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
517*4882a593Smuzhiyun char *keyname)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun int size_exp, size_mod, size_seq;
520*4882a593Smuzhiyun const BIGNUM *key_e, *key_n;
521*4882a593Smuzhiyun uint8_t *cur;
522*4882a593Smuzhiyun char *errmsg = "Failed to encode %s\n";
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun RSA_get0_key(key, NULL, &key_e, NULL);
525*4882a593Smuzhiyun RSA_get0_key(key, &key_n, NULL, NULL);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (!key || !key_e || !key_n || !dst) {
528*4882a593Smuzhiyun fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
529*4882a593Smuzhiyun key, key_e, key_n, dst);
530*4882a593Smuzhiyun fprintf(stderr, errmsg, keyname);
531*4882a593Smuzhiyun return -EINVAL;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun /*
535*4882a593Smuzhiyun * According to the specs, the key should be PKCS#1 DER encoded.
536*4882a593Smuzhiyun * But unfortunately the really required encoding seems to be different;
537*4882a593Smuzhiyun * it violates DER...! (But it still conformes to BER.)
538*4882a593Smuzhiyun * (Length always in long form w/ 2 byte length code; no leading zero
539*4882a593Smuzhiyun * when MSB of first byte is set...)
540*4882a593Smuzhiyun * So we cannot use the encoding func provided by OpenSSL and have to
541*4882a593Smuzhiyun * do the encoding manually.
542*4882a593Smuzhiyun */
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun size_exp = BN_num_bytes(key_e);
545*4882a593Smuzhiyun size_mod = BN_num_bytes(key_n);
546*4882a593Smuzhiyun size_seq = 4 + size_mod + 4 + size_exp;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (size_mod > 256) {
549*4882a593Smuzhiyun fprintf(stderr, "export pk failed: wrong mod size: %d\n",
550*4882a593Smuzhiyun size_mod);
551*4882a593Smuzhiyun fprintf(stderr, errmsg, keyname);
552*4882a593Smuzhiyun return -EINVAL;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun if (4 + size_seq > sizeof(dst->key)) {
556*4882a593Smuzhiyun fprintf(stderr, "export pk failed: seq too large (%d, %lu)\n",
557*4882a593Smuzhiyun 4 + size_seq, sizeof(dst->key));
558*4882a593Smuzhiyun fprintf(stderr, errmsg, keyname);
559*4882a593Smuzhiyun return -ENOBUFS;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun cur = dst->key;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* PKCS#1 (RFC3447) RSAPublicKey structure */
565*4882a593Smuzhiyun *cur++ = 0x30; /* SEQUENCE */
566*4882a593Smuzhiyun *cur++ = 0x82;
567*4882a593Smuzhiyun *cur++ = (size_seq >> 8) & 0xFF;
568*4882a593Smuzhiyun *cur++ = size_seq & 0xFF;
569*4882a593Smuzhiyun /* Modulus */
570*4882a593Smuzhiyun *cur++ = 0x02; /* INTEGER */
571*4882a593Smuzhiyun *cur++ = 0x82;
572*4882a593Smuzhiyun *cur++ = (size_mod >> 8) & 0xFF;
573*4882a593Smuzhiyun *cur++ = size_mod & 0xFF;
574*4882a593Smuzhiyun BN_bn2bin(key_n, cur);
575*4882a593Smuzhiyun cur += size_mod;
576*4882a593Smuzhiyun /* Exponent */
577*4882a593Smuzhiyun *cur++ = 0x02; /* INTEGER */
578*4882a593Smuzhiyun *cur++ = 0x82;
579*4882a593Smuzhiyun *cur++ = (size_exp >> 8) & 0xFF;
580*4882a593Smuzhiyun *cur++ = size_exp & 0xFF;
581*4882a593Smuzhiyun BN_bn2bin(key_e, cur);
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun if (hashf) {
584*4882a593Smuzhiyun struct hash_v1 pk_hash;
585*4882a593Smuzhiyun int i;
586*4882a593Smuzhiyun int ret = 0;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun ret = kwb_compute_pubkey_hash(dst, &pk_hash);
589*4882a593Smuzhiyun if (ret < 0) {
590*4882a593Smuzhiyun fprintf(stderr, errmsg, keyname);
591*4882a593Smuzhiyun return ret;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun fprintf(hashf, "SHA256 = ");
595*4882a593Smuzhiyun for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
596*4882a593Smuzhiyun fprintf(hashf, "%02X", pk_hash.hash[i]);
597*4882a593Smuzhiyun fprintf(hashf, "\n");
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun return 0;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
kwb_sign(RSA * key,void * data,int datasz,struct sig_v1 * sig,char * signame)603*4882a593Smuzhiyun int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun EVP_PKEY *evp_key;
606*4882a593Smuzhiyun EVP_MD_CTX *ctx;
607*4882a593Smuzhiyun unsigned int sig_size;
608*4882a593Smuzhiyun int size;
609*4882a593Smuzhiyun int ret = 0;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun evp_key = EVP_PKEY_new();
612*4882a593Smuzhiyun if (!evp_key)
613*4882a593Smuzhiyun return openssl_err("EVP_PKEY object creation failed");
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (!EVP_PKEY_set1_RSA(evp_key, key)) {
616*4882a593Smuzhiyun ret = openssl_err("EVP key setup failed");
617*4882a593Smuzhiyun goto err_key;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun size = EVP_PKEY_size(evp_key);
621*4882a593Smuzhiyun if (size > sizeof(sig->sig)) {
622*4882a593Smuzhiyun fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
623*4882a593Smuzhiyun size);
624*4882a593Smuzhiyun ret = -ENOBUFS;
625*4882a593Smuzhiyun goto err_key;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun ctx = EVP_MD_CTX_create();
629*4882a593Smuzhiyun if (!ctx) {
630*4882a593Smuzhiyun ret = openssl_err("EVP context creation failed");
631*4882a593Smuzhiyun goto err_key;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun EVP_MD_CTX_init(ctx);
634*4882a593Smuzhiyun if (!EVP_SignInit(ctx, EVP_sha256())) {
635*4882a593Smuzhiyun ret = openssl_err("Signer setup failed");
636*4882a593Smuzhiyun goto err_ctx;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (!EVP_SignUpdate(ctx, data, datasz)) {
640*4882a593Smuzhiyun ret = openssl_err("Signing data failed");
641*4882a593Smuzhiyun goto err_ctx;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
645*4882a593Smuzhiyun ret = openssl_err("Could not obtain signature");
646*4882a593Smuzhiyun goto err_ctx;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun EVP_MD_CTX_cleanup(ctx);
650*4882a593Smuzhiyun EVP_MD_CTX_destroy(ctx);
651*4882a593Smuzhiyun EVP_PKEY_free(evp_key);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun return 0;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun err_ctx:
656*4882a593Smuzhiyun EVP_MD_CTX_destroy(ctx);
657*4882a593Smuzhiyun err_key:
658*4882a593Smuzhiyun EVP_PKEY_free(evp_key);
659*4882a593Smuzhiyun fprintf(stderr, "Failed to create %s signature\n", signame);
660*4882a593Smuzhiyun return ret;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
kwb_verify(RSA * key,void * data,int datasz,struct sig_v1 * sig,char * signame)663*4882a593Smuzhiyun int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
664*4882a593Smuzhiyun char *signame)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun EVP_PKEY *evp_key;
667*4882a593Smuzhiyun EVP_MD_CTX *ctx;
668*4882a593Smuzhiyun int size;
669*4882a593Smuzhiyun int ret = 0;
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun evp_key = EVP_PKEY_new();
672*4882a593Smuzhiyun if (!evp_key)
673*4882a593Smuzhiyun return openssl_err("EVP_PKEY object creation failed");
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun if (!EVP_PKEY_set1_RSA(evp_key, key)) {
676*4882a593Smuzhiyun ret = openssl_err("EVP key setup failed");
677*4882a593Smuzhiyun goto err_key;
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun size = EVP_PKEY_size(evp_key);
681*4882a593Smuzhiyun if (size > sizeof(sig->sig)) {
682*4882a593Smuzhiyun fprintf(stderr, "Invalid signature size (%d bytes)\n",
683*4882a593Smuzhiyun size);
684*4882a593Smuzhiyun ret = -EINVAL;
685*4882a593Smuzhiyun goto err_key;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun ctx = EVP_MD_CTX_create();
689*4882a593Smuzhiyun if (!ctx) {
690*4882a593Smuzhiyun ret = openssl_err("EVP context creation failed");
691*4882a593Smuzhiyun goto err_key;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun EVP_MD_CTX_init(ctx);
694*4882a593Smuzhiyun if (!EVP_VerifyInit(ctx, EVP_sha256())) {
695*4882a593Smuzhiyun ret = openssl_err("Verifier setup failed");
696*4882a593Smuzhiyun goto err_ctx;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun if (!EVP_VerifyUpdate(ctx, data, datasz)) {
700*4882a593Smuzhiyun ret = openssl_err("Hashing data failed");
701*4882a593Smuzhiyun goto err_ctx;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun if (!EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key)) {
705*4882a593Smuzhiyun ret = openssl_err("Could not verify signature");
706*4882a593Smuzhiyun goto err_ctx;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun EVP_MD_CTX_cleanup(ctx);
710*4882a593Smuzhiyun EVP_MD_CTX_destroy(ctx);
711*4882a593Smuzhiyun EVP_PKEY_free(evp_key);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun return 0;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun err_ctx:
716*4882a593Smuzhiyun EVP_MD_CTX_destroy(ctx);
717*4882a593Smuzhiyun err_key:
718*4882a593Smuzhiyun EVP_PKEY_free(evp_key);
719*4882a593Smuzhiyun fprintf(stderr, "Failed to verify %s signature\n", signame);
720*4882a593Smuzhiyun return ret;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
kwb_sign_and_verify(RSA * key,void * data,int datasz,struct sig_v1 * sig,char * signame)723*4882a593Smuzhiyun int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
724*4882a593Smuzhiyun char *signame)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun if (kwb_sign(key, data, datasz, sig, signame) < 0)
727*4882a593Smuzhiyun return -1;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun if (kwb_verify(key, data, datasz, sig, signame) < 0)
730*4882a593Smuzhiyun return -1;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun return 0;
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun
kwb_dump_fuse_cmds_38x(FILE * out,struct secure_hdr_v1 * sec_hdr)736*4882a593Smuzhiyun int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun struct hash_v1 kak_pub_hash;
739*4882a593Smuzhiyun struct image_cfg_element *e;
740*4882a593Smuzhiyun unsigned int fuse_line;
741*4882a593Smuzhiyun int i, idx;
742*4882a593Smuzhiyun uint8_t *ptr;
743*4882a593Smuzhiyun uint32_t val;
744*4882a593Smuzhiyun int ret = 0;
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun if (!out || !sec_hdr)
747*4882a593Smuzhiyun return -EINVAL;
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
750*4882a593Smuzhiyun if (ret < 0)
751*4882a593Smuzhiyun goto done;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun fprintf(out, "# burn KAK pub key hash\n");
754*4882a593Smuzhiyun ptr = kak_pub_hash.hash;
755*4882a593Smuzhiyun for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
756*4882a593Smuzhiyun fprintf(out, "fuse prog -y %u 0 ", fuse_line);
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun for (i = 4; i-- > 0;)
759*4882a593Smuzhiyun fprintf(out, "%02hx", (ushort)ptr[i]);
760*4882a593Smuzhiyun ptr += 4;
761*4882a593Smuzhiyun fprintf(out, " 00");
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun if (fuse_line < 30) {
764*4882a593Smuzhiyun for (i = 3; i-- > 0;)
765*4882a593Smuzhiyun fprintf(out, "%02hx", (ushort)ptr[i]);
766*4882a593Smuzhiyun ptr += 3;
767*4882a593Smuzhiyun } else {
768*4882a593Smuzhiyun fprintf(out, "000000");
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun fprintf(out, " 1\n");
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun fprintf(out, "# burn CSK selection\n");
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun idx = image_get_csk_index();
777*4882a593Smuzhiyun if (idx < 0 || idx > 15) {
778*4882a593Smuzhiyun ret = -EINVAL;
779*4882a593Smuzhiyun goto done;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun if (idx > 0) {
782*4882a593Smuzhiyun for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
783*4882a593Smuzhiyun fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
784*4882a593Smuzhiyun fuse_line);
785*4882a593Smuzhiyun } else {
786*4882a593Smuzhiyun fprintf(out, "# CSK index is 0; no mods needed\n");
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_BOX_ID);
790*4882a593Smuzhiyun if (e) {
791*4882a593Smuzhiyun fprintf(out, "# set box ID\n");
792*4882a593Smuzhiyun fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_FLASH_ID);
796*4882a593Smuzhiyun if (e) {
797*4882a593Smuzhiyun fprintf(out, "# set flash ID\n");
798*4882a593Smuzhiyun fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun fprintf(out, "# enable secure mode ");
802*4882a593Smuzhiyun fprintf(out, "(must be the last fuse line written)\n");
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun val = 1;
805*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
806*4882a593Smuzhiyun if (!e) {
807*4882a593Smuzhiyun fprintf(stderr, "ERROR: secured mode boot device not given\n");
808*4882a593Smuzhiyun ret = -EINVAL;
809*4882a593Smuzhiyun goto done;
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (e->sec_boot_dev > 0xff) {
813*4882a593Smuzhiyun fprintf(stderr, "ERROR: secured mode boot device invalid\n");
814*4882a593Smuzhiyun ret = -EINVAL;
815*4882a593Smuzhiyun goto done;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun val |= (e->sec_boot_dev << 8);
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
823*4882a593Smuzhiyun for (fuse_line = 0; fuse_line < 24; ++fuse_line)
824*4882a593Smuzhiyun fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun fprintf(out, "# OK, that's all :-)\n");
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun done:
829*4882a593Smuzhiyun return ret;
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun
kwb_dump_fuse_cmds(struct secure_hdr_v1 * sec_hdr)832*4882a593Smuzhiyun static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun int ret = 0;
835*4882a593Smuzhiyun struct image_cfg_element *e;
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
838*4882a593Smuzhiyun if (!e)
839*4882a593Smuzhiyun return 0;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun if (!strcmp(e->name, "a38x")) {
842*4882a593Smuzhiyun FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun kwb_dump_fuse_cmds_38x(out, sec_hdr);
845*4882a593Smuzhiyun fclose(out);
846*4882a593Smuzhiyun goto done;
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun ret = -ENOSYS;
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun done:
852*4882a593Smuzhiyun return ret;
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun #endif
856*4882a593Smuzhiyun
image_create_v0(size_t * imagesz,struct image_tool_params * params,int payloadsz)857*4882a593Smuzhiyun static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
858*4882a593Smuzhiyun int payloadsz)
859*4882a593Smuzhiyun {
860*4882a593Smuzhiyun struct image_cfg_element *e;
861*4882a593Smuzhiyun size_t headersz;
862*4882a593Smuzhiyun struct main_hdr_v0 *main_hdr;
863*4882a593Smuzhiyun uint8_t *image;
864*4882a593Smuzhiyun int has_ext = 0;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun /*
867*4882a593Smuzhiyun * Calculate the size of the header and the size of the
868*4882a593Smuzhiyun * payload
869*4882a593Smuzhiyun */
870*4882a593Smuzhiyun headersz = sizeof(struct main_hdr_v0);
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun if (image_count_options(IMAGE_CFG_DATA) > 0) {
873*4882a593Smuzhiyun has_ext = 1;
874*4882a593Smuzhiyun headersz += sizeof(struct ext_hdr_v0);
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
878*4882a593Smuzhiyun fprintf(stderr, "More than one payload, not possible\n");
879*4882a593Smuzhiyun return NULL;
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun image = malloc(headersz);
883*4882a593Smuzhiyun if (!image) {
884*4882a593Smuzhiyun fprintf(stderr, "Cannot allocate memory for image\n");
885*4882a593Smuzhiyun return NULL;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun memset(image, 0, headersz);
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun main_hdr = (struct main_hdr_v0 *)image;
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun /* Fill in the main header */
893*4882a593Smuzhiyun main_hdr->blocksize =
894*4882a593Smuzhiyun cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz);
895*4882a593Smuzhiyun main_hdr->srcaddr = cpu_to_le32(headersz);
896*4882a593Smuzhiyun main_hdr->ext = has_ext;
897*4882a593Smuzhiyun main_hdr->destaddr = cpu_to_le32(params->addr);
898*4882a593Smuzhiyun main_hdr->execaddr = cpu_to_le32(params->ep);
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_BOOT_FROM);
901*4882a593Smuzhiyun if (e)
902*4882a593Smuzhiyun main_hdr->blockid = e->bootfrom;
903*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
904*4882a593Smuzhiyun if (e)
905*4882a593Smuzhiyun main_hdr->nandeccmode = e->nandeccmode;
906*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
907*4882a593Smuzhiyun if (e)
908*4882a593Smuzhiyun main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
909*4882a593Smuzhiyun main_hdr->checksum = image_checksum8(image,
910*4882a593Smuzhiyun sizeof(struct main_hdr_v0));
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun /* Generate the ext header */
913*4882a593Smuzhiyun if (has_ext) {
914*4882a593Smuzhiyun struct ext_hdr_v0 *ext_hdr;
915*4882a593Smuzhiyun int cfgi, datai;
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun ext_hdr = (struct ext_hdr_v0 *)
918*4882a593Smuzhiyun (image + sizeof(struct main_hdr_v0));
919*4882a593Smuzhiyun ext_hdr->offset = cpu_to_le32(0x40);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
922*4882a593Smuzhiyun e = &image_cfg[cfgi];
923*4882a593Smuzhiyun if (e->type != IMAGE_CFG_DATA)
924*4882a593Smuzhiyun continue;
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun ext_hdr->rcfg[datai].raddr =
927*4882a593Smuzhiyun cpu_to_le32(e->regdata.raddr);
928*4882a593Smuzhiyun ext_hdr->rcfg[datai].rdata =
929*4882a593Smuzhiyun cpu_to_le32(e->regdata.rdata);
930*4882a593Smuzhiyun datai++;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun ext_hdr->checksum = image_checksum8(ext_hdr,
934*4882a593Smuzhiyun sizeof(struct ext_hdr_v0));
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun *imagesz = headersz;
938*4882a593Smuzhiyun return image;
939*4882a593Smuzhiyun }
940*4882a593Smuzhiyun
image_headersz_v1(int * hasext)941*4882a593Smuzhiyun static size_t image_headersz_v1(int *hasext)
942*4882a593Smuzhiyun {
943*4882a593Smuzhiyun struct image_cfg_element *binarye;
944*4882a593Smuzhiyun size_t headersz;
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun /*
947*4882a593Smuzhiyun * Calculate the size of the header and the size of the
948*4882a593Smuzhiyun * payload
949*4882a593Smuzhiyun */
950*4882a593Smuzhiyun headersz = sizeof(struct main_hdr_v1);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun if (image_count_options(IMAGE_CFG_BINARY) > 1) {
953*4882a593Smuzhiyun fprintf(stderr, "More than one binary blob, not supported\n");
954*4882a593Smuzhiyun return 0;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
958*4882a593Smuzhiyun fprintf(stderr, "More than one payload, not possible\n");
959*4882a593Smuzhiyun return 0;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun binarye = image_find_option(IMAGE_CFG_BINARY);
963*4882a593Smuzhiyun if (binarye) {
964*4882a593Smuzhiyun int ret;
965*4882a593Smuzhiyun struct stat s;
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun ret = stat(binarye->binary.file, &s);
968*4882a593Smuzhiyun if (ret < 0) {
969*4882a593Smuzhiyun char cwd[PATH_MAX];
970*4882a593Smuzhiyun char *dir = cwd;
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun memset(cwd, 0, sizeof(cwd));
973*4882a593Smuzhiyun if (!getcwd(cwd, sizeof(cwd))) {
974*4882a593Smuzhiyun dir = "current working directory";
975*4882a593Smuzhiyun perror("getcwd() failed");
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun fprintf(stderr,
979*4882a593Smuzhiyun "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
980*4882a593Smuzhiyun "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
981*4882a593Smuzhiyun "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
982*4882a593Smuzhiyun binarye->binary.file, dir);
983*4882a593Smuzhiyun return 0;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun headersz += sizeof(struct opt_hdr_v1) +
987*4882a593Smuzhiyun s.st_size +
988*4882a593Smuzhiyun (binarye->binary.nargs + 2) * sizeof(uint32_t);
989*4882a593Smuzhiyun if (hasext)
990*4882a593Smuzhiyun *hasext = 1;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
994*4882a593Smuzhiyun if (image_get_csk_index() >= 0) {
995*4882a593Smuzhiyun headersz += sizeof(struct secure_hdr_v1);
996*4882a593Smuzhiyun if (hasext)
997*4882a593Smuzhiyun *hasext = 1;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun #endif
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun #if defined(CONFIG_SYS_U_BOOT_OFFS)
1002*4882a593Smuzhiyun if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
1003*4882a593Smuzhiyun fprintf(stderr,
1004*4882a593Smuzhiyun "Error: Image header (incl. SPL image) too big!\n");
1005*4882a593Smuzhiyun fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
1006*4882a593Smuzhiyun (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
1007*4882a593Smuzhiyun fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
1008*4882a593Smuzhiyun return 0;
1009*4882a593Smuzhiyun }
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun headersz = CONFIG_SYS_U_BOOT_OFFS;
1012*4882a593Smuzhiyun #endif
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun /*
1015*4882a593Smuzhiyun * The payload should be aligned on some reasonable
1016*4882a593Smuzhiyun * boundary
1017*4882a593Smuzhiyun */
1018*4882a593Smuzhiyun return ALIGN_SUP(headersz, 4096);
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun
add_binary_header_v1(uint8_t * cur)1021*4882a593Smuzhiyun int add_binary_header_v1(uint8_t *cur)
1022*4882a593Smuzhiyun {
1023*4882a593Smuzhiyun struct image_cfg_element *binarye;
1024*4882a593Smuzhiyun struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
1025*4882a593Smuzhiyun uint32_t *args;
1026*4882a593Smuzhiyun size_t binhdrsz;
1027*4882a593Smuzhiyun struct stat s;
1028*4882a593Smuzhiyun int argi;
1029*4882a593Smuzhiyun FILE *bin;
1030*4882a593Smuzhiyun int ret;
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun binarye = image_find_option(IMAGE_CFG_BINARY);
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun if (!binarye)
1035*4882a593Smuzhiyun return 0;
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun bin = fopen(binarye->binary.file, "r");
1040*4882a593Smuzhiyun if (!bin) {
1041*4882a593Smuzhiyun fprintf(stderr, "Cannot open binary file %s\n",
1042*4882a593Smuzhiyun binarye->binary.file);
1043*4882a593Smuzhiyun return -1;
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun if (fstat(fileno(bin), &s)) {
1047*4882a593Smuzhiyun fprintf(stderr, "Cannot stat binary file %s\n",
1048*4882a593Smuzhiyun binarye->binary.file);
1049*4882a593Smuzhiyun goto err_close;
1050*4882a593Smuzhiyun }
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun binhdrsz = sizeof(struct opt_hdr_v1) +
1053*4882a593Smuzhiyun (binarye->binary.nargs + 2) * sizeof(uint32_t) +
1054*4882a593Smuzhiyun s.st_size;
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun /*
1057*4882a593Smuzhiyun * The size includes the binary image size, rounded
1058*4882a593Smuzhiyun * up to a 4-byte boundary. Plus 4 bytes for the
1059*4882a593Smuzhiyun * next-header byte and 3-byte alignment at the end.
1060*4882a593Smuzhiyun */
1061*4882a593Smuzhiyun binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
1062*4882a593Smuzhiyun hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1063*4882a593Smuzhiyun hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun cur += sizeof(struct opt_hdr_v1);
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun args = (uint32_t *)cur;
1068*4882a593Smuzhiyun *args = cpu_to_le32(binarye->binary.nargs);
1069*4882a593Smuzhiyun args++;
1070*4882a593Smuzhiyun for (argi = 0; argi < binarye->binary.nargs; argi++)
1071*4882a593Smuzhiyun args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun ret = fread(cur, s.st_size, 1, bin);
1076*4882a593Smuzhiyun if (ret != 1) {
1077*4882a593Smuzhiyun fprintf(stderr,
1078*4882a593Smuzhiyun "Could not read binary image %s\n",
1079*4882a593Smuzhiyun binarye->binary.file);
1080*4882a593Smuzhiyun goto err_close;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun fclose(bin);
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun cur += ALIGN_SUP(s.st_size, 4);
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun /*
1088*4882a593Smuzhiyun * For now, we don't support more than one binary
1089*4882a593Smuzhiyun * header, and no other header types are
1090*4882a593Smuzhiyun * supported. So, the binary header is necessarily the
1091*4882a593Smuzhiyun * last one
1092*4882a593Smuzhiyun */
1093*4882a593Smuzhiyun *((uint32_t *)cur) = 0x00000000;
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun cur += sizeof(uint32_t);
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun return 0;
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun err_close:
1100*4882a593Smuzhiyun fclose(bin);
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun return -1;
1103*4882a593Smuzhiyun }
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
1106*4882a593Smuzhiyun
export_pub_kak_hash(RSA * kak,struct secure_hdr_v1 * secure_hdr)1107*4882a593Smuzhiyun int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun FILE *hashf;
1110*4882a593Smuzhiyun int res;
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun hashf = fopen("pub_kak_hash.txt", "w");
1113*4882a593Smuzhiyun
1114*4882a593Smuzhiyun res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun fclose(hashf);
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun return res < 0 ? 1 : 0;
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun
kwb_sign_csk_with_kak(struct image_tool_params * params,struct secure_hdr_v1 * secure_hdr,RSA * csk)1121*4882a593Smuzhiyun int kwb_sign_csk_with_kak(struct image_tool_params *params,
1122*4882a593Smuzhiyun struct secure_hdr_v1 *secure_hdr, RSA *csk)
1123*4882a593Smuzhiyun {
1124*4882a593Smuzhiyun RSA *kak = NULL;
1125*4882a593Smuzhiyun RSA *kak_pub = NULL;
1126*4882a593Smuzhiyun int csk_idx = image_get_csk_index();
1127*4882a593Smuzhiyun struct sig_v1 tmp_sig;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun if (csk_idx >= 16) {
1130*4882a593Smuzhiyun fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1131*4882a593Smuzhiyun return 1;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyun if (kwb_load_kak(params, &kak) < 0)
1135*4882a593Smuzhiyun return 1;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun if (export_pub_kak_hash(kak, secure_hdr))
1138*4882a593Smuzhiyun return 1;
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1141*4882a593Smuzhiyun return 1;
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1144*4882a593Smuzhiyun return 1;
1145*4882a593Smuzhiyun
1146*4882a593Smuzhiyun if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1147*4882a593Smuzhiyun sizeof(secure_hdr->csk) +
1148*4882a593Smuzhiyun sizeof(secure_hdr->csksig),
1149*4882a593Smuzhiyun &tmp_sig, "CSK") < 0)
1150*4882a593Smuzhiyun return 1;
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun if (kwb_verify(kak_pub, &secure_hdr->csk,
1153*4882a593Smuzhiyun sizeof(secure_hdr->csk) +
1154*4882a593Smuzhiyun sizeof(secure_hdr->csksig),
1155*4882a593Smuzhiyun &tmp_sig, "CSK (2)") < 0)
1156*4882a593Smuzhiyun return 1;
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun secure_hdr->csksig = tmp_sig;
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun return 0;
1161*4882a593Smuzhiyun }
1162*4882a593Smuzhiyun
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)1163*4882a593Smuzhiyun int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1164*4882a593Smuzhiyun int payloadsz, size_t headersz, uint8_t *image,
1165*4882a593Smuzhiyun struct secure_hdr_v1 *secure_hdr)
1166*4882a593Smuzhiyun {
1167*4882a593Smuzhiyun struct image_cfg_element *e_jtagdelay;
1168*4882a593Smuzhiyun struct image_cfg_element *e_boxid;
1169*4882a593Smuzhiyun struct image_cfg_element *e_flashid;
1170*4882a593Smuzhiyun RSA *csk = NULL;
1171*4882a593Smuzhiyun unsigned char *image_ptr;
1172*4882a593Smuzhiyun size_t image_size;
1173*4882a593Smuzhiyun struct sig_v1 tmp_sig;
1174*4882a593Smuzhiyun bool specialized_img = image_get_spezialized_img();
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun kwb_msg("Create secure header content\n");
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1179*4882a593Smuzhiyun e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1180*4882a593Smuzhiyun e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun if (kwb_load_csk(params, &csk) < 0)
1183*4882a593Smuzhiyun return 1;
1184*4882a593Smuzhiyun
1185*4882a593Smuzhiyun secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1186*4882a593Smuzhiyun secure_hdr->headersz_msb = 0;
1187*4882a593Smuzhiyun secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1188*4882a593Smuzhiyun if (e_jtagdelay)
1189*4882a593Smuzhiyun secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1190*4882a593Smuzhiyun if (e_boxid && specialized_img)
1191*4882a593Smuzhiyun secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1192*4882a593Smuzhiyun if (e_flashid && specialized_img)
1193*4882a593Smuzhiyun secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1196*4882a593Smuzhiyun return 1;
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun image_ptr = ptr + headersz;
1199*4882a593Smuzhiyun image_size = payloadsz - headersz;
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun if (kwb_sign_and_verify(csk, image_ptr, image_size,
1202*4882a593Smuzhiyun &secure_hdr->imgsig, "image") < 0)
1203*4882a593Smuzhiyun return 1;
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1206*4882a593Smuzhiyun return 1;
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun secure_hdr->hdrsig = tmp_sig;
1209*4882a593Smuzhiyun
1210*4882a593Smuzhiyun kwb_dump_fuse_cmds(secure_hdr);
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun return 0;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun #endif
1215*4882a593Smuzhiyun
image_create_v1(size_t * imagesz,struct image_tool_params * params,uint8_t * ptr,int payloadsz)1216*4882a593Smuzhiyun static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
1217*4882a593Smuzhiyun uint8_t *ptr, int payloadsz)
1218*4882a593Smuzhiyun {
1219*4882a593Smuzhiyun struct image_cfg_element *e;
1220*4882a593Smuzhiyun struct main_hdr_v1 *main_hdr;
1221*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
1222*4882a593Smuzhiyun struct secure_hdr_v1 *secure_hdr = NULL;
1223*4882a593Smuzhiyun #endif
1224*4882a593Smuzhiyun size_t headersz;
1225*4882a593Smuzhiyun uint8_t *image, *cur;
1226*4882a593Smuzhiyun int hasext = 0;
1227*4882a593Smuzhiyun uint8_t *next_ext = NULL;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun /*
1230*4882a593Smuzhiyun * Calculate the size of the header and the size of the
1231*4882a593Smuzhiyun * payload
1232*4882a593Smuzhiyun */
1233*4882a593Smuzhiyun headersz = image_headersz_v1(&hasext);
1234*4882a593Smuzhiyun if (headersz == 0)
1235*4882a593Smuzhiyun return NULL;
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun image = malloc(headersz);
1238*4882a593Smuzhiyun if (!image) {
1239*4882a593Smuzhiyun fprintf(stderr, "Cannot allocate memory for image\n");
1240*4882a593Smuzhiyun return NULL;
1241*4882a593Smuzhiyun }
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun memset(image, 0, headersz);
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun main_hdr = (struct main_hdr_v1 *)image;
1246*4882a593Smuzhiyun cur = image;
1247*4882a593Smuzhiyun cur += sizeof(struct main_hdr_v1);
1248*4882a593Smuzhiyun next_ext = &main_hdr->ext;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun /* Fill the main header */
1251*4882a593Smuzhiyun main_hdr->blocksize =
1252*4882a593Smuzhiyun cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
1253*4882a593Smuzhiyun main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
1254*4882a593Smuzhiyun main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
1255*4882a593Smuzhiyun main_hdr->destaddr = cpu_to_le32(params->addr)
1256*4882a593Smuzhiyun - sizeof(image_header_t);
1257*4882a593Smuzhiyun main_hdr->execaddr = cpu_to_le32(params->ep);
1258*4882a593Smuzhiyun main_hdr->srcaddr = cpu_to_le32(headersz);
1259*4882a593Smuzhiyun main_hdr->ext = hasext;
1260*4882a593Smuzhiyun main_hdr->version = 1;
1261*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_BOOT_FROM);
1262*4882a593Smuzhiyun if (e)
1263*4882a593Smuzhiyun main_hdr->blockid = e->bootfrom;
1264*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1265*4882a593Smuzhiyun if (e)
1266*4882a593Smuzhiyun main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
1267*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1268*4882a593Smuzhiyun if (e)
1269*4882a593Smuzhiyun main_hdr->nandbadblklocation = e->nandbadblklocation;
1270*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_BAUDRATE);
1271*4882a593Smuzhiyun if (e)
1272*4882a593Smuzhiyun main_hdr->options = baudrate_to_option(e->baudrate);
1273*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_DEBUG);
1274*4882a593Smuzhiyun if (e)
1275*4882a593Smuzhiyun main_hdr->flags = e->debug ? 0x1 : 0;
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
1278*4882a593Smuzhiyun if (image_get_csk_index() >= 0) {
1279*4882a593Smuzhiyun /*
1280*4882a593Smuzhiyun * only reserve the space here; we fill the header later since
1281*4882a593Smuzhiyun * we need the header to be complete to compute the signatures
1282*4882a593Smuzhiyun */
1283*4882a593Smuzhiyun secure_hdr = (struct secure_hdr_v1 *)cur;
1284*4882a593Smuzhiyun cur += sizeof(struct secure_hdr_v1);
1285*4882a593Smuzhiyun next_ext = &secure_hdr->next;
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun #endif
1288*4882a593Smuzhiyun *next_ext = 1;
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun if (add_binary_header_v1(cur))
1291*4882a593Smuzhiyun return NULL;
1292*4882a593Smuzhiyun
1293*4882a593Smuzhiyun #if defined(CONFIG_KWB_SECURE)
1294*4882a593Smuzhiyun if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
1295*4882a593Smuzhiyun headersz, image, secure_hdr))
1296*4882a593Smuzhiyun return NULL;
1297*4882a593Smuzhiyun #endif
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun /* Calculate and set the header checksum */
1300*4882a593Smuzhiyun main_hdr->checksum = image_checksum8(main_hdr, headersz);
1301*4882a593Smuzhiyun
1302*4882a593Smuzhiyun *imagesz = headersz;
1303*4882a593Smuzhiyun return image;
1304*4882a593Smuzhiyun }
1305*4882a593Smuzhiyun
recognize_keyword(char * keyword)1306*4882a593Smuzhiyun int recognize_keyword(char *keyword)
1307*4882a593Smuzhiyun {
1308*4882a593Smuzhiyun int kw_id;
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1311*4882a593Smuzhiyun if (!strcmp(keyword, id_strs[kw_id]))
1312*4882a593Smuzhiyun return kw_id;
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun return 0;
1315*4882a593Smuzhiyun }
1316*4882a593Smuzhiyun
image_create_config_parse_oneline(char * line,struct image_cfg_element * el)1317*4882a593Smuzhiyun static int image_create_config_parse_oneline(char *line,
1318*4882a593Smuzhiyun struct image_cfg_element *el)
1319*4882a593Smuzhiyun {
1320*4882a593Smuzhiyun char *keyword, *saveptr, *value1, *value2;
1321*4882a593Smuzhiyun char delimiters[] = " \t";
1322*4882a593Smuzhiyun int keyword_id, ret, argi;
1323*4882a593Smuzhiyun char *unknown_msg = "Ignoring unknown line '%s'\n";
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun keyword = strtok_r(line, delimiters, &saveptr);
1326*4882a593Smuzhiyun keyword_id = recognize_keyword(keyword);
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun if (!keyword_id) {
1329*4882a593Smuzhiyun fprintf(stderr, unknown_msg, line);
1330*4882a593Smuzhiyun return 0;
1331*4882a593Smuzhiyun }
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun el->type = keyword_id;
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun value1 = strtok_r(NULL, delimiters, &saveptr);
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun if (!value1) {
1338*4882a593Smuzhiyun fprintf(stderr, "Parameter missing in line '%s'\n", line);
1339*4882a593Smuzhiyun return -1;
1340*4882a593Smuzhiyun }
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun switch (keyword_id) {
1343*4882a593Smuzhiyun case IMAGE_CFG_VERSION:
1344*4882a593Smuzhiyun el->version = atoi(value1);
1345*4882a593Smuzhiyun break;
1346*4882a593Smuzhiyun case IMAGE_CFG_BOOT_FROM:
1347*4882a593Smuzhiyun ret = image_boot_mode_id(value1);
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun if (ret < 0) {
1350*4882a593Smuzhiyun fprintf(stderr, "Invalid boot media '%s'\n", value1);
1351*4882a593Smuzhiyun return -1;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun el->bootfrom = ret;
1354*4882a593Smuzhiyun break;
1355*4882a593Smuzhiyun case IMAGE_CFG_NAND_BLKSZ:
1356*4882a593Smuzhiyun el->nandblksz = strtoul(value1, NULL, 16);
1357*4882a593Smuzhiyun break;
1358*4882a593Smuzhiyun case IMAGE_CFG_NAND_BADBLK_LOCATION:
1359*4882a593Smuzhiyun el->nandbadblklocation = strtoul(value1, NULL, 16);
1360*4882a593Smuzhiyun break;
1361*4882a593Smuzhiyun case IMAGE_CFG_NAND_ECC_MODE:
1362*4882a593Smuzhiyun ret = image_nand_ecc_mode_id(value1);
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun if (ret < 0) {
1365*4882a593Smuzhiyun fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
1366*4882a593Smuzhiyun return -1;
1367*4882a593Smuzhiyun }
1368*4882a593Smuzhiyun el->nandeccmode = ret;
1369*4882a593Smuzhiyun break;
1370*4882a593Smuzhiyun case IMAGE_CFG_NAND_PAGESZ:
1371*4882a593Smuzhiyun el->nandpagesz = strtoul(value1, NULL, 16);
1372*4882a593Smuzhiyun break;
1373*4882a593Smuzhiyun case IMAGE_CFG_BINARY:
1374*4882a593Smuzhiyun argi = 0;
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun el->binary.file = strdup(value1);
1377*4882a593Smuzhiyun while (1) {
1378*4882a593Smuzhiyun char *value = strtok_r(NULL, delimiters, &saveptr);
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun if (!value)
1381*4882a593Smuzhiyun break;
1382*4882a593Smuzhiyun el->binary.args[argi] = strtoul(value, NULL, 16);
1383*4882a593Smuzhiyun argi++;
1384*4882a593Smuzhiyun if (argi >= BINARY_MAX_ARGS) {
1385*4882a593Smuzhiyun fprintf(stderr,
1386*4882a593Smuzhiyun "Too many arguments for BINARY\n");
1387*4882a593Smuzhiyun return -1;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun }
1390*4882a593Smuzhiyun el->binary.nargs = argi;
1391*4882a593Smuzhiyun break;
1392*4882a593Smuzhiyun case IMAGE_CFG_DATA:
1393*4882a593Smuzhiyun value2 = strtok_r(NULL, delimiters, &saveptr);
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun if (!value1 || !value2) {
1396*4882a593Smuzhiyun fprintf(stderr,
1397*4882a593Smuzhiyun "Invalid number of arguments for DATA\n");
1398*4882a593Smuzhiyun return -1;
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun el->regdata.raddr = strtoul(value1, NULL, 16);
1402*4882a593Smuzhiyun el->regdata.rdata = strtoul(value2, NULL, 16);
1403*4882a593Smuzhiyun break;
1404*4882a593Smuzhiyun case IMAGE_CFG_BAUDRATE:
1405*4882a593Smuzhiyun el->baudrate = strtoul(value1, NULL, 10);
1406*4882a593Smuzhiyun break;
1407*4882a593Smuzhiyun case IMAGE_CFG_DEBUG:
1408*4882a593Smuzhiyun el->debug = strtoul(value1, NULL, 10);
1409*4882a593Smuzhiyun break;
1410*4882a593Smuzhiyun case IMAGE_CFG_KAK:
1411*4882a593Smuzhiyun el->key_name = strdup(value1);
1412*4882a593Smuzhiyun break;
1413*4882a593Smuzhiyun case IMAGE_CFG_CSK:
1414*4882a593Smuzhiyun el->key_name = strdup(value1);
1415*4882a593Smuzhiyun break;
1416*4882a593Smuzhiyun case IMAGE_CFG_CSK_INDEX:
1417*4882a593Smuzhiyun el->csk_idx = strtol(value1, NULL, 0);
1418*4882a593Smuzhiyun break;
1419*4882a593Smuzhiyun case IMAGE_CFG_JTAG_DELAY:
1420*4882a593Smuzhiyun el->jtag_delay = strtoul(value1, NULL, 0);
1421*4882a593Smuzhiyun break;
1422*4882a593Smuzhiyun case IMAGE_CFG_BOX_ID:
1423*4882a593Smuzhiyun el->boxid = strtoul(value1, NULL, 0);
1424*4882a593Smuzhiyun break;
1425*4882a593Smuzhiyun case IMAGE_CFG_FLASH_ID:
1426*4882a593Smuzhiyun el->flashid = strtoul(value1, NULL, 0);
1427*4882a593Smuzhiyun break;
1428*4882a593Smuzhiyun case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1429*4882a593Smuzhiyun el->sec_specialized_img = true;
1430*4882a593Smuzhiyun break;
1431*4882a593Smuzhiyun case IMAGE_CFG_SEC_COMMON_IMG:
1432*4882a593Smuzhiyun el->sec_specialized_img = false;
1433*4882a593Smuzhiyun break;
1434*4882a593Smuzhiyun case IMAGE_CFG_SEC_BOOT_DEV:
1435*4882a593Smuzhiyun el->sec_boot_dev = strtoul(value1, NULL, 0);
1436*4882a593Smuzhiyun break;
1437*4882a593Smuzhiyun case IMAGE_CFG_SEC_FUSE_DUMP:
1438*4882a593Smuzhiyun el->name = strdup(value1);
1439*4882a593Smuzhiyun break;
1440*4882a593Smuzhiyun default:
1441*4882a593Smuzhiyun fprintf(stderr, unknown_msg, line);
1442*4882a593Smuzhiyun }
1443*4882a593Smuzhiyun
1444*4882a593Smuzhiyun return 0;
1445*4882a593Smuzhiyun }
1446*4882a593Smuzhiyun
1447*4882a593Smuzhiyun /*
1448*4882a593Smuzhiyun * Parse the configuration file 'fcfg' into the array of configuration
1449*4882a593Smuzhiyun * elements 'image_cfg', and return the number of configuration
1450*4882a593Smuzhiyun * elements in 'cfgn'.
1451*4882a593Smuzhiyun */
image_create_config_parse(FILE * fcfg)1452*4882a593Smuzhiyun static int image_create_config_parse(FILE *fcfg)
1453*4882a593Smuzhiyun {
1454*4882a593Smuzhiyun int ret;
1455*4882a593Smuzhiyun int cfgi = 0;
1456*4882a593Smuzhiyun
1457*4882a593Smuzhiyun /* Parse the configuration file */
1458*4882a593Smuzhiyun while (!feof(fcfg)) {
1459*4882a593Smuzhiyun char *line;
1460*4882a593Smuzhiyun char buf[256];
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun /* Read the current line */
1463*4882a593Smuzhiyun memset(buf, 0, sizeof(buf));
1464*4882a593Smuzhiyun line = fgets(buf, sizeof(buf), fcfg);
1465*4882a593Smuzhiyun if (!line)
1466*4882a593Smuzhiyun break;
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun /* Ignore useless lines */
1469*4882a593Smuzhiyun if (line[0] == '\n' || line[0] == '#')
1470*4882a593Smuzhiyun continue;
1471*4882a593Smuzhiyun
1472*4882a593Smuzhiyun /* Strip final newline */
1473*4882a593Smuzhiyun if (line[strlen(line) - 1] == '\n')
1474*4882a593Smuzhiyun line[strlen(line) - 1] = 0;
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun /* Parse the current line */
1477*4882a593Smuzhiyun ret = image_create_config_parse_oneline(line,
1478*4882a593Smuzhiyun &image_cfg[cfgi]);
1479*4882a593Smuzhiyun if (ret)
1480*4882a593Smuzhiyun return ret;
1481*4882a593Smuzhiyun
1482*4882a593Smuzhiyun cfgi++;
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1485*4882a593Smuzhiyun fprintf(stderr,
1486*4882a593Smuzhiyun "Too many configuration elements in .cfg file\n");
1487*4882a593Smuzhiyun return -1;
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun cfgn = cfgi;
1492*4882a593Smuzhiyun return 0;
1493*4882a593Smuzhiyun }
1494*4882a593Smuzhiyun
image_get_version(void)1495*4882a593Smuzhiyun static int image_get_version(void)
1496*4882a593Smuzhiyun {
1497*4882a593Smuzhiyun struct image_cfg_element *e;
1498*4882a593Smuzhiyun
1499*4882a593Smuzhiyun e = image_find_option(IMAGE_CFG_VERSION);
1500*4882a593Smuzhiyun if (!e)
1501*4882a593Smuzhiyun return -1;
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun return e->version;
1504*4882a593Smuzhiyun }
1505*4882a593Smuzhiyun
kwbimage_set_header(void * ptr,struct stat * sbuf,int ifd,struct image_tool_params * params)1506*4882a593Smuzhiyun static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
1507*4882a593Smuzhiyun struct image_tool_params *params)
1508*4882a593Smuzhiyun {
1509*4882a593Smuzhiyun FILE *fcfg;
1510*4882a593Smuzhiyun void *image = NULL;
1511*4882a593Smuzhiyun int version;
1512*4882a593Smuzhiyun size_t headersz = 0;
1513*4882a593Smuzhiyun uint32_t checksum;
1514*4882a593Smuzhiyun int ret;
1515*4882a593Smuzhiyun int size;
1516*4882a593Smuzhiyun
1517*4882a593Smuzhiyun fcfg = fopen(params->imagename, "r");
1518*4882a593Smuzhiyun if (!fcfg) {
1519*4882a593Smuzhiyun fprintf(stderr, "Could not open input file %s\n",
1520*4882a593Smuzhiyun params->imagename);
1521*4882a593Smuzhiyun exit(EXIT_FAILURE);
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1525*4882a593Smuzhiyun sizeof(struct image_cfg_element));
1526*4882a593Smuzhiyun if (!image_cfg) {
1527*4882a593Smuzhiyun fprintf(stderr, "Cannot allocate memory\n");
1528*4882a593Smuzhiyun fclose(fcfg);
1529*4882a593Smuzhiyun exit(EXIT_FAILURE);
1530*4882a593Smuzhiyun }
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun memset(image_cfg, 0,
1533*4882a593Smuzhiyun IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1534*4882a593Smuzhiyun rewind(fcfg);
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun ret = image_create_config_parse(fcfg);
1537*4882a593Smuzhiyun fclose(fcfg);
1538*4882a593Smuzhiyun if (ret) {
1539*4882a593Smuzhiyun free(image_cfg);
1540*4882a593Smuzhiyun exit(EXIT_FAILURE);
1541*4882a593Smuzhiyun }
1542*4882a593Smuzhiyun
1543*4882a593Smuzhiyun /* The MVEBU BootROM does not allow non word aligned payloads */
1544*4882a593Smuzhiyun sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4);
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun version = image_get_version();
1547*4882a593Smuzhiyun switch (version) {
1548*4882a593Smuzhiyun /*
1549*4882a593Smuzhiyun * Fallback to version 0 if no version is provided in the
1550*4882a593Smuzhiyun * cfg file
1551*4882a593Smuzhiyun */
1552*4882a593Smuzhiyun case -1:
1553*4882a593Smuzhiyun case 0:
1554*4882a593Smuzhiyun image = image_create_v0(&headersz, params, sbuf->st_size);
1555*4882a593Smuzhiyun break;
1556*4882a593Smuzhiyun
1557*4882a593Smuzhiyun case 1:
1558*4882a593Smuzhiyun image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
1559*4882a593Smuzhiyun break;
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun default:
1562*4882a593Smuzhiyun fprintf(stderr, "Unsupported version %d\n", version);
1563*4882a593Smuzhiyun free(image_cfg);
1564*4882a593Smuzhiyun exit(EXIT_FAILURE);
1565*4882a593Smuzhiyun }
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun if (!image) {
1568*4882a593Smuzhiyun fprintf(stderr, "Could not create image\n");
1569*4882a593Smuzhiyun free(image_cfg);
1570*4882a593Smuzhiyun exit(EXIT_FAILURE);
1571*4882a593Smuzhiyun }
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun free(image_cfg);
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun /* Build and add image checksum header */
1576*4882a593Smuzhiyun checksum =
1577*4882a593Smuzhiyun cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size));
1578*4882a593Smuzhiyun size = write(ifd, &checksum, sizeof(uint32_t));
1579*4882a593Smuzhiyun if (size != sizeof(uint32_t)) {
1580*4882a593Smuzhiyun fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
1581*4882a593Smuzhiyun params->cmdname, size, params->imagefile);
1582*4882a593Smuzhiyun exit(EXIT_FAILURE);
1583*4882a593Smuzhiyun }
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun sbuf->st_size += sizeof(uint32_t);
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun /* Finally copy the header into the image area */
1588*4882a593Smuzhiyun memcpy(ptr, image, headersz);
1589*4882a593Smuzhiyun
1590*4882a593Smuzhiyun free(image);
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun
kwbimage_print_header(const void * ptr)1593*4882a593Smuzhiyun static void kwbimage_print_header(const void *ptr)
1594*4882a593Smuzhiyun {
1595*4882a593Smuzhiyun struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
1596*4882a593Smuzhiyun
1597*4882a593Smuzhiyun printf("Image Type: MVEBU Boot from %s Image\n",
1598*4882a593Smuzhiyun image_boot_mode_name(mhdr->blockid));
1599*4882a593Smuzhiyun printf("Image version:%d\n", image_version((void *)ptr));
1600*4882a593Smuzhiyun printf("Data Size: ");
1601*4882a593Smuzhiyun genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1602*4882a593Smuzhiyun printf("Load Address: %08x\n", mhdr->destaddr);
1603*4882a593Smuzhiyun printf("Entry Point: %08x\n", mhdr->execaddr);
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun
kwbimage_check_image_types(uint8_t type)1606*4882a593Smuzhiyun static int kwbimage_check_image_types(uint8_t type)
1607*4882a593Smuzhiyun {
1608*4882a593Smuzhiyun if (type == IH_TYPE_KWBIMAGE)
1609*4882a593Smuzhiyun return EXIT_SUCCESS;
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun return EXIT_FAILURE;
1612*4882a593Smuzhiyun }
1613*4882a593Smuzhiyun
kwbimage_verify_header(unsigned char * ptr,int image_size,struct image_tool_params * params)1614*4882a593Smuzhiyun static int kwbimage_verify_header(unsigned char *ptr, int image_size,
1615*4882a593Smuzhiyun struct image_tool_params *params)
1616*4882a593Smuzhiyun {
1617*4882a593Smuzhiyun uint8_t checksum;
1618*4882a593Smuzhiyun
1619*4882a593Smuzhiyun if (!main_hdr_checksum_ok(ptr))
1620*4882a593Smuzhiyun return -FDT_ERR_BADSTRUCTURE;
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun /* Only version 0 extended header has checksum */
1623*4882a593Smuzhiyun if (image_version((void *)ptr) == 0) {
1624*4882a593Smuzhiyun struct ext_hdr_v0 *ext_hdr;
1625*4882a593Smuzhiyun
1626*4882a593Smuzhiyun ext_hdr = (struct ext_hdr_v0 *)
1627*4882a593Smuzhiyun (ptr + sizeof(struct main_hdr_v0));
1628*4882a593Smuzhiyun checksum = image_checksum8(ext_hdr,
1629*4882a593Smuzhiyun sizeof(struct ext_hdr_v0)
1630*4882a593Smuzhiyun - sizeof(uint8_t));
1631*4882a593Smuzhiyun if (checksum != ext_hdr->checksum)
1632*4882a593Smuzhiyun return -FDT_ERR_BADSTRUCTURE;
1633*4882a593Smuzhiyun }
1634*4882a593Smuzhiyun
1635*4882a593Smuzhiyun return 0;
1636*4882a593Smuzhiyun }
1637*4882a593Smuzhiyun
kwbimage_generate(struct image_tool_params * params,struct image_type_params * tparams)1638*4882a593Smuzhiyun static int kwbimage_generate(struct image_tool_params *params,
1639*4882a593Smuzhiyun struct image_type_params *tparams)
1640*4882a593Smuzhiyun {
1641*4882a593Smuzhiyun FILE *fcfg;
1642*4882a593Smuzhiyun int alloc_len;
1643*4882a593Smuzhiyun int version;
1644*4882a593Smuzhiyun void *hdr;
1645*4882a593Smuzhiyun int ret;
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun fcfg = fopen(params->imagename, "r");
1648*4882a593Smuzhiyun if (!fcfg) {
1649*4882a593Smuzhiyun fprintf(stderr, "Could not open input file %s\n",
1650*4882a593Smuzhiyun params->imagename);
1651*4882a593Smuzhiyun exit(EXIT_FAILURE);
1652*4882a593Smuzhiyun }
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1655*4882a593Smuzhiyun sizeof(struct image_cfg_element));
1656*4882a593Smuzhiyun if (!image_cfg) {
1657*4882a593Smuzhiyun fprintf(stderr, "Cannot allocate memory\n");
1658*4882a593Smuzhiyun fclose(fcfg);
1659*4882a593Smuzhiyun exit(EXIT_FAILURE);
1660*4882a593Smuzhiyun }
1661*4882a593Smuzhiyun
1662*4882a593Smuzhiyun memset(image_cfg, 0,
1663*4882a593Smuzhiyun IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1664*4882a593Smuzhiyun rewind(fcfg);
1665*4882a593Smuzhiyun
1666*4882a593Smuzhiyun ret = image_create_config_parse(fcfg);
1667*4882a593Smuzhiyun fclose(fcfg);
1668*4882a593Smuzhiyun if (ret) {
1669*4882a593Smuzhiyun free(image_cfg);
1670*4882a593Smuzhiyun exit(EXIT_FAILURE);
1671*4882a593Smuzhiyun }
1672*4882a593Smuzhiyun
1673*4882a593Smuzhiyun version = image_get_version();
1674*4882a593Smuzhiyun switch (version) {
1675*4882a593Smuzhiyun /*
1676*4882a593Smuzhiyun * Fallback to version 0 if no version is provided in the
1677*4882a593Smuzhiyun * cfg file
1678*4882a593Smuzhiyun */
1679*4882a593Smuzhiyun case -1:
1680*4882a593Smuzhiyun case 0:
1681*4882a593Smuzhiyun alloc_len = sizeof(struct main_hdr_v0) +
1682*4882a593Smuzhiyun sizeof(struct ext_hdr_v0);
1683*4882a593Smuzhiyun break;
1684*4882a593Smuzhiyun
1685*4882a593Smuzhiyun case 1:
1686*4882a593Smuzhiyun alloc_len = image_headersz_v1(NULL);
1687*4882a593Smuzhiyun break;
1688*4882a593Smuzhiyun
1689*4882a593Smuzhiyun default:
1690*4882a593Smuzhiyun fprintf(stderr, "Unsupported version %d\n", version);
1691*4882a593Smuzhiyun free(image_cfg);
1692*4882a593Smuzhiyun exit(EXIT_FAILURE);
1693*4882a593Smuzhiyun }
1694*4882a593Smuzhiyun
1695*4882a593Smuzhiyun free(image_cfg);
1696*4882a593Smuzhiyun
1697*4882a593Smuzhiyun hdr = malloc(alloc_len);
1698*4882a593Smuzhiyun if (!hdr) {
1699*4882a593Smuzhiyun fprintf(stderr, "%s: malloc return failure: %s\n",
1700*4882a593Smuzhiyun params->cmdname, strerror(errno));
1701*4882a593Smuzhiyun exit(EXIT_FAILURE);
1702*4882a593Smuzhiyun }
1703*4882a593Smuzhiyun
1704*4882a593Smuzhiyun memset(hdr, 0, alloc_len);
1705*4882a593Smuzhiyun tparams->header_size = alloc_len;
1706*4882a593Smuzhiyun tparams->hdr = hdr;
1707*4882a593Smuzhiyun
1708*4882a593Smuzhiyun /*
1709*4882a593Smuzhiyun * The resulting image needs to be 4-byte aligned. At least
1710*4882a593Smuzhiyun * the Marvell hdrparser tool complains if its unaligned.
1711*4882a593Smuzhiyun * By returning 1 here in this function, called via
1712*4882a593Smuzhiyun * tparams->vrec_header() in mkimage.c, mkimage will
1713*4882a593Smuzhiyun * automatically pad the the resulting image to a 4-byte
1714*4882a593Smuzhiyun * size if necessary.
1715*4882a593Smuzhiyun */
1716*4882a593Smuzhiyun return 1;
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun
1719*4882a593Smuzhiyun /*
1720*4882a593Smuzhiyun * Report Error if xflag is set in addition to default
1721*4882a593Smuzhiyun */
kwbimage_check_params(struct image_tool_params * params)1722*4882a593Smuzhiyun static int kwbimage_check_params(struct image_tool_params *params)
1723*4882a593Smuzhiyun {
1724*4882a593Smuzhiyun if (!strlen(params->imagename)) {
1725*4882a593Smuzhiyun char *msg = "Configuration file for kwbimage creation omitted";
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
1728*4882a593Smuzhiyun return CFG_INVALID;
1729*4882a593Smuzhiyun }
1730*4882a593Smuzhiyun
1731*4882a593Smuzhiyun return (params->dflag && (params->fflag || params->lflag)) ||
1732*4882a593Smuzhiyun (params->fflag && (params->dflag || params->lflag)) ||
1733*4882a593Smuzhiyun (params->lflag && (params->dflag || params->fflag)) ||
1734*4882a593Smuzhiyun (params->xflag) || !(strlen(params->imagename));
1735*4882a593Smuzhiyun }
1736*4882a593Smuzhiyun
1737*4882a593Smuzhiyun /*
1738*4882a593Smuzhiyun * kwbimage type parameters definition
1739*4882a593Smuzhiyun */
1740*4882a593Smuzhiyun U_BOOT_IMAGE_TYPE(
1741*4882a593Smuzhiyun kwbimage,
1742*4882a593Smuzhiyun "Marvell MVEBU Boot Image support",
1743*4882a593Smuzhiyun 0,
1744*4882a593Smuzhiyun NULL,
1745*4882a593Smuzhiyun kwbimage_check_params,
1746*4882a593Smuzhiyun kwbimage_verify_header,
1747*4882a593Smuzhiyun kwbimage_print_header,
1748*4882a593Smuzhiyun kwbimage_set_header,
1749*4882a593Smuzhiyun NULL,
1750*4882a593Smuzhiyun kwbimage_check_image_types,
1751*4882a593Smuzhiyun NULL,
1752*4882a593Smuzhiyun kwbimage_generate
1753*4882a593Smuzhiyun );
1754