blob: 5665198db01b20f2c8b6d5dc8967d3b53d7fcaec [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +02003 * Image manipulator for Marvell SoCs
Mario Six10d14492017-01-11 16:01:00 +01004 * supports Kirkwood, Dove, Armada 370, Armada XP, and Armada 38x
Stefan Roese3b8b19d2014-10-22 12:13:23 +02005 *
6 * (C) Copyright 2013 Thomas Petazzoni
7 * <thomas.petazzoni@free-electrons.com>
Prafulla Wadaskar07329412009-09-07 15:05:02 +05308 *
Mario Six10d14492017-01-11 16:01:00 +01009 * Not implemented: support for the register headers in v1 images
Prafulla Wadaskar07329412009-09-07 15:05:02 +053010 */
11
Guilherme Maciel Ferreira8ed4d1c2013-12-01 12:43:10 -070012#include "imagetool.h"
Andreas Bießmann7abec5b2014-10-24 23:39:11 +020013#include <limits.h>
Prafulla Wadaskar07329412009-09-07 15:05:02 +053014#include <image.h>
Mario Six10d14492017-01-11 16:01:00 +010015#include <stdarg.h>
Stefan Roese3b8b19d2014-10-22 12:13:23 +020016#include <stdint.h>
Prafulla Wadaskar07329412009-09-07 15:05:02 +053017#include "kwbimage.h"
18
Jelle van der Waae0e55592017-05-08 21:31:20 +020019#include <openssl/bn.h>
Mario Six10d14492017-01-11 16:01:00 +010020#include <openssl/rsa.h>
21#include <openssl/pem.h>
22#include <openssl/err.h>
23#include <openssl/evp.h>
Jelle van der Waae0e55592017-05-08 21:31:20 +020024
Jonathan Gray237d0592018-02-21 02:59:01 +110025#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
26 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
Jelle van der Waae0e55592017-05-08 21:31:20 +020027static void RSA_get0_key(const RSA *r,
28 const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
29{
30 if (n != NULL)
31 *n = r->n;
32 if (e != NULL)
33 *e = r->e;
34 if (d != NULL)
35 *d = r->d;
36}
37
Jonathan Gray237d0592018-02-21 02:59:01 +110038#elif !defined(LIBRESSL_VERSION_NUMBER)
Jelle van der Waae0e55592017-05-08 21:31:20 +020039void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
40{
41 EVP_MD_CTX_reset(ctx);
42}
43#endif
Mario Six10d14492017-01-11 16:01:00 +010044
Stefan Roese3b8b19d2014-10-22 12:13:23 +020045static struct image_cfg_element *image_cfg;
46static int cfgn;
Mario Six10d14492017-01-11 16:01:00 +010047static int verbose_mode;
Stefan Roese3b8b19d2014-10-22 12:13:23 +020048
49struct boot_mode {
50 unsigned int id;
51 const char *name;
52};
53
Mario Six10d14492017-01-11 16:01:00 +010054/*
55 * SHA2-256 hash
56 */
57struct hash_v1 {
58 uint8_t hash[32];
59};
60
Stefan Roese3b8b19d2014-10-22 12:13:23 +020061struct boot_mode boot_modes[] = {
62 { 0x4D, "i2c" },
63 { 0x5A, "spi" },
64 { 0x8B, "nand" },
65 { 0x78, "sata" },
66 { 0x9C, "pex" },
67 { 0x69, "uart" },
Stefan Roese539fe4a2015-07-20 11:20:37 +020068 { 0xAE, "sdio" },
Stefan Roese3b8b19d2014-10-22 12:13:23 +020069 {},
Prafulla Wadaskar07329412009-09-07 15:05:02 +053070};
71
Stefan Roese3b8b19d2014-10-22 12:13:23 +020072struct nand_ecc_mode {
73 unsigned int id;
74 const char *name;
75};
76
77struct nand_ecc_mode nand_ecc_modes[] = {
78 { 0x00, "default" },
79 { 0x01, "hamming" },
80 { 0x02, "rs" },
81 { 0x03, "disabled" },
82 {},
83};
84
85/* Used to identify an undefined execution or destination address */
86#define ADDR_INVALID ((uint32_t)-1)
87
Pali Rohár13b70402021-07-23 11:14:07 +020088#define BINARY_MAX_ARGS 255
Stefan Roese3b8b19d2014-10-22 12:13:23 +020089
90/* In-memory representation of a line of the configuration file */
Mario Six62da6762017-01-11 16:00:59 +010091
92enum image_cfg_type {
93 IMAGE_CFG_VERSION = 0x1,
94 IMAGE_CFG_BOOT_FROM,
95 IMAGE_CFG_DEST_ADDR,
96 IMAGE_CFG_EXEC_ADDR,
97 IMAGE_CFG_NAND_BLKSZ,
98 IMAGE_CFG_NAND_BADBLK_LOCATION,
99 IMAGE_CFG_NAND_ECC_MODE,
100 IMAGE_CFG_NAND_PAGESZ,
101 IMAGE_CFG_BINARY,
Mario Six62da6762017-01-11 16:00:59 +0100102 IMAGE_CFG_DATA,
Pali Rohárc0cfd1a2021-07-23 11:14:12 +0200103 IMAGE_CFG_DATA_DELAY,
Mario Six62da6762017-01-11 16:00:59 +0100104 IMAGE_CFG_BAUDRATE,
105 IMAGE_CFG_DEBUG,
Mario Six10d14492017-01-11 16:01:00 +0100106 IMAGE_CFG_KAK,
107 IMAGE_CFG_CSK,
108 IMAGE_CFG_CSK_INDEX,
109 IMAGE_CFG_JTAG_DELAY,
110 IMAGE_CFG_BOX_ID,
111 IMAGE_CFG_FLASH_ID,
112 IMAGE_CFG_SEC_COMMON_IMG,
113 IMAGE_CFG_SEC_SPECIALIZED_IMG,
114 IMAGE_CFG_SEC_BOOT_DEV,
115 IMAGE_CFG_SEC_FUSE_DUMP,
Mario Six62da6762017-01-11 16:00:59 +0100116
117 IMAGE_CFG_COUNT
118} type;
119
120static const char * const id_strs[] = {
121 [IMAGE_CFG_VERSION] = "VERSION",
122 [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
123 [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
124 [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
125 [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
126 [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
127 [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
128 [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
129 [IMAGE_CFG_BINARY] = "BINARY",
Mario Six62da6762017-01-11 16:00:59 +0100130 [IMAGE_CFG_DATA] = "DATA",
Pali Rohárc0cfd1a2021-07-23 11:14:12 +0200131 [IMAGE_CFG_DATA_DELAY] = "DATA_DELAY",
Mario Six62da6762017-01-11 16:00:59 +0100132 [IMAGE_CFG_BAUDRATE] = "BAUDRATE",
133 [IMAGE_CFG_DEBUG] = "DEBUG",
Mario Six10d14492017-01-11 16:01:00 +0100134 [IMAGE_CFG_KAK] = "KAK",
135 [IMAGE_CFG_CSK] = "CSK",
136 [IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
137 [IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
138 [IMAGE_CFG_BOX_ID] = "BOX_ID",
139 [IMAGE_CFG_FLASH_ID] = "FLASH_ID",
140 [IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
141 [IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
142 [IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
143 [IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
Mario Six62da6762017-01-11 16:00:59 +0100144};
145
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200146struct image_cfg_element {
Mario Six62da6762017-01-11 16:00:59 +0100147 enum image_cfg_type type;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200148 union {
149 unsigned int version;
150 unsigned int bootfrom;
151 struct {
152 const char *file;
153 unsigned int args[BINARY_MAX_ARGS];
154 unsigned int nargs;
155 } binary;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200156 unsigned int dstaddr;
157 unsigned int execaddr;
158 unsigned int nandblksz;
159 unsigned int nandbadblklocation;
160 unsigned int nandeccmode;
161 unsigned int nandpagesz;
162 struct ext_hdr_v0_reg regdata;
Pali Rohárc0cfd1a2021-07-23 11:14:12 +0200163 unsigned int regdata_delay;
Chris Packham883bf452016-11-09 22:07:45 +1300164 unsigned int baudrate;
Chris Packham1e0728a2016-11-09 22:21:45 +1300165 unsigned int debug;
Mario Six10d14492017-01-11 16:01:00 +0100166 const char *key_name;
167 int csk_idx;
168 uint8_t jtag_delay;
169 uint32_t boxid;
170 uint32_t flashid;
171 bool sec_specialized_img;
172 unsigned int sec_boot_dev;
173 const char *name;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200174 };
175};
176
177#define IMAGE_CFG_ELEMENT_MAX 256
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530178
179/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200180 * Utility functions to manipulate boot mode and ecc modes (convert
181 * them back and forth between description strings and the
182 * corresponding numerical identifiers).
183 */
184
185static const char *image_boot_mode_name(unsigned int id)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530186{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200187 int i;
Mario Sixd6009d72017-01-11 16:00:54 +0100188
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200189 for (i = 0; boot_modes[i].name; i++)
190 if (boot_modes[i].id == id)
191 return boot_modes[i].name;
192 return NULL;
193}
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530194
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200195int image_boot_mode_id(const char *boot_mode_name)
196{
197 int i;
Mario Sixd6009d72017-01-11 16:00:54 +0100198
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200199 for (i = 0; boot_modes[i].name; i++)
200 if (!strcmp(boot_modes[i].name, boot_mode_name))
201 return boot_modes[i].id;
202
203 return -1;
204}
205
206int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
207{
208 int i;
Mario Sixd6009d72017-01-11 16:00:54 +0100209
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200210 for (i = 0; nand_ecc_modes[i].name; i++)
211 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
212 return nand_ecc_modes[i].id;
213 return -1;
214}
215
216static struct image_cfg_element *
217image_find_option(unsigned int optiontype)
218{
219 int i;
220
221 for (i = 0; i < cfgn; i++) {
222 if (image_cfg[i].type == optiontype)
223 return &image_cfg[i];
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530224 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200225
226 return NULL;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530227}
228
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200229static unsigned int
230image_count_options(unsigned int optiontype)
231{
232 int i;
233 unsigned int count = 0;
234
235 for (i = 0; i < cfgn; i++)
236 if (image_cfg[i].type == optiontype)
237 count++;
238
239 return count;
240}
241
Mario Six10d14492017-01-11 16:01:00 +0100242static int image_get_csk_index(void)
243{
244 struct image_cfg_element *e;
245
246 e = image_find_option(IMAGE_CFG_CSK_INDEX);
247 if (!e)
248 return -1;
249
250 return e->csk_idx;
251}
252
253static bool image_get_spezialized_img(void)
254{
255 struct image_cfg_element *e;
256
257 e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
258 if (!e)
259 return false;
260
261 return e->sec_specialized_img;
262}
263
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530264/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200265 * Compute a 8-bit checksum of a memory area. This algorithm follows
266 * the requirements of the Marvell SoC BootROM specifications.
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530267 */
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200268static uint8_t image_checksum8(void *start, uint32_t len)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530269{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200270 uint8_t csum = 0;
271 uint8_t *p = start;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530272
273 /* check len and return zero checksum if invalid */
274 if (!len)
275 return 0;
276
277 do {
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200278 csum += *p;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530279 p++;
280 } while (--len);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200281
282 return csum;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530283}
284
Baruch Siach4a5b99b2017-07-04 20:23:40 +0300285size_t kwbimage_header_size(unsigned char *ptr)
286{
287 if (image_version((void *)ptr) == 0)
288 return sizeof(struct main_hdr_v0);
289 else
290 return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr);
291}
292
293/*
294 * Verify checksum over a complete header that includes the checksum field.
295 * Return 1 when OK, otherwise 0.
296 */
297static int main_hdr_checksum_ok(void *hdr)
298{
299 /* Offsets of checksum in v0 and v1 headers are the same */
300 struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
301 uint8_t checksum;
302
303 checksum = image_checksum8(hdr, kwbimage_header_size(hdr));
304 /* Calculated checksum includes the header checksum field. Compensate
305 * for that.
306 */
307 checksum -= main_hdr->checksum;
308
309 return checksum == main_hdr->checksum;
310}
311
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200312static uint32_t image_checksum32(void *start, uint32_t len)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530313{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200314 uint32_t csum = 0;
315 uint32_t *p = start;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530316
317 /* check len and return zero checksum if invalid */
318 if (!len)
319 return 0;
320
321 if (len % sizeof(uint32_t)) {
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200322 fprintf(stderr, "Length %d is not in multiple of %zu\n",
323 len, sizeof(uint32_t));
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530324 return 0;
325 }
326
327 do {
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200328 csum += *p;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530329 p++;
330 len -= sizeof(uint32_t);
331 } while (len > 0);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200332
333 return csum;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530334}
335
Chris Packham883bf452016-11-09 22:07:45 +1300336static uint8_t baudrate_to_option(unsigned int baudrate)
337{
338 switch (baudrate) {
339 case 2400:
340 return MAIN_HDR_V1_OPT_BAUD_2400;
341 case 4800:
342 return MAIN_HDR_V1_OPT_BAUD_4800;
343 case 9600:
344 return MAIN_HDR_V1_OPT_BAUD_9600;
345 case 19200:
346 return MAIN_HDR_V1_OPT_BAUD_19200;
347 case 38400:
348 return MAIN_HDR_V1_OPT_BAUD_38400;
349 case 57600:
350 return MAIN_HDR_V1_OPT_BAUD_57600;
351 case 115200:
352 return MAIN_HDR_V1_OPT_BAUD_115200;
353 default:
354 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
355 }
356}
357
Mario Six10d14492017-01-11 16:01:00 +0100358static void kwb_msg(const char *fmt, ...)
359{
360 if (verbose_mode) {
361 va_list ap;
362
363 va_start(ap, fmt);
364 vfprintf(stdout, fmt, ap);
365 va_end(ap);
366 }
367}
368
369static int openssl_err(const char *msg)
370{
371 unsigned long ssl_err = ERR_get_error();
372
373 fprintf(stderr, "%s", msg);
374 fprintf(stderr, ": %s\n",
375 ERR_error_string(ssl_err, 0));
376
377 return -1;
378}
379
380static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
381{
382 char path[PATH_MAX];
383 RSA *rsa;
384 FILE *f;
385
386 if (!keydir)
387 keydir = ".";
388
389 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
390 f = fopen(path, "r");
391 if (!f) {
392 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
393 path, strerror(errno));
394 return -ENOENT;
395 }
396
397 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
398 if (!rsa) {
399 openssl_err("Failure reading private key");
400 fclose(f);
401 return -EPROTO;
402 }
403 fclose(f);
404 *p_rsa = rsa;
405
406 return 0;
407}
408
409static int kwb_load_cfg_key(struct image_tool_params *params,
410 unsigned int cfg_option, const char *key_name,
411 RSA **p_key)
412{
413 struct image_cfg_element *e_key;
414 RSA *key;
415 int res;
416
417 *p_key = NULL;
418
419 e_key = image_find_option(cfg_option);
420 if (!e_key) {
421 fprintf(stderr, "%s not configured\n", key_name);
422 return -ENOENT;
423 }
424
425 res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
426 if (res < 0) {
427 fprintf(stderr, "Failed to load %s\n", key_name);
428 return -ENOENT;
429 }
430
431 *p_key = key;
432
433 return 0;
434}
435
436static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
437{
438 return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
439}
440
441static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
442{
443 return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
444}
445
446static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
447 struct hash_v1 *hash)
448{
449 EVP_MD_CTX *ctx;
450 unsigned int key_size;
451 unsigned int hash_size;
452 int ret = 0;
453
454 if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
455 return -EINVAL;
456
457 key_size = (pk->key[2] << 8) + pk->key[3] + 4;
458
459 ctx = EVP_MD_CTX_create();
460 if (!ctx)
461 return openssl_err("EVP context creation failed");
462
463 EVP_MD_CTX_init(ctx);
464 if (!EVP_DigestInit(ctx, EVP_sha256())) {
465 ret = openssl_err("Digest setup failed");
466 goto hash_err_ctx;
467 }
468
469 if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
470 ret = openssl_err("Hashing data failed");
471 goto hash_err_ctx;
472 }
473
474 if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
475 ret = openssl_err("Could not obtain hash");
476 goto hash_err_ctx;
477 }
478
479 EVP_MD_CTX_cleanup(ctx);
480
481hash_err_ctx:
482 EVP_MD_CTX_destroy(ctx);
483 return ret;
484}
485
486static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
487{
488 RSA *rsa;
489 const unsigned char *ptr;
490
491 if (!key || !src)
492 goto fail;
493
494 ptr = src->key;
495 rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
496 if (!rsa) {
497 openssl_err("error decoding public key");
498 goto fail;
499 }
500
501 return 0;
502fail:
503 fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
504 return -EINVAL;
505}
506
507static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
508 char *keyname)
509{
510 int size_exp, size_mod, size_seq;
Jelle van der Waae0e55592017-05-08 21:31:20 +0200511 const BIGNUM *key_e, *key_n;
Mario Six10d14492017-01-11 16:01:00 +0100512 uint8_t *cur;
513 char *errmsg = "Failed to encode %s\n";
514
Jelle van der Waae0e55592017-05-08 21:31:20 +0200515 RSA_get0_key(key, NULL, &key_e, NULL);
516 RSA_get0_key(key, &key_n, NULL, NULL);
517
518 if (!key || !key_e || !key_n || !dst) {
Mario Six10d14492017-01-11 16:01:00 +0100519 fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
Jelle van der Waae0e55592017-05-08 21:31:20 +0200520 key, key_e, key_n, dst);
Mario Six10d14492017-01-11 16:01:00 +0100521 fprintf(stderr, errmsg, keyname);
522 return -EINVAL;
523 }
524
525 /*
526 * According to the specs, the key should be PKCS#1 DER encoded.
527 * But unfortunately the really required encoding seems to be different;
528 * it violates DER...! (But it still conformes to BER.)
529 * (Length always in long form w/ 2 byte length code; no leading zero
530 * when MSB of first byte is set...)
531 * So we cannot use the encoding func provided by OpenSSL and have to
532 * do the encoding manually.
533 */
534
Jelle van der Waae0e55592017-05-08 21:31:20 +0200535 size_exp = BN_num_bytes(key_e);
536 size_mod = BN_num_bytes(key_n);
Mario Six10d14492017-01-11 16:01:00 +0100537 size_seq = 4 + size_mod + 4 + size_exp;
538
539 if (size_mod > 256) {
540 fprintf(stderr, "export pk failed: wrong mod size: %d\n",
541 size_mod);
542 fprintf(stderr, errmsg, keyname);
543 return -EINVAL;
544 }
545
546 if (4 + size_seq > sizeof(dst->key)) {
547 fprintf(stderr, "export pk failed: seq too large (%d, %lu)\n",
548 4 + size_seq, sizeof(dst->key));
549 fprintf(stderr, errmsg, keyname);
550 return -ENOBUFS;
551 }
552
553 cur = dst->key;
554
555 /* PKCS#1 (RFC3447) RSAPublicKey structure */
556 *cur++ = 0x30; /* SEQUENCE */
557 *cur++ = 0x82;
558 *cur++ = (size_seq >> 8) & 0xFF;
559 *cur++ = size_seq & 0xFF;
560 /* Modulus */
561 *cur++ = 0x02; /* INTEGER */
562 *cur++ = 0x82;
563 *cur++ = (size_mod >> 8) & 0xFF;
564 *cur++ = size_mod & 0xFF;
Jelle van der Waae0e55592017-05-08 21:31:20 +0200565 BN_bn2bin(key_n, cur);
Mario Six10d14492017-01-11 16:01:00 +0100566 cur += size_mod;
567 /* Exponent */
568 *cur++ = 0x02; /* INTEGER */
569 *cur++ = 0x82;
570 *cur++ = (size_exp >> 8) & 0xFF;
571 *cur++ = size_exp & 0xFF;
Jelle van der Waae0e55592017-05-08 21:31:20 +0200572 BN_bn2bin(key_e, cur);
Mario Six10d14492017-01-11 16:01:00 +0100573
574 if (hashf) {
575 struct hash_v1 pk_hash;
576 int i;
577 int ret = 0;
578
579 ret = kwb_compute_pubkey_hash(dst, &pk_hash);
580 if (ret < 0) {
581 fprintf(stderr, errmsg, keyname);
582 return ret;
583 }
584
585 fprintf(hashf, "SHA256 = ");
586 for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
587 fprintf(hashf, "%02X", pk_hash.hash[i]);
588 fprintf(hashf, "\n");
589 }
590
591 return 0;
592}
593
594int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig, char *signame)
595{
596 EVP_PKEY *evp_key;
597 EVP_MD_CTX *ctx;
598 unsigned int sig_size;
599 int size;
600 int ret = 0;
601
602 evp_key = EVP_PKEY_new();
603 if (!evp_key)
604 return openssl_err("EVP_PKEY object creation failed");
605
606 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
607 ret = openssl_err("EVP key setup failed");
608 goto err_key;
609 }
610
611 size = EVP_PKEY_size(evp_key);
612 if (size > sizeof(sig->sig)) {
613 fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
614 size);
615 ret = -ENOBUFS;
616 goto err_key;
617 }
618
619 ctx = EVP_MD_CTX_create();
620 if (!ctx) {
621 ret = openssl_err("EVP context creation failed");
622 goto err_key;
623 }
624 EVP_MD_CTX_init(ctx);
625 if (!EVP_SignInit(ctx, EVP_sha256())) {
626 ret = openssl_err("Signer setup failed");
627 goto err_ctx;
628 }
629
630 if (!EVP_SignUpdate(ctx, data, datasz)) {
631 ret = openssl_err("Signing data failed");
632 goto err_ctx;
633 }
634
635 if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
636 ret = openssl_err("Could not obtain signature");
637 goto err_ctx;
638 }
639
640 EVP_MD_CTX_cleanup(ctx);
641 EVP_MD_CTX_destroy(ctx);
642 EVP_PKEY_free(evp_key);
643
644 return 0;
645
646err_ctx:
647 EVP_MD_CTX_destroy(ctx);
648err_key:
649 EVP_PKEY_free(evp_key);
650 fprintf(stderr, "Failed to create %s signature\n", signame);
651 return ret;
652}
653
654int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
655 char *signame)
656{
657 EVP_PKEY *evp_key;
658 EVP_MD_CTX *ctx;
659 int size;
660 int ret = 0;
661
662 evp_key = EVP_PKEY_new();
663 if (!evp_key)
664 return openssl_err("EVP_PKEY object creation failed");
665
666 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
667 ret = openssl_err("EVP key setup failed");
668 goto err_key;
669 }
670
671 size = EVP_PKEY_size(evp_key);
672 if (size > sizeof(sig->sig)) {
673 fprintf(stderr, "Invalid signature size (%d bytes)\n",
674 size);
675 ret = -EINVAL;
676 goto err_key;
677 }
678
679 ctx = EVP_MD_CTX_create();
680 if (!ctx) {
681 ret = openssl_err("EVP context creation failed");
682 goto err_key;
683 }
684 EVP_MD_CTX_init(ctx);
685 if (!EVP_VerifyInit(ctx, EVP_sha256())) {
686 ret = openssl_err("Verifier setup failed");
687 goto err_ctx;
688 }
689
690 if (!EVP_VerifyUpdate(ctx, data, datasz)) {
691 ret = openssl_err("Hashing data failed");
692 goto err_ctx;
693 }
694
Young Xiaoda575f52019-04-17 17:20:24 +0800695 if (EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key) != 1) {
Mario Six10d14492017-01-11 16:01:00 +0100696 ret = openssl_err("Could not verify signature");
697 goto err_ctx;
698 }
699
700 EVP_MD_CTX_cleanup(ctx);
701 EVP_MD_CTX_destroy(ctx);
702 EVP_PKEY_free(evp_key);
703
704 return 0;
705
706err_ctx:
707 EVP_MD_CTX_destroy(ctx);
708err_key:
709 EVP_PKEY_free(evp_key);
710 fprintf(stderr, "Failed to verify %s signature\n", signame);
711 return ret;
712}
713
714int kwb_sign_and_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
715 char *signame)
716{
717 if (kwb_sign(key, data, datasz, sig, signame) < 0)
718 return -1;
719
720 if (kwb_verify(key, data, datasz, sig, signame) < 0)
721 return -1;
722
723 return 0;
724}
725
726
727int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
728{
729 struct hash_v1 kak_pub_hash;
730 struct image_cfg_element *e;
731 unsigned int fuse_line;
732 int i, idx;
733 uint8_t *ptr;
734 uint32_t val;
735 int ret = 0;
736
737 if (!out || !sec_hdr)
738 return -EINVAL;
739
740 ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
741 if (ret < 0)
742 goto done;
743
744 fprintf(out, "# burn KAK pub key hash\n");
745 ptr = kak_pub_hash.hash;
746 for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
747 fprintf(out, "fuse prog -y %u 0 ", fuse_line);
748
749 for (i = 4; i-- > 0;)
750 fprintf(out, "%02hx", (ushort)ptr[i]);
751 ptr += 4;
752 fprintf(out, " 00");
753
754 if (fuse_line < 30) {
755 for (i = 3; i-- > 0;)
756 fprintf(out, "%02hx", (ushort)ptr[i]);
757 ptr += 3;
758 } else {
759 fprintf(out, "000000");
760 }
761
762 fprintf(out, " 1\n");
763 }
764
765 fprintf(out, "# burn CSK selection\n");
766
767 idx = image_get_csk_index();
768 if (idx < 0 || idx > 15) {
769 ret = -EINVAL;
770 goto done;
771 }
772 if (idx > 0) {
773 for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
774 fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
775 fuse_line);
776 } else {
777 fprintf(out, "# CSK index is 0; no mods needed\n");
778 }
779
780 e = image_find_option(IMAGE_CFG_BOX_ID);
781 if (e) {
782 fprintf(out, "# set box ID\n");
783 fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
784 }
785
786 e = image_find_option(IMAGE_CFG_FLASH_ID);
787 if (e) {
788 fprintf(out, "# set flash ID\n");
789 fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
790 }
791
792 fprintf(out, "# enable secure mode ");
793 fprintf(out, "(must be the last fuse line written)\n");
794
795 val = 1;
796 e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
797 if (!e) {
798 fprintf(stderr, "ERROR: secured mode boot device not given\n");
799 ret = -EINVAL;
800 goto done;
801 }
802
803 if (e->sec_boot_dev > 0xff) {
804 fprintf(stderr, "ERROR: secured mode boot device invalid\n");
805 ret = -EINVAL;
806 goto done;
807 }
808
809 val |= (e->sec_boot_dev << 8);
810
811 fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
812
813 fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
814 for (fuse_line = 0; fuse_line < 24; ++fuse_line)
815 fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
816
817 fprintf(out, "# OK, that's all :-)\n");
818
819done:
820 return ret;
821}
822
823static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
824{
825 int ret = 0;
826 struct image_cfg_element *e;
827
828 e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
829 if (!e)
830 return 0;
831
832 if (!strcmp(e->name, "a38x")) {
833 FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
834
835 kwb_dump_fuse_cmds_38x(out, sec_hdr);
836 fclose(out);
837 goto done;
838 }
839
840 ret = -ENOSYS;
841
842done:
843 return ret;
844}
845
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200846static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
847 int payloadsz)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530848{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200849 struct image_cfg_element *e;
850 size_t headersz;
851 struct main_hdr_v0 *main_hdr;
Mario Six7497cd62017-01-11 16:00:55 +0100852 uint8_t *image;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200853 int has_ext = 0;
854
855 /*
856 * Calculate the size of the header and the size of the
857 * payload
858 */
859 headersz = sizeof(struct main_hdr_v0);
860
861 if (image_count_options(IMAGE_CFG_DATA) > 0) {
862 has_ext = 1;
863 headersz += sizeof(struct ext_hdr_v0);
864 }
865
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200866 image = malloc(headersz);
867 if (!image) {
868 fprintf(stderr, "Cannot allocate memory for image\n");
869 return NULL;
870 }
871
872 memset(image, 0, headersz);
873
Mario Six7497cd62017-01-11 16:00:55 +0100874 main_hdr = (struct main_hdr_v0 *)image;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530875
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200876 /* Fill in the main header */
Reinhard Pfau3efeaae2015-11-29 15:48:25 +0100877 main_hdr->blocksize =
Pali Rohárcfb60a92021-07-23 11:13:56 +0200878 cpu_to_le32(payloadsz - headersz);
Reinhard Pfau3efeaae2015-11-29 15:48:25 +0100879 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200880 main_hdr->ext = has_ext;
Reinhard Pfau3efeaae2015-11-29 15:48:25 +0100881 main_hdr->destaddr = cpu_to_le32(params->addr);
882 main_hdr->execaddr = cpu_to_le32(params->ep);
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530883
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200884 e = image_find_option(IMAGE_CFG_BOOT_FROM);
885 if (e)
886 main_hdr->blockid = e->bootfrom;
887 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
888 if (e)
889 main_hdr->nandeccmode = e->nandeccmode;
890 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
891 if (e)
Reinhard Pfau3efeaae2015-11-29 15:48:25 +0100892 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200893 main_hdr->checksum = image_checksum8(image,
894 sizeof(struct main_hdr_v0));
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530895
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200896 /* Generate the ext header */
897 if (has_ext) {
Mario Six6f273632017-01-11 16:00:56 +0100898 struct ext_hdr_v0 *ext_hdr;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200899 int cfgi, datai;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530900
Mario Six7497cd62017-01-11 16:00:55 +0100901 ext_hdr = (struct ext_hdr_v0 *)
902 (image + sizeof(struct main_hdr_v0));
Reinhard Pfau3efeaae2015-11-29 15:48:25 +0100903 ext_hdr->offset = cpu_to_le32(0x40);
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530904
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200905 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
906 e = &image_cfg[cfgi];
907 if (e->type != IMAGE_CFG_DATA)
908 continue;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530909
Reinhard Pfau3efeaae2015-11-29 15:48:25 +0100910 ext_hdr->rcfg[datai].raddr =
911 cpu_to_le32(e->regdata.raddr);
912 ext_hdr->rcfg[datai].rdata =
913 cpu_to_le32(e->regdata.rdata);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200914 datai++;
915 }
916
917 ext_hdr->checksum = image_checksum8(ext_hdr,
918 sizeof(struct ext_hdr_v0));
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530919 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530920
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200921 *imagesz = headersz;
922 return image;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530923}
924
Mario Six855cf9e2017-01-11 16:00:57 +0100925static size_t image_headersz_v1(int *hasext)
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200926{
927 struct image_cfg_element *binarye;
Pali Rohárfbe10ac2021-07-23 11:14:11 +0200928 unsigned int count;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200929 size_t headersz;
Pali Roháre0a6dc72021-07-23 11:14:09 +0200930 int cfgi;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530931
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200932 /*
933 * Calculate the size of the header and the size of the
934 * payload
935 */
936 headersz = sizeof(struct main_hdr_v1);
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530937
Pali Rohárfbe10ac2021-07-23 11:14:11 +0200938 count = image_count_options(IMAGE_CFG_DATA);
939 if (count > 0)
940 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
941
Pali Roháre0a6dc72021-07-23 11:14:09 +0200942 for (cfgi = 0; cfgi < cfgn; cfgi++) {
Mario Six6f273632017-01-11 16:00:56 +0100943 int ret;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200944 struct stat s;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530945
Pali Roháre0a6dc72021-07-23 11:14:09 +0200946 binarye = &image_cfg[cfgi];
947 if (binarye->type != IMAGE_CFG_BINARY)
948 continue;
949
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200950 ret = stat(binarye->binary.file, &s);
951 if (ret < 0) {
Andreas Bießmann7abec5b2014-10-24 23:39:11 +0200952 char cwd[PATH_MAX];
953 char *dir = cwd;
954
955 memset(cwd, 0, sizeof(cwd));
956 if (!getcwd(cwd, sizeof(cwd))) {
957 dir = "current working directory";
958 perror("getcwd() failed");
959 }
960
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200961 fprintf(stderr,
962 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
963 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
964 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
Andreas Bießmann7abec5b2014-10-24 23:39:11 +0200965 binarye->binary.file, dir);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200966 return 0;
967 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530968
Reinhard Pfau5286c0d2015-11-29 15:52:14 +0100969 headersz += sizeof(struct opt_hdr_v1) +
Pali Rohárd79cbc92021-07-23 11:14:08 +0200970 ALIGN(s.st_size, 4) +
Reinhard Pfau5286c0d2015-11-29 15:52:14 +0100971 (binarye->binary.nargs + 2) * sizeof(uint32_t);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200972 if (hasext)
973 *hasext = 1;
974 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530975
Mario Six10d14492017-01-11 16:01:00 +0100976 if (image_get_csk_index() >= 0) {
977 headersz += sizeof(struct secure_hdr_v1);
978 if (hasext)
979 *hasext = 1;
980 }
Mario Six10d14492017-01-11 16:01:00 +0100981
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200982 /*
983 * The payload should be aligned on some reasonable
984 * boundary
985 */
Kever Yang0b21cde2020-03-30 11:56:20 +0800986 return ALIGN(headersz, 4096);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200987}
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530988
Pali Roháre0a6dc72021-07-23 11:14:09 +0200989int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
990 struct image_cfg_element *binarye)
Mario Six030ca162017-01-11 16:00:58 +0100991{
Pali Roháre0a6dc72021-07-23 11:14:09 +0200992 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur;
Mario Six030ca162017-01-11 16:00:58 +0100993 uint32_t *args;
994 size_t binhdrsz;
995 struct stat s;
996 int argi;
997 FILE *bin;
998 int ret;
999
Mario Six030ca162017-01-11 16:00:58 +01001000 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1001
1002 bin = fopen(binarye->binary.file, "r");
1003 if (!bin) {
1004 fprintf(stderr, "Cannot open binary file %s\n",
1005 binarye->binary.file);
1006 return -1;
1007 }
1008
Mario Sixe3edf162017-02-13 10:11:55 +01001009 if (fstat(fileno(bin), &s)) {
1010 fprintf(stderr, "Cannot stat binary file %s\n",
1011 binarye->binary.file);
1012 goto err_close;
1013 }
Mario Six030ca162017-01-11 16:00:58 +01001014
1015 binhdrsz = sizeof(struct opt_hdr_v1) +
1016 (binarye->binary.nargs + 2) * sizeof(uint32_t) +
Pali Rohárd79cbc92021-07-23 11:14:08 +02001017 ALIGN(s.st_size, 4);
Mario Six030ca162017-01-11 16:00:58 +01001018 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1019 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1020
Pali Roháre0a6dc72021-07-23 11:14:09 +02001021 *cur += sizeof(struct opt_hdr_v1);
Mario Six030ca162017-01-11 16:00:58 +01001022
Pali Roháre0a6dc72021-07-23 11:14:09 +02001023 args = (uint32_t *)*cur;
Mario Six030ca162017-01-11 16:00:58 +01001024 *args = cpu_to_le32(binarye->binary.nargs);
1025 args++;
1026 for (argi = 0; argi < binarye->binary.nargs; argi++)
1027 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1028
Pali Roháre0a6dc72021-07-23 11:14:09 +02001029 *cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
Mario Six030ca162017-01-11 16:00:58 +01001030
Pali Roháre0a6dc72021-07-23 11:14:09 +02001031 ret = fread(*cur, s.st_size, 1, bin);
Mario Six030ca162017-01-11 16:00:58 +01001032 if (ret != 1) {
1033 fprintf(stderr,
1034 "Could not read binary image %s\n",
1035 binarye->binary.file);
Mario Sixe3edf162017-02-13 10:11:55 +01001036 goto err_close;
Mario Six030ca162017-01-11 16:00:58 +01001037 }
1038
1039 fclose(bin);
1040
Pali Roháre0a6dc72021-07-23 11:14:09 +02001041 *cur += ALIGN(s.st_size, 4);
Mario Six030ca162017-01-11 16:00:58 +01001042
Pali Roháre0a6dc72021-07-23 11:14:09 +02001043 *((uint32_t *)*cur) = 0x00000000;
1044 **next_ext = 1;
1045 *next_ext = *cur;
Mario Six030ca162017-01-11 16:00:58 +01001046
Pali Roháre0a6dc72021-07-23 11:14:09 +02001047 *cur += sizeof(uint32_t);
Mario Six030ca162017-01-11 16:00:58 +01001048
1049 return 0;
Mario Sixe3edf162017-02-13 10:11:55 +01001050
1051err_close:
1052 fclose(bin);
1053
1054 return -1;
Mario Six030ca162017-01-11 16:00:58 +01001055}
Mario Six10d14492017-01-11 16:01:00 +01001056
Mario Six10d14492017-01-11 16:01:00 +01001057int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
1058{
1059 FILE *hashf;
1060 int res;
1061
1062 hashf = fopen("pub_kak_hash.txt", "w");
1063
1064 res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1065
1066 fclose(hashf);
1067
1068 return res < 0 ? 1 : 0;
1069}
1070
1071int kwb_sign_csk_with_kak(struct image_tool_params *params,
1072 struct secure_hdr_v1 *secure_hdr, RSA *csk)
1073{
1074 RSA *kak = NULL;
1075 RSA *kak_pub = NULL;
1076 int csk_idx = image_get_csk_index();
1077 struct sig_v1 tmp_sig;
1078
1079 if (csk_idx >= 16) {
1080 fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1081 return 1;
1082 }
1083
1084 if (kwb_load_kak(params, &kak) < 0)
1085 return 1;
1086
1087 if (export_pub_kak_hash(kak, secure_hdr))
1088 return 1;
1089
1090 if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1091 return 1;
1092
1093 if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1094 return 1;
1095
1096 if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1097 sizeof(secure_hdr->csk) +
1098 sizeof(secure_hdr->csksig),
1099 &tmp_sig, "CSK") < 0)
1100 return 1;
1101
1102 if (kwb_verify(kak_pub, &secure_hdr->csk,
1103 sizeof(secure_hdr->csk) +
1104 sizeof(secure_hdr->csksig),
1105 &tmp_sig, "CSK (2)") < 0)
1106 return 1;
1107
1108 secure_hdr->csksig = tmp_sig;
1109
1110 return 0;
1111}
1112
1113int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1114 int payloadsz, size_t headersz, uint8_t *image,
1115 struct secure_hdr_v1 *secure_hdr)
1116{
1117 struct image_cfg_element *e_jtagdelay;
1118 struct image_cfg_element *e_boxid;
1119 struct image_cfg_element *e_flashid;
1120 RSA *csk = NULL;
1121 unsigned char *image_ptr;
1122 size_t image_size;
1123 struct sig_v1 tmp_sig;
1124 bool specialized_img = image_get_spezialized_img();
1125
1126 kwb_msg("Create secure header content\n");
1127
1128 e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1129 e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1130 e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1131
1132 if (kwb_load_csk(params, &csk) < 0)
1133 return 1;
1134
1135 secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1136 secure_hdr->headersz_msb = 0;
1137 secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1138 if (e_jtagdelay)
1139 secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1140 if (e_boxid && specialized_img)
1141 secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1142 if (e_flashid && specialized_img)
1143 secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1144
1145 if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1146 return 1;
1147
1148 image_ptr = ptr + headersz;
1149 image_size = payloadsz - headersz;
1150
1151 if (kwb_sign_and_verify(csk, image_ptr, image_size,
1152 &secure_hdr->imgsig, "image") < 0)
1153 return 1;
1154
1155 if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1156 return 1;
1157
1158 secure_hdr->hdrsig = tmp_sig;
1159
1160 kwb_dump_fuse_cmds(secure_hdr);
1161
1162 return 0;
1163}
Mario Six030ca162017-01-11 16:00:58 +01001164
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001165static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
Mario Six10d14492017-01-11 16:01:00 +01001166 uint8_t *ptr, int payloadsz)
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001167{
Mario Six030ca162017-01-11 16:00:58 +01001168 struct image_cfg_element *e;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001169 struct main_hdr_v1 *main_hdr;
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001170 struct register_set_hdr_v1 *register_set_hdr;
Mario Six10d14492017-01-11 16:01:00 +01001171 struct secure_hdr_v1 *secure_hdr = NULL;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001172 size_t headersz;
Mario Six7497cd62017-01-11 16:00:55 +01001173 uint8_t *image, *cur;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001174 int hasext = 0;
Mario Six10d14492017-01-11 16:01:00 +01001175 uint8_t *next_ext = NULL;
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001176 int cfgi, datai, size;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301177
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001178 /*
1179 * Calculate the size of the header and the size of the
1180 * payload
1181 */
Mario Six855cf9e2017-01-11 16:00:57 +01001182 headersz = image_headersz_v1(&hasext);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001183 if (headersz == 0)
1184 return NULL;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301185
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001186 image = malloc(headersz);
1187 if (!image) {
1188 fprintf(stderr, "Cannot allocate memory for image\n");
1189 return NULL;
1190 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301191
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001192 memset(image, 0, headersz);
1193
Mario Six7497cd62017-01-11 16:00:55 +01001194 main_hdr = (struct main_hdr_v1 *)image;
Mario Six10d14492017-01-11 16:01:00 +01001195 cur = image;
1196 cur += sizeof(struct main_hdr_v1);
1197 next_ext = &main_hdr->ext;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001198
1199 /* Fill the main header */
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001200 main_hdr->blocksize =
Pali Rohárcfb60a92021-07-23 11:13:56 +02001201 cpu_to_le32(payloadsz - headersz);
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001202 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001203 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
Pali Rohárf8171a52021-07-23 11:14:06 +02001204 main_hdr->destaddr = cpu_to_le32(params->addr);
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001205 main_hdr->execaddr = cpu_to_le32(params->ep);
1206 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001207 main_hdr->ext = hasext;
1208 main_hdr->version = 1;
1209 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1210 if (e)
1211 main_hdr->blockid = e->bootfrom;
1212 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1213 if (e)
1214 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
1215 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1216 if (e)
1217 main_hdr->nandbadblklocation = e->nandbadblklocation;
Chris Packham883bf452016-11-09 22:07:45 +13001218 e = image_find_option(IMAGE_CFG_BAUDRATE);
1219 if (e)
1220 main_hdr->options = baudrate_to_option(e->baudrate);
Chris Packham1e0728a2016-11-09 22:21:45 +13001221 e = image_find_option(IMAGE_CFG_DEBUG);
1222 if (e)
1223 main_hdr->flags = e->debug ? 0x1 : 0;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001224
Pali Rohár6f6f65e2021-07-23 11:13:59 +02001225 /*
1226 * For SATA srcaddr is specified in number of sectors starting from
1227 * sector 0. The main header is stored at sector number 1.
1228 * This expects the sector size to be 512 bytes.
1229 * Header size is already aligned.
1230 */
1231 if (main_hdr->blockid == IBR_HDR_SATA_ID)
1232 main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1);
1233
1234 /*
1235 * For SDIO srcaddr is specified in number of sectors starting from
1236 * sector 0. The main header is stored at sector number 0.
1237 * This expects sector size to be 512 bytes.
1238 * Header size is already aligned.
1239 */
1240 if (main_hdr->blockid == IBR_HDR_SDIO_ID)
1241 main_hdr->srcaddr = cpu_to_le32(headersz / 512);
1242
1243 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1244 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1245 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1246
Mario Six10d14492017-01-11 16:01:00 +01001247 if (image_get_csk_index() >= 0) {
1248 /*
1249 * only reserve the space here; we fill the header later since
1250 * we need the header to be complete to compute the signatures
1251 */
1252 secure_hdr = (struct secure_hdr_v1 *)cur;
1253 cur += sizeof(struct secure_hdr_v1);
Pali Roháre0a6dc72021-07-23 11:14:09 +02001254 *next_ext = 1;
Mario Six10d14492017-01-11 16:01:00 +01001255 next_ext = &secure_hdr->next;
1256 }
Mario Six10d14492017-01-11 16:01:00 +01001257
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001258 datai = 0;
1259 register_set_hdr = (struct register_set_hdr_v1 *)cur;
1260 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1261 e = &image_cfg[cfgi];
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001262 if (e->type != IMAGE_CFG_DATA &&
1263 e->type != IMAGE_CFG_DATA_DELAY)
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001264 continue;
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001265 if (e->type == IMAGE_CFG_DATA_DELAY) {
1266 size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
1267 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1268 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1269 register_set_hdr->headersz_msb = size >> 16;
1270 register_set_hdr->data[datai].last_entry.delay = e->regdata_delay;
1271 cur += size;
1272 *next_ext = 1;
1273 next_ext = &register_set_hdr->data[datai].last_entry.next;
1274 datai = 0;
1275 continue;
1276 }
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001277 register_set_hdr->data[datai].entry.address =
1278 cpu_to_le32(e->regdata.raddr);
1279 register_set_hdr->data[datai].entry.value =
1280 cpu_to_le32(e->regdata.rdata);
1281 datai++;
1282 }
1283 if (datai != 0) {
1284 size = sizeof(struct register_set_hdr_v1) + 8 * datai + 4;
1285 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1286 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1287 register_set_hdr->headersz_msb = size >> 16;
1288 /* Set delay to the smallest possible value 1ms. */
1289 register_set_hdr->data[datai].last_entry.delay = 1;
1290 cur += size;
1291 *next_ext = 1;
1292 next_ext = &register_set_hdr->data[datai].last_entry.next;
1293 }
1294
Pali Roháre0a6dc72021-07-23 11:14:09 +02001295 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1296 e = &image_cfg[cfgi];
1297 if (e->type != IMAGE_CFG_BINARY)
1298 continue;
1299
1300 if (add_binary_header_v1(&cur, &next_ext, e))
1301 return NULL;
1302 }
Mario Six10d14492017-01-11 16:01:00 +01001303
Mario Six10d14492017-01-11 16:01:00 +01001304 if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz,
1305 headersz, image, secure_hdr))
1306 return NULL;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001307
1308 /* Calculate and set the header checksum */
1309 main_hdr->checksum = image_checksum8(main_hdr, headersz);
1310
1311 *imagesz = headersz;
1312 return image;
1313}
1314
Mario Six62da6762017-01-11 16:00:59 +01001315int recognize_keyword(char *keyword)
1316{
1317 int kw_id;
1318
1319 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1320 if (!strcmp(keyword, id_strs[kw_id]))
1321 return kw_id;
1322
1323 return 0;
1324}
1325
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001326static int image_create_config_parse_oneline(char *line,
1327 struct image_cfg_element *el)
1328{
Mario Six62da6762017-01-11 16:00:59 +01001329 char *keyword, *saveptr, *value1, *value2;
1330 char delimiters[] = " \t";
1331 int keyword_id, ret, argi;
1332 char *unknown_msg = "Ignoring unknown line '%s'\n";
1333
1334 keyword = strtok_r(line, delimiters, &saveptr);
1335 keyword_id = recognize_keyword(keyword);
1336
1337 if (!keyword_id) {
1338 fprintf(stderr, unknown_msg, line);
1339 return 0;
1340 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001341
Mario Six62da6762017-01-11 16:00:59 +01001342 el->type = keyword_id;
Mario Sixd6009d72017-01-11 16:00:54 +01001343
Mario Six62da6762017-01-11 16:00:59 +01001344 value1 = strtok_r(NULL, delimiters, &saveptr);
1345
1346 if (!value1) {
1347 fprintf(stderr, "Parameter missing in line '%s'\n", line);
1348 return -1;
1349 }
1350
1351 switch (keyword_id) {
1352 case IMAGE_CFG_VERSION:
1353 el->version = atoi(value1);
1354 break;
1355 case IMAGE_CFG_BOOT_FROM:
1356 ret = image_boot_mode_id(value1);
Mario Sixd6009d72017-01-11 16:00:54 +01001357
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001358 if (ret < 0) {
Mario Six62da6762017-01-11 16:00:59 +01001359 fprintf(stderr, "Invalid boot media '%s'\n", value1);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001360 return -1;
1361 }
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001362 el->bootfrom = ret;
Mario Six62da6762017-01-11 16:00:59 +01001363 break;
1364 case IMAGE_CFG_NAND_BLKSZ:
1365 el->nandblksz = strtoul(value1, NULL, 16);
1366 break;
1367 case IMAGE_CFG_NAND_BADBLK_LOCATION:
1368 el->nandbadblklocation = strtoul(value1, NULL, 16);
1369 break;
1370 case IMAGE_CFG_NAND_ECC_MODE:
1371 ret = image_nand_ecc_mode_id(value1);
Mario Sixd6009d72017-01-11 16:00:54 +01001372
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001373 if (ret < 0) {
Mario Six62da6762017-01-11 16:00:59 +01001374 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001375 return -1;
1376 }
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001377 el->nandeccmode = ret;
Mario Six62da6762017-01-11 16:00:59 +01001378 break;
1379 case IMAGE_CFG_NAND_PAGESZ:
1380 el->nandpagesz = strtoul(value1, NULL, 16);
1381 break;
1382 case IMAGE_CFG_BINARY:
1383 argi = 0;
Mario Sixd6009d72017-01-11 16:00:54 +01001384
Mario Six62da6762017-01-11 16:00:59 +01001385 el->binary.file = strdup(value1);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001386 while (1) {
Mario Six62da6762017-01-11 16:00:59 +01001387 char *value = strtok_r(NULL, delimiters, &saveptr);
1388
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001389 if (!value)
1390 break;
1391 el->binary.args[argi] = strtoul(value, NULL, 16);
1392 argi++;
1393 if (argi >= BINARY_MAX_ARGS) {
1394 fprintf(stderr,
Mario Six62da6762017-01-11 16:00:59 +01001395 "Too many arguments for BINARY\n");
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001396 return -1;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301397 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301398 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001399 el->binary.nargs = argi;
Mario Six62da6762017-01-11 16:00:59 +01001400 break;
1401 case IMAGE_CFG_DATA:
1402 value2 = strtok_r(NULL, delimiters, &saveptr);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001403
1404 if (!value1 || !value2) {
1405 fprintf(stderr,
1406 "Invalid number of arguments for DATA\n");
1407 return -1;
1408 }
1409
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001410 el->regdata.raddr = strtoul(value1, NULL, 16);
1411 el->regdata.rdata = strtoul(value2, NULL, 16);
Mario Six62da6762017-01-11 16:00:59 +01001412 break;
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001413 case IMAGE_CFG_DATA_DELAY:
1414 if (!strcmp(value1, "SDRAM_SETUP"))
1415 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP;
1416 else
1417 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_MS(strtoul(value1, NULL, 10));
1418 break;
Mario Six62da6762017-01-11 16:00:59 +01001419 case IMAGE_CFG_BAUDRATE:
1420 el->baudrate = strtoul(value1, NULL, 10);
1421 break;
1422 case IMAGE_CFG_DEBUG:
1423 el->debug = strtoul(value1, NULL, 10);
1424 break;
Mario Six10d14492017-01-11 16:01:00 +01001425 case IMAGE_CFG_KAK:
1426 el->key_name = strdup(value1);
1427 break;
1428 case IMAGE_CFG_CSK:
1429 el->key_name = strdup(value1);
1430 break;
1431 case IMAGE_CFG_CSK_INDEX:
1432 el->csk_idx = strtol(value1, NULL, 0);
1433 break;
1434 case IMAGE_CFG_JTAG_DELAY:
1435 el->jtag_delay = strtoul(value1, NULL, 0);
1436 break;
1437 case IMAGE_CFG_BOX_ID:
1438 el->boxid = strtoul(value1, NULL, 0);
1439 break;
1440 case IMAGE_CFG_FLASH_ID:
1441 el->flashid = strtoul(value1, NULL, 0);
1442 break;
1443 case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1444 el->sec_specialized_img = true;
1445 break;
1446 case IMAGE_CFG_SEC_COMMON_IMG:
1447 el->sec_specialized_img = false;
1448 break;
1449 case IMAGE_CFG_SEC_BOOT_DEV:
1450 el->sec_boot_dev = strtoul(value1, NULL, 0);
1451 break;
1452 case IMAGE_CFG_SEC_FUSE_DUMP:
1453 el->name = strdup(value1);
1454 break;
Mario Six62da6762017-01-11 16:00:59 +01001455 default:
1456 fprintf(stderr, unknown_msg, line);
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301457 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301458
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001459 return 0;
1460}
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301461
1462/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001463 * Parse the configuration file 'fcfg' into the array of configuration
1464 * elements 'image_cfg', and return the number of configuration
1465 * elements in 'cfgn'.
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301466 */
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001467static int image_create_config_parse(FILE *fcfg)
1468{
1469 int ret;
1470 int cfgi = 0;
1471
1472 /* Parse the configuration file */
1473 while (!feof(fcfg)) {
1474 char *line;
1475 char buf[256];
1476
1477 /* Read the current line */
1478 memset(buf, 0, sizeof(buf));
1479 line = fgets(buf, sizeof(buf), fcfg);
1480 if (!line)
1481 break;
1482
1483 /* Ignore useless lines */
1484 if (line[0] == '\n' || line[0] == '#')
1485 continue;
1486
1487 /* Strip final newline */
1488 if (line[strlen(line) - 1] == '\n')
1489 line[strlen(line) - 1] = 0;
1490
1491 /* Parse the current line */
1492 ret = image_create_config_parse_oneline(line,
1493 &image_cfg[cfgi]);
1494 if (ret)
1495 return ret;
1496
1497 cfgi++;
1498
1499 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1500 fprintf(stderr,
1501 "Too many configuration elements in .cfg file\n");
1502 return -1;
1503 }
1504 }
1505
1506 cfgn = cfgi;
1507 return 0;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301508}
1509
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001510static int image_get_version(void)
1511{
1512 struct image_cfg_element *e;
1513
1514 e = image_find_option(IMAGE_CFG_VERSION);
1515 if (!e)
1516 return -1;
1517
1518 return e->version;
1519}
1520
Pali Rohár04785152021-07-23 11:13:57 +02001521static int image_get_bootfrom(void)
1522{
1523 struct image_cfg_element *e;
1524
1525 e = image_find_option(IMAGE_CFG_BOOT_FROM);
1526 if (!e)
1527 return -1;
1528
1529 return e->bootfrom;
1530}
1531
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001532static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
Guilherme Maciel Ferreira8ed4d1c2013-12-01 12:43:10 -07001533 struct image_tool_params *params)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301534{
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001535 FILE *fcfg;
1536 void *image = NULL;
1537 int version;
Łukasz Majewskif04dab42014-11-21 09:22:43 +01001538 size_t headersz = 0;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301539 uint32_t checksum;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001540 int ret;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301541
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001542 fcfg = fopen(params->imagename, "r");
1543 if (!fcfg) {
1544 fprintf(stderr, "Could not open input file %s\n",
1545 params->imagename);
1546 exit(EXIT_FAILURE);
1547 }
1548
1549 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1550 sizeof(struct image_cfg_element));
1551 if (!image_cfg) {
1552 fprintf(stderr, "Cannot allocate memory\n");
1553 fclose(fcfg);
1554 exit(EXIT_FAILURE);
1555 }
1556
1557 memset(image_cfg, 0,
1558 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1559 rewind(fcfg);
1560
1561 ret = image_create_config_parse(fcfg);
1562 fclose(fcfg);
1563 if (ret) {
1564 free(image_cfg);
1565 exit(EXIT_FAILURE);
1566 }
1567
1568 version = image_get_version();
Stefan Roese933918c2014-10-28 11:32:24 +01001569 switch (version) {
1570 /*
1571 * Fallback to version 0 if no version is provided in the
1572 * cfg file
1573 */
1574 case -1:
1575 case 0:
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001576 image = image_create_v0(&headersz, params, sbuf->st_size);
Stefan Roese933918c2014-10-28 11:32:24 +01001577 break;
1578
1579 case 1:
Mario Six10d14492017-01-11 16:01:00 +01001580 image = image_create_v1(&headersz, params, ptr, sbuf->st_size);
Stefan Roese933918c2014-10-28 11:32:24 +01001581 break;
1582
1583 default:
1584 fprintf(stderr, "Unsupported version %d\n", version);
1585 free(image_cfg);
1586 exit(EXIT_FAILURE);
1587 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301588
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001589 if (!image) {
1590 fprintf(stderr, "Could not create image\n");
1591 free(image_cfg);
1592 exit(EXIT_FAILURE);
1593 }
1594
1595 free(image_cfg);
1596
1597 /* Build and add image checksum header */
Pali Rohárcfb60a92021-07-23 11:13:56 +02001598 checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + headersz,
1599 sbuf->st_size - headersz - sizeof(uint32_t)));
1600 memcpy((uint8_t *)ptr + sbuf->st_size - sizeof(uint32_t), &checksum,
1601 sizeof(uint32_t));
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301602
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001603 /* Finally copy the header into the image area */
1604 memcpy(ptr, image, headersz);
1605
1606 free(image);
1607}
1608
1609static void kwbimage_print_header(const void *ptr)
1610{
1611 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
1612
1613 printf("Image Type: MVEBU Boot from %s Image\n",
1614 image_boot_mode_name(mhdr->blockid));
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001615 printf("Image version:%d\n", image_version((void *)ptr));
Pali Rohárcd614ad2021-07-23 11:14:04 +02001616 if (image_version((void *)ptr) == 1) {
1617 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
1618
1619 if (mhdr->ext & 0x1) {
1620 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1621 ((uint8_t *)ptr +
1622 sizeof(*mhdr));
1623
1624 while (1) {
1625 uint32_t ohdr_size;
1626
1627 ohdr_size = (ohdr->headersz_msb << 16) |
1628 le16_to_cpu(ohdr->headersz_lsb);
1629 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
1630 printf("BIN Hdr Size: ");
1631 genimg_print_size(ohdr_size - 12 - 4 * ohdr->data[0]);
1632 }
1633 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1634 break;
1635 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1636 ohdr_size);
1637 }
1638 }
1639 }
Gerald Kerma8f9e5832014-10-31 01:03:27 +01001640 printf("Data Size: ");
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001641 genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1642 printf("Load Address: %08x\n", mhdr->destaddr);
1643 printf("Entry Point: %08x\n", mhdr->execaddr);
1644}
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301645
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001646static int kwbimage_check_image_types(uint8_t type)
1647{
1648 if (type == IH_TYPE_KWBIMAGE)
1649 return EXIT_SUCCESS;
Mario Sixd6009d72017-01-11 16:00:54 +01001650
1651 return EXIT_FAILURE;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301652}
1653
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001654static int kwbimage_verify_header(unsigned char *ptr, int image_size,
1655 struct image_tool_params *params)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301656{
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001657 uint8_t checksum;
Alexander Graf22e87fc2018-03-15 11:14:19 +01001658 size_t header_size = kwbimage_header_size(ptr);
1659
1660 if (header_size > image_size)
1661 return -FDT_ERR_BADSTRUCTURE;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301662
Baruch Siach4a5b99b2017-07-04 20:23:40 +03001663 if (!main_hdr_checksum_ok(ptr))
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001664 return -FDT_ERR_BADSTRUCTURE;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301665
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001666 /* Only version 0 extended header has checksum */
1667 if (image_version((void *)ptr) == 0) {
Pali Rohár03345b92021-07-23 11:14:01 +02001668 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Mario Six6f273632017-01-11 16:00:56 +01001669
Pali Rohár03345b92021-07-23 11:14:01 +02001670 if (mhdr->ext & 0x1) {
1671 struct ext_hdr_v0 *ext_hdr;
1672
1673 ext_hdr = (struct ext_hdr_v0 *)
Mario Six7497cd62017-01-11 16:00:55 +01001674 (ptr + sizeof(struct main_hdr_v0));
Pali Rohár03345b92021-07-23 11:14:01 +02001675 checksum = image_checksum8(ext_hdr,
1676 sizeof(struct ext_hdr_v0)
1677 - sizeof(uint8_t));
1678 if (checksum != ext_hdr->checksum)
1679 return -FDT_ERR_BADSTRUCTURE;
1680 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001681 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301682
Pali Rohárfdb575a2021-07-23 11:14:02 +02001683 if (image_version((void *)ptr) == 1) {
1684 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Pali Rohár48bc68c2021-07-23 11:14:03 +02001685 uint32_t offset;
1686 uint32_t size;
Pali Rohárfdb575a2021-07-23 11:14:02 +02001687
1688 if (mhdr->ext & 0x1) {
1689 uint32_t ohdr_size;
1690 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1691 (ptr + sizeof(*mhdr));
1692
1693 while (1) {
1694 if ((uint8_t *)ohdr + sizeof(*ohdr) >
1695 (uint8_t *)mhdr + header_size)
1696 return -FDT_ERR_BADSTRUCTURE;
1697
1698 ohdr_size = (ohdr->headersz_msb << 16) |
1699 le16_to_cpu(ohdr->headersz_lsb);
1700
1701 if (ohdr_size < 8 ||
1702 (uint8_t *)ohdr + ohdr_size >
1703 (uint8_t *)mhdr + header_size)
1704 return -FDT_ERR_BADSTRUCTURE;
1705
1706 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1707 break;
1708 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1709 ohdr_size);
1710 }
1711 }
Pali Rohár48bc68c2021-07-23 11:14:03 +02001712
1713 offset = le32_to_cpu(mhdr->srcaddr);
1714
1715 /*
1716 * For SATA srcaddr is specified in number of sectors.
1717 * The main header is must be stored at sector number 1.
1718 * This expects that sector size is 512 bytes and recalculates
1719 * data offset to bytes relative to the main header.
1720 */
1721 if (mhdr->blockid == IBR_HDR_SATA_ID) {
1722 if (offset < 1)
1723 return -FDT_ERR_BADSTRUCTURE;
1724 offset -= 1;
1725 offset *= 512;
1726 }
1727
1728 /*
1729 * For SDIO srcaddr is specified in number of sectors.
1730 * This expects that sector size is 512 bytes and recalculates
1731 * data offset to bytes.
1732 */
1733 if (mhdr->blockid == IBR_HDR_SDIO_ID)
1734 offset *= 512;
1735
1736 /*
1737 * For PCIe srcaddr is always set to 0xFFFFFFFF.
1738 * This expects that data starts after all headers.
1739 */
1740 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
1741 offset = header_size;
1742
1743 if (offset > image_size || offset % 4 != 0)
1744 return -FDT_ERR_BADSTRUCTURE;
1745
1746 size = le32_to_cpu(mhdr->blocksize);
1747 if (offset + size > image_size || size % 4 != 0)
1748 return -FDT_ERR_BADSTRUCTURE;
1749
1750 if (image_checksum32(ptr + offset, size - 4) !=
1751 *(uint32_t *)(ptr + offset + size - 4))
1752 return -FDT_ERR_BADSTRUCTURE;
Pali Rohárfdb575a2021-07-23 11:14:02 +02001753 }
1754
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301755 return 0;
1756}
1757
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001758static int kwbimage_generate(struct image_tool_params *params,
1759 struct image_type_params *tparams)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301760{
Patrick Wildtef84f822017-05-10 22:18:54 +02001761 FILE *fcfg;
Pali Rohárcfb60a92021-07-23 11:13:56 +02001762 struct stat s;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001763 int alloc_len;
Pali Rohár04785152021-07-23 11:13:57 +02001764 int bootfrom;
Patrick Wildtef84f822017-05-10 22:18:54 +02001765 int version;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001766 void *hdr;
Patrick Wildtef84f822017-05-10 22:18:54 +02001767 int ret;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301768
Patrick Wildtef84f822017-05-10 22:18:54 +02001769 fcfg = fopen(params->imagename, "r");
1770 if (!fcfg) {
1771 fprintf(stderr, "Could not open input file %s\n",
1772 params->imagename);
1773 exit(EXIT_FAILURE);
1774 }
1775
Pali Rohárcfb60a92021-07-23 11:13:56 +02001776 if (stat(params->datafile, &s)) {
1777 fprintf(stderr, "Could not stat data file %s: %s\n",
1778 params->datafile, strerror(errno));
1779 exit(EXIT_FAILURE);
1780 }
1781
Patrick Wildtef84f822017-05-10 22:18:54 +02001782 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1783 sizeof(struct image_cfg_element));
1784 if (!image_cfg) {
1785 fprintf(stderr, "Cannot allocate memory\n");
1786 fclose(fcfg);
1787 exit(EXIT_FAILURE);
1788 }
1789
1790 memset(image_cfg, 0,
1791 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1792 rewind(fcfg);
1793
1794 ret = image_create_config_parse(fcfg);
1795 fclose(fcfg);
1796 if (ret) {
1797 free(image_cfg);
1798 exit(EXIT_FAILURE);
1799 }
1800
Pali Rohár04785152021-07-23 11:13:57 +02001801 bootfrom = image_get_bootfrom();
Patrick Wildtef84f822017-05-10 22:18:54 +02001802 version = image_get_version();
1803 switch (version) {
1804 /*
1805 * Fallback to version 0 if no version is provided in the
1806 * cfg file
1807 */
1808 case -1:
1809 case 0:
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001810 alloc_len = sizeof(struct main_hdr_v0) +
1811 sizeof(struct ext_hdr_v0);
Patrick Wildtef84f822017-05-10 22:18:54 +02001812 break;
1813
1814 case 1:
Mario Six855cf9e2017-01-11 16:00:57 +01001815 alloc_len = image_headersz_v1(NULL);
Patrick Wildtef84f822017-05-10 22:18:54 +02001816 break;
1817
1818 default:
1819 fprintf(stderr, "Unsupported version %d\n", version);
1820 free(image_cfg);
1821 exit(EXIT_FAILURE);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001822 }
1823
Patrick Wildtef84f822017-05-10 22:18:54 +02001824 free(image_cfg);
1825
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001826 hdr = malloc(alloc_len);
1827 if (!hdr) {
1828 fprintf(stderr, "%s: malloc return failure: %s\n",
1829 params->cmdname, strerror(errno));
1830 exit(EXIT_FAILURE);
1831 }
1832
1833 memset(hdr, 0, alloc_len);
1834 tparams->header_size = alloc_len;
1835 tparams->hdr = hdr;
1836
Stefan Roeseda43fd32015-11-24 09:14:59 +01001837 /*
1838 * The resulting image needs to be 4-byte aligned. At least
1839 * the Marvell hdrparser tool complains if its unaligned.
Pali Rohárcfb60a92021-07-23 11:13:56 +02001840 * After the image data is stored 4-byte checksum.
Pali Rohár04785152021-07-23 11:13:57 +02001841 * Final SPI and NAND images must be aligned to 256 bytes.
Pali Rohár6f6f65e2021-07-23 11:13:59 +02001842 * Final SATA and SDIO images must be aligned to 512 bytes.
Stefan Roeseda43fd32015-11-24 09:14:59 +01001843 */
Pali Rohár04785152021-07-23 11:13:57 +02001844 if (bootfrom == IBR_HDR_SPI_ID || bootfrom == IBR_HDR_NAND_ID)
1845 return 4 + (256 - (alloc_len + s.st_size + 4) % 256) % 256;
Pali Rohár6f6f65e2021-07-23 11:13:59 +02001846 else if (bootfrom == IBR_HDR_SATA_ID || bootfrom == IBR_HDR_SDIO_ID)
1847 return 4 + (512 - (alloc_len + s.st_size + 4) % 512) % 512;
Pali Rohár04785152021-07-23 11:13:57 +02001848 else
1849 return 4 + (4 - s.st_size % 4) % 4;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301850}
1851
Pali Rohár5ec2c582021-07-23 11:14:34 +02001852static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params)
1853{
1854 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
1855 size_t header_size = kwbimage_header_size(ptr);
1856 int idx = params->pflag;
1857 int cur_idx = 0;
1858 uint32_t offset;
1859 ulong image;
1860 ulong size;
1861
1862 if (image_version((void *)ptr) == 1 && (mhdr->ext & 0x1)) {
1863 struct opt_hdr_v1 *ohdr = (struct opt_hdr_v1 *)
1864 ((uint8_t *)ptr +
1865 sizeof(*mhdr));
1866
1867 while (1) {
1868 uint32_t ohdr_size = (ohdr->headersz_msb << 16) |
1869 le16_to_cpu(ohdr->headersz_lsb);
1870
1871 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
1872 if (idx == cur_idx) {
1873 image = (ulong)&ohdr->data[4 +
1874 4 * ohdr->data[0]];
1875 size = ohdr_size - 12 -
1876 4 * ohdr->data[0];
1877 goto extract;
1878 }
1879 ++cur_idx;
1880 }
1881 if (!(*((uint8_t *)ohdr + ohdr_size - 4) & 0x1))
1882 break;
1883 ohdr = (struct opt_hdr_v1 *)((uint8_t *)ohdr +
1884 ohdr_size);
1885 }
1886 }
1887
1888 if (idx != cur_idx) {
1889 printf("Image %d is not present\n", idx);
1890 return -1;
1891 }
1892
1893 offset = le32_to_cpu(mhdr->srcaddr);
1894
1895 if (mhdr->blockid == IBR_HDR_SATA_ID) {
1896 offset -= 1;
1897 offset *= 512;
1898 }
1899
1900 if (mhdr->blockid == IBR_HDR_SDIO_ID)
1901 offset *= 512;
1902
1903 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
1904 offset = header_size;
1905
1906 image = (ulong)((uint8_t *)ptr + offset);
1907 size = le32_to_cpu(mhdr->blocksize) - 4;
1908
1909extract:
1910 return imagetool_save_subimage(params->outfile, image, size);
1911}
1912
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001913/*
1914 * Report Error if xflag is set in addition to default
1915 */
1916static int kwbimage_check_params(struct image_tool_params *params)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301917{
Pali Rohár5ec2c582021-07-23 11:14:34 +02001918 if (!params->iflag && (!params->imagename || !strlen(params->imagename))) {
Mario Sixd6009d72017-01-11 16:00:54 +01001919 char *msg = "Configuration file for kwbimage creation omitted";
1920
1921 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001922 return CFG_INVALID;
1923 }
1924
1925 return (params->dflag && (params->fflag || params->lflag)) ||
1926 (params->fflag && (params->dflag || params->lflag)) ||
1927 (params->lflag && (params->dflag || params->fflag)) ||
Pali Rohár5ec2c582021-07-23 11:14:34 +02001928 (params->xflag);
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301929}
1930
1931/*
1932 * kwbimage type parameters definition
1933 */
Guilherme Maciel Ferreira28be1cf2015-01-15 02:48:07 -02001934U_BOOT_IMAGE_TYPE(
1935 kwbimage,
1936 "Marvell MVEBU Boot Image support",
1937 0,
1938 NULL,
1939 kwbimage_check_params,
1940 kwbimage_verify_header,
1941 kwbimage_print_header,
1942 kwbimage_set_header,
Pali Rohár5ec2c582021-07-23 11:14:34 +02001943 kwbimage_extract_subimage,
Guilherme Maciel Ferreira28be1cf2015-01-15 02:48:07 -02001944 kwbimage_check_image_types,
1945 NULL,
1946 kwbimage_generate
1947);