blob: 76c25628d42b12f85dc0061701738580502571f7 [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
92#define BINARY_MAX_ARGS 8
93
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,
106 IMAGE_CFG_PAYLOAD,
107 IMAGE_CFG_DATA,
108 IMAGE_CFG_BAUDRATE,
109 IMAGE_CFG_DEBUG,
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100110 IMAGE_CFG_KAK,
111 IMAGE_CFG_CSK,
112 IMAGE_CFG_CSK_INDEX,
113 IMAGE_CFG_JTAG_DELAY,
114 IMAGE_CFG_BOX_ID,
115 IMAGE_CFG_FLASH_ID,
116 IMAGE_CFG_SEC_COMMON_IMG,
117 IMAGE_CFG_SEC_SPECIALIZED_IMG,
118 IMAGE_CFG_SEC_BOOT_DEV,
119 IMAGE_CFG_SEC_FUSE_DUMP,
Mario Six4991b4f2017-01-11 16:00:59 +0100120
121 IMAGE_CFG_COUNT
122} type;
123
124static const char * const id_strs[] = {
125 [IMAGE_CFG_VERSION] = "VERSION",
126 [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
127 [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
128 [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
129 [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
130 [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
131 [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
132 [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
133 [IMAGE_CFG_BINARY] = "BINARY",
134 [IMAGE_CFG_PAYLOAD] = "PAYLOAD",
135 [IMAGE_CFG_DATA] = "DATA",
136 [IMAGE_CFG_BAUDRATE] = "BAUDRATE",
137 [IMAGE_CFG_DEBUG] = "DEBUG",
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100138 [IMAGE_CFG_KAK] = "KAK",
139 [IMAGE_CFG_CSK] = "CSK",
140 [IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
141 [IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
142 [IMAGE_CFG_BOX_ID] = "BOX_ID",
143 [IMAGE_CFG_FLASH_ID] = "FLASH_ID",
144 [IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
145 [IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
146 [IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
147 [IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
Mario Six4991b4f2017-01-11 16:00:59 +0100148};
149
Stefan Roese4acd2d22014-10-22 12:13:23 +0200150struct image_cfg_element {
Mario Six4991b4f2017-01-11 16:00:59 +0100151 enum image_cfg_type type;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200152 union {
153 unsigned int version;
154 unsigned int bootfrom;
155 struct {
156 const char *file;
157 unsigned int args[BINARY_MAX_ARGS];
158 unsigned int nargs;
159 } binary;
160 const char *payload;
161 unsigned int dstaddr;
162 unsigned int execaddr;
163 unsigned int nandblksz;
164 unsigned int nandbadblklocation;
165 unsigned int nandeccmode;
166 unsigned int nandpagesz;
167 struct ext_hdr_v0_reg regdata;
Chris Packham4bdb5472016-11-09 22:07:45 +1300168 unsigned int baudrate;
Chris Packham2611c052016-11-09 22:21:45 +1300169 unsigned int debug;
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100170 const char *key_name;
171 int csk_idx;
172 uint8_t jtag_delay;
173 uint32_t boxid;
174 uint32_t flashid;
175 bool sec_specialized_img;
176 unsigned int sec_boot_dev;
177 const char *name;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200178 };
179};
180
181#define IMAGE_CFG_ELEMENT_MAX 256
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530182
183/*
Stefan Roese4acd2d22014-10-22 12:13:23 +0200184 * Utility functions to manipulate boot mode and ecc modes (convert
185 * them back and forth between description strings and the
186 * corresponding numerical identifiers).
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530187 */
Stefan Roese4acd2d22014-10-22 12:13:23 +0200188
189static const char *image_boot_mode_name(unsigned int id)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530190{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200191 int i;
Mario Six94490a42017-01-11 16:00:54 +0100192
Stefan Roese4acd2d22014-10-22 12:13:23 +0200193 for (i = 0; boot_modes[i].name; i++)
194 if (boot_modes[i].id == id)
195 return boot_modes[i].name;
196 return NULL;
197}
198
199int image_boot_mode_id(const char *boot_mode_name)
200{
201 int i;
Mario Six94490a42017-01-11 16:00:54 +0100202
Stefan Roese4acd2d22014-10-22 12:13:23 +0200203 for (i = 0; boot_modes[i].name; i++)
204 if (!strcmp(boot_modes[i].name, boot_mode_name))
205 return boot_modes[i].id;
206
207 return -1;
208}
209
210int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
211{
212 int i;
Mario Six94490a42017-01-11 16:00:54 +0100213
Stefan Roese4acd2d22014-10-22 12:13:23 +0200214 for (i = 0; nand_ecc_modes[i].name; i++)
215 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
216 return nand_ecc_modes[i].id;
217 return -1;
218}
219
220static struct image_cfg_element *
221image_find_option(unsigned int optiontype)
222{
223 int i;
224
225 for (i = 0; i < cfgn; i++) {
226 if (image_cfg[i].type == optiontype)
227 return &image_cfg[i];
228 }
229
230 return NULL;
231}
232
233static unsigned int
234image_count_options(unsigned int optiontype)
235{
236 int i;
237 unsigned int count = 0;
238
239 for (i = 0; i < cfgn; i++)
240 if (image_cfg[i].type == optiontype)
241 count++;
242
243 return count;
244}
245
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100246#if defined(CONFIG_KWB_SECURE)
247
248static int image_get_csk_index(void)
249{
250 struct image_cfg_element *e;
251
252 e = image_find_option(IMAGE_CFG_CSK_INDEX);
253 if (!e)
254 return -1;
255
256 return e->csk_idx;
257}
258
259static bool image_get_spezialized_img(void)
260{
261 struct image_cfg_element *e;
262
263 e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
264 if (!e)
265 return false;
266
267 return e->sec_specialized_img;
268}
269
270#endif
271
Stefan Roese4acd2d22014-10-22 12:13:23 +0200272/*
273 * Compute a 8-bit checksum of a memory area. This algorithm follows
274 * the requirements of the Marvell SoC BootROM specifications.
275 */
276static uint8_t image_checksum8(void *start, uint32_t len)
277{
278 uint8_t csum = 0;
279 uint8_t *p = start;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530280
281 /* check len and return zero checksum if invalid */
282 if (!len)
283 return 0;
284
285 do {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200286 csum += *p;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530287 p++;
288 } while (--len);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200289
290 return csum;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530291}
292
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +0300293size_t kwbimage_header_size(unsigned char *ptr)
294{
295 if (image_version((void *)ptr) == 0)
296 return sizeof(struct main_hdr_v0);
297 else
298 return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr);
299}
300
301/*
302 * Verify checksum over a complete header that includes the checksum field.
303 * Return 1 when OK, otherwise 0.
304 */
305static int main_hdr_checksum_ok(void *hdr)
306{
307 /* Offsets of checksum in v0 and v1 headers are the same */
308 struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
309 uint8_t checksum;
310
311 checksum = image_checksum8(hdr, kwbimage_header_size(hdr));
312 /* Calculated checksum includes the header checksum field. Compensate
313 * for that.
314 */
315 checksum -= main_hdr->checksum;
316
317 return checksum == main_hdr->checksum;
318}
319
Stefan Roese4acd2d22014-10-22 12:13:23 +0200320static uint32_t image_checksum32(void *start, uint32_t len)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530321{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200322 uint32_t csum = 0;
323 uint32_t *p = start;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530324
325 /* check len and return zero checksum if invalid */
326 if (!len)
327 return 0;
328
329 if (len % sizeof(uint32_t)) {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200330 fprintf(stderr, "Length %d is not in multiple of %zu\n",
331 len, sizeof(uint32_t));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530332 return 0;
333 }
334
335 do {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200336 csum += *p;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530337 p++;
338 len -= sizeof(uint32_t);
339 } while (len > 0);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200340
341 return csum;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530342}
343
Chris Packham4bdb5472016-11-09 22:07:45 +1300344static uint8_t baudrate_to_option(unsigned int baudrate)
345{
346 switch (baudrate) {
347 case 2400:
348 return MAIN_HDR_V1_OPT_BAUD_2400;
349 case 4800:
350 return MAIN_HDR_V1_OPT_BAUD_4800;
351 case 9600:
352 return MAIN_HDR_V1_OPT_BAUD_9600;
353 case 19200:
354 return MAIN_HDR_V1_OPT_BAUD_19200;
355 case 38400:
356 return MAIN_HDR_V1_OPT_BAUD_38400;
357 case 57600:
358 return MAIN_HDR_V1_OPT_BAUD_57600;
359 case 115200:
360 return MAIN_HDR_V1_OPT_BAUD_115200;
361 default:
362 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
363 }
364}
365
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100366#if defined(CONFIG_KWB_SECURE)
367static void kwb_msg(const char *fmt, ...)
368{
369 if (verbose_mode) {
370 va_list ap;
371
372 va_start(ap, fmt);
373 vfprintf(stdout, fmt, ap);
374 va_end(ap);
375 }
376}
377
378static int openssl_err(const char *msg)
379{
380 unsigned long ssl_err = ERR_get_error();
381
382 fprintf(stderr, "%s", msg);
383 fprintf(stderr, ": %s\n",
384 ERR_error_string(ssl_err, 0));
385
386 return -1;
387}
388
389static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
390{
391 char path[PATH_MAX];
392 RSA *rsa;
393 FILE *f;
394
395 if (!keydir)
396 keydir = ".";
397
398 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
399 f = fopen(path, "r");
400 if (!f) {
401 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
402 path, strerror(errno));
403 return -ENOENT;
404 }
405
406 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
407 if (!rsa) {
408 openssl_err("Failure reading private key");
409 fclose(f);
410 return -EPROTO;
411 }
412 fclose(f);
413 *p_rsa = rsa;
414
415 return 0;
416}
417
418static int kwb_load_cfg_key(struct image_tool_params *params,
419 unsigned int cfg_option, const char *key_name,
420 RSA **p_key)
421{
422 struct image_cfg_element *e_key;
423 RSA *key;
424 int res;
425
426 *p_key = NULL;
427
428 e_key = image_find_option(cfg_option);
429 if (!e_key) {
430 fprintf(stderr, "%s not configured\n", key_name);
431 return -ENOENT;
432 }
433
434 res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
435 if (res < 0) {
436 fprintf(stderr, "Failed to load %s\n", key_name);
437 return -ENOENT;
438 }
439
440 *p_key = key;
441
442 return 0;
443}
444
445static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
446{
447 return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
448}
449
450static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
451{
452 return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
453}
454
455static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
456 struct hash_v1 *hash)
457{
458 EVP_MD_CTX *ctx;
459 unsigned int key_size;
460 unsigned int hash_size;
461 int ret = 0;
462
463 if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
464 return -EINVAL;
465
466 key_size = (pk->key[2] << 8) + pk->key[3] + 4;
467
468 ctx = EVP_MD_CTX_create();
469 if (!ctx)
470 return openssl_err("EVP context creation failed");
471
472 EVP_MD_CTX_init(ctx);
473 if (!EVP_DigestInit(ctx, EVP_sha256())) {
474 ret = openssl_err("Digest setup failed");
475 goto hash_err_ctx;
476 }
477
478 if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
479 ret = openssl_err("Hashing data failed");
480 goto hash_err_ctx;
481 }
482
483 if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
484 ret = openssl_err("Could not obtain hash");
485 goto hash_err_ctx;
486 }
487
488 EVP_MD_CTX_cleanup(ctx);
489
490hash_err_ctx:
491 EVP_MD_CTX_destroy(ctx);
492 return ret;
493}
494
495static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
496{
497 RSA *rsa;
498 const unsigned char *ptr;
499
500 if (!key || !src)
501 goto fail;
502
503 ptr = src->key;
504 rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
505 if (!rsa) {
506 openssl_err("error decoding public key");
507 goto fail;
508 }
509
510 return 0;
511fail:
512 fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
513 return -EINVAL;
514}
515
516static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
517 char *keyname)
518{
519 int size_exp, size_mod, size_seq;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200520 const BIGNUM *key_e, *key_n;
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100521 uint8_t *cur;
522 char *errmsg = "Failed to encode %s\n";
523
Jelle van der Waae15843b2017-05-08 21:31:20 +0200524 RSA_get0_key(key, NULL, &key_e, NULL);
525 RSA_get0_key(key, &key_n, NULL, NULL);
526
527 if (!key || !key_e || !key_n || !dst) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100528 fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
Jelle van der Waae15843b2017-05-08 21:31:20 +0200529 key, key_e, key_n, dst);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100530 fprintf(stderr, errmsg, keyname);
531 return -EINVAL;
532 }
533
534 /*
535 * According to the specs, the key should be PKCS#1 DER encoded.
536 * But unfortunately the really required encoding seems to be different;
537 * it violates DER...! (But it still conformes to BER.)
538 * (Length always in long form w/ 2 byte length code; no leading zero
539 * when MSB of first byte is set...)
540 * So we cannot use the encoding func provided by OpenSSL and have to
541 * do the encoding manually.
542 */
543
Jelle van der Waae15843b2017-05-08 21:31:20 +0200544 size_exp = BN_num_bytes(key_e);
545 size_mod = BN_num_bytes(key_n);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100546 size_seq = 4 + size_mod + 4 + size_exp;
547
548 if (size_mod > 256) {
549 fprintf(stderr, "export pk failed: wrong mod size: %d\n",
550 size_mod);
551 fprintf(stderr, errmsg, keyname);
552 return -EINVAL;
553 }
554
555 if (4 + size_seq > sizeof(dst->key)) {
556 fprintf(stderr, "export pk failed: seq too large (%d, %lu)\n",
557 4 + size_seq, sizeof(dst->key));
558 fprintf(stderr, errmsg, keyname);
559 return -ENOBUFS;
560 }
561
562 cur = dst->key;
563
564 /* PKCS#1 (RFC3447) RSAPublicKey structure */
565 *cur++ = 0x30; /* SEQUENCE */
566 *cur++ = 0x82;
567 *cur++ = (size_seq >> 8) & 0xFF;
568 *cur++ = size_seq & 0xFF;
569 /* Modulus */
570 *cur++ = 0x02; /* INTEGER */
571 *cur++ = 0x82;
572 *cur++ = (size_mod >> 8) & 0xFF;
573 *cur++ = size_mod & 0xFF;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200574 BN_bn2bin(key_n, cur);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100575 cur += size_mod;
576 /* Exponent */
577 *cur++ = 0x02; /* INTEGER */
578 *cur++ = 0x82;
579 *cur++ = (size_exp >> 8) & 0xFF;
580 *cur++ = size_exp & 0xFF;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200581 BN_bn2bin(key_e, cur);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100582
583 if (hashf) {
584 struct hash_v1 pk_hash;
585 int i;
586 int ret = 0;
587
588 ret = kwb_compute_pubkey_hash(dst, &pk_hash);
589 if (ret < 0) {
590 fprintf(stderr, errmsg, keyname);
591 return ret;
592 }
593
594 fprintf(hashf, "SHA256 = ");
595 for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
596 fprintf(hashf, "%02X", pk_hash.hash[i]);
597 fprintf(hashf, "\n");
598 }
599
600 return 0;
601}
602
603int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
604{
605 EVP_PKEY *evp_key;
606 EVP_MD_CTX *ctx;
607 unsigned int sig_size;
608 int size;
609 int ret = 0;
610
611 evp_key = EVP_PKEY_new();
612 if (!evp_key)
613 return openssl_err("EVP_PKEY object creation failed");
614
615 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
616 ret = openssl_err("EVP key setup failed");
617 goto err_key;
618 }
619
620 size = EVP_PKEY_size(evp_key);
621 if (size > sizeof(sig->sig)) {
622 fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
623 size);
624 ret = -ENOBUFS;
625 goto err_key;
626 }
627
628 ctx = EVP_MD_CTX_create();
629 if (!ctx) {
630 ret = openssl_err("EVP context creation failed");
631 goto err_key;
632 }
633 EVP_MD_CTX_init(ctx);
634 if (!EVP_SignInit(ctx, EVP_sha256())) {
635 ret = openssl_err("Signer setup failed");
636 goto err_ctx;
637 }
638
639 if (!EVP_SignUpdate(ctx, data, datasz)) {
640 ret = openssl_err("Signing data failed");
641 goto err_ctx;
642 }
643
644 if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
645 ret = openssl_err("Could not obtain signature");
646 goto err_ctx;
647 }
648
649 EVP_MD_CTX_cleanup(ctx);
650 EVP_MD_CTX_destroy(ctx);
651 EVP_PKEY_free(evp_key);
652
653 return 0;
654
655err_ctx:
656 EVP_MD_CTX_destroy(ctx);
657err_key:
658 EVP_PKEY_free(evp_key);
659 fprintf(stderr, "Failed to create %s signature\n", signame);
660 return ret;
661}
662
663int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
664 char *signame)
665{
666 EVP_PKEY *evp_key;
667 EVP_MD_CTX *ctx;
668 int size;
669 int ret = 0;
670
671 evp_key = EVP_PKEY_new();
672 if (!evp_key)
673 return openssl_err("EVP_PKEY object creation failed");
674
675 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
676 ret = openssl_err("EVP key setup failed");
677 goto err_key;
678 }
679
680 size = EVP_PKEY_size(evp_key);
681 if (size > sizeof(sig->sig)) {
682 fprintf(stderr, "Invalid signature size (%d bytes)\n",
683 size);
684 ret = -EINVAL;
685 goto err_key;
686 }
687
688 ctx = EVP_MD_CTX_create();
689 if (!ctx) {
690 ret = openssl_err("EVP context creation failed");
691 goto err_key;
692 }
693 EVP_MD_CTX_init(ctx);
694 if (!EVP_VerifyInit(ctx, EVP_sha256())) {
695 ret = openssl_err("Verifier setup failed");
696 goto err_ctx;
697 }
698
699 if (!EVP_VerifyUpdate(ctx, data, datasz)) {
700 ret = openssl_err("Hashing data failed");
701 goto err_ctx;
702 }
703
Young Xiao22515122019-04-17 17:20:24 +0800704 if (EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key) != 1) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100705 ret = openssl_err("Could not verify signature");
706 goto err_ctx;
707 }
708
709 EVP_MD_CTX_cleanup(ctx);
710 EVP_MD_CTX_destroy(ctx);
711 EVP_PKEY_free(evp_key);
712
713 return 0;
714
715err_ctx:
716 EVP_MD_CTX_destroy(ctx);
717err_key:
718 EVP_PKEY_free(evp_key);
719 fprintf(stderr, "Failed to verify %s signature\n", signame);
720 return ret;
721}
722
723int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
724 char *signame)
725{
726 if (kwb_sign(key, data, datasz, sig, signame) < 0)
727 return -1;
728
729 if (kwb_verify(key, data, datasz, sig, signame) < 0)
730 return -1;
731
732 return 0;
733}
734
735
736int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
737{
738 struct hash_v1 kak_pub_hash;
739 struct image_cfg_element *e;
740 unsigned int fuse_line;
741 int i, idx;
742 uint8_t *ptr;
743 uint32_t val;
744 int ret = 0;
745
746 if (!out || !sec_hdr)
747 return -EINVAL;
748
749 ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
750 if (ret < 0)
751 goto done;
752
753 fprintf(out, "# burn KAK pub key hash\n");
754 ptr = kak_pub_hash.hash;
755 for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
756 fprintf(out, "fuse prog -y %u 0 ", fuse_line);
757
758 for (i = 4; i-- > 0;)
759 fprintf(out, "%02hx", (ushort)ptr[i]);
760 ptr += 4;
761 fprintf(out, " 00");
762
763 if (fuse_line < 30) {
764 for (i = 3; i-- > 0;)
765 fprintf(out, "%02hx", (ushort)ptr[i]);
766 ptr += 3;
767 } else {
768 fprintf(out, "000000");
769 }
770
771 fprintf(out, " 1\n");
772 }
773
774 fprintf(out, "# burn CSK selection\n");
775
776 idx = image_get_csk_index();
777 if (idx < 0 || idx > 15) {
778 ret = -EINVAL;
779 goto done;
780 }
781 if (idx > 0) {
782 for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
783 fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
784 fuse_line);
785 } else {
786 fprintf(out, "# CSK index is 0; no mods needed\n");
787 }
788
789 e = image_find_option(IMAGE_CFG_BOX_ID);
790 if (e) {
791 fprintf(out, "# set box ID\n");
792 fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
793 }
794
795 e = image_find_option(IMAGE_CFG_FLASH_ID);
796 if (e) {
797 fprintf(out, "# set flash ID\n");
798 fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
799 }
800
801 fprintf(out, "# enable secure mode ");
802 fprintf(out, "(must be the last fuse line written)\n");
803
804 val = 1;
805 e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
806 if (!e) {
807 fprintf(stderr, "ERROR: secured mode boot device not given\n");
808 ret = -EINVAL;
809 goto done;
810 }
811
812 if (e->sec_boot_dev > 0xff) {
813 fprintf(stderr, "ERROR: secured mode boot device invalid\n");
814 ret = -EINVAL;
815 goto done;
816 }
817
818 val |= (e->sec_boot_dev << 8);
819
820 fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
821
822 fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
823 for (fuse_line = 0; fuse_line < 24; ++fuse_line)
824 fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
825
826 fprintf(out, "# OK, that's all :-)\n");
827
828done:
829 return ret;
830}
831
832static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
833{
834 int ret = 0;
835 struct image_cfg_element *e;
836
837 e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
838 if (!e)
839 return 0;
840
841 if (!strcmp(e->name, "a38x")) {
842 FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
843
844 kwb_dump_fuse_cmds_38x(out, sec_hdr);
845 fclose(out);
846 goto done;
847 }
848
849 ret = -ENOSYS;
850
851done:
852 return ret;
853}
854
855#endif
856
Stefan Roese4acd2d22014-10-22 12:13:23 +0200857static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
858 int payloadsz)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530859{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200860 struct image_cfg_element *e;
861 size_t headersz;
862 struct main_hdr_v0 *main_hdr;
Mario Six885fba12017-01-11 16:00:55 +0100863 uint8_t *image;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200864 int has_ext = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530865
Stefan Roese4acd2d22014-10-22 12:13:23 +0200866 /*
867 * Calculate the size of the header and the size of the
868 * payload
869 */
870 headersz = sizeof(struct main_hdr_v0);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530871
Stefan Roese4acd2d22014-10-22 12:13:23 +0200872 if (image_count_options(IMAGE_CFG_DATA) > 0) {
873 has_ext = 1;
874 headersz += sizeof(struct ext_hdr_v0);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530875 }
876
Stefan Roese4acd2d22014-10-22 12:13:23 +0200877 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
878 fprintf(stderr, "More than one payload, not possible\n");
879 return NULL;
880 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530881
Stefan Roese4acd2d22014-10-22 12:13:23 +0200882 image = malloc(headersz);
883 if (!image) {
884 fprintf(stderr, "Cannot allocate memory for image\n");
885 return NULL;
886 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530887
Stefan Roese4acd2d22014-10-22 12:13:23 +0200888 memset(image, 0, headersz);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530889
Mario Six885fba12017-01-11 16:00:55 +0100890 main_hdr = (struct main_hdr_v0 *)image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530891
Stefan Roese4acd2d22014-10-22 12:13:23 +0200892 /* Fill in the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100893 main_hdr->blocksize =
Pali Rohár37cb9c12021-07-23 11:13:56 +0200894 cpu_to_le32(payloadsz - headersz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100895 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200896 main_hdr->ext = has_ext;
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100897 main_hdr->destaddr = cpu_to_le32(params->addr);
898 main_hdr->execaddr = cpu_to_le32(params->ep);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530899
Stefan Roese4acd2d22014-10-22 12:13:23 +0200900 e = image_find_option(IMAGE_CFG_BOOT_FROM);
901 if (e)
902 main_hdr->blockid = e->bootfrom;
903 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
904 if (e)
905 main_hdr->nandeccmode = e->nandeccmode;
906 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
907 if (e)
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100908 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200909 main_hdr->checksum = image_checksum8(image,
910 sizeof(struct main_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530911
Stefan Roese4acd2d22014-10-22 12:13:23 +0200912 /* Generate the ext header */
913 if (has_ext) {
Mario Sixe89016c2017-01-11 16:00:56 +0100914 struct ext_hdr_v0 *ext_hdr;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200915 int cfgi, datai;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530916
Mario Six885fba12017-01-11 16:00:55 +0100917 ext_hdr = (struct ext_hdr_v0 *)
918 (image + sizeof(struct main_hdr_v0));
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100919 ext_hdr->offset = cpu_to_le32(0x40);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530920
Stefan Roese4acd2d22014-10-22 12:13:23 +0200921 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
922 e = &image_cfg[cfgi];
923 if (e->type != IMAGE_CFG_DATA)
924 continue;
925
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100926 ext_hdr->rcfg[datai].raddr =
927 cpu_to_le32(e->regdata.raddr);
928 ext_hdr->rcfg[datai].rdata =
929 cpu_to_le32(e->regdata.rdata);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200930 datai++;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530931 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530932
Stefan Roese4acd2d22014-10-22 12:13:23 +0200933 ext_hdr->checksum = image_checksum8(ext_hdr,
934 sizeof(struct ext_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530935 }
936
Stefan Roese4acd2d22014-10-22 12:13:23 +0200937 *imagesz = headersz;
938 return image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530939}
940
Mario Sixe93cf532017-01-11 16:00:57 +0100941static size_t image_headersz_v1(int *hasext)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530942{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200943 struct image_cfg_element *binarye;
944 size_t headersz;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530945
Stefan Roese4acd2d22014-10-22 12:13:23 +0200946 /*
947 * Calculate the size of the header and the size of the
948 * payload
949 */
950 headersz = sizeof(struct main_hdr_v1);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530951
Stefan Roese4acd2d22014-10-22 12:13:23 +0200952 if (image_count_options(IMAGE_CFG_BINARY) > 1) {
953 fprintf(stderr, "More than one binary blob, not supported\n");
954 return 0;
955 }
956
957 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
958 fprintf(stderr, "More than one payload, not possible\n");
959 return 0;
960 }
961
962 binarye = image_find_option(IMAGE_CFG_BINARY);
963 if (binarye) {
Mario Sixe89016c2017-01-11 16:00:56 +0100964 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200965 struct stat s;
966
967 ret = stat(binarye->binary.file, &s);
968 if (ret < 0) {
Andreas Bießmanne5f1a582014-10-24 23:39:11 +0200969 char cwd[PATH_MAX];
970 char *dir = cwd;
971
972 memset(cwd, 0, sizeof(cwd));
973 if (!getcwd(cwd, sizeof(cwd))) {
974 dir = "current working directory";
975 perror("getcwd() failed");
976 }
977
Stefan Roese4acd2d22014-10-22 12:13:23 +0200978 fprintf(stderr,
979 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
980 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
981 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
Andreas Bießmanne5f1a582014-10-24 23:39:11 +0200982 binarye->binary.file, dir);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200983 return 0;
984 }
985
Reinhard Pfau76b391c2015-11-29 15:52:14 +0100986 headersz += sizeof(struct opt_hdr_v1) +
987 s.st_size +
988 (binarye->binary.nargs + 2) * sizeof(uint32_t);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200989 if (hasext)
990 *hasext = 1;
991 }
992
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100993#if defined(CONFIG_KWB_SECURE)
994 if (image_get_csk_index() >= 0) {
995 headersz += sizeof(struct secure_hdr_v1);
996 if (hasext)
997 *hasext = 1;
998 }
999#endif
1000
Stefan Roese7ddf8cf2015-07-20 11:20:38 +02001001#if defined(CONFIG_SYS_U_BOOT_OFFS)
1002 if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
Mario Six94490a42017-01-11 16:00:54 +01001003 fprintf(stderr,
1004 "Error: Image header (incl. SPL image) too big!\n");
Stefan Roese7ddf8cf2015-07-20 11:20:38 +02001005 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
1006 (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
1007 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
Kevin Smitha0aad122015-03-16 14:58:21 +00001008 return 0;
Kevin Smitha0aad122015-03-16 14:58:21 +00001009 }
Mario Six79066ef2017-01-11 16:00:58 +01001010
Mario Six94490a42017-01-11 16:00:54 +01001011 headersz = CONFIG_SYS_U_BOOT_OFFS;
Kevin Smitha0aad122015-03-16 14:58:21 +00001012#endif
1013
Stefan Roese4acd2d22014-10-22 12:13:23 +02001014 /*
1015 * The payload should be aligned on some reasonable
1016 * boundary
1017 */
Kever Yange002ee72020-03-30 11:56:20 +08001018 return ALIGN(headersz, 4096);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001019}
1020
Mario Six79066ef2017-01-11 16:00:58 +01001021int add_binary_header_v1(uint8_t *cur)
1022{
1023 struct image_cfg_element *binarye;
1024 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)cur;
1025 uint32_t *args;
1026 size_t binhdrsz;
1027 struct stat s;
1028 int argi;
1029 FILE *bin;
1030 int ret;
1031
1032 binarye = image_find_option(IMAGE_CFG_BINARY);
1033
1034 if (!binarye)
1035 return 0;
1036
1037 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1038
1039 bin = fopen(binarye->binary.file, "r");
1040 if (!bin) {
1041 fprintf(stderr, "Cannot open binary file %s\n",
1042 binarye->binary.file);
1043 return -1;
1044 }
1045
Mario Six1f6c8a52017-02-13 10:11:55 +01001046 if (fstat(fileno(bin), &s)) {
1047 fprintf(stderr, "Cannot stat binary file %s\n",
1048 binarye->binary.file);
1049 goto err_close;
1050 }
Mario Six79066ef2017-01-11 16:00:58 +01001051
1052 binhdrsz = sizeof(struct opt_hdr_v1) +
1053 (binarye->binary.nargs + 2) * sizeof(uint32_t) +
1054 s.st_size;
1055
1056 /*
1057 * The size includes the binary image size, rounded
1058 * up to a 4-byte boundary. Plus 4 bytes for the
1059 * next-header byte and 3-byte alignment at the end.
1060 */
Kever Yange002ee72020-03-30 11:56:20 +08001061 binhdrsz = ALIGN(binhdrsz, 4) + 4;
Mario Six79066ef2017-01-11 16:00:58 +01001062 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1063 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1064
1065 cur += sizeof(struct opt_hdr_v1);
1066
1067 args = (uint32_t *)cur;
1068 *args = cpu_to_le32(binarye->binary.nargs);
1069 args++;
1070 for (argi = 0; argi < binarye->binary.nargs; argi++)
1071 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1072
1073 cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
1074
1075 ret = fread(cur, s.st_size, 1, bin);
1076 if (ret != 1) {
1077 fprintf(stderr,
1078 "Could not read binary image %s\n",
1079 binarye->binary.file);
Mario Six1f6c8a52017-02-13 10:11:55 +01001080 goto err_close;
Mario Six79066ef2017-01-11 16:00:58 +01001081 }
1082
1083 fclose(bin);
1084
Kever Yange002ee72020-03-30 11:56:20 +08001085 cur += ALIGN(s.st_size, 4);
Mario Six79066ef2017-01-11 16:00:58 +01001086
1087 /*
1088 * For now, we don't support more than one binary
1089 * header, and no other header types are
1090 * supported. So, the binary header is necessarily the
1091 * last one
1092 */
1093 *((uint32_t *)cur) = 0x00000000;
1094
1095 cur += sizeof(uint32_t);
1096
1097 return 0;
Mario Six1f6c8a52017-02-13 10:11:55 +01001098
1099err_close:
1100 fclose(bin);
1101
1102 return -1;
Mario Six79066ef2017-01-11 16:00:58 +01001103}
1104
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001105#if defined(CONFIG_KWB_SECURE)
1106
1107int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
1108{
1109 FILE *hashf;
1110 int res;
1111
1112 hashf = fopen("pub_kak_hash.txt", "w");
1113
1114 res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1115
1116 fclose(hashf);
1117
1118 return res < 0 ? 1 : 0;
1119}
1120
1121int kwb_sign_csk_with_kak(struct image_tool_params *params,
1122 struct secure_hdr_v1 *secure_hdr, RSA *csk)
1123{
1124 RSA *kak = NULL;
1125 RSA *kak_pub = NULL;
1126 int csk_idx = image_get_csk_index();
1127 struct sig_v1 tmp_sig;
1128
1129 if (csk_idx >= 16) {
1130 fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1131 return 1;
1132 }
1133
1134 if (kwb_load_kak(params, &kak) < 0)
1135 return 1;
1136
1137 if (export_pub_kak_hash(kak, secure_hdr))
1138 return 1;
1139
1140 if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1141 return 1;
1142
1143 if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1144 return 1;
1145
1146 if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1147 sizeof(secure_hdr->csk) +
1148 sizeof(secure_hdr->csksig),
1149 &tmp_sig, "CSK") < 0)
1150 return 1;
1151
1152 if (kwb_verify(kak_pub, &secure_hdr->csk,
1153 sizeof(secure_hdr->csk) +
1154 sizeof(secure_hdr->csksig),
1155 &tmp_sig, "CSK (2)") < 0)
1156 return 1;
1157
1158 secure_hdr->csksig = tmp_sig;
1159
1160 return 0;
1161}
1162
1163int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1164 int payloadsz, size_t headersz, uint8_t *image,
1165 struct secure_hdr_v1 *secure_hdr)
1166{
1167 struct image_cfg_element *e_jtagdelay;
1168 struct image_cfg_element *e_boxid;
1169 struct image_cfg_element *e_flashid;
1170 RSA *csk = NULL;
1171 unsigned char *image_ptr;
1172 size_t image_size;
1173 struct sig_v1 tmp_sig;
1174 bool specialized_img = image_get_spezialized_img();
1175
1176 kwb_msg("Create secure header content\n");
1177
1178 e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1179 e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1180 e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1181
1182 if (kwb_load_csk(params, &csk) < 0)
1183 return 1;
1184
1185 secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1186 secure_hdr->headersz_msb = 0;
1187 secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1188 if (e_jtagdelay)
1189 secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1190 if (e_boxid && specialized_img)
1191 secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1192 if (e_flashid && specialized_img)
1193 secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1194
1195 if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1196 return 1;
1197
1198 image_ptr = ptr + headersz;
1199 image_size = payloadsz - headersz;
1200
1201 if (kwb_sign_and_verify(csk, image_ptr, image_size,
1202 &secure_hdr->imgsig, "image") < 0)
1203 return 1;
1204
1205 if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1206 return 1;
1207
1208 secure_hdr->hdrsig = tmp_sig;
1209
1210 kwb_dump_fuse_cmds(secure_hdr);
1211
1212 return 0;
1213}
1214#endif
1215
Stefan Roese4acd2d22014-10-22 12:13:23 +02001216static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001217 uint8_t *ptr, int payloadsz)
Stefan Roese4acd2d22014-10-22 12:13:23 +02001218{
Mario Six79066ef2017-01-11 16:00:58 +01001219 struct image_cfg_element *e;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001220 struct main_hdr_v1 *main_hdr;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001221#if defined(CONFIG_KWB_SECURE)
1222 struct secure_hdr_v1 *secure_hdr = NULL;
1223#endif
Stefan Roese4acd2d22014-10-22 12:13:23 +02001224 size_t headersz;
Mario Six885fba12017-01-11 16:00:55 +01001225 uint8_t *image, *cur;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001226 int hasext = 0;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001227 uint8_t *next_ext = NULL;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001228
1229 /*
1230 * Calculate the size of the header and the size of the
1231 * payload
1232 */
Mario Sixe93cf532017-01-11 16:00:57 +01001233 headersz = image_headersz_v1(&hasext);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001234 if (headersz == 0)
1235 return NULL;
1236
1237 image = malloc(headersz);
1238 if (!image) {
1239 fprintf(stderr, "Cannot allocate memory for image\n");
1240 return NULL;
1241 }
1242
1243 memset(image, 0, headersz);
1244
Mario Six885fba12017-01-11 16:00:55 +01001245 main_hdr = (struct main_hdr_v1 *)image;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001246 cur = image;
1247 cur += sizeof(struct main_hdr_v1);
1248 next_ext = &main_hdr->ext;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001249
1250 /* Fill the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001251 main_hdr->blocksize =
Pali Rohár37cb9c12021-07-23 11:13:56 +02001252 cpu_to_le32(payloadsz - headersz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001253 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001254 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
Pali Rohárcc3443f2021-07-23 11:14:06 +02001255 main_hdr->destaddr = cpu_to_le32(params->addr);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001256 main_hdr->execaddr = cpu_to_le32(params->ep);
1257 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001258 main_hdr->ext = hasext;
1259 main_hdr->version = 1;
1260 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1261 if (e)
1262 main_hdr->blockid = e->bootfrom;
1263 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1264 if (e)
1265 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
1266 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1267 if (e)
1268 main_hdr->nandbadblklocation = e->nandbadblklocation;
Chris Packham4bdb5472016-11-09 22:07:45 +13001269 e = image_find_option(IMAGE_CFG_BAUDRATE);
1270 if (e)
1271 main_hdr->options = baudrate_to_option(e->baudrate);
Chris Packham2611c052016-11-09 22:21:45 +13001272 e = image_find_option(IMAGE_CFG_DEBUG);
1273 if (e)
1274 main_hdr->flags = e->debug ? 0x1 : 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001275
Pali Rohár501a54a2021-07-23 11:13:59 +02001276 /*
1277 * For SATA srcaddr is specified in number of sectors starting from
1278 * sector 0. The main header is stored at sector number 1.
1279 * This expects the sector size to be 512 bytes.
1280 * Header size is already aligned.
1281 */
1282 if (main_hdr->blockid == IBR_HDR_SATA_ID)
1283 main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1);
1284
1285 /*
1286 * For SDIO srcaddr is specified in number of sectors starting from
1287 * sector 0. The main header is stored at sector number 0.
1288 * This expects sector size to be 512 bytes.
1289 * Header size is already aligned.
1290 */
1291 if (main_hdr->blockid == IBR_HDR_SDIO_ID)
1292 main_hdr->srcaddr = cpu_to_le32(headersz / 512);
1293
1294 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1295 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1296 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1297
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001298#if defined(CONFIG_KWB_SECURE)
1299 if (image_get_csk_index() >= 0) {
1300 /*
1301 * only reserve the space here; we fill the header later since
1302 * we need the header to be complete to compute the signatures
1303 */
1304 secure_hdr = (struct secure_hdr_v1 *)cur;
1305 cur += sizeof(struct secure_hdr_v1);
1306 next_ext = &secure_hdr->next;
1307 }
1308#endif
1309 *next_ext = 1;
1310
Mario Six79066ef2017-01-11 16:00:58 +01001311 if (add_binary_header_v1(cur))
1312 return NULL;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001313
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001314#if defined(CONFIG_KWB_SECURE)
1315 if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
1316 headersz, image, secure_hdr))
1317 return NULL;
1318#endif
1319
Stefan Roese4acd2d22014-10-22 12:13:23 +02001320 /* Calculate and set the header checksum */
1321 main_hdr->checksum = image_checksum8(main_hdr, headersz);
1322
1323 *imagesz = headersz;
1324 return image;
1325}
1326
Mario Six4991b4f2017-01-11 16:00:59 +01001327int recognize_keyword(char *keyword)
1328{
1329 int kw_id;
1330
1331 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1332 if (!strcmp(keyword, id_strs[kw_id]))
1333 return kw_id;
1334
1335 return 0;
1336}
1337
Stefan Roese4acd2d22014-10-22 12:13:23 +02001338static int image_create_config_parse_oneline(char *line,
1339 struct image_cfg_element *el)
1340{
Mario Six4991b4f2017-01-11 16:00:59 +01001341 char *keyword, *saveptr, *value1, *value2;
1342 char delimiters[] = " \t";
1343 int keyword_id, ret, argi;
1344 char *unknown_msg = "Ignoring unknown line '%s'\n";
Stefan Roese4acd2d22014-10-22 12:13:23 +02001345
Mario Six4991b4f2017-01-11 16:00:59 +01001346 keyword = strtok_r(line, delimiters, &saveptr);
1347 keyword_id = recognize_keyword(keyword);
Mario Six94490a42017-01-11 16:00:54 +01001348
Mario Six4991b4f2017-01-11 16:00:59 +01001349 if (!keyword_id) {
1350 fprintf(stderr, unknown_msg, line);
1351 return 0;
1352 }
1353
1354 el->type = keyword_id;
1355
1356 value1 = strtok_r(NULL, delimiters, &saveptr);
1357
1358 if (!value1) {
1359 fprintf(stderr, "Parameter missing in line '%s'\n", line);
1360 return -1;
1361 }
1362
1363 switch (keyword_id) {
1364 case IMAGE_CFG_VERSION:
1365 el->version = atoi(value1);
1366 break;
1367 case IMAGE_CFG_BOOT_FROM:
1368 ret = image_boot_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001369
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001370 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001371 fprintf(stderr, "Invalid boot media '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001372 return -1;
1373 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001374 el->bootfrom = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001375 break;
1376 case IMAGE_CFG_NAND_BLKSZ:
1377 el->nandblksz = strtoul(value1, NULL, 16);
1378 break;
1379 case IMAGE_CFG_NAND_BADBLK_LOCATION:
1380 el->nandbadblklocation = strtoul(value1, NULL, 16);
1381 break;
1382 case IMAGE_CFG_NAND_ECC_MODE:
1383 ret = image_nand_ecc_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001384
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001385 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001386 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001387 return -1;
1388 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001389 el->nandeccmode = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001390 break;
1391 case IMAGE_CFG_NAND_PAGESZ:
1392 el->nandpagesz = strtoul(value1, NULL, 16);
1393 break;
1394 case IMAGE_CFG_BINARY:
1395 argi = 0;
Mario Six94490a42017-01-11 16:00:54 +01001396
Mario Six4991b4f2017-01-11 16:00:59 +01001397 el->binary.file = strdup(value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001398 while (1) {
Mario Six4991b4f2017-01-11 16:00:59 +01001399 char *value = strtok_r(NULL, delimiters, &saveptr);
1400
Stefan Roese4acd2d22014-10-22 12:13:23 +02001401 if (!value)
1402 break;
1403 el->binary.args[argi] = strtoul(value, NULL, 16);
1404 argi++;
1405 if (argi >= BINARY_MAX_ARGS) {
1406 fprintf(stderr,
Mario Six4991b4f2017-01-11 16:00:59 +01001407 "Too many arguments for BINARY\n");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001408 return -1;
1409 }
1410 }
1411 el->binary.nargs = argi;
Mario Six4991b4f2017-01-11 16:00:59 +01001412 break;
1413 case IMAGE_CFG_DATA:
1414 value2 = strtok_r(NULL, delimiters, &saveptr);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001415
1416 if (!value1 || !value2) {
1417 fprintf(stderr,
1418 "Invalid number of arguments for DATA\n");
1419 return -1;
1420 }
1421
Stefan Roese4acd2d22014-10-22 12:13:23 +02001422 el->regdata.raddr = strtoul(value1, NULL, 16);
1423 el->regdata.rdata = strtoul(value2, NULL, 16);
Mario Six4991b4f2017-01-11 16:00:59 +01001424 break;
1425 case IMAGE_CFG_BAUDRATE:
1426 el->baudrate = strtoul(value1, NULL, 10);
1427 break;
1428 case IMAGE_CFG_DEBUG:
1429 el->debug = strtoul(value1, NULL, 10);
1430 break;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001431 case IMAGE_CFG_KAK:
1432 el->key_name = strdup(value1);
1433 break;
1434 case IMAGE_CFG_CSK:
1435 el->key_name = strdup(value1);
1436 break;
1437 case IMAGE_CFG_CSK_INDEX:
1438 el->csk_idx = strtol(value1, NULL, 0);
1439 break;
1440 case IMAGE_CFG_JTAG_DELAY:
1441 el->jtag_delay = strtoul(value1, NULL, 0);
1442 break;
1443 case IMAGE_CFG_BOX_ID:
1444 el->boxid = strtoul(value1, NULL, 0);
1445 break;
1446 case IMAGE_CFG_FLASH_ID:
1447 el->flashid = strtoul(value1, NULL, 0);
1448 break;
1449 case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1450 el->sec_specialized_img = true;
1451 break;
1452 case IMAGE_CFG_SEC_COMMON_IMG:
1453 el->sec_specialized_img = false;
1454 break;
1455 case IMAGE_CFG_SEC_BOOT_DEV:
1456 el->sec_boot_dev = strtoul(value1, NULL, 0);
1457 break;
1458 case IMAGE_CFG_SEC_FUSE_DUMP:
1459 el->name = strdup(value1);
1460 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001461 default:
1462 fprintf(stderr, unknown_msg, line);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001463 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301464
1465 return 0;
1466}
1467
Stefan Roese4acd2d22014-10-22 12:13:23 +02001468/*
1469 * Parse the configuration file 'fcfg' into the array of configuration
1470 * elements 'image_cfg', and return the number of configuration
1471 * elements in 'cfgn'.
1472 */
1473static int image_create_config_parse(FILE *fcfg)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301474{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001475 int ret;
1476 int cfgi = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301477
Stefan Roese4acd2d22014-10-22 12:13:23 +02001478 /* Parse the configuration file */
1479 while (!feof(fcfg)) {
1480 char *line;
1481 char buf[256];
1482
1483 /* Read the current line */
1484 memset(buf, 0, sizeof(buf));
1485 line = fgets(buf, sizeof(buf), fcfg);
1486 if (!line)
1487 break;
1488
1489 /* Ignore useless lines */
1490 if (line[0] == '\n' || line[0] == '#')
1491 continue;
1492
1493 /* Strip final newline */
1494 if (line[strlen(line) - 1] == '\n')
1495 line[strlen(line) - 1] = 0;
1496
1497 /* Parse the current line */
1498 ret = image_create_config_parse_oneline(line,
1499 &image_cfg[cfgi]);
1500 if (ret)
1501 return ret;
1502
1503 cfgi++;
1504
1505 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1506 fprintf(stderr,
1507 "Too many configuration elements in .cfg file\n");
1508 return -1;
1509 }
1510 }
1511
1512 cfgn = cfgi;
1513 return 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301514}
1515
Stefan Roese4acd2d22014-10-22 12:13:23 +02001516static int image_get_version(void)
1517{
1518 struct image_cfg_element *e;
1519
1520 e = image_find_option(IMAGE_CFG_VERSION);
1521 if (!e)
1522 return -1;
1523
1524 return e->version;
1525}
1526
Pali Rohárc934aad2021-07-23 11:13:57 +02001527static int image_get_bootfrom(void)
1528{
1529 struct image_cfg_element *e;
1530
1531 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1532 if (!e)
1533 return -1;
1534
1535 return e->bootfrom;
1536}
1537
Stefan Roese4acd2d22014-10-22 12:13:23 +02001538static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
1539 struct image_tool_params *params)
1540{
1541 FILE *fcfg;
1542 void *image = NULL;
1543 int version;
Łukasz Majewski93e93712014-11-21 09:22:43 +01001544 size_t headersz = 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001545 uint32_t checksum;
1546 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001547
1548 fcfg = fopen(params->imagename, "r");
1549 if (!fcfg) {
1550 fprintf(stderr, "Could not open input file %s\n",
1551 params->imagename);
1552 exit(EXIT_FAILURE);
1553 }
1554
1555 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1556 sizeof(struct image_cfg_element));
1557 if (!image_cfg) {
1558 fprintf(stderr, "Cannot allocate memory\n");
1559 fclose(fcfg);
1560 exit(EXIT_FAILURE);
1561 }
1562
1563 memset(image_cfg, 0,
1564 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1565 rewind(fcfg);
1566
1567 ret = image_create_config_parse(fcfg);
1568 fclose(fcfg);
1569 if (ret) {
1570 free(image_cfg);
1571 exit(EXIT_FAILURE);
1572 }
1573
1574 version = image_get_version();
Stefan Roese934a5292014-10-28 11:32:24 +01001575 switch (version) {
1576 /*
1577 * Fallback to version 0 if no version is provided in the
1578 * cfg file
1579 */
1580 case -1:
1581 case 0:
Stefan Roese4acd2d22014-10-22 12:13:23 +02001582 image = image_create_v0(&headersz, params, sbuf->st_size);
Stefan Roese934a5292014-10-28 11:32:24 +01001583 break;
1584
1585 case 1:
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001586 image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
Stefan Roese934a5292014-10-28 11:32:24 +01001587 break;
1588
1589 default:
1590 fprintf(stderr, "Unsupported version %d\n", version);
1591 free(image_cfg);
1592 exit(EXIT_FAILURE);
1593 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001594
1595 if (!image) {
1596 fprintf(stderr, "Could not create image\n");
1597 free(image_cfg);
1598 exit(EXIT_FAILURE);
1599 }
1600
1601 free(image_cfg);
1602
1603 /* Build and add image checksum header */
Pali Rohár37cb9c12021-07-23 11:13:56 +02001604 checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + headersz,
1605 sbuf->st_size - headersz - sizeof(uint32_t)));
1606 memcpy((uint8_t *)ptr + sbuf->st_size - sizeof(uint32_t), &checksum,
1607 sizeof(uint32_t));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001608
1609 /* Finally copy the header into the image area */
1610 memcpy(ptr, image, headersz);
1611
1612 free(image);
1613}
1614
1615static void kwbimage_print_header(const void *ptr)
1616{
1617 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
1618
1619 printf("Image Type: MVEBU Boot from %s Image\n",
1620 image_boot_mode_name(mhdr->blockid));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001621 printf("Image version:%d\n", image_version((void *)ptr));
Pali Rohár34dcf952021-07-23 11:14:04 +02001622 if (image_version((void *)ptr) == 1) {
1623 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
1624
1625 if (mhdr->ext & 0x1) {
1626 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1627 ((uint8_t *)ptr +
1628 sizeof(*mhdr));
1629
1630 while (1) {
1631 uint32_t ohdr_size;
1632
1633 ohdr_size = (ohdr->headersz_msb << 16) |
1634 le16_to_cpu(ohdr->headersz_lsb);
1635 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
1636 printf("BIN Hdr Size: ");
1637 genimg_print_size(ohdr_size - 12 - 4 * ohdr->data[0]);
1638 }
1639 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1640 break;
1641 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1642 ohdr_size);
1643 }
1644 }
1645 }
Gerald Kerma26f195c2014-10-31 01:03:27 +01001646 printf("Data Size: ");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001647 genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1648 printf("Load Address: %08x\n", mhdr->destaddr);
1649 printf("Entry Point: %08x\n", mhdr->execaddr);
1650}
1651
1652static int kwbimage_check_image_types(uint8_t type)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301653{
1654 if (type == IH_TYPE_KWBIMAGE)
1655 return EXIT_SUCCESS;
Mario Six94490a42017-01-11 16:00:54 +01001656
1657 return EXIT_FAILURE;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301658}
1659
Stefan Roese4acd2d22014-10-22 12:13:23 +02001660static int kwbimage_verify_header(unsigned char *ptr, int image_size,
1661 struct image_tool_params *params)
1662{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001663 uint8_t checksum;
Alexander Graf6cd56782018-03-15 11:14:19 +01001664 size_t header_size = kwbimage_header_size(ptr);
1665
1666 if (header_size > image_size)
1667 return -FDT_ERR_BADSTRUCTURE;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001668
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +03001669 if (!main_hdr_checksum_ok(ptr))
Stefan Roese4acd2d22014-10-22 12:13:23 +02001670 return -FDT_ERR_BADSTRUCTURE;
1671
1672 /* Only version 0 extended header has checksum */
1673 if (image_version((void *)ptr) == 0) {
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001674 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Mario Sixe89016c2017-01-11 16:00:56 +01001675
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001676 if (mhdr->ext & 0x1) {
1677 struct ext_hdr_v0 *ext_hdr;
1678
1679 ext_hdr = (struct ext_hdr_v0 *)
Mario Six885fba12017-01-11 16:00:55 +01001680 (ptr + sizeof(struct main_hdr_v0));
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001681 checksum = image_checksum8(ext_hdr,
1682 sizeof(struct ext_hdr_v0)
1683 - sizeof(uint8_t));
1684 if (checksum != ext_hdr->checksum)
1685 return -FDT_ERR_BADSTRUCTURE;
1686 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001687 }
1688
Pali Rohár93804452021-07-23 11:14:02 +02001689 if (image_version((void *)ptr) == 1) {
1690 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Pali Roháre0c243c2021-07-23 11:14:03 +02001691 uint32_t offset;
1692 uint32_t size;
Pali Rohár93804452021-07-23 11:14:02 +02001693
1694 if (mhdr->ext & 0x1) {
1695 uint32_t ohdr_size;
1696 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1697 (ptr + sizeof(*mhdr));
1698
1699 while (1) {
1700 if ((uint8_t *)ohdr + sizeof(*ohdr) >
1701 (uint8_t *)mhdr + header_size)
1702 return -FDT_ERR_BADSTRUCTURE;
1703
1704 ohdr_size = (ohdr->headersz_msb << 16) |
1705 le16_to_cpu(ohdr->headersz_lsb);
1706
1707 if (ohdr_size < 8 ||
1708 (uint8_t *)ohdr + ohdr_size >
1709 (uint8_t *)mhdr + header_size)
1710 return -FDT_ERR_BADSTRUCTURE;
1711
1712 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1713 break;
1714 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1715 ohdr_size);
1716 }
1717 }
Pali Roháre0c243c2021-07-23 11:14:03 +02001718
1719 offset = le32_to_cpu(mhdr->srcaddr);
1720
1721 /*
1722 * For SATA srcaddr is specified in number of sectors.
1723 * The main header is must be stored at sector number 1.
1724 * This expects that sector size is 512 bytes and recalculates
1725 * data offset to bytes relative to the main header.
1726 */
1727 if (mhdr->blockid == IBR_HDR_SATA_ID) {
1728 if (offset < 1)
1729 return -FDT_ERR_BADSTRUCTURE;
1730 offset -= 1;
1731 offset *= 512;
1732 }
1733
1734 /*
1735 * For SDIO srcaddr is specified in number of sectors.
1736 * This expects that sector size is 512 bytes and recalculates
1737 * data offset to bytes.
1738 */
1739 if (mhdr->blockid == IBR_HDR_SDIO_ID)
1740 offset *= 512;
1741
1742 /*
1743 * For PCIe srcaddr is always set to 0xFFFFFFFF.
1744 * This expects that data starts after all headers.
1745 */
1746 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
1747 offset = header_size;
1748
1749 if (offset > image_size || offset % 4 != 0)
1750 return -FDT_ERR_BADSTRUCTURE;
1751
1752 size = le32_to_cpu(mhdr->blocksize);
1753 if (offset + size > image_size || size % 4 != 0)
1754 return -FDT_ERR_BADSTRUCTURE;
1755
1756 if (image_checksum32(ptr + offset, size - 4) !=
1757 *(uint32_t *)(ptr + offset + size - 4))
1758 return -FDT_ERR_BADSTRUCTURE;
Pali Rohár93804452021-07-23 11:14:02 +02001759 }
1760
Stefan Roese4acd2d22014-10-22 12:13:23 +02001761 return 0;
1762}
1763
1764static int kwbimage_generate(struct image_tool_params *params,
1765 struct image_type_params *tparams)
1766{
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001767 FILE *fcfg;
Pali Rohár37cb9c12021-07-23 11:13:56 +02001768 struct stat s;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001769 int alloc_len;
Pali Rohárc934aad2021-07-23 11:13:57 +02001770 int bootfrom;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001771 int version;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001772 void *hdr;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001773 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001774
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001775 fcfg = fopen(params->imagename, "r");
1776 if (!fcfg) {
1777 fprintf(stderr, "Could not open input file %s\n",
1778 params->imagename);
1779 exit(EXIT_FAILURE);
1780 }
1781
Pali Rohár37cb9c12021-07-23 11:13:56 +02001782 if (stat(params->datafile, &s)) {
1783 fprintf(stderr, "Could not stat data file %s: %s\n",
1784 params->datafile, strerror(errno));
1785 exit(EXIT_FAILURE);
1786 }
1787
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001788 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1789 sizeof(struct image_cfg_element));
1790 if (!image_cfg) {
1791 fprintf(stderr, "Cannot allocate memory\n");
1792 fclose(fcfg);
1793 exit(EXIT_FAILURE);
1794 }
1795
1796 memset(image_cfg, 0,
1797 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1798 rewind(fcfg);
1799
1800 ret = image_create_config_parse(fcfg);
1801 fclose(fcfg);
1802 if (ret) {
1803 free(image_cfg);
1804 exit(EXIT_FAILURE);
1805 }
1806
Pali Rohárc934aad2021-07-23 11:13:57 +02001807 bootfrom = image_get_bootfrom();
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001808 version = image_get_version();
1809 switch (version) {
1810 /*
1811 * Fallback to version 0 if no version is provided in the
1812 * cfg file
1813 */
1814 case -1:
1815 case 0:
Stefan Roese4acd2d22014-10-22 12:13:23 +02001816 alloc_len = sizeof(struct main_hdr_v0) +
1817 sizeof(struct ext_hdr_v0);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001818 break;
1819
1820 case 1:
Mario Sixe93cf532017-01-11 16:00:57 +01001821 alloc_len = image_headersz_v1(NULL);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001822 break;
1823
1824 default:
1825 fprintf(stderr, "Unsupported version %d\n", version);
1826 free(image_cfg);
1827 exit(EXIT_FAILURE);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001828 }
1829
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001830 free(image_cfg);
1831
Stefan Roese4acd2d22014-10-22 12:13:23 +02001832 hdr = malloc(alloc_len);
1833 if (!hdr) {
1834 fprintf(stderr, "%s: malloc return failure: %s\n",
1835 params->cmdname, strerror(errno));
1836 exit(EXIT_FAILURE);
1837 }
1838
1839 memset(hdr, 0, alloc_len);
1840 tparams->header_size = alloc_len;
1841 tparams->hdr = hdr;
1842
Stefan Roese77720852015-11-24 09:14:59 +01001843 /*
1844 * The resulting image needs to be 4-byte aligned. At least
1845 * the Marvell hdrparser tool complains if its unaligned.
Pali Rohár37cb9c12021-07-23 11:13:56 +02001846 * After the image data is stored 4-byte checksum.
Pali Rohárc934aad2021-07-23 11:13:57 +02001847 * Final SPI and NAND images must be aligned to 256 bytes.
Pali Rohár501a54a2021-07-23 11:13:59 +02001848 * Final SATA and SDIO images must be aligned to 512 bytes.
Stefan Roese77720852015-11-24 09:14:59 +01001849 */
Pali Rohárc934aad2021-07-23 11:13:57 +02001850 if (bootfrom == IBR_HDR_SPI_ID || bootfrom == IBR_HDR_NAND_ID)
1851 return 4 + (256 - (alloc_len + s.st_size + 4) % 256) % 256;
Pali Rohár501a54a2021-07-23 11:13:59 +02001852 else if (bootfrom == IBR_HDR_SATA_ID || bootfrom == IBR_HDR_SDIO_ID)
1853 return 4 + (512 - (alloc_len + s.st_size + 4) % 512) % 512;
Pali Rohárc934aad2021-07-23 11:13:57 +02001854 else
1855 return 4 + (4 - s.st_size % 4) % 4;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001856}
1857
1858/*
1859 * Report Error if xflag is set in addition to default
1860 */
1861static int kwbimage_check_params(struct image_tool_params *params)
1862{
1863 if (!strlen(params->imagename)) {
Mario Six94490a42017-01-11 16:00:54 +01001864 char *msg = "Configuration file for kwbimage creation omitted";
1865
1866 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001867 return CFG_INVALID;
1868 }
1869
1870 return (params->dflag && (params->fflag || params->lflag)) ||
1871 (params->fflag && (params->dflag || params->lflag)) ||
1872 (params->lflag && (params->dflag || params->fflag)) ||
1873 (params->xflag) || !(strlen(params->imagename));
1874}
1875
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301876/*
1877 * kwbimage type parameters definition
1878 */
Guilherme Maciel Ferreiraa93648d2015-01-15 02:48:07 -02001879U_BOOT_IMAGE_TYPE(
1880 kwbimage,
1881 "Marvell MVEBU Boot Image support",
1882 0,
1883 NULL,
1884 kwbimage_check_params,
1885 kwbimage_verify_header,
1886 kwbimage_print_header,
1887 kwbimage_set_header,
1888 NULL,
1889 kwbimage_check_image_types,
1890 NULL,
1891 kwbimage_generate
1892);