blob: b585f49180703041579bf4738512526e71563bb9 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05302/*
Stefan Roese4acd2d22014-10-22 12:13:23 +02003 * Image manipulator for Marvell SoCs
Mario Sixa1b6b0a2017-01-11 16:01:00 +01004 * supports Kirkwood, Dove, Armada 370, Armada XP, and Armada 38x
Stefan Roese4acd2d22014-10-22 12:13:23 +02005 *
6 * (C) Copyright 2013 Thomas Petazzoni
7 * <thomas.petazzoni@free-electrons.com>
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05308 *
Mario Sixa1b6b0a2017-01-11 16:01:00 +01009 * Not implemented: support for the register headers in v1 images
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053010 */
11
Guilherme Maciel Ferreiraf86ed6a2013-12-01 12:43:10 -070012#include "imagetool.h"
Andreas Bießmanne5f1a582014-10-24 23:39:11 +020013#include <limits.h>
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053014#include <image.h>
Mario Sixa1b6b0a2017-01-11 16:01:00 +010015#include <stdarg.h>
Stefan Roese4acd2d22014-10-22 12:13:23 +020016#include <stdint.h>
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053017#include "kwbimage.h"
18
Mario Sixa1b6b0a2017-01-11 16:01:00 +010019#ifdef CONFIG_KWB_SECURE
Jelle van der Waae15843b2017-05-08 21:31:20 +020020#include <openssl/bn.h>
Mario Sixa1b6b0a2017-01-11 16:01:00 +010021#include <openssl/rsa.h>
22#include <openssl/pem.h>
23#include <openssl/err.h>
24#include <openssl/evp.h>
Jelle van der Waae15843b2017-05-08 21:31:20 +020025
Jonathan Graya2d5efd2018-02-21 02:59:01 +110026#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
27 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
Jelle van der Waae15843b2017-05-08 21:31:20 +020028static void RSA_get0_key(const RSA *r,
29 const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
30{
31 if (n != NULL)
32 *n = r->n;
33 if (e != NULL)
34 *e = r->e;
35 if (d != NULL)
36 *d = r->d;
37}
38
Jonathan Graya2d5efd2018-02-21 02:59:01 +110039#elif !defined(LIBRESSL_VERSION_NUMBER)
Jelle van der Waae15843b2017-05-08 21:31:20 +020040void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
41{
42 EVP_MD_CTX_reset(ctx);
43}
44#endif
Mario Sixa1b6b0a2017-01-11 16:01:00 +010045#endif
46
Stefan Roese4acd2d22014-10-22 12:13:23 +020047static struct image_cfg_element *image_cfg;
48static int cfgn;
Mario Sixa1b6b0a2017-01-11 16:01:00 +010049#ifdef CONFIG_KWB_SECURE
50static int verbose_mode;
51#endif
Stefan Roese4acd2d22014-10-22 12:13:23 +020052
53struct boot_mode {
54 unsigned int id;
55 const char *name;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053056};
57
Mario Sixa1b6b0a2017-01-11 16:01:00 +010058/*
59 * SHA2-256 hash
60 */
61struct hash_v1 {
62 uint8_t hash[32];
63};
64
Stefan Roese4acd2d22014-10-22 12:13:23 +020065struct boot_mode boot_modes[] = {
66 { 0x4D, "i2c" },
67 { 0x5A, "spi" },
68 { 0x8B, "nand" },
69 { 0x78, "sata" },
70 { 0x9C, "pex" },
71 { 0x69, "uart" },
Stefan Roese1bbe63c2015-07-20 11:20:37 +020072 { 0xAE, "sdio" },
Stefan Roese4acd2d22014-10-22 12:13:23 +020073 {},
74};
75
76struct nand_ecc_mode {
77 unsigned int id;
78 const char *name;
79};
80
81struct nand_ecc_mode nand_ecc_modes[] = {
82 { 0x00, "default" },
83 { 0x01, "hamming" },
84 { 0x02, "rs" },
85 { 0x03, "disabled" },
86 {},
87};
88
89/* Used to identify an undefined execution or destination address */
90#define ADDR_INVALID ((uint32_t)-1)
91
Pali Rohár6c7f1522021-07-23 11:14:07 +020092#define BINARY_MAX_ARGS 255
Stefan Roese4acd2d22014-10-22 12:13:23 +020093
94/* In-memory representation of a line of the configuration file */
Mario Six4991b4f2017-01-11 16:00:59 +010095
96enum image_cfg_type {
97 IMAGE_CFG_VERSION = 0x1,
98 IMAGE_CFG_BOOT_FROM,
99 IMAGE_CFG_DEST_ADDR,
100 IMAGE_CFG_EXEC_ADDR,
101 IMAGE_CFG_NAND_BLKSZ,
102 IMAGE_CFG_NAND_BADBLK_LOCATION,
103 IMAGE_CFG_NAND_ECC_MODE,
104 IMAGE_CFG_NAND_PAGESZ,
105 IMAGE_CFG_BINARY,
Mario Six4991b4f2017-01-11 16:00:59 +0100106 IMAGE_CFG_DATA,
107 IMAGE_CFG_BAUDRATE,
108 IMAGE_CFG_DEBUG,
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100109 IMAGE_CFG_KAK,
110 IMAGE_CFG_CSK,
111 IMAGE_CFG_CSK_INDEX,
112 IMAGE_CFG_JTAG_DELAY,
113 IMAGE_CFG_BOX_ID,
114 IMAGE_CFG_FLASH_ID,
115 IMAGE_CFG_SEC_COMMON_IMG,
116 IMAGE_CFG_SEC_SPECIALIZED_IMG,
117 IMAGE_CFG_SEC_BOOT_DEV,
118 IMAGE_CFG_SEC_FUSE_DUMP,
Mario Six4991b4f2017-01-11 16:00:59 +0100119
120 IMAGE_CFG_COUNT
121} type;
122
123static const char * const id_strs[] = {
124 [IMAGE_CFG_VERSION] = "VERSION",
125 [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
126 [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
127 [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
128 [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
129 [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
130 [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
131 [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
132 [IMAGE_CFG_BINARY] = "BINARY",
Mario Six4991b4f2017-01-11 16:00:59 +0100133 [IMAGE_CFG_DATA] = "DATA",
134 [IMAGE_CFG_BAUDRATE] = "BAUDRATE",
135 [IMAGE_CFG_DEBUG] = "DEBUG",
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100136 [IMAGE_CFG_KAK] = "KAK",
137 [IMAGE_CFG_CSK] = "CSK",
138 [IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
139 [IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
140 [IMAGE_CFG_BOX_ID] = "BOX_ID",
141 [IMAGE_CFG_FLASH_ID] = "FLASH_ID",
142 [IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
143 [IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
144 [IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
145 [IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
Mario Six4991b4f2017-01-11 16:00:59 +0100146};
147
Stefan Roese4acd2d22014-10-22 12:13:23 +0200148struct image_cfg_element {
Mario Six4991b4f2017-01-11 16:00:59 +0100149 enum image_cfg_type type;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200150 union {
151 unsigned int version;
152 unsigned int bootfrom;
153 struct {
154 const char *file;
155 unsigned int args[BINARY_MAX_ARGS];
156 unsigned int nargs;
157 } binary;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200158 unsigned int dstaddr;
159 unsigned int execaddr;
160 unsigned int nandblksz;
161 unsigned int nandbadblklocation;
162 unsigned int nandeccmode;
163 unsigned int nandpagesz;
164 struct ext_hdr_v0_reg regdata;
Chris Packham4bdb5472016-11-09 22:07:45 +1300165 unsigned int baudrate;
Chris Packham2611c052016-11-09 22:21:45 +1300166 unsigned int debug;
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100167 const char *key_name;
168 int csk_idx;
169 uint8_t jtag_delay;
170 uint32_t boxid;
171 uint32_t flashid;
172 bool sec_specialized_img;
173 unsigned int sec_boot_dev;
174 const char *name;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200175 };
176};
177
178#define IMAGE_CFG_ELEMENT_MAX 256
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530179
180/*
Stefan Roese4acd2d22014-10-22 12:13:23 +0200181 * Utility functions to manipulate boot mode and ecc modes (convert
182 * them back and forth between description strings and the
183 * corresponding numerical identifiers).
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530184 */
Stefan Roese4acd2d22014-10-22 12:13:23 +0200185
186static const char *image_boot_mode_name(unsigned int id)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530187{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200188 int i;
Mario Six94490a42017-01-11 16:00:54 +0100189
Stefan Roese4acd2d22014-10-22 12:13:23 +0200190 for (i = 0; boot_modes[i].name; i++)
191 if (boot_modes[i].id == id)
192 return boot_modes[i].name;
193 return NULL;
194}
195
196int image_boot_mode_id(const char *boot_mode_name)
197{
198 int i;
Mario Six94490a42017-01-11 16:00:54 +0100199
Stefan Roese4acd2d22014-10-22 12:13:23 +0200200 for (i = 0; boot_modes[i].name; i++)
201 if (!strcmp(boot_modes[i].name, boot_mode_name))
202 return boot_modes[i].id;
203
204 return -1;
205}
206
207int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
208{
209 int i;
Mario Six94490a42017-01-11 16:00:54 +0100210
Stefan Roese4acd2d22014-10-22 12:13:23 +0200211 for (i = 0; nand_ecc_modes[i].name; i++)
212 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
213 return nand_ecc_modes[i].id;
214 return -1;
215}
216
217static struct image_cfg_element *
218image_find_option(unsigned int optiontype)
219{
220 int i;
221
222 for (i = 0; i < cfgn; i++) {
223 if (image_cfg[i].type == optiontype)
224 return &image_cfg[i];
225 }
226
227 return NULL;
228}
229
230static unsigned int
231image_count_options(unsigned int optiontype)
232{
233 int i;
234 unsigned int count = 0;
235
236 for (i = 0; i < cfgn; i++)
237 if (image_cfg[i].type == optiontype)
238 count++;
239
240 return count;
241}
242
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100243#if defined(CONFIG_KWB_SECURE)
244
245static int image_get_csk_index(void)
246{
247 struct image_cfg_element *e;
248
249 e = image_find_option(IMAGE_CFG_CSK_INDEX);
250 if (!e)
251 return -1;
252
253 return e->csk_idx;
254}
255
256static bool image_get_spezialized_img(void)
257{
258 struct image_cfg_element *e;
259
260 e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
261 if (!e)
262 return false;
263
264 return e->sec_specialized_img;
265}
266
267#endif
268
Stefan Roese4acd2d22014-10-22 12:13:23 +0200269/*
270 * Compute a 8-bit checksum of a memory area. This algorithm follows
271 * the requirements of the Marvell SoC BootROM specifications.
272 */
273static uint8_t image_checksum8(void *start, uint32_t len)
274{
275 uint8_t csum = 0;
276 uint8_t *p = start;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530277
278 /* check len and return zero checksum if invalid */
279 if (!len)
280 return 0;
281
282 do {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200283 csum += *p;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530284 p++;
285 } while (--len);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200286
287 return csum;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530288}
289
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +0300290size_t kwbimage_header_size(unsigned char *ptr)
291{
292 if (image_version((void *)ptr) == 0)
293 return sizeof(struct main_hdr_v0);
294 else
295 return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr);
296}
297
298/*
299 * Verify checksum over a complete header that includes the checksum field.
300 * Return 1 when OK, otherwise 0.
301 */
302static int main_hdr_checksum_ok(void *hdr)
303{
304 /* Offsets of checksum in v0 and v1 headers are the same */
305 struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
306 uint8_t checksum;
307
308 checksum = image_checksum8(hdr, kwbimage_header_size(hdr));
309 /* Calculated checksum includes the header checksum field. Compensate
310 * for that.
311 */
312 checksum -= main_hdr->checksum;
313
314 return checksum == main_hdr->checksum;
315}
316
Stefan Roese4acd2d22014-10-22 12:13:23 +0200317static uint32_t image_checksum32(void *start, uint32_t len)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530318{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200319 uint32_t csum = 0;
320 uint32_t *p = start;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530321
322 /* check len and return zero checksum if invalid */
323 if (!len)
324 return 0;
325
326 if (len % sizeof(uint32_t)) {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200327 fprintf(stderr, "Length %d is not in multiple of %zu\n",
328 len, sizeof(uint32_t));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530329 return 0;
330 }
331
332 do {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200333 csum += *p;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530334 p++;
335 len -= sizeof(uint32_t);
336 } while (len > 0);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200337
338 return csum;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530339}
340
Chris Packham4bdb5472016-11-09 22:07:45 +1300341static uint8_t baudrate_to_option(unsigned int baudrate)
342{
343 switch (baudrate) {
344 case 2400:
345 return MAIN_HDR_V1_OPT_BAUD_2400;
346 case 4800:
347 return MAIN_HDR_V1_OPT_BAUD_4800;
348 case 9600:
349 return MAIN_HDR_V1_OPT_BAUD_9600;
350 case 19200:
351 return MAIN_HDR_V1_OPT_BAUD_19200;
352 case 38400:
353 return MAIN_HDR_V1_OPT_BAUD_38400;
354 case 57600:
355 return MAIN_HDR_V1_OPT_BAUD_57600;
356 case 115200:
357 return MAIN_HDR_V1_OPT_BAUD_115200;
358 default:
359 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
360 }
361}
362
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100363#if defined(CONFIG_KWB_SECURE)
364static void kwb_msg(const char *fmt, ...)
365{
366 if (verbose_mode) {
367 va_list ap;
368
369 va_start(ap, fmt);
370 vfprintf(stdout, fmt, ap);
371 va_end(ap);
372 }
373}
374
375static int openssl_err(const char *msg)
376{
377 unsigned long ssl_err = ERR_get_error();
378
379 fprintf(stderr, "%s", msg);
380 fprintf(stderr, ": %s\n",
381 ERR_error_string(ssl_err, 0));
382
383 return -1;
384}
385
386static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
387{
388 char path[PATH_MAX];
389 RSA *rsa;
390 FILE *f;
391
392 if (!keydir)
393 keydir = ".";
394
395 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
396 f = fopen(path, "r");
397 if (!f) {
398 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
399 path, strerror(errno));
400 return -ENOENT;
401 }
402
403 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
404 if (!rsa) {
405 openssl_err("Failure reading private key");
406 fclose(f);
407 return -EPROTO;
408 }
409 fclose(f);
410 *p_rsa = rsa;
411
412 return 0;
413}
414
415static int kwb_load_cfg_key(struct image_tool_params *params,
416 unsigned int cfg_option, const char *key_name,
417 RSA **p_key)
418{
419 struct image_cfg_element *e_key;
420 RSA *key;
421 int res;
422
423 *p_key = NULL;
424
425 e_key = image_find_option(cfg_option);
426 if (!e_key) {
427 fprintf(stderr, "%s not configured\n", key_name);
428 return -ENOENT;
429 }
430
431 res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
432 if (res < 0) {
433 fprintf(stderr, "Failed to load %s\n", key_name);
434 return -ENOENT;
435 }
436
437 *p_key = key;
438
439 return 0;
440}
441
442static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
443{
444 return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
445}
446
447static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
448{
449 return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
450}
451
452static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
453 struct hash_v1 *hash)
454{
455 EVP_MD_CTX *ctx;
456 unsigned int key_size;
457 unsigned int hash_size;
458 int ret = 0;
459
460 if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
461 return -EINVAL;
462
463 key_size = (pk->key[2] << 8) + pk->key[3] + 4;
464
465 ctx = EVP_MD_CTX_create();
466 if (!ctx)
467 return openssl_err("EVP context creation failed");
468
469 EVP_MD_CTX_init(ctx);
470 if (!EVP_DigestInit(ctx, EVP_sha256())) {
471 ret = openssl_err("Digest setup failed");
472 goto hash_err_ctx;
473 }
474
475 if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
476 ret = openssl_err("Hashing data failed");
477 goto hash_err_ctx;
478 }
479
480 if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
481 ret = openssl_err("Could not obtain hash");
482 goto hash_err_ctx;
483 }
484
485 EVP_MD_CTX_cleanup(ctx);
486
487hash_err_ctx:
488 EVP_MD_CTX_destroy(ctx);
489 return ret;
490}
491
492static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
493{
494 RSA *rsa;
495 const unsigned char *ptr;
496
497 if (!key || !src)
498 goto fail;
499
500 ptr = src->key;
501 rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
502 if (!rsa) {
503 openssl_err("error decoding public key");
504 goto fail;
505 }
506
507 return 0;
508fail:
509 fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
510 return -EINVAL;
511}
512
513static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
514 char *keyname)
515{
516 int size_exp, size_mod, size_seq;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200517 const BIGNUM *key_e, *key_n;
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100518 uint8_t *cur;
519 char *errmsg = "Failed to encode %s\n";
520
Jelle van der Waae15843b2017-05-08 21:31:20 +0200521 RSA_get0_key(key, NULL, &key_e, NULL);
522 RSA_get0_key(key, &key_n, NULL, NULL);
523
524 if (!key || !key_e || !key_n || !dst) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100525 fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
Jelle van der Waae15843b2017-05-08 21:31:20 +0200526 key, key_e, key_n, dst);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100527 fprintf(stderr, errmsg, keyname);
528 return -EINVAL;
529 }
530
531 /*
532 * According to the specs, the key should be PKCS#1 DER encoded.
533 * But unfortunately the really required encoding seems to be different;
534 * it violates DER...! (But it still conformes to BER.)
535 * (Length always in long form w/ 2 byte length code; no leading zero
536 * when MSB of first byte is set...)
537 * So we cannot use the encoding func provided by OpenSSL and have to
538 * do the encoding manually.
539 */
540
Jelle van der Waae15843b2017-05-08 21:31:20 +0200541 size_exp = BN_num_bytes(key_e);
542 size_mod = BN_num_bytes(key_n);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100543 size_seq = 4 + size_mod + 4 + size_exp;
544
545 if (size_mod > 256) {
546 fprintf(stderr, "export pk failed: wrong mod size: %d\n",
547 size_mod);
548 fprintf(stderr, errmsg, keyname);
549 return -EINVAL;
550 }
551
552 if (4 + size_seq > sizeof(dst->key)) {
553 fprintf(stderr, "export pk failed: seq too large (%d, %lu)\n",
554 4 + size_seq, sizeof(dst->key));
555 fprintf(stderr, errmsg, keyname);
556 return -ENOBUFS;
557 }
558
559 cur = dst->key;
560
561 /* PKCS#1 (RFC3447) RSAPublicKey structure */
562 *cur++ = 0x30; /* SEQUENCE */
563 *cur++ = 0x82;
564 *cur++ = (size_seq >> 8) & 0xFF;
565 *cur++ = size_seq & 0xFF;
566 /* Modulus */
567 *cur++ = 0x02; /* INTEGER */
568 *cur++ = 0x82;
569 *cur++ = (size_mod >> 8) & 0xFF;
570 *cur++ = size_mod & 0xFF;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200571 BN_bn2bin(key_n, cur);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100572 cur += size_mod;
573 /* Exponent */
574 *cur++ = 0x02; /* INTEGER */
575 *cur++ = 0x82;
576 *cur++ = (size_exp >> 8) & 0xFF;
577 *cur++ = size_exp & 0xFF;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200578 BN_bn2bin(key_e, cur);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100579
580 if (hashf) {
581 struct hash_v1 pk_hash;
582 int i;
583 int ret = 0;
584
585 ret = kwb_compute_pubkey_hash(dst, &pk_hash);
586 if (ret < 0) {
587 fprintf(stderr, errmsg, keyname);
588 return ret;
589 }
590
591 fprintf(hashf, "SHA256 = ");
592 for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
593 fprintf(hashf, "%02X", pk_hash.hash[i]);
594 fprintf(hashf, "\n");
595 }
596
597 return 0;
598}
599
600int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
601{
602 EVP_PKEY *evp_key;
603 EVP_MD_CTX *ctx;
604 unsigned int sig_size;
605 int size;
606 int ret = 0;
607
608 evp_key = EVP_PKEY_new();
609 if (!evp_key)
610 return openssl_err("EVP_PKEY object creation failed");
611
612 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
613 ret = openssl_err("EVP key setup failed");
614 goto err_key;
615 }
616
617 size = EVP_PKEY_size(evp_key);
618 if (size > sizeof(sig->sig)) {
619 fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
620 size);
621 ret = -ENOBUFS;
622 goto err_key;
623 }
624
625 ctx = EVP_MD_CTX_create();
626 if (!ctx) {
627 ret = openssl_err("EVP context creation failed");
628 goto err_key;
629 }
630 EVP_MD_CTX_init(ctx);
631 if (!EVP_SignInit(ctx, EVP_sha256())) {
632 ret = openssl_err("Signer setup failed");
633 goto err_ctx;
634 }
635
636 if (!EVP_SignUpdate(ctx, data, datasz)) {
637 ret = openssl_err("Signing data failed");
638 goto err_ctx;
639 }
640
641 if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
642 ret = openssl_err("Could not obtain signature");
643 goto err_ctx;
644 }
645
646 EVP_MD_CTX_cleanup(ctx);
647 EVP_MD_CTX_destroy(ctx);
648 EVP_PKEY_free(evp_key);
649
650 return 0;
651
652err_ctx:
653 EVP_MD_CTX_destroy(ctx);
654err_key:
655 EVP_PKEY_free(evp_key);
656 fprintf(stderr, "Failed to create %s signature\n", signame);
657 return ret;
658}
659
660int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
661 char *signame)
662{
663 EVP_PKEY *evp_key;
664 EVP_MD_CTX *ctx;
665 int size;
666 int ret = 0;
667
668 evp_key = EVP_PKEY_new();
669 if (!evp_key)
670 return openssl_err("EVP_PKEY object creation failed");
671
672 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
673 ret = openssl_err("EVP key setup failed");
674 goto err_key;
675 }
676
677 size = EVP_PKEY_size(evp_key);
678 if (size > sizeof(sig->sig)) {
679 fprintf(stderr, "Invalid signature size (%d bytes)\n",
680 size);
681 ret = -EINVAL;
682 goto err_key;
683 }
684
685 ctx = EVP_MD_CTX_create();
686 if (!ctx) {
687 ret = openssl_err("EVP context creation failed");
688 goto err_key;
689 }
690 EVP_MD_CTX_init(ctx);
691 if (!EVP_VerifyInit(ctx, EVP_sha256())) {
692 ret = openssl_err("Verifier setup failed");
693 goto err_ctx;
694 }
695
696 if (!EVP_VerifyUpdate(ctx, data, datasz)) {
697 ret = openssl_err("Hashing data failed");
698 goto err_ctx;
699 }
700
Young Xiao22515122019-04-17 17:20:24 +0800701 if (EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key) != 1) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100702 ret = openssl_err("Could not verify signature");
703 goto err_ctx;
704 }
705
706 EVP_MD_CTX_cleanup(ctx);
707 EVP_MD_CTX_destroy(ctx);
708 EVP_PKEY_free(evp_key);
709
710 return 0;
711
712err_ctx:
713 EVP_MD_CTX_destroy(ctx);
714err_key:
715 EVP_PKEY_free(evp_key);
716 fprintf(stderr, "Failed to verify %s signature\n", signame);
717 return ret;
718}
719
720int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
721 char *signame)
722{
723 if (kwb_sign(key, data, datasz, sig, signame) < 0)
724 return -1;
725
726 if (kwb_verify(key, data, datasz, sig, signame) < 0)
727 return -1;
728
729 return 0;
730}
731
732
733int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
734{
735 struct hash_v1 kak_pub_hash;
736 struct image_cfg_element *e;
737 unsigned int fuse_line;
738 int i, idx;
739 uint8_t *ptr;
740 uint32_t val;
741 int ret = 0;
742
743 if (!out || !sec_hdr)
744 return -EINVAL;
745
746 ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
747 if (ret < 0)
748 goto done;
749
750 fprintf(out, "# burn KAK pub key hash\n");
751 ptr = kak_pub_hash.hash;
752 for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
753 fprintf(out, "fuse prog -y %u 0 ", fuse_line);
754
755 for (i = 4; i-- > 0;)
756 fprintf(out, "%02hx", (ushort)ptr[i]);
757 ptr += 4;
758 fprintf(out, " 00");
759
760 if (fuse_line < 30) {
761 for (i = 3; i-- > 0;)
762 fprintf(out, "%02hx", (ushort)ptr[i]);
763 ptr += 3;
764 } else {
765 fprintf(out, "000000");
766 }
767
768 fprintf(out, " 1\n");
769 }
770
771 fprintf(out, "# burn CSK selection\n");
772
773 idx = image_get_csk_index();
774 if (idx < 0 || idx > 15) {
775 ret = -EINVAL;
776 goto done;
777 }
778 if (idx > 0) {
779 for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
780 fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
781 fuse_line);
782 } else {
783 fprintf(out, "# CSK index is 0; no mods needed\n");
784 }
785
786 e = image_find_option(IMAGE_CFG_BOX_ID);
787 if (e) {
788 fprintf(out, "# set box ID\n");
789 fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
790 }
791
792 e = image_find_option(IMAGE_CFG_FLASH_ID);
793 if (e) {
794 fprintf(out, "# set flash ID\n");
795 fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
796 }
797
798 fprintf(out, "# enable secure mode ");
799 fprintf(out, "(must be the last fuse line written)\n");
800
801 val = 1;
802 e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
803 if (!e) {
804 fprintf(stderr, "ERROR: secured mode boot device not given\n");
805 ret = -EINVAL;
806 goto done;
807 }
808
809 if (e->sec_boot_dev > 0xff) {
810 fprintf(stderr, "ERROR: secured mode boot device invalid\n");
811 ret = -EINVAL;
812 goto done;
813 }
814
815 val |= (e->sec_boot_dev << 8);
816
817 fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
818
819 fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
820 for (fuse_line = 0; fuse_line < 24; ++fuse_line)
821 fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
822
823 fprintf(out, "# OK, that's all :-)\n");
824
825done:
826 return ret;
827}
828
829static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
830{
831 int ret = 0;
832 struct image_cfg_element *e;
833
834 e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
835 if (!e)
836 return 0;
837
838 if (!strcmp(e->name, "a38x")) {
839 FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
840
841 kwb_dump_fuse_cmds_38x(out, sec_hdr);
842 fclose(out);
843 goto done;
844 }
845
846 ret = -ENOSYS;
847
848done:
849 return ret;
850}
851
852#endif
853
Stefan Roese4acd2d22014-10-22 12:13:23 +0200854static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
855 int payloadsz)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530856{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200857 struct image_cfg_element *e;
858 size_t headersz;
859 struct main_hdr_v0 *main_hdr;
Mario Six885fba12017-01-11 16:00:55 +0100860 uint8_t *image;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200861 int has_ext = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530862
Stefan Roese4acd2d22014-10-22 12:13:23 +0200863 /*
864 * Calculate the size of the header and the size of the
865 * payload
866 */
867 headersz = sizeof(struct main_hdr_v0);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530868
Stefan Roese4acd2d22014-10-22 12:13:23 +0200869 if (image_count_options(IMAGE_CFG_DATA) > 0) {
870 has_ext = 1;
871 headersz += sizeof(struct ext_hdr_v0);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530872 }
873
Stefan Roese4acd2d22014-10-22 12:13:23 +0200874 image = malloc(headersz);
875 if (!image) {
876 fprintf(stderr, "Cannot allocate memory for image\n");
877 return NULL;
878 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530879
Stefan Roese4acd2d22014-10-22 12:13:23 +0200880 memset(image, 0, headersz);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530881
Mario Six885fba12017-01-11 16:00:55 +0100882 main_hdr = (struct main_hdr_v0 *)image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530883
Stefan Roese4acd2d22014-10-22 12:13:23 +0200884 /* Fill in the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100885 main_hdr->blocksize =
Pali Rohár37cb9c12021-07-23 11:13:56 +0200886 cpu_to_le32(payloadsz - headersz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100887 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200888 main_hdr->ext = has_ext;
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100889 main_hdr->destaddr = cpu_to_le32(params->addr);
890 main_hdr->execaddr = cpu_to_le32(params->ep);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530891
Stefan Roese4acd2d22014-10-22 12:13:23 +0200892 e = image_find_option(IMAGE_CFG_BOOT_FROM);
893 if (e)
894 main_hdr->blockid = e->bootfrom;
895 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
896 if (e)
897 main_hdr->nandeccmode = e->nandeccmode;
898 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
899 if (e)
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100900 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200901 main_hdr->checksum = image_checksum8(image,
902 sizeof(struct main_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530903
Stefan Roese4acd2d22014-10-22 12:13:23 +0200904 /* Generate the ext header */
905 if (has_ext) {
Mario Sixe89016c2017-01-11 16:00:56 +0100906 struct ext_hdr_v0 *ext_hdr;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200907 int cfgi, datai;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530908
Mario Six885fba12017-01-11 16:00:55 +0100909 ext_hdr = (struct ext_hdr_v0 *)
910 (image + sizeof(struct main_hdr_v0));
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100911 ext_hdr->offset = cpu_to_le32(0x40);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530912
Stefan Roese4acd2d22014-10-22 12:13:23 +0200913 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
914 e = &image_cfg[cfgi];
915 if (e->type != IMAGE_CFG_DATA)
916 continue;
917
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100918 ext_hdr->rcfg[datai].raddr =
919 cpu_to_le32(e->regdata.raddr);
920 ext_hdr->rcfg[datai].rdata =
921 cpu_to_le32(e->regdata.rdata);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200922 datai++;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530923 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530924
Stefan Roese4acd2d22014-10-22 12:13:23 +0200925 ext_hdr->checksum = image_checksum8(ext_hdr,
926 sizeof(struct ext_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530927 }
928
Stefan Roese4acd2d22014-10-22 12:13:23 +0200929 *imagesz = headersz;
930 return image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530931}
932
Mario Sixe93cf532017-01-11 16:00:57 +0100933static size_t image_headersz_v1(int *hasext)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530934{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200935 struct image_cfg_element *binarye;
Pali Rohár02ba70a2021-07-23 11:14:11 +0200936 unsigned int count;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200937 size_t headersz;
Pali Rohárd9fb82c2021-07-23 11:14:09 +0200938 int cfgi;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530939
Stefan Roese4acd2d22014-10-22 12:13:23 +0200940 /*
941 * Calculate the size of the header and the size of the
942 * payload
943 */
944 headersz = sizeof(struct main_hdr_v1);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530945
Pali Rohár02ba70a2021-07-23 11:14:11 +0200946 count = image_count_options(IMAGE_CFG_DATA);
947 if (count > 0)
948 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
949
Pali Rohárd9fb82c2021-07-23 11:14:09 +0200950 for (cfgi = 0; cfgi < cfgn; cfgi++) {
Mario Sixe89016c2017-01-11 16:00:56 +0100951 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200952 struct stat s;
953
Pali Rohárd9fb82c2021-07-23 11:14:09 +0200954 binarye = &image_cfg[cfgi];
955 if (binarye->type != IMAGE_CFG_BINARY)
956 continue;
957
Stefan Roese4acd2d22014-10-22 12:13:23 +0200958 ret = stat(binarye->binary.file, &s);
959 if (ret < 0) {
Andreas Bießmanne5f1a582014-10-24 23:39:11 +0200960 char cwd[PATH_MAX];
961 char *dir = cwd;
962
963 memset(cwd, 0, sizeof(cwd));
964 if (!getcwd(cwd, sizeof(cwd))) {
965 dir = "current working directory";
966 perror("getcwd() failed");
967 }
968
Stefan Roese4acd2d22014-10-22 12:13:23 +0200969 fprintf(stderr,
970 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
971 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
972 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
Andreas Bießmanne5f1a582014-10-24 23:39:11 +0200973 binarye->binary.file, dir);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200974 return 0;
975 }
976
Reinhard Pfau76b391c2015-11-29 15:52:14 +0100977 headersz += sizeof(struct opt_hdr_v1) +
Pali Rohár6458fd42021-07-23 11:14:08 +0200978 ALIGN(s.st_size, 4) +
Reinhard Pfau76b391c2015-11-29 15:52:14 +0100979 (binarye->binary.nargs + 2) * sizeof(uint32_t);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200980 if (hasext)
981 *hasext = 1;
982 }
983
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100984#if defined(CONFIG_KWB_SECURE)
985 if (image_get_csk_index() >= 0) {
986 headersz += sizeof(struct secure_hdr_v1);
987 if (hasext)
988 *hasext = 1;
989 }
990#endif
991
Stefan Roese7ddf8cf2015-07-20 11:20:38 +0200992#if defined(CONFIG_SYS_U_BOOT_OFFS)
993 if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
Mario Six94490a42017-01-11 16:00:54 +0100994 fprintf(stderr,
995 "Error: Image header (incl. SPL image) too big!\n");
Stefan Roese7ddf8cf2015-07-20 11:20:38 +0200996 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
997 (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
998 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
Kevin Smitha0aad122015-03-16 14:58:21 +0000999 return 0;
Kevin Smitha0aad122015-03-16 14:58:21 +00001000 }
Mario Six79066ef2017-01-11 16:00:58 +01001001
Mario Six94490a42017-01-11 16:00:54 +01001002 headersz = CONFIG_SYS_U_BOOT_OFFS;
Kevin Smitha0aad122015-03-16 14:58:21 +00001003#endif
1004
Stefan Roese4acd2d22014-10-22 12:13:23 +02001005 /*
1006 * The payload should be aligned on some reasonable
1007 * boundary
1008 */
Kever Yange002ee72020-03-30 11:56:20 +08001009 return ALIGN(headersz, 4096);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001010}
1011
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001012int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
1013 struct image_cfg_element *binarye)
Mario Six79066ef2017-01-11 16:00:58 +01001014{
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001015 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur;
Mario Six79066ef2017-01-11 16:00:58 +01001016 uint32_t *args;
1017 size_t binhdrsz;
1018 struct stat s;
1019 int argi;
1020 FILE *bin;
1021 int ret;
1022
Mario Six79066ef2017-01-11 16:00:58 +01001023 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1024
1025 bin = fopen(binarye->binary.file, "r");
1026 if (!bin) {
1027 fprintf(stderr, "Cannot open binary file %s\n",
1028 binarye->binary.file);
1029 return -1;
1030 }
1031
Mario Six1f6c8a52017-02-13 10:11:55 +01001032 if (fstat(fileno(bin), &s)) {
1033 fprintf(stderr, "Cannot stat binary file %s\n",
1034 binarye->binary.file);
1035 goto err_close;
1036 }
Mario Six79066ef2017-01-11 16:00:58 +01001037
1038 binhdrsz = sizeof(struct opt_hdr_v1) +
1039 (binarye->binary.nargs + 2) * sizeof(uint32_t) +
Pali Rohár6458fd42021-07-23 11:14:08 +02001040 ALIGN(s.st_size, 4);
Mario Six79066ef2017-01-11 16:00:58 +01001041 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1042 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1043
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001044 *cur += sizeof(struct opt_hdr_v1);
Mario Six79066ef2017-01-11 16:00:58 +01001045
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001046 args = (uint32_t *)*cur;
Mario Six79066ef2017-01-11 16:00:58 +01001047 *args = cpu_to_le32(binarye->binary.nargs);
1048 args++;
1049 for (argi = 0; argi < binarye->binary.nargs; argi++)
1050 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1051
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001052 *cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
Mario Six79066ef2017-01-11 16:00:58 +01001053
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001054 ret = fread(*cur, s.st_size, 1, bin);
Mario Six79066ef2017-01-11 16:00:58 +01001055 if (ret != 1) {
1056 fprintf(stderr,
1057 "Could not read binary image %s\n",
1058 binarye->binary.file);
Mario Six1f6c8a52017-02-13 10:11:55 +01001059 goto err_close;
Mario Six79066ef2017-01-11 16:00:58 +01001060 }
1061
1062 fclose(bin);
1063
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001064 *cur += ALIGN(s.st_size, 4);
Mario Six79066ef2017-01-11 16:00:58 +01001065
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001066 *((uint32_t *)*cur) = 0x00000000;
1067 **next_ext = 1;
1068 *next_ext = *cur;
Mario Six79066ef2017-01-11 16:00:58 +01001069
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001070 *cur += sizeof(uint32_t);
Mario Six79066ef2017-01-11 16:00:58 +01001071
1072 return 0;
Mario Six1f6c8a52017-02-13 10:11:55 +01001073
1074err_close:
1075 fclose(bin);
1076
1077 return -1;
Mario Six79066ef2017-01-11 16:00:58 +01001078}
1079
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001080#if defined(CONFIG_KWB_SECURE)
1081
1082int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
1083{
1084 FILE *hashf;
1085 int res;
1086
1087 hashf = fopen("pub_kak_hash.txt", "w");
1088
1089 res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1090
1091 fclose(hashf);
1092
1093 return res < 0 ? 1 : 0;
1094}
1095
1096int kwb_sign_csk_with_kak(struct image_tool_params *params,
1097 struct secure_hdr_v1 *secure_hdr, RSA *csk)
1098{
1099 RSA *kak = NULL;
1100 RSA *kak_pub = NULL;
1101 int csk_idx = image_get_csk_index();
1102 struct sig_v1 tmp_sig;
1103
1104 if (csk_idx >= 16) {
1105 fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1106 return 1;
1107 }
1108
1109 if (kwb_load_kak(params, &kak) < 0)
1110 return 1;
1111
1112 if (export_pub_kak_hash(kak, secure_hdr))
1113 return 1;
1114
1115 if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1116 return 1;
1117
1118 if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1119 return 1;
1120
1121 if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1122 sizeof(secure_hdr->csk) +
1123 sizeof(secure_hdr->csksig),
1124 &tmp_sig, "CSK") < 0)
1125 return 1;
1126
1127 if (kwb_verify(kak_pub, &secure_hdr->csk,
1128 sizeof(secure_hdr->csk) +
1129 sizeof(secure_hdr->csksig),
1130 &tmp_sig, "CSK (2)") < 0)
1131 return 1;
1132
1133 secure_hdr->csksig = tmp_sig;
1134
1135 return 0;
1136}
1137
1138int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1139 int payloadsz, size_t headersz, uint8_t *image,
1140 struct secure_hdr_v1 *secure_hdr)
1141{
1142 struct image_cfg_element *e_jtagdelay;
1143 struct image_cfg_element *e_boxid;
1144 struct image_cfg_element *e_flashid;
1145 RSA *csk = NULL;
1146 unsigned char *image_ptr;
1147 size_t image_size;
1148 struct sig_v1 tmp_sig;
1149 bool specialized_img = image_get_spezialized_img();
1150
1151 kwb_msg("Create secure header content\n");
1152
1153 e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1154 e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1155 e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1156
1157 if (kwb_load_csk(params, &csk) < 0)
1158 return 1;
1159
1160 secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1161 secure_hdr->headersz_msb = 0;
1162 secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1163 if (e_jtagdelay)
1164 secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1165 if (e_boxid && specialized_img)
1166 secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1167 if (e_flashid && specialized_img)
1168 secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1169
1170 if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1171 return 1;
1172
1173 image_ptr = ptr + headersz;
1174 image_size = payloadsz - headersz;
1175
1176 if (kwb_sign_and_verify(csk, image_ptr, image_size,
1177 &secure_hdr->imgsig, "image") < 0)
1178 return 1;
1179
1180 if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1181 return 1;
1182
1183 secure_hdr->hdrsig = tmp_sig;
1184
1185 kwb_dump_fuse_cmds(secure_hdr);
1186
1187 return 0;
1188}
1189#endif
1190
Stefan Roese4acd2d22014-10-22 12:13:23 +02001191static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001192 uint8_t *ptr, int payloadsz)
Stefan Roese4acd2d22014-10-22 12:13:23 +02001193{
Mario Six79066ef2017-01-11 16:00:58 +01001194 struct image_cfg_element *e;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001195 struct main_hdr_v1 *main_hdr;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001196 struct register_set_hdr_v1 *register_set_hdr;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001197#if defined(CONFIG_KWB_SECURE)
1198 struct secure_hdr_v1 *secure_hdr = NULL;
1199#endif
Stefan Roese4acd2d22014-10-22 12:13:23 +02001200 size_t headersz;
Mario Six885fba12017-01-11 16:00:55 +01001201 uint8_t *image, *cur;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001202 int hasext = 0;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001203 uint8_t *next_ext = NULL;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001204 int cfgi, datai, size;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001205
1206 /*
1207 * Calculate the size of the header and the size of the
1208 * payload
1209 */
Mario Sixe93cf532017-01-11 16:00:57 +01001210 headersz = image_headersz_v1(&hasext);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001211 if (headersz == 0)
1212 return NULL;
1213
1214 image = malloc(headersz);
1215 if (!image) {
1216 fprintf(stderr, "Cannot allocate memory for image\n");
1217 return NULL;
1218 }
1219
1220 memset(image, 0, headersz);
1221
Mario Six885fba12017-01-11 16:00:55 +01001222 main_hdr = (struct main_hdr_v1 *)image;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001223 cur = image;
1224 cur += sizeof(struct main_hdr_v1);
1225 next_ext = &main_hdr->ext;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001226
1227 /* Fill the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001228 main_hdr->blocksize =
Pali Rohár37cb9c12021-07-23 11:13:56 +02001229 cpu_to_le32(payloadsz - headersz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001230 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001231 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
Pali Rohárcc3443f2021-07-23 11:14:06 +02001232 main_hdr->destaddr = cpu_to_le32(params->addr);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001233 main_hdr->execaddr = cpu_to_le32(params->ep);
1234 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001235 main_hdr->ext = hasext;
1236 main_hdr->version = 1;
1237 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1238 if (e)
1239 main_hdr->blockid = e->bootfrom;
1240 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1241 if (e)
1242 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
1243 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1244 if (e)
1245 main_hdr->nandbadblklocation = e->nandbadblklocation;
Chris Packham4bdb5472016-11-09 22:07:45 +13001246 e = image_find_option(IMAGE_CFG_BAUDRATE);
1247 if (e)
1248 main_hdr->options = baudrate_to_option(e->baudrate);
Chris Packham2611c052016-11-09 22:21:45 +13001249 e = image_find_option(IMAGE_CFG_DEBUG);
1250 if (e)
1251 main_hdr->flags = e->debug ? 0x1 : 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001252
Pali Rohár501a54a2021-07-23 11:13:59 +02001253 /*
1254 * For SATA srcaddr is specified in number of sectors starting from
1255 * sector 0. The main header is stored at sector number 1.
1256 * This expects the sector size to be 512 bytes.
1257 * Header size is already aligned.
1258 */
1259 if (main_hdr->blockid == IBR_HDR_SATA_ID)
1260 main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1);
1261
1262 /*
1263 * For SDIO srcaddr is specified in number of sectors starting from
1264 * sector 0. The main header is stored at sector number 0.
1265 * This expects sector size to be 512 bytes.
1266 * Header size is already aligned.
1267 */
1268 if (main_hdr->blockid == IBR_HDR_SDIO_ID)
1269 main_hdr->srcaddr = cpu_to_le32(headersz / 512);
1270
1271 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1272 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1273 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1274
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001275#if defined(CONFIG_KWB_SECURE)
1276 if (image_get_csk_index() >= 0) {
1277 /*
1278 * only reserve the space here; we fill the header later since
1279 * we need the header to be complete to compute the signatures
1280 */
1281 secure_hdr = (struct secure_hdr_v1 *)cur;
1282 cur += sizeof(struct secure_hdr_v1);
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001283 *next_ext = 1;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001284 next_ext = &secure_hdr->next;
1285 }
1286#endif
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001287
Pali Rohár02ba70a2021-07-23 11:14:11 +02001288 datai = 0;
1289 register_set_hdr = (struct register_set_hdr_v1 *)cur;
1290 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1291 e = &image_cfg[cfgi];
1292 if (e->type != IMAGE_CFG_DATA)
1293 continue;
1294 register_set_hdr->data[datai].entry.address =
1295 cpu_to_le32(e->regdata.raddr);
1296 register_set_hdr->data[datai].entry.value =
1297 cpu_to_le32(e->regdata.rdata);
1298 datai++;
1299 }
1300 if (datai != 0) {
1301 size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
1302 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1303 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1304 register_set_hdr->headersz_msb = size >> 16;
1305 /* Set delay to the smallest possible value 1ms. */
1306 register_set_hdr->data[datai].last_entry.delay = 1;
1307 cur += size;
1308 *next_ext = 1;
1309 next_ext = &register_set_hdr->data[datai].last_entry.next;
1310 }
1311
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001312 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1313 e = &image_cfg[cfgi];
1314 if (e->type != IMAGE_CFG_BINARY)
1315 continue;
1316
1317 if (add_binary_header_v1(&cur, &next_ext, e))
1318 return NULL;
1319 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001320
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001321#if defined(CONFIG_KWB_SECURE)
1322 if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
1323 headersz, image, secure_hdr))
1324 return NULL;
1325#endif
1326
Stefan Roese4acd2d22014-10-22 12:13:23 +02001327 /* Calculate and set the header checksum */
1328 main_hdr->checksum = image_checksum8(main_hdr, headersz);
1329
1330 *imagesz = headersz;
1331 return image;
1332}
1333
Mario Six4991b4f2017-01-11 16:00:59 +01001334int recognize_keyword(char *keyword)
1335{
1336 int kw_id;
1337
1338 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1339 if (!strcmp(keyword, id_strs[kw_id]))
1340 return kw_id;
1341
1342 return 0;
1343}
1344
Stefan Roese4acd2d22014-10-22 12:13:23 +02001345static int image_create_config_parse_oneline(char *line,
1346 struct image_cfg_element *el)
1347{
Mario Six4991b4f2017-01-11 16:00:59 +01001348 char *keyword, *saveptr, *value1, *value2;
1349 char delimiters[] = " \t";
1350 int keyword_id, ret, argi;
1351 char *unknown_msg = "Ignoring unknown line '%s'\n";
Stefan Roese4acd2d22014-10-22 12:13:23 +02001352
Mario Six4991b4f2017-01-11 16:00:59 +01001353 keyword = strtok_r(line, delimiters, &saveptr);
1354 keyword_id = recognize_keyword(keyword);
Mario Six94490a42017-01-11 16:00:54 +01001355
Mario Six4991b4f2017-01-11 16:00:59 +01001356 if (!keyword_id) {
1357 fprintf(stderr, unknown_msg, line);
1358 return 0;
1359 }
1360
1361 el->type = keyword_id;
1362
1363 value1 = strtok_r(NULL, delimiters, &saveptr);
1364
1365 if (!value1) {
1366 fprintf(stderr, "Parameter missing in line '%s'\n", line);
1367 return -1;
1368 }
1369
1370 switch (keyword_id) {
1371 case IMAGE_CFG_VERSION:
1372 el->version = atoi(value1);
1373 break;
1374 case IMAGE_CFG_BOOT_FROM:
1375 ret = image_boot_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001376
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001377 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001378 fprintf(stderr, "Invalid boot media '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001379 return -1;
1380 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001381 el->bootfrom = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001382 break;
1383 case IMAGE_CFG_NAND_BLKSZ:
1384 el->nandblksz = strtoul(value1, NULL, 16);
1385 break;
1386 case IMAGE_CFG_NAND_BADBLK_LOCATION:
1387 el->nandbadblklocation = strtoul(value1, NULL, 16);
1388 break;
1389 case IMAGE_CFG_NAND_ECC_MODE:
1390 ret = image_nand_ecc_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001391
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001392 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001393 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001394 return -1;
1395 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001396 el->nandeccmode = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001397 break;
1398 case IMAGE_CFG_NAND_PAGESZ:
1399 el->nandpagesz = strtoul(value1, NULL, 16);
1400 break;
1401 case IMAGE_CFG_BINARY:
1402 argi = 0;
Mario Six94490a42017-01-11 16:00:54 +01001403
Mario Six4991b4f2017-01-11 16:00:59 +01001404 el->binary.file = strdup(value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001405 while (1) {
Mario Six4991b4f2017-01-11 16:00:59 +01001406 char *value = strtok_r(NULL, delimiters, &saveptr);
1407
Stefan Roese4acd2d22014-10-22 12:13:23 +02001408 if (!value)
1409 break;
1410 el->binary.args[argi] = strtoul(value, NULL, 16);
1411 argi++;
1412 if (argi >= BINARY_MAX_ARGS) {
1413 fprintf(stderr,
Mario Six4991b4f2017-01-11 16:00:59 +01001414 "Too many arguments for BINARY\n");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001415 return -1;
1416 }
1417 }
1418 el->binary.nargs = argi;
Mario Six4991b4f2017-01-11 16:00:59 +01001419 break;
1420 case IMAGE_CFG_DATA:
1421 value2 = strtok_r(NULL, delimiters, &saveptr);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001422
1423 if (!value1 || !value2) {
1424 fprintf(stderr,
1425 "Invalid number of arguments for DATA\n");
1426 return -1;
1427 }
1428
Stefan Roese4acd2d22014-10-22 12:13:23 +02001429 el->regdata.raddr = strtoul(value1, NULL, 16);
1430 el->regdata.rdata = strtoul(value2, NULL, 16);
Mario Six4991b4f2017-01-11 16:00:59 +01001431 break;
1432 case IMAGE_CFG_BAUDRATE:
1433 el->baudrate = strtoul(value1, NULL, 10);
1434 break;
1435 case IMAGE_CFG_DEBUG:
1436 el->debug = strtoul(value1, NULL, 10);
1437 break;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001438 case IMAGE_CFG_KAK:
1439 el->key_name = strdup(value1);
1440 break;
1441 case IMAGE_CFG_CSK:
1442 el->key_name = strdup(value1);
1443 break;
1444 case IMAGE_CFG_CSK_INDEX:
1445 el->csk_idx = strtol(value1, NULL, 0);
1446 break;
1447 case IMAGE_CFG_JTAG_DELAY:
1448 el->jtag_delay = strtoul(value1, NULL, 0);
1449 break;
1450 case IMAGE_CFG_BOX_ID:
1451 el->boxid = strtoul(value1, NULL, 0);
1452 break;
1453 case IMAGE_CFG_FLASH_ID:
1454 el->flashid = strtoul(value1, NULL, 0);
1455 break;
1456 case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1457 el->sec_specialized_img = true;
1458 break;
1459 case IMAGE_CFG_SEC_COMMON_IMG:
1460 el->sec_specialized_img = false;
1461 break;
1462 case IMAGE_CFG_SEC_BOOT_DEV:
1463 el->sec_boot_dev = strtoul(value1, NULL, 0);
1464 break;
1465 case IMAGE_CFG_SEC_FUSE_DUMP:
1466 el->name = strdup(value1);
1467 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001468 default:
1469 fprintf(stderr, unknown_msg, line);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001470 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301471
1472 return 0;
1473}
1474
Stefan Roese4acd2d22014-10-22 12:13:23 +02001475/*
1476 * Parse the configuration file 'fcfg' into the array of configuration
1477 * elements 'image_cfg', and return the number of configuration
1478 * elements in 'cfgn'.
1479 */
1480static int image_create_config_parse(FILE *fcfg)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301481{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001482 int ret;
1483 int cfgi = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301484
Stefan Roese4acd2d22014-10-22 12:13:23 +02001485 /* Parse the configuration file */
1486 while (!feof(fcfg)) {
1487 char *line;
1488 char buf[256];
1489
1490 /* Read the current line */
1491 memset(buf, 0, sizeof(buf));
1492 line = fgets(buf, sizeof(buf), fcfg);
1493 if (!line)
1494 break;
1495
1496 /* Ignore useless lines */
1497 if (line[0] == '\n' || line[0] == '#')
1498 continue;
1499
1500 /* Strip final newline */
1501 if (line[strlen(line) - 1] == '\n')
1502 line[strlen(line) - 1] = 0;
1503
1504 /* Parse the current line */
1505 ret = image_create_config_parse_oneline(line,
1506 &image_cfg[cfgi]);
1507 if (ret)
1508 return ret;
1509
1510 cfgi++;
1511
1512 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1513 fprintf(stderr,
1514 "Too many configuration elements in .cfg file\n");
1515 return -1;
1516 }
1517 }
1518
1519 cfgn = cfgi;
1520 return 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301521}
1522
Stefan Roese4acd2d22014-10-22 12:13:23 +02001523static int image_get_version(void)
1524{
1525 struct image_cfg_element *e;
1526
1527 e = image_find_option(IMAGE_CFG_VERSION);
1528 if (!e)
1529 return -1;
1530
1531 return e->version;
1532}
1533
Pali Rohárc934aad2021-07-23 11:13:57 +02001534static int image_get_bootfrom(void)
1535{
1536 struct image_cfg_element *e;
1537
1538 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1539 if (!e)
1540 return -1;
1541
1542 return e->bootfrom;
1543}
1544
Stefan Roese4acd2d22014-10-22 12:13:23 +02001545static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
1546 struct image_tool_params *params)
1547{
1548 FILE *fcfg;
1549 void *image = NULL;
1550 int version;
Łukasz Majewski93e93712014-11-21 09:22:43 +01001551 size_t headersz = 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001552 uint32_t checksum;
1553 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001554
1555 fcfg = fopen(params->imagename, "r");
1556 if (!fcfg) {
1557 fprintf(stderr, "Could not open input file %s\n",
1558 params->imagename);
1559 exit(EXIT_FAILURE);
1560 }
1561
1562 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1563 sizeof(struct image_cfg_element));
1564 if (!image_cfg) {
1565 fprintf(stderr, "Cannot allocate memory\n");
1566 fclose(fcfg);
1567 exit(EXIT_FAILURE);
1568 }
1569
1570 memset(image_cfg, 0,
1571 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1572 rewind(fcfg);
1573
1574 ret = image_create_config_parse(fcfg);
1575 fclose(fcfg);
1576 if (ret) {
1577 free(image_cfg);
1578 exit(EXIT_FAILURE);
1579 }
1580
1581 version = image_get_version();
Stefan Roese934a5292014-10-28 11:32:24 +01001582 switch (version) {
1583 /*
1584 * Fallback to version 0 if no version is provided in the
1585 * cfg file
1586 */
1587 case -1:
1588 case 0:
Stefan Roese4acd2d22014-10-22 12:13:23 +02001589 image = image_create_v0(&headersz, params, sbuf->st_size);
Stefan Roese934a5292014-10-28 11:32:24 +01001590 break;
1591
1592 case 1:
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001593 image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
Stefan Roese934a5292014-10-28 11:32:24 +01001594 break;
1595
1596 default:
1597 fprintf(stderr, "Unsupported version %d\n", version);
1598 free(image_cfg);
1599 exit(EXIT_FAILURE);
1600 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001601
1602 if (!image) {
1603 fprintf(stderr, "Could not create image\n");
1604 free(image_cfg);
1605 exit(EXIT_FAILURE);
1606 }
1607
1608 free(image_cfg);
1609
1610 /* Build and add image checksum header */
Pali Rohár37cb9c12021-07-23 11:13:56 +02001611 checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + headersz,
1612 sbuf->st_size - headersz - sizeof(uint32_t)));
1613 memcpy((uint8_t *)ptr + sbuf->st_size - sizeof(uint32_t), &checksum,
1614 sizeof(uint32_t));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001615
1616 /* Finally copy the header into the image area */
1617 memcpy(ptr, image, headersz);
1618
1619 free(image);
1620}
1621
1622static void kwbimage_print_header(const void *ptr)
1623{
1624 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
1625
1626 printf("Image Type: MVEBU Boot from %s Image\n",
1627 image_boot_mode_name(mhdr->blockid));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001628 printf("Image version:%d\n", image_version((void *)ptr));
Pali Rohár34dcf952021-07-23 11:14:04 +02001629 if (image_version((void *)ptr) == 1) {
1630 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
1631
1632 if (mhdr->ext & 0x1) {
1633 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1634 ((uint8_t *)ptr +
1635 sizeof(*mhdr));
1636
1637 while (1) {
1638 uint32_t ohdr_size;
1639
1640 ohdr_size = (ohdr->headersz_msb << 16) |
1641 le16_to_cpu(ohdr->headersz_lsb);
1642 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
1643 printf("BIN Hdr Size: ");
1644 genimg_print_size(ohdr_size - 12 - 4 * ohdr->data[0]);
1645 }
1646 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1647 break;
1648 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1649 ohdr_size);
1650 }
1651 }
1652 }
Gerald Kerma26f195c2014-10-31 01:03:27 +01001653 printf("Data Size: ");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001654 genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1655 printf("Load Address: %08x\n", mhdr->destaddr);
1656 printf("Entry Point: %08x\n", mhdr->execaddr);
1657}
1658
1659static int kwbimage_check_image_types(uint8_t type)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301660{
1661 if (type == IH_TYPE_KWBIMAGE)
1662 return EXIT_SUCCESS;
Mario Six94490a42017-01-11 16:00:54 +01001663
1664 return EXIT_FAILURE;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301665}
1666
Stefan Roese4acd2d22014-10-22 12:13:23 +02001667static int kwbimage_verify_header(unsigned char *ptr, int image_size,
1668 struct image_tool_params *params)
1669{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001670 uint8_t checksum;
Alexander Graf6cd56782018-03-15 11:14:19 +01001671 size_t header_size = kwbimage_header_size(ptr);
1672
1673 if (header_size > image_size)
1674 return -FDT_ERR_BADSTRUCTURE;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001675
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +03001676 if (!main_hdr_checksum_ok(ptr))
Stefan Roese4acd2d22014-10-22 12:13:23 +02001677 return -FDT_ERR_BADSTRUCTURE;
1678
1679 /* Only version 0 extended header has checksum */
1680 if (image_version((void *)ptr) == 0) {
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001681 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Mario Sixe89016c2017-01-11 16:00:56 +01001682
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001683 if (mhdr->ext & 0x1) {
1684 struct ext_hdr_v0 *ext_hdr;
1685
1686 ext_hdr = (struct ext_hdr_v0 *)
Mario Six885fba12017-01-11 16:00:55 +01001687 (ptr + sizeof(struct main_hdr_v0));
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001688 checksum = image_checksum8(ext_hdr,
1689 sizeof(struct ext_hdr_v0)
1690 - sizeof(uint8_t));
1691 if (checksum != ext_hdr->checksum)
1692 return -FDT_ERR_BADSTRUCTURE;
1693 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001694 }
1695
Pali Rohár93804452021-07-23 11:14:02 +02001696 if (image_version((void *)ptr) == 1) {
1697 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Pali Roháre0c243c2021-07-23 11:14:03 +02001698 uint32_t offset;
1699 uint32_t size;
Pali Rohár93804452021-07-23 11:14:02 +02001700
1701 if (mhdr->ext & 0x1) {
1702 uint32_t ohdr_size;
1703 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1704 (ptr + sizeof(*mhdr));
1705
1706 while (1) {
1707 if ((uint8_t *)ohdr + sizeof(*ohdr) >
1708 (uint8_t *)mhdr + header_size)
1709 return -FDT_ERR_BADSTRUCTURE;
1710
1711 ohdr_size = (ohdr->headersz_msb << 16) |
1712 le16_to_cpu(ohdr->headersz_lsb);
1713
1714 if (ohdr_size < 8 ||
1715 (uint8_t *)ohdr + ohdr_size >
1716 (uint8_t *)mhdr + header_size)
1717 return -FDT_ERR_BADSTRUCTURE;
1718
1719 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1720 break;
1721 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1722 ohdr_size);
1723 }
1724 }
Pali Roháre0c243c2021-07-23 11:14:03 +02001725
1726 offset = le32_to_cpu(mhdr->srcaddr);
1727
1728 /*
1729 * For SATA srcaddr is specified in number of sectors.
1730 * The main header is must be stored at sector number 1.
1731 * This expects that sector size is 512 bytes and recalculates
1732 * data offset to bytes relative to the main header.
1733 */
1734 if (mhdr->blockid == IBR_HDR_SATA_ID) {
1735 if (offset < 1)
1736 return -FDT_ERR_BADSTRUCTURE;
1737 offset -= 1;
1738 offset *= 512;
1739 }
1740
1741 /*
1742 * For SDIO srcaddr is specified in number of sectors.
1743 * This expects that sector size is 512 bytes and recalculates
1744 * data offset to bytes.
1745 */
1746 if (mhdr->blockid == IBR_HDR_SDIO_ID)
1747 offset *= 512;
1748
1749 /*
1750 * For PCIe srcaddr is always set to 0xFFFFFFFF.
1751 * This expects that data starts after all headers.
1752 */
1753 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
1754 offset = header_size;
1755
1756 if (offset > image_size || offset % 4 != 0)
1757 return -FDT_ERR_BADSTRUCTURE;
1758
1759 size = le32_to_cpu(mhdr->blocksize);
1760 if (offset + size > image_size || size % 4 != 0)
1761 return -FDT_ERR_BADSTRUCTURE;
1762
1763 if (image_checksum32(ptr + offset, size - 4) !=
1764 *(uint32_t *)(ptr + offset + size - 4))
1765 return -FDT_ERR_BADSTRUCTURE;
Pali Rohár93804452021-07-23 11:14:02 +02001766 }
1767
Stefan Roese4acd2d22014-10-22 12:13:23 +02001768 return 0;
1769}
1770
1771static int kwbimage_generate(struct image_tool_params *params,
1772 struct image_type_params *tparams)
1773{
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001774 FILE *fcfg;
Pali Rohár37cb9c12021-07-23 11:13:56 +02001775 struct stat s;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001776 int alloc_len;
Pali Rohárc934aad2021-07-23 11:13:57 +02001777 int bootfrom;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001778 int version;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001779 void *hdr;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001780 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001781
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001782 fcfg = fopen(params->imagename, "r");
1783 if (!fcfg) {
1784 fprintf(stderr, "Could not open input file %s\n",
1785 params->imagename);
1786 exit(EXIT_FAILURE);
1787 }
1788
Pali Rohár37cb9c12021-07-23 11:13:56 +02001789 if (stat(params->datafile, &s)) {
1790 fprintf(stderr, "Could not stat data file %s: %s\n",
1791 params->datafile, strerror(errno));
1792 exit(EXIT_FAILURE);
1793 }
1794
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001795 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1796 sizeof(struct image_cfg_element));
1797 if (!image_cfg) {
1798 fprintf(stderr, "Cannot allocate memory\n");
1799 fclose(fcfg);
1800 exit(EXIT_FAILURE);
1801 }
1802
1803 memset(image_cfg, 0,
1804 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1805 rewind(fcfg);
1806
1807 ret = image_create_config_parse(fcfg);
1808 fclose(fcfg);
1809 if (ret) {
1810 free(image_cfg);
1811 exit(EXIT_FAILURE);
1812 }
1813
Pali Rohárc934aad2021-07-23 11:13:57 +02001814 bootfrom = image_get_bootfrom();
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001815 version = image_get_version();
1816 switch (version) {
1817 /*
1818 * Fallback to version 0 if no version is provided in the
1819 * cfg file
1820 */
1821 case -1:
1822 case 0:
Stefan Roese4acd2d22014-10-22 12:13:23 +02001823 alloc_len = sizeof(struct main_hdr_v0) +
1824 sizeof(struct ext_hdr_v0);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001825 break;
1826
1827 case 1:
Mario Sixe93cf532017-01-11 16:00:57 +01001828 alloc_len = image_headersz_v1(NULL);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001829 break;
1830
1831 default:
1832 fprintf(stderr, "Unsupported version %d\n", version);
1833 free(image_cfg);
1834 exit(EXIT_FAILURE);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001835 }
1836
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001837 free(image_cfg);
1838
Stefan Roese4acd2d22014-10-22 12:13:23 +02001839 hdr = malloc(alloc_len);
1840 if (!hdr) {
1841 fprintf(stderr, "%s: malloc return failure: %s\n",
1842 params->cmdname, strerror(errno));
1843 exit(EXIT_FAILURE);
1844 }
1845
1846 memset(hdr, 0, alloc_len);
1847 tparams->header_size = alloc_len;
1848 tparams->hdr = hdr;
1849
Stefan Roese77720852015-11-24 09:14:59 +01001850 /*
1851 * The resulting image needs to be 4-byte aligned. At least
1852 * the Marvell hdrparser tool complains if its unaligned.
Pali Rohár37cb9c12021-07-23 11:13:56 +02001853 * After the image data is stored 4-byte checksum.
Pali Rohárc934aad2021-07-23 11:13:57 +02001854 * Final SPI and NAND images must be aligned to 256 bytes.
Pali Rohár501a54a2021-07-23 11:13:59 +02001855 * Final SATA and SDIO images must be aligned to 512 bytes.
Stefan Roese77720852015-11-24 09:14:59 +01001856 */
Pali Rohárc934aad2021-07-23 11:13:57 +02001857 if (bootfrom == IBR_HDR_SPI_ID || bootfrom == IBR_HDR_NAND_ID)
1858 return 4 + (256 - (alloc_len + s.st_size + 4) % 256) % 256;
Pali Rohár501a54a2021-07-23 11:13:59 +02001859 else if (bootfrom == IBR_HDR_SATA_ID || bootfrom == IBR_HDR_SDIO_ID)
1860 return 4 + (512 - (alloc_len + s.st_size + 4) % 512) % 512;
Pali Rohárc934aad2021-07-23 11:13:57 +02001861 else
1862 return 4 + (4 - s.st_size % 4) % 4;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001863}
1864
1865/*
1866 * Report Error if xflag is set in addition to default
1867 */
1868static int kwbimage_check_params(struct image_tool_params *params)
1869{
1870 if (!strlen(params->imagename)) {
Mario Six94490a42017-01-11 16:00:54 +01001871 char *msg = "Configuration file for kwbimage creation omitted";
1872
1873 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001874 return CFG_INVALID;
1875 }
1876
1877 return (params->dflag && (params->fflag || params->lflag)) ||
1878 (params->fflag && (params->dflag || params->lflag)) ||
1879 (params->lflag && (params->dflag || params->fflag)) ||
1880 (params->xflag) || !(strlen(params->imagename));
1881}
1882
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301883/*
1884 * kwbimage type parameters definition
1885 */
Guilherme Maciel Ferreiraa93648d2015-01-15 02:48:07 -02001886U_BOOT_IMAGE_TYPE(
1887 kwbimage,
1888 "Marvell MVEBU Boot Image support",
1889 0,
1890 NULL,
1891 kwbimage_check_params,
1892 kwbimage_verify_header,
1893 kwbimage_print_header,
1894 kwbimage_set_header,
1895 NULL,
1896 kwbimage_check_image_types,
1897 NULL,
1898 kwbimage_generate
1899);