blob: 469e5b55f2ae2816d257fc1873f721a7ae30250b [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,
Pali Rohárf63c5832021-07-23 11:14:12 +0200107 IMAGE_CFG_DATA_DELAY,
Mario Six4991b4f2017-01-11 16:00:59 +0100108 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",
Mario Six4991b4f2017-01-11 16:00:59 +0100134 [IMAGE_CFG_DATA] = "DATA",
Pali Rohárf63c5832021-07-23 11:14:12 +0200135 [IMAGE_CFG_DATA_DELAY] = "DATA_DELAY",
Mario Six4991b4f2017-01-11 16:00:59 +0100136 [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;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200160 unsigned int dstaddr;
161 unsigned int execaddr;
162 unsigned int nandblksz;
163 unsigned int nandbadblklocation;
164 unsigned int nandeccmode;
165 unsigned int nandpagesz;
166 struct ext_hdr_v0_reg regdata;
Pali Rohárf63c5832021-07-23 11:14:12 +0200167 unsigned int regdata_delay;
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 image = malloc(headersz);
878 if (!image) {
879 fprintf(stderr, "Cannot allocate memory for image\n");
880 return NULL;
881 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530882
Stefan Roese4acd2d22014-10-22 12:13:23 +0200883 memset(image, 0, headersz);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530884
Mario Six885fba12017-01-11 16:00:55 +0100885 main_hdr = (struct main_hdr_v0 *)image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530886
Stefan Roese4acd2d22014-10-22 12:13:23 +0200887 /* Fill in the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100888 main_hdr->blocksize =
Pali Rohár37cb9c12021-07-23 11:13:56 +0200889 cpu_to_le32(payloadsz - headersz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100890 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200891 main_hdr->ext = has_ext;
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100892 main_hdr->destaddr = cpu_to_le32(params->addr);
893 main_hdr->execaddr = cpu_to_le32(params->ep);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530894
Stefan Roese4acd2d22014-10-22 12:13:23 +0200895 e = image_find_option(IMAGE_CFG_BOOT_FROM);
896 if (e)
897 main_hdr->blockid = e->bootfrom;
898 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
899 if (e)
900 main_hdr->nandeccmode = e->nandeccmode;
901 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
902 if (e)
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100903 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200904 main_hdr->checksum = image_checksum8(image,
905 sizeof(struct main_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530906
Stefan Roese4acd2d22014-10-22 12:13:23 +0200907 /* Generate the ext header */
908 if (has_ext) {
Mario Sixe89016c2017-01-11 16:00:56 +0100909 struct ext_hdr_v0 *ext_hdr;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200910 int cfgi, datai;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530911
Mario Six885fba12017-01-11 16:00:55 +0100912 ext_hdr = (struct ext_hdr_v0 *)
913 (image + sizeof(struct main_hdr_v0));
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100914 ext_hdr->offset = cpu_to_le32(0x40);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530915
Stefan Roese4acd2d22014-10-22 12:13:23 +0200916 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
917 e = &image_cfg[cfgi];
918 if (e->type != IMAGE_CFG_DATA)
919 continue;
920
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100921 ext_hdr->rcfg[datai].raddr =
922 cpu_to_le32(e->regdata.raddr);
923 ext_hdr->rcfg[datai].rdata =
924 cpu_to_le32(e->regdata.rdata);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200925 datai++;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530926 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530927
Stefan Roese4acd2d22014-10-22 12:13:23 +0200928 ext_hdr->checksum = image_checksum8(ext_hdr,
929 sizeof(struct ext_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530930 }
931
Stefan Roese4acd2d22014-10-22 12:13:23 +0200932 *imagesz = headersz;
933 return image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530934}
935
Mario Sixe93cf532017-01-11 16:00:57 +0100936static size_t image_headersz_v1(int *hasext)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530937{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200938 struct image_cfg_element *binarye;
Pali Rohár02ba70a2021-07-23 11:14:11 +0200939 unsigned int count;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200940 size_t headersz;
Pali Rohárd9fb82c2021-07-23 11:14:09 +0200941 int cfgi;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530942
Stefan Roese4acd2d22014-10-22 12:13:23 +0200943 /*
944 * Calculate the size of the header and the size of the
945 * payload
946 */
947 headersz = sizeof(struct main_hdr_v1);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530948
Pali Rohár02ba70a2021-07-23 11:14:11 +0200949 count = image_count_options(IMAGE_CFG_DATA);
950 if (count > 0)
951 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
952
Pali Rohárd9fb82c2021-07-23 11:14:09 +0200953 for (cfgi = 0; cfgi < cfgn; cfgi++) {
Mario Sixe89016c2017-01-11 16:00:56 +0100954 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200955 struct stat s;
956
Pali Rohárd9fb82c2021-07-23 11:14:09 +0200957 binarye = &image_cfg[cfgi];
958 if (binarye->type != IMAGE_CFG_BINARY)
959 continue;
960
Stefan Roese4acd2d22014-10-22 12:13:23 +0200961 ret = stat(binarye->binary.file, &s);
962 if (ret < 0) {
Andreas Bießmanne5f1a582014-10-24 23:39:11 +0200963 char cwd[PATH_MAX];
964 char *dir = cwd;
965
966 memset(cwd, 0, sizeof(cwd));
967 if (!getcwd(cwd, sizeof(cwd))) {
968 dir = "current working directory";
969 perror("getcwd() failed");
970 }
971
Stefan Roese4acd2d22014-10-22 12:13:23 +0200972 fprintf(stderr,
973 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
974 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
975 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
Andreas Bießmanne5f1a582014-10-24 23:39:11 +0200976 binarye->binary.file, dir);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200977 return 0;
978 }
979
Reinhard Pfau76b391c2015-11-29 15:52:14 +0100980 headersz += sizeof(struct opt_hdr_v1) +
Pali Rohár6458fd42021-07-23 11:14:08 +0200981 ALIGN(s.st_size, 4) +
Reinhard Pfau76b391c2015-11-29 15:52:14 +0100982 (binarye->binary.nargs + 2) * sizeof(uint32_t);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200983 if (hasext)
984 *hasext = 1;
985 }
986
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100987#if defined(CONFIG_KWB_SECURE)
988 if (image_get_csk_index() >= 0) {
989 headersz += sizeof(struct secure_hdr_v1);
990 if (hasext)
991 *hasext = 1;
992 }
993#endif
994
Stefan Roese7ddf8cf2015-07-20 11:20:38 +0200995#if defined(CONFIG_SYS_U_BOOT_OFFS)
996 if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
Mario Six94490a42017-01-11 16:00:54 +0100997 fprintf(stderr,
998 "Error: Image header (incl. SPL image) too big!\n");
Stefan Roese7ddf8cf2015-07-20 11:20:38 +0200999 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
1000 (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
1001 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
Kevin Smitha0aad122015-03-16 14:58:21 +00001002 return 0;
Kevin Smitha0aad122015-03-16 14:58:21 +00001003 }
Mario Six79066ef2017-01-11 16:00:58 +01001004
Mario Six94490a42017-01-11 16:00:54 +01001005 headersz = CONFIG_SYS_U_BOOT_OFFS;
Kevin Smitha0aad122015-03-16 14:58:21 +00001006#endif
1007
Stefan Roese4acd2d22014-10-22 12:13:23 +02001008 /*
1009 * The payload should be aligned on some reasonable
1010 * boundary
1011 */
Kever Yange002ee72020-03-30 11:56:20 +08001012 return ALIGN(headersz, 4096);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001013}
1014
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001015int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
1016 struct image_cfg_element *binarye)
Mario Six79066ef2017-01-11 16:00:58 +01001017{
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001018 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur;
Mario Six79066ef2017-01-11 16:00:58 +01001019 uint32_t *args;
1020 size_t binhdrsz;
1021 struct stat s;
1022 int argi;
1023 FILE *bin;
1024 int ret;
1025
Mario Six79066ef2017-01-11 16:00:58 +01001026 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1027
1028 bin = fopen(binarye->binary.file, "r");
1029 if (!bin) {
1030 fprintf(stderr, "Cannot open binary file %s\n",
1031 binarye->binary.file);
1032 return -1;
1033 }
1034
Mario Six1f6c8a52017-02-13 10:11:55 +01001035 if (fstat(fileno(bin), &s)) {
1036 fprintf(stderr, "Cannot stat binary file %s\n",
1037 binarye->binary.file);
1038 goto err_close;
1039 }
Mario Six79066ef2017-01-11 16:00:58 +01001040
1041 binhdrsz = sizeof(struct opt_hdr_v1) +
1042 (binarye->binary.nargs + 2) * sizeof(uint32_t) +
Pali Rohár6458fd42021-07-23 11:14:08 +02001043 ALIGN(s.st_size, 4);
Mario Six79066ef2017-01-11 16:00:58 +01001044 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1045 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1046
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001047 *cur += sizeof(struct opt_hdr_v1);
Mario Six79066ef2017-01-11 16:00:58 +01001048
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001049 args = (uint32_t *)*cur;
Mario Six79066ef2017-01-11 16:00:58 +01001050 *args = cpu_to_le32(binarye->binary.nargs);
1051 args++;
1052 for (argi = 0; argi < binarye->binary.nargs; argi++)
1053 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1054
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001055 *cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
Mario Six79066ef2017-01-11 16:00:58 +01001056
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001057 ret = fread(*cur, s.st_size, 1, bin);
Mario Six79066ef2017-01-11 16:00:58 +01001058 if (ret != 1) {
1059 fprintf(stderr,
1060 "Could not read binary image %s\n",
1061 binarye->binary.file);
Mario Six1f6c8a52017-02-13 10:11:55 +01001062 goto err_close;
Mario Six79066ef2017-01-11 16:00:58 +01001063 }
1064
1065 fclose(bin);
1066
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001067 *cur += ALIGN(s.st_size, 4);
Mario Six79066ef2017-01-11 16:00:58 +01001068
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001069 *((uint32_t *)*cur) = 0x00000000;
1070 **next_ext = 1;
1071 *next_ext = *cur;
Mario Six79066ef2017-01-11 16:00:58 +01001072
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001073 *cur += sizeof(uint32_t);
Mario Six79066ef2017-01-11 16:00:58 +01001074
1075 return 0;
Mario Six1f6c8a52017-02-13 10:11:55 +01001076
1077err_close:
1078 fclose(bin);
1079
1080 return -1;
Mario Six79066ef2017-01-11 16:00:58 +01001081}
1082
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001083#if defined(CONFIG_KWB_SECURE)
1084
1085int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
1086{
1087 FILE *hashf;
1088 int res;
1089
1090 hashf = fopen("pub_kak_hash.txt", "w");
1091
1092 res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1093
1094 fclose(hashf);
1095
1096 return res < 0 ? 1 : 0;
1097}
1098
1099int kwb_sign_csk_with_kak(struct image_tool_params *params,
1100 struct secure_hdr_v1 *secure_hdr, RSA *csk)
1101{
1102 RSA *kak = NULL;
1103 RSA *kak_pub = NULL;
1104 int csk_idx = image_get_csk_index();
1105 struct sig_v1 tmp_sig;
1106
1107 if (csk_idx >= 16) {
1108 fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1109 return 1;
1110 }
1111
1112 if (kwb_load_kak(params, &kak) < 0)
1113 return 1;
1114
1115 if (export_pub_kak_hash(kak, secure_hdr))
1116 return 1;
1117
1118 if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1119 return 1;
1120
1121 if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1122 return 1;
1123
1124 if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1125 sizeof(secure_hdr->csk) +
1126 sizeof(secure_hdr->csksig),
1127 &tmp_sig, "CSK") < 0)
1128 return 1;
1129
1130 if (kwb_verify(kak_pub, &secure_hdr->csk,
1131 sizeof(secure_hdr->csk) +
1132 sizeof(secure_hdr->csksig),
1133 &tmp_sig, "CSK (2)") < 0)
1134 return 1;
1135
1136 secure_hdr->csksig = tmp_sig;
1137
1138 return 0;
1139}
1140
1141int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1142 int payloadsz, size_t headersz, uint8_t *image,
1143 struct secure_hdr_v1 *secure_hdr)
1144{
1145 struct image_cfg_element *e_jtagdelay;
1146 struct image_cfg_element *e_boxid;
1147 struct image_cfg_element *e_flashid;
1148 RSA *csk = NULL;
1149 unsigned char *image_ptr;
1150 size_t image_size;
1151 struct sig_v1 tmp_sig;
1152 bool specialized_img = image_get_spezialized_img();
1153
1154 kwb_msg("Create secure header content\n");
1155
1156 e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1157 e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1158 e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1159
1160 if (kwb_load_csk(params, &csk) < 0)
1161 return 1;
1162
1163 secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1164 secure_hdr->headersz_msb = 0;
1165 secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1166 if (e_jtagdelay)
1167 secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1168 if (e_boxid && specialized_img)
1169 secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1170 if (e_flashid && specialized_img)
1171 secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1172
1173 if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1174 return 1;
1175
1176 image_ptr = ptr + headersz;
1177 image_size = payloadsz - headersz;
1178
1179 if (kwb_sign_and_verify(csk, image_ptr, image_size,
1180 &secure_hdr->imgsig, "image") < 0)
1181 return 1;
1182
1183 if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1184 return 1;
1185
1186 secure_hdr->hdrsig = tmp_sig;
1187
1188 kwb_dump_fuse_cmds(secure_hdr);
1189
1190 return 0;
1191}
1192#endif
1193
Stefan Roese4acd2d22014-10-22 12:13:23 +02001194static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001195 uint8_t *ptr, int payloadsz)
Stefan Roese4acd2d22014-10-22 12:13:23 +02001196{
Mario Six79066ef2017-01-11 16:00:58 +01001197 struct image_cfg_element *e;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001198 struct main_hdr_v1 *main_hdr;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001199 struct register_set_hdr_v1 *register_set_hdr;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001200#if defined(CONFIG_KWB_SECURE)
1201 struct secure_hdr_v1 *secure_hdr = NULL;
1202#endif
Stefan Roese4acd2d22014-10-22 12:13:23 +02001203 size_t headersz;
Mario Six885fba12017-01-11 16:00:55 +01001204 uint8_t *image, *cur;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001205 int hasext = 0;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001206 uint8_t *next_ext = NULL;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001207 int cfgi, datai, size;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001208
1209 /*
1210 * Calculate the size of the header and the size of the
1211 * payload
1212 */
Mario Sixe93cf532017-01-11 16:00:57 +01001213 headersz = image_headersz_v1(&hasext);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001214 if (headersz == 0)
1215 return NULL;
1216
1217 image = malloc(headersz);
1218 if (!image) {
1219 fprintf(stderr, "Cannot allocate memory for image\n");
1220 return NULL;
1221 }
1222
1223 memset(image, 0, headersz);
1224
Mario Six885fba12017-01-11 16:00:55 +01001225 main_hdr = (struct main_hdr_v1 *)image;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001226 cur = image;
1227 cur += sizeof(struct main_hdr_v1);
1228 next_ext = &main_hdr->ext;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001229
1230 /* Fill the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001231 main_hdr->blocksize =
Pali Rohár37cb9c12021-07-23 11:13:56 +02001232 cpu_to_le32(payloadsz - headersz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001233 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001234 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
Pali Rohárcc3443f2021-07-23 11:14:06 +02001235 main_hdr->destaddr = cpu_to_le32(params->addr);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001236 main_hdr->execaddr = cpu_to_le32(params->ep);
1237 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001238 main_hdr->ext = hasext;
1239 main_hdr->version = 1;
1240 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1241 if (e)
1242 main_hdr->blockid = e->bootfrom;
1243 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1244 if (e)
1245 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
1246 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1247 if (e)
1248 main_hdr->nandbadblklocation = e->nandbadblklocation;
Chris Packham4bdb5472016-11-09 22:07:45 +13001249 e = image_find_option(IMAGE_CFG_BAUDRATE);
1250 if (e)
1251 main_hdr->options = baudrate_to_option(e->baudrate);
Chris Packham2611c052016-11-09 22:21:45 +13001252 e = image_find_option(IMAGE_CFG_DEBUG);
1253 if (e)
1254 main_hdr->flags = e->debug ? 0x1 : 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001255
Pali Rohár501a54a2021-07-23 11:13:59 +02001256 /*
1257 * For SATA srcaddr is specified in number of sectors starting from
1258 * sector 0. The main header is stored at sector number 1.
1259 * This expects the sector size to be 512 bytes.
1260 * Header size is already aligned.
1261 */
1262 if (main_hdr->blockid == IBR_HDR_SATA_ID)
1263 main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1);
1264
1265 /*
1266 * For SDIO srcaddr is specified in number of sectors starting from
1267 * sector 0. The main header is stored at sector number 0.
1268 * This expects sector size to be 512 bytes.
1269 * Header size is already aligned.
1270 */
1271 if (main_hdr->blockid == IBR_HDR_SDIO_ID)
1272 main_hdr->srcaddr = cpu_to_le32(headersz / 512);
1273
1274 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1275 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1276 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1277
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001278#if defined(CONFIG_KWB_SECURE)
1279 if (image_get_csk_index() >= 0) {
1280 /*
1281 * only reserve the space here; we fill the header later since
1282 * we need the header to be complete to compute the signatures
1283 */
1284 secure_hdr = (struct secure_hdr_v1 *)cur;
1285 cur += sizeof(struct secure_hdr_v1);
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001286 *next_ext = 1;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001287 next_ext = &secure_hdr->next;
1288 }
1289#endif
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001290
Pali Rohár02ba70a2021-07-23 11:14:11 +02001291 datai = 0;
1292 register_set_hdr = (struct register_set_hdr_v1 *)cur;
1293 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1294 e = &image_cfg[cfgi];
Pali Rohárf63c5832021-07-23 11:14:12 +02001295 if (e->type != IMAGE_CFG_DATA &&
1296 e->type != IMAGE_CFG_DATA_DELAY)
Pali Rohár02ba70a2021-07-23 11:14:11 +02001297 continue;
Pali Rohárf63c5832021-07-23 11:14:12 +02001298 if (e->type == IMAGE_CFG_DATA_DELAY) {
1299 size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
1300 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1301 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1302 register_set_hdr->headersz_msb = size >> 16;
1303 register_set_hdr->data[datai].last_entry.delay = e->regdata_delay;
1304 cur += size;
1305 *next_ext = 1;
1306 next_ext = &register_set_hdr->data[datai].last_entry.next;
1307 datai = 0;
1308 continue;
1309 }
Pali Rohár02ba70a2021-07-23 11:14:11 +02001310 register_set_hdr->data[datai].entry.address =
1311 cpu_to_le32(e->regdata.raddr);
1312 register_set_hdr->data[datai].entry.value =
1313 cpu_to_le32(e->regdata.rdata);
1314 datai++;
1315 }
1316 if (datai != 0) {
1317 size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
1318 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1319 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1320 register_set_hdr->headersz_msb = size >> 16;
1321 /* Set delay to the smallest possible value 1ms. */
1322 register_set_hdr->data[datai].last_entry.delay = 1;
1323 cur += size;
1324 *next_ext = 1;
1325 next_ext = &register_set_hdr->data[datai].last_entry.next;
1326 }
1327
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001328 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1329 e = &image_cfg[cfgi];
1330 if (e->type != IMAGE_CFG_BINARY)
1331 continue;
1332
1333 if (add_binary_header_v1(&cur, &next_ext, e))
1334 return NULL;
1335 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001336
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001337#if defined(CONFIG_KWB_SECURE)
1338 if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
1339 headersz, image, secure_hdr))
1340 return NULL;
1341#endif
1342
Stefan Roese4acd2d22014-10-22 12:13:23 +02001343 /* Calculate and set the header checksum */
1344 main_hdr->checksum = image_checksum8(main_hdr, headersz);
1345
1346 *imagesz = headersz;
1347 return image;
1348}
1349
Mario Six4991b4f2017-01-11 16:00:59 +01001350int recognize_keyword(char *keyword)
1351{
1352 int kw_id;
1353
1354 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1355 if (!strcmp(keyword, id_strs[kw_id]))
1356 return kw_id;
1357
1358 return 0;
1359}
1360
Stefan Roese4acd2d22014-10-22 12:13:23 +02001361static int image_create_config_parse_oneline(char *line,
1362 struct image_cfg_element *el)
1363{
Mario Six4991b4f2017-01-11 16:00:59 +01001364 char *keyword, *saveptr, *value1, *value2;
1365 char delimiters[] = " \t";
1366 int keyword_id, ret, argi;
1367 char *unknown_msg = "Ignoring unknown line '%s'\n";
Stefan Roese4acd2d22014-10-22 12:13:23 +02001368
Mario Six4991b4f2017-01-11 16:00:59 +01001369 keyword = strtok_r(line, delimiters, &saveptr);
1370 keyword_id = recognize_keyword(keyword);
Mario Six94490a42017-01-11 16:00:54 +01001371
Mario Six4991b4f2017-01-11 16:00:59 +01001372 if (!keyword_id) {
1373 fprintf(stderr, unknown_msg, line);
1374 return 0;
1375 }
1376
1377 el->type = keyword_id;
1378
1379 value1 = strtok_r(NULL, delimiters, &saveptr);
1380
1381 if (!value1) {
1382 fprintf(stderr, "Parameter missing in line '%s'\n", line);
1383 return -1;
1384 }
1385
1386 switch (keyword_id) {
1387 case IMAGE_CFG_VERSION:
1388 el->version = atoi(value1);
1389 break;
1390 case IMAGE_CFG_BOOT_FROM:
1391 ret = image_boot_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001392
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001393 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001394 fprintf(stderr, "Invalid boot media '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001395 return -1;
1396 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001397 el->bootfrom = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001398 break;
1399 case IMAGE_CFG_NAND_BLKSZ:
1400 el->nandblksz = strtoul(value1, NULL, 16);
1401 break;
1402 case IMAGE_CFG_NAND_BADBLK_LOCATION:
1403 el->nandbadblklocation = strtoul(value1, NULL, 16);
1404 break;
1405 case IMAGE_CFG_NAND_ECC_MODE:
1406 ret = image_nand_ecc_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001407
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001408 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001409 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001410 return -1;
1411 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001412 el->nandeccmode = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001413 break;
1414 case IMAGE_CFG_NAND_PAGESZ:
1415 el->nandpagesz = strtoul(value1, NULL, 16);
1416 break;
1417 case IMAGE_CFG_BINARY:
1418 argi = 0;
Mario Six94490a42017-01-11 16:00:54 +01001419
Mario Six4991b4f2017-01-11 16:00:59 +01001420 el->binary.file = strdup(value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001421 while (1) {
Mario Six4991b4f2017-01-11 16:00:59 +01001422 char *value = strtok_r(NULL, delimiters, &saveptr);
1423
Stefan Roese4acd2d22014-10-22 12:13:23 +02001424 if (!value)
1425 break;
1426 el->binary.args[argi] = strtoul(value, NULL, 16);
1427 argi++;
1428 if (argi >= BINARY_MAX_ARGS) {
1429 fprintf(stderr,
Mario Six4991b4f2017-01-11 16:00:59 +01001430 "Too many arguments for BINARY\n");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001431 return -1;
1432 }
1433 }
1434 el->binary.nargs = argi;
Mario Six4991b4f2017-01-11 16:00:59 +01001435 break;
1436 case IMAGE_CFG_DATA:
1437 value2 = strtok_r(NULL, delimiters, &saveptr);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001438
1439 if (!value1 || !value2) {
1440 fprintf(stderr,
1441 "Invalid number of arguments for DATA\n");
1442 return -1;
1443 }
1444
Stefan Roese4acd2d22014-10-22 12:13:23 +02001445 el->regdata.raddr = strtoul(value1, NULL, 16);
1446 el->regdata.rdata = strtoul(value2, NULL, 16);
Mario Six4991b4f2017-01-11 16:00:59 +01001447 break;
Pali Rohárf63c5832021-07-23 11:14:12 +02001448 case IMAGE_CFG_DATA_DELAY:
1449 if (!strcmp(value1, "SDRAM_SETUP"))
1450 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP;
1451 else
1452 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_MS(strtoul(value1, NULL, 10));
1453 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001454 case IMAGE_CFG_BAUDRATE:
1455 el->baudrate = strtoul(value1, NULL, 10);
1456 break;
1457 case IMAGE_CFG_DEBUG:
1458 el->debug = strtoul(value1, NULL, 10);
1459 break;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001460 case IMAGE_CFG_KAK:
1461 el->key_name = strdup(value1);
1462 break;
1463 case IMAGE_CFG_CSK:
1464 el->key_name = strdup(value1);
1465 break;
1466 case IMAGE_CFG_CSK_INDEX:
1467 el->csk_idx = strtol(value1, NULL, 0);
1468 break;
1469 case IMAGE_CFG_JTAG_DELAY:
1470 el->jtag_delay = strtoul(value1, NULL, 0);
1471 break;
1472 case IMAGE_CFG_BOX_ID:
1473 el->boxid = strtoul(value1, NULL, 0);
1474 break;
1475 case IMAGE_CFG_FLASH_ID:
1476 el->flashid = strtoul(value1, NULL, 0);
1477 break;
1478 case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1479 el->sec_specialized_img = true;
1480 break;
1481 case IMAGE_CFG_SEC_COMMON_IMG:
1482 el->sec_specialized_img = false;
1483 break;
1484 case IMAGE_CFG_SEC_BOOT_DEV:
1485 el->sec_boot_dev = strtoul(value1, NULL, 0);
1486 break;
1487 case IMAGE_CFG_SEC_FUSE_DUMP:
1488 el->name = strdup(value1);
1489 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001490 default:
1491 fprintf(stderr, unknown_msg, line);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001492 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301493
1494 return 0;
1495}
1496
Stefan Roese4acd2d22014-10-22 12:13:23 +02001497/*
1498 * Parse the configuration file 'fcfg' into the array of configuration
1499 * elements 'image_cfg', and return the number of configuration
1500 * elements in 'cfgn'.
1501 */
1502static int image_create_config_parse(FILE *fcfg)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301503{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001504 int ret;
1505 int cfgi = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301506
Stefan Roese4acd2d22014-10-22 12:13:23 +02001507 /* Parse the configuration file */
1508 while (!feof(fcfg)) {
1509 char *line;
1510 char buf[256];
1511
1512 /* Read the current line */
1513 memset(buf, 0, sizeof(buf));
1514 line = fgets(buf, sizeof(buf), fcfg);
1515 if (!line)
1516 break;
1517
1518 /* Ignore useless lines */
1519 if (line[0] == '\n' || line[0] == '#')
1520 continue;
1521
1522 /* Strip final newline */
1523 if (line[strlen(line) - 1] == '\n')
1524 line[strlen(line) - 1] = 0;
1525
1526 /* Parse the current line */
1527 ret = image_create_config_parse_oneline(line,
1528 &image_cfg[cfgi]);
1529 if (ret)
1530 return ret;
1531
1532 cfgi++;
1533
1534 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1535 fprintf(stderr,
1536 "Too many configuration elements in .cfg file\n");
1537 return -1;
1538 }
1539 }
1540
1541 cfgn = cfgi;
1542 return 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301543}
1544
Stefan Roese4acd2d22014-10-22 12:13:23 +02001545static int image_get_version(void)
1546{
1547 struct image_cfg_element *e;
1548
1549 e = image_find_option(IMAGE_CFG_VERSION);
1550 if (!e)
1551 return -1;
1552
1553 return e->version;
1554}
1555
Pali Rohárc934aad2021-07-23 11:13:57 +02001556static int image_get_bootfrom(void)
1557{
1558 struct image_cfg_element *e;
1559
1560 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1561 if (!e)
1562 return -1;
1563
1564 return e->bootfrom;
1565}
1566
Stefan Roese4acd2d22014-10-22 12:13:23 +02001567static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
1568 struct image_tool_params *params)
1569{
1570 FILE *fcfg;
1571 void *image = NULL;
1572 int version;
Łukasz Majewski93e93712014-11-21 09:22:43 +01001573 size_t headersz = 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001574 uint32_t checksum;
1575 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001576
1577 fcfg = fopen(params->imagename, "r");
1578 if (!fcfg) {
1579 fprintf(stderr, "Could not open input file %s\n",
1580 params->imagename);
1581 exit(EXIT_FAILURE);
1582 }
1583
1584 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1585 sizeof(struct image_cfg_element));
1586 if (!image_cfg) {
1587 fprintf(stderr, "Cannot allocate memory\n");
1588 fclose(fcfg);
1589 exit(EXIT_FAILURE);
1590 }
1591
1592 memset(image_cfg, 0,
1593 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1594 rewind(fcfg);
1595
1596 ret = image_create_config_parse(fcfg);
1597 fclose(fcfg);
1598 if (ret) {
1599 free(image_cfg);
1600 exit(EXIT_FAILURE);
1601 }
1602
1603 version = image_get_version();
Stefan Roese934a5292014-10-28 11:32:24 +01001604 switch (version) {
1605 /*
1606 * Fallback to version 0 if no version is provided in the
1607 * cfg file
1608 */
1609 case -1:
1610 case 0:
Stefan Roese4acd2d22014-10-22 12:13:23 +02001611 image = image_create_v0(&headersz, params, sbuf->st_size);
Stefan Roese934a5292014-10-28 11:32:24 +01001612 break;
1613
1614 case 1:
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001615 image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
Stefan Roese934a5292014-10-28 11:32:24 +01001616 break;
1617
1618 default:
1619 fprintf(stderr, "Unsupported version %d\n", version);
1620 free(image_cfg);
1621 exit(EXIT_FAILURE);
1622 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001623
1624 if (!image) {
1625 fprintf(stderr, "Could not create image\n");
1626 free(image_cfg);
1627 exit(EXIT_FAILURE);
1628 }
1629
1630 free(image_cfg);
1631
1632 /* Build and add image checksum header */
Pali Rohár37cb9c12021-07-23 11:13:56 +02001633 checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + headersz,
1634 sbuf->st_size - headersz - sizeof(uint32_t)));
1635 memcpy((uint8_t *)ptr + sbuf->st_size - sizeof(uint32_t), &checksum,
1636 sizeof(uint32_t));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001637
1638 /* Finally copy the header into the image area */
1639 memcpy(ptr, image, headersz);
1640
1641 free(image);
1642}
1643
1644static void kwbimage_print_header(const void *ptr)
1645{
1646 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
1647
1648 printf("Image Type: MVEBU Boot from %s Image\n",
1649 image_boot_mode_name(mhdr->blockid));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001650 printf("Image version:%d\n", image_version((void *)ptr));
Pali Rohár34dcf952021-07-23 11:14:04 +02001651 if (image_version((void *)ptr) == 1) {
1652 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
1653
1654 if (mhdr->ext & 0x1) {
1655 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1656 ((uint8_t *)ptr +
1657 sizeof(*mhdr));
1658
1659 while (1) {
1660 uint32_t ohdr_size;
1661
1662 ohdr_size = (ohdr->headersz_msb << 16) |
1663 le16_to_cpu(ohdr->headersz_lsb);
1664 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
1665 printf("BIN Hdr Size: ");
1666 genimg_print_size(ohdr_size - 12 - 4 * ohdr->data[0]);
1667 }
1668 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1669 break;
1670 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1671 ohdr_size);
1672 }
1673 }
1674 }
Gerald Kerma26f195c2014-10-31 01:03:27 +01001675 printf("Data Size: ");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001676 genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1677 printf("Load Address: %08x\n", mhdr->destaddr);
1678 printf("Entry Point: %08x\n", mhdr->execaddr);
1679}
1680
1681static int kwbimage_check_image_types(uint8_t type)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301682{
1683 if (type == IH_TYPE_KWBIMAGE)
1684 return EXIT_SUCCESS;
Mario Six94490a42017-01-11 16:00:54 +01001685
1686 return EXIT_FAILURE;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301687}
1688
Stefan Roese4acd2d22014-10-22 12:13:23 +02001689static int kwbimage_verify_header(unsigned char *ptr, int image_size,
1690 struct image_tool_params *params)
1691{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001692 uint8_t checksum;
Alexander Graf6cd56782018-03-15 11:14:19 +01001693 size_t header_size = kwbimage_header_size(ptr);
1694
1695 if (header_size > image_size)
1696 return -FDT_ERR_BADSTRUCTURE;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001697
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +03001698 if (!main_hdr_checksum_ok(ptr))
Stefan Roese4acd2d22014-10-22 12:13:23 +02001699 return -FDT_ERR_BADSTRUCTURE;
1700
1701 /* Only version 0 extended header has checksum */
1702 if (image_version((void *)ptr) == 0) {
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001703 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Mario Sixe89016c2017-01-11 16:00:56 +01001704
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001705 if (mhdr->ext & 0x1) {
1706 struct ext_hdr_v0 *ext_hdr;
1707
1708 ext_hdr = (struct ext_hdr_v0 *)
Mario Six885fba12017-01-11 16:00:55 +01001709 (ptr + sizeof(struct main_hdr_v0));
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001710 checksum = image_checksum8(ext_hdr,
1711 sizeof(struct ext_hdr_v0)
1712 - sizeof(uint8_t));
1713 if (checksum != ext_hdr->checksum)
1714 return -FDT_ERR_BADSTRUCTURE;
1715 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001716 }
1717
Pali Rohár93804452021-07-23 11:14:02 +02001718 if (image_version((void *)ptr) == 1) {
1719 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Pali Roháre0c243c2021-07-23 11:14:03 +02001720 uint32_t offset;
1721 uint32_t size;
Pali Rohár93804452021-07-23 11:14:02 +02001722
1723 if (mhdr->ext & 0x1) {
1724 uint32_t ohdr_size;
1725 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1726 (ptr + sizeof(*mhdr));
1727
1728 while (1) {
1729 if ((uint8_t *)ohdr + sizeof(*ohdr) >
1730 (uint8_t *)mhdr + header_size)
1731 return -FDT_ERR_BADSTRUCTURE;
1732
1733 ohdr_size = (ohdr->headersz_msb << 16) |
1734 le16_to_cpu(ohdr->headersz_lsb);
1735
1736 if (ohdr_size < 8 ||
1737 (uint8_t *)ohdr + ohdr_size >
1738 (uint8_t *)mhdr + header_size)
1739 return -FDT_ERR_BADSTRUCTURE;
1740
1741 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1742 break;
1743 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1744 ohdr_size);
1745 }
1746 }
Pali Roháre0c243c2021-07-23 11:14:03 +02001747
1748 offset = le32_to_cpu(mhdr->srcaddr);
1749
1750 /*
1751 * For SATA srcaddr is specified in number of sectors.
1752 * The main header is must be stored at sector number 1.
1753 * This expects that sector size is 512 bytes and recalculates
1754 * data offset to bytes relative to the main header.
1755 */
1756 if (mhdr->blockid == IBR_HDR_SATA_ID) {
1757 if (offset < 1)
1758 return -FDT_ERR_BADSTRUCTURE;
1759 offset -= 1;
1760 offset *= 512;
1761 }
1762
1763 /*
1764 * For SDIO srcaddr is specified in number of sectors.
1765 * This expects that sector size is 512 bytes and recalculates
1766 * data offset to bytes.
1767 */
1768 if (mhdr->blockid == IBR_HDR_SDIO_ID)
1769 offset *= 512;
1770
1771 /*
1772 * For PCIe srcaddr is always set to 0xFFFFFFFF.
1773 * This expects that data starts after all headers.
1774 */
1775 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
1776 offset = header_size;
1777
1778 if (offset > image_size || offset % 4 != 0)
1779 return -FDT_ERR_BADSTRUCTURE;
1780
1781 size = le32_to_cpu(mhdr->blocksize);
1782 if (offset + size > image_size || size % 4 != 0)
1783 return -FDT_ERR_BADSTRUCTURE;
1784
1785 if (image_checksum32(ptr + offset, size - 4) !=
1786 *(uint32_t *)(ptr + offset + size - 4))
1787 return -FDT_ERR_BADSTRUCTURE;
Pali Rohár93804452021-07-23 11:14:02 +02001788 }
1789
Stefan Roese4acd2d22014-10-22 12:13:23 +02001790 return 0;
1791}
1792
1793static int kwbimage_generate(struct image_tool_params *params,
1794 struct image_type_params *tparams)
1795{
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001796 FILE *fcfg;
Pali Rohár37cb9c12021-07-23 11:13:56 +02001797 struct stat s;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001798 int alloc_len;
Pali Rohárc934aad2021-07-23 11:13:57 +02001799 int bootfrom;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001800 int version;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001801 void *hdr;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001802 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001803
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001804 fcfg = fopen(params->imagename, "r");
1805 if (!fcfg) {
1806 fprintf(stderr, "Could not open input file %s\n",
1807 params->imagename);
1808 exit(EXIT_FAILURE);
1809 }
1810
Pali Rohár37cb9c12021-07-23 11:13:56 +02001811 if (stat(params->datafile, &s)) {
1812 fprintf(stderr, "Could not stat data file %s: %s\n",
1813 params->datafile, strerror(errno));
1814 exit(EXIT_FAILURE);
1815 }
1816
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001817 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1818 sizeof(struct image_cfg_element));
1819 if (!image_cfg) {
1820 fprintf(stderr, "Cannot allocate memory\n");
1821 fclose(fcfg);
1822 exit(EXIT_FAILURE);
1823 }
1824
1825 memset(image_cfg, 0,
1826 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1827 rewind(fcfg);
1828
1829 ret = image_create_config_parse(fcfg);
1830 fclose(fcfg);
1831 if (ret) {
1832 free(image_cfg);
1833 exit(EXIT_FAILURE);
1834 }
1835
Pali Rohárc934aad2021-07-23 11:13:57 +02001836 bootfrom = image_get_bootfrom();
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001837 version = image_get_version();
1838 switch (version) {
1839 /*
1840 * Fallback to version 0 if no version is provided in the
1841 * cfg file
1842 */
1843 case -1:
1844 case 0:
Stefan Roese4acd2d22014-10-22 12:13:23 +02001845 alloc_len = sizeof(struct main_hdr_v0) +
1846 sizeof(struct ext_hdr_v0);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001847 break;
1848
1849 case 1:
Mario Sixe93cf532017-01-11 16:00:57 +01001850 alloc_len = image_headersz_v1(NULL);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001851 break;
1852
1853 default:
1854 fprintf(stderr, "Unsupported version %d\n", version);
1855 free(image_cfg);
1856 exit(EXIT_FAILURE);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001857 }
1858
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001859 free(image_cfg);
1860
Stefan Roese4acd2d22014-10-22 12:13:23 +02001861 hdr = malloc(alloc_len);
1862 if (!hdr) {
1863 fprintf(stderr, "%s: malloc return failure: %s\n",
1864 params->cmdname, strerror(errno));
1865 exit(EXIT_FAILURE);
1866 }
1867
1868 memset(hdr, 0, alloc_len);
1869 tparams->header_size = alloc_len;
1870 tparams->hdr = hdr;
1871
Stefan Roese77720852015-11-24 09:14:59 +01001872 /*
1873 * The resulting image needs to be 4-byte aligned. At least
1874 * the Marvell hdrparser tool complains if its unaligned.
Pali Rohár37cb9c12021-07-23 11:13:56 +02001875 * After the image data is stored 4-byte checksum.
Pali Rohárc934aad2021-07-23 11:13:57 +02001876 * Final SPI and NAND images must be aligned to 256 bytes.
Pali Rohár501a54a2021-07-23 11:13:59 +02001877 * Final SATA and SDIO images must be aligned to 512 bytes.
Stefan Roese77720852015-11-24 09:14:59 +01001878 */
Pali Rohárc934aad2021-07-23 11:13:57 +02001879 if (bootfrom == IBR_HDR_SPI_ID || bootfrom == IBR_HDR_NAND_ID)
1880 return 4 + (256 - (alloc_len + s.st_size + 4) % 256) % 256;
Pali Rohár501a54a2021-07-23 11:13:59 +02001881 else if (bootfrom == IBR_HDR_SATA_ID || bootfrom == IBR_HDR_SDIO_ID)
1882 return 4 + (512 - (alloc_len + s.st_size + 4) % 512) % 512;
Pali Rohárc934aad2021-07-23 11:13:57 +02001883 else
1884 return 4 + (4 - s.st_size % 4) % 4;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001885}
1886
1887/*
1888 * Report Error if xflag is set in addition to default
1889 */
1890static int kwbimage_check_params(struct image_tool_params *params)
1891{
1892 if (!strlen(params->imagename)) {
Mario Six94490a42017-01-11 16:00:54 +01001893 char *msg = "Configuration file for kwbimage creation omitted";
1894
1895 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001896 return CFG_INVALID;
1897 }
1898
1899 return (params->dflag && (params->fflag || params->lflag)) ||
1900 (params->fflag && (params->dflag || params->lflag)) ||
1901 (params->lflag && (params->dflag || params->fflag)) ||
1902 (params->xflag) || !(strlen(params->imagename));
1903}
1904
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301905/*
1906 * kwbimage type parameters definition
1907 */
Guilherme Maciel Ferreiraa93648d2015-01-15 02:48:07 -02001908U_BOOT_IMAGE_TYPE(
1909 kwbimage,
1910 "Marvell MVEBU Boot Image support",
1911 0,
1912 NULL,
1913 kwbimage_check_params,
1914 kwbimage_verify_header,
1915 kwbimage_print_header,
1916 kwbimage_set_header,
1917 NULL,
1918 kwbimage_check_image_types,
1919 NULL,
1920 kwbimage_generate
1921);