blob: 44843be2c13abaa6c05894aefb3784d11f54ed71 [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
Pali Rohár8010f4f2021-09-24 23:07:02 +02004 * supports Kirkwood, Dove, Armada 370, Armada XP, Armada 375, Armada 38x and
5 * Armada 39x
Stefan Roese4acd2d22014-10-22 12:13:23 +02006 *
7 * (C) Copyright 2013 Thomas Petazzoni
8 * <thomas.petazzoni@free-electrons.com>
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05309 */
10
Heinrich Schuchardt3a8b9192021-12-18 11:25:12 +010011#define OPENSSL_API_COMPAT 0x10101000L
12
Guilherme Maciel Ferreiraf86ed6a2013-12-01 12:43:10 -070013#include "imagetool.h"
Andreas Bießmanne5f1a582014-10-24 23:39:11 +020014#include <limits.h>
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053015#include <image.h>
Mario Sixa1b6b0a2017-01-11 16:01:00 +010016#include <stdarg.h>
Stefan Roese4acd2d22014-10-22 12:13:23 +020017#include <stdint.h>
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053018#include "kwbimage.h"
19
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
Stefan Roese4acd2d22014-10-22 12:13:23 +020046static struct image_cfg_element *image_cfg;
47static int cfgn;
Mario Sixa1b6b0a2017-01-11 16:01:00 +010048static int verbose_mode;
Stefan Roese4acd2d22014-10-22 12:13:23 +020049
50struct boot_mode {
51 unsigned int id;
52 const char *name;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +053053};
54
Mario Sixa1b6b0a2017-01-11 16:01:00 +010055/*
56 * SHA2-256 hash
57 */
58struct hash_v1 {
59 uint8_t hash[32];
60};
61
Stefan Roese4acd2d22014-10-22 12:13:23 +020062struct boot_mode boot_modes[] = {
Pali Roháre515a332021-08-11 10:14:17 +020063 { IBR_HDR_I2C_ID, "i2c" },
64 { IBR_HDR_SPI_ID, "spi" },
65 { IBR_HDR_NAND_ID, "nand" },
66 { IBR_HDR_SATA_ID, "sata" },
67 { IBR_HDR_PEX_ID, "pex" },
68 { IBR_HDR_UART_ID, "uart" },
69 { IBR_HDR_SDIO_ID, "sdio" },
Stefan Roese4acd2d22014-10-22 12:13:23 +020070 {},
71};
72
73struct nand_ecc_mode {
74 unsigned int id;
75 const char *name;
76};
77
78struct nand_ecc_mode nand_ecc_modes[] = {
Pali Roháre515a332021-08-11 10:14:17 +020079 { IBR_HDR_ECC_DEFAULT, "default" },
80 { IBR_HDR_ECC_FORCED_HAMMING, "hamming" },
81 { IBR_HDR_ECC_FORCED_RS, "rs" },
82 { IBR_HDR_ECC_DISABLED, "disabled" },
Stefan Roese4acd2d22014-10-22 12:13:23 +020083 {},
84};
85
86/* Used to identify an undefined execution or destination address */
87#define ADDR_INVALID ((uint32_t)-1)
88
Pali Rohár6c7f1522021-07-23 11:14:07 +020089#define BINARY_MAX_ARGS 255
Stefan Roese4acd2d22014-10-22 12:13:23 +020090
91/* In-memory representation of a line of the configuration file */
Mario Six4991b4f2017-01-11 16:00:59 +010092
93enum image_cfg_type {
94 IMAGE_CFG_VERSION = 0x1,
95 IMAGE_CFG_BOOT_FROM,
96 IMAGE_CFG_DEST_ADDR,
97 IMAGE_CFG_EXEC_ADDR,
98 IMAGE_CFG_NAND_BLKSZ,
99 IMAGE_CFG_NAND_BADBLK_LOCATION,
100 IMAGE_CFG_NAND_ECC_MODE,
101 IMAGE_CFG_NAND_PAGESZ,
Pali Roháraf496052022-01-12 18:20:40 +0100102 IMAGE_CFG_CPU,
Mario Six4991b4f2017-01-11 16:00:59 +0100103 IMAGE_CFG_BINARY,
Mario Six4991b4f2017-01-11 16:00:59 +0100104 IMAGE_CFG_DATA,
Pali Rohárf63c5832021-07-23 11:14:12 +0200105 IMAGE_CFG_DATA_DELAY,
Mario Six4991b4f2017-01-11 16:00:59 +0100106 IMAGE_CFG_BAUDRATE,
Pali Rohár12f2c032021-11-08 18:12:41 +0100107 IMAGE_CFG_UART_PORT,
108 IMAGE_CFG_UART_MPP,
Mario Six4991b4f2017-01-11 16:00:59 +0100109 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",
Pali Roháraf496052022-01-12 18:20:40 +0100133 [IMAGE_CFG_CPU] = "CPU",
Mario Six4991b4f2017-01-11 16:00:59 +0100134 [IMAGE_CFG_BINARY] = "BINARY",
Mario Six4991b4f2017-01-11 16:00:59 +0100135 [IMAGE_CFG_DATA] = "DATA",
Pali Rohárf63c5832021-07-23 11:14:12 +0200136 [IMAGE_CFG_DATA_DELAY] = "DATA_DELAY",
Mario Six4991b4f2017-01-11 16:00:59 +0100137 [IMAGE_CFG_BAUDRATE] = "BAUDRATE",
Pali Rohár12f2c032021-11-08 18:12:41 +0100138 [IMAGE_CFG_UART_PORT] = "UART_PORT",
139 [IMAGE_CFG_UART_MPP] = "UART_MPP",
Mario Six4991b4f2017-01-11 16:00:59 +0100140 [IMAGE_CFG_DEBUG] = "DEBUG",
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100141 [IMAGE_CFG_KAK] = "KAK",
142 [IMAGE_CFG_CSK] = "CSK",
143 [IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
144 [IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
145 [IMAGE_CFG_BOX_ID] = "BOX_ID",
146 [IMAGE_CFG_FLASH_ID] = "FLASH_ID",
147 [IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
148 [IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
149 [IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
150 [IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
Mario Six4991b4f2017-01-11 16:00:59 +0100151};
152
Stefan Roese4acd2d22014-10-22 12:13:23 +0200153struct image_cfg_element {
Mario Six4991b4f2017-01-11 16:00:59 +0100154 enum image_cfg_type type;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200155 union {
156 unsigned int version;
Pali Roháraf496052022-01-12 18:20:40 +0100157 unsigned int cpu_sheeva;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200158 unsigned int bootfrom;
159 struct {
160 const char *file;
161 unsigned int args[BINARY_MAX_ARGS];
162 unsigned int nargs;
163 } binary;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200164 unsigned int dstaddr;
165 unsigned int execaddr;
166 unsigned int nandblksz;
167 unsigned int nandbadblklocation;
168 unsigned int nandeccmode;
169 unsigned int nandpagesz;
170 struct ext_hdr_v0_reg regdata;
Pali Rohárf63c5832021-07-23 11:14:12 +0200171 unsigned int regdata_delay;
Chris Packham4bdb5472016-11-09 22:07:45 +1300172 unsigned int baudrate;
Pali Rohár12f2c032021-11-08 18:12:41 +0100173 unsigned int uart_port;
174 unsigned int uart_mpp;
Chris Packham2611c052016-11-09 22:21:45 +1300175 unsigned int debug;
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100176 const char *key_name;
177 int csk_idx;
178 uint8_t jtag_delay;
179 uint32_t boxid;
180 uint32_t flashid;
181 bool sec_specialized_img;
182 unsigned int sec_boot_dev;
183 const char *name;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200184 };
185};
186
187#define IMAGE_CFG_ELEMENT_MAX 256
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530188
189/*
Stefan Roese4acd2d22014-10-22 12:13:23 +0200190 * Utility functions to manipulate boot mode and ecc modes (convert
191 * them back and forth between description strings and the
192 * corresponding numerical identifiers).
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530193 */
Stefan Roese4acd2d22014-10-22 12:13:23 +0200194
195static const char *image_boot_mode_name(unsigned int id)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530196{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200197 int i;
Mario Six94490a42017-01-11 16:00:54 +0100198
Stefan Roese4acd2d22014-10-22 12:13:23 +0200199 for (i = 0; boot_modes[i].name; i++)
200 if (boot_modes[i].id == id)
201 return boot_modes[i].name;
202 return NULL;
203}
204
Pali Rohár6eb20bb2022-01-12 18:20:35 +0100205static int image_boot_mode_id(const char *boot_mode_name)
Stefan Roese4acd2d22014-10-22 12:13:23 +0200206{
207 int i;
Mario Six94490a42017-01-11 16:00:54 +0100208
Stefan Roese4acd2d22014-10-22 12:13:23 +0200209 for (i = 0; boot_modes[i].name; i++)
210 if (!strcmp(boot_modes[i].name, boot_mode_name))
211 return boot_modes[i].id;
212
213 return -1;
214}
215
Pali Rohár6eb20bb2022-01-12 18:20:35 +0100216static int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
Stefan Roese4acd2d22014-10-22 12:13:23 +0200217{
218 int i;
Mario Six94490a42017-01-11 16:00:54 +0100219
Stefan Roese4acd2d22014-10-22 12:13:23 +0200220 for (i = 0; nand_ecc_modes[i].name; i++)
221 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
222 return nand_ecc_modes[i].id;
223 return -1;
224}
225
226static struct image_cfg_element *
227image_find_option(unsigned int optiontype)
228{
229 int i;
230
231 for (i = 0; i < cfgn; i++) {
232 if (image_cfg[i].type == optiontype)
233 return &image_cfg[i];
234 }
235
236 return NULL;
237}
238
239static unsigned int
240image_count_options(unsigned int optiontype)
241{
242 int i;
243 unsigned int count = 0;
244
245 for (i = 0; i < cfgn; i++)
246 if (image_cfg[i].type == optiontype)
247 count++;
248
249 return count;
250}
251
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100252static int image_get_csk_index(void)
253{
254 struct image_cfg_element *e;
255
256 e = image_find_option(IMAGE_CFG_CSK_INDEX);
257 if (!e)
258 return -1;
259
260 return e->csk_idx;
261}
262
263static bool image_get_spezialized_img(void)
264{
265 struct image_cfg_element *e;
266
267 e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
268 if (!e)
269 return false;
270
271 return e->sec_specialized_img;
272}
273
Pali Rohárd1547b32021-11-08 18:12:43 +0100274static int image_get_bootfrom(void)
275{
276 struct image_cfg_element *e;
277
278 e = image_find_option(IMAGE_CFG_BOOT_FROM);
279 if (!e)
280 /* fallback to SPI if no BOOT_FROM is not provided */
281 return IBR_HDR_SPI_ID;
282
283 return e->bootfrom;
284}
285
Pali Roháraf496052022-01-12 18:20:40 +0100286static int image_is_cpu_sheeva(void)
287{
288 struct image_cfg_element *e;
289
290 e = image_find_option(IMAGE_CFG_CPU);
291 if (!e)
292 return 0;
293
294 return e->cpu_sheeva;
295}
296
Stefan Roese4acd2d22014-10-22 12:13:23 +0200297/*
298 * Compute a 8-bit checksum of a memory area. This algorithm follows
299 * the requirements of the Marvell SoC BootROM specifications.
300 */
301static uint8_t image_checksum8(void *start, uint32_t len)
302{
303 uint8_t csum = 0;
304 uint8_t *p = start;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530305
306 /* check len and return zero checksum if invalid */
307 if (!len)
308 return 0;
309
310 do {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200311 csum += *p;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530312 p++;
313 } while (--len);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200314
315 return csum;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530316}
317
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +0300318/*
319 * Verify checksum over a complete header that includes the checksum field.
320 * Return 1 when OK, otherwise 0.
321 */
322static int main_hdr_checksum_ok(void *hdr)
323{
324 /* Offsets of checksum in v0 and v1 headers are the same */
325 struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
326 uint8_t checksum;
327
Marek Behúnfe2fd732021-09-24 23:07:01 +0200328 checksum = image_checksum8(hdr, kwbheader_size_for_csum(hdr));
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +0300329 /* Calculated checksum includes the header checksum field. Compensate
330 * for that.
331 */
332 checksum -= main_hdr->checksum;
333
334 return checksum == main_hdr->checksum;
335}
336
Stefan Roese4acd2d22014-10-22 12:13:23 +0200337static uint32_t image_checksum32(void *start, uint32_t len)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530338{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200339 uint32_t csum = 0;
340 uint32_t *p = start;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530341
342 /* check len and return zero checksum if invalid */
343 if (!len)
344 return 0;
345
346 if (len % sizeof(uint32_t)) {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200347 fprintf(stderr, "Length %d is not in multiple of %zu\n",
348 len, sizeof(uint32_t));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530349 return 0;
350 }
351
352 do {
Stefan Roese4acd2d22014-10-22 12:13:23 +0200353 csum += *p;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530354 p++;
355 len -= sizeof(uint32_t);
356 } while (len > 0);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200357
358 return csum;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530359}
360
Chris Packham4bdb5472016-11-09 22:07:45 +1300361static uint8_t baudrate_to_option(unsigned int baudrate)
362{
363 switch (baudrate) {
364 case 2400:
365 return MAIN_HDR_V1_OPT_BAUD_2400;
366 case 4800:
367 return MAIN_HDR_V1_OPT_BAUD_4800;
368 case 9600:
369 return MAIN_HDR_V1_OPT_BAUD_9600;
370 case 19200:
371 return MAIN_HDR_V1_OPT_BAUD_19200;
372 case 38400:
373 return MAIN_HDR_V1_OPT_BAUD_38400;
374 case 57600:
375 return MAIN_HDR_V1_OPT_BAUD_57600;
376 case 115200:
377 return MAIN_HDR_V1_OPT_BAUD_115200;
378 default:
379 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
380 }
381}
382
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100383static void kwb_msg(const char *fmt, ...)
384{
385 if (verbose_mode) {
386 va_list ap;
387
388 va_start(ap, fmt);
389 vfprintf(stdout, fmt, ap);
390 va_end(ap);
391 }
392}
393
394static int openssl_err(const char *msg)
395{
396 unsigned long ssl_err = ERR_get_error();
397
398 fprintf(stderr, "%s", msg);
399 fprintf(stderr, ": %s\n",
400 ERR_error_string(ssl_err, 0));
401
402 return -1;
403}
404
405static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
406{
407 char path[PATH_MAX];
408 RSA *rsa;
409 FILE *f;
410
411 if (!keydir)
412 keydir = ".";
413
414 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
415 f = fopen(path, "r");
416 if (!f) {
417 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
418 path, strerror(errno));
419 return -ENOENT;
420 }
421
422 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
423 if (!rsa) {
424 openssl_err("Failure reading private key");
425 fclose(f);
426 return -EPROTO;
427 }
428 fclose(f);
429 *p_rsa = rsa;
430
431 return 0;
432}
433
434static int kwb_load_cfg_key(struct image_tool_params *params,
435 unsigned int cfg_option, const char *key_name,
436 RSA **p_key)
437{
438 struct image_cfg_element *e_key;
439 RSA *key;
440 int res;
441
442 *p_key = NULL;
443
444 e_key = image_find_option(cfg_option);
445 if (!e_key) {
446 fprintf(stderr, "%s not configured\n", key_name);
447 return -ENOENT;
448 }
449
450 res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
451 if (res < 0) {
452 fprintf(stderr, "Failed to load %s\n", key_name);
453 return -ENOENT;
454 }
455
456 *p_key = key;
457
458 return 0;
459}
460
461static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
462{
463 return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
464}
465
466static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
467{
468 return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
469}
470
471static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
472 struct hash_v1 *hash)
473{
474 EVP_MD_CTX *ctx;
475 unsigned int key_size;
476 unsigned int hash_size;
477 int ret = 0;
478
479 if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
480 return -EINVAL;
481
482 key_size = (pk->key[2] << 8) + pk->key[3] + 4;
483
484 ctx = EVP_MD_CTX_create();
485 if (!ctx)
486 return openssl_err("EVP context creation failed");
487
488 EVP_MD_CTX_init(ctx);
489 if (!EVP_DigestInit(ctx, EVP_sha256())) {
490 ret = openssl_err("Digest setup failed");
491 goto hash_err_ctx;
492 }
493
494 if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
495 ret = openssl_err("Hashing data failed");
496 goto hash_err_ctx;
497 }
498
499 if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
500 ret = openssl_err("Could not obtain hash");
501 goto hash_err_ctx;
502 }
503
504 EVP_MD_CTX_cleanup(ctx);
505
506hash_err_ctx:
507 EVP_MD_CTX_destroy(ctx);
508 return ret;
509}
510
511static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
512{
513 RSA *rsa;
514 const unsigned char *ptr;
515
516 if (!key || !src)
517 goto fail;
518
519 ptr = src->key;
520 rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
521 if (!rsa) {
522 openssl_err("error decoding public key");
523 goto fail;
524 }
525
526 return 0;
527fail:
528 fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
529 return -EINVAL;
530}
531
532static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
533 char *keyname)
534{
535 int size_exp, size_mod, size_seq;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200536 const BIGNUM *key_e, *key_n;
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100537 uint8_t *cur;
538 char *errmsg = "Failed to encode %s\n";
539
Jelle van der Waae15843b2017-05-08 21:31:20 +0200540 RSA_get0_key(key, NULL, &key_e, NULL);
541 RSA_get0_key(key, &key_n, NULL, NULL);
542
543 if (!key || !key_e || !key_n || !dst) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100544 fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
Jelle van der Waae15843b2017-05-08 21:31:20 +0200545 key, key_e, key_n, dst);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100546 fprintf(stderr, errmsg, keyname);
547 return -EINVAL;
548 }
549
550 /*
551 * According to the specs, the key should be PKCS#1 DER encoded.
552 * But unfortunately the really required encoding seems to be different;
553 * it violates DER...! (But it still conformes to BER.)
554 * (Length always in long form w/ 2 byte length code; no leading zero
555 * when MSB of first byte is set...)
556 * So we cannot use the encoding func provided by OpenSSL and have to
557 * do the encoding manually.
558 */
559
Jelle van der Waae15843b2017-05-08 21:31:20 +0200560 size_exp = BN_num_bytes(key_e);
561 size_mod = BN_num_bytes(key_n);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100562 size_seq = 4 + size_mod + 4 + size_exp;
563
564 if (size_mod > 256) {
565 fprintf(stderr, "export pk failed: wrong mod size: %d\n",
566 size_mod);
567 fprintf(stderr, errmsg, keyname);
568 return -EINVAL;
569 }
570
571 if (4 + size_seq > sizeof(dst->key)) {
Marek Behún3b5da642021-09-24 23:06:38 +0200572 fprintf(stderr, "export pk failed: seq too large (%d, %zu)\n",
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100573 4 + size_seq, sizeof(dst->key));
574 fprintf(stderr, errmsg, keyname);
575 return -ENOBUFS;
576 }
577
578 cur = dst->key;
579
580 /* PKCS#1 (RFC3447) RSAPublicKey structure */
581 *cur++ = 0x30; /* SEQUENCE */
582 *cur++ = 0x82;
583 *cur++ = (size_seq >> 8) & 0xFF;
584 *cur++ = size_seq & 0xFF;
585 /* Modulus */
586 *cur++ = 0x02; /* INTEGER */
587 *cur++ = 0x82;
588 *cur++ = (size_mod >> 8) & 0xFF;
589 *cur++ = size_mod & 0xFF;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200590 BN_bn2bin(key_n, cur);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100591 cur += size_mod;
592 /* Exponent */
593 *cur++ = 0x02; /* INTEGER */
594 *cur++ = 0x82;
595 *cur++ = (size_exp >> 8) & 0xFF;
596 *cur++ = size_exp & 0xFF;
Jelle van der Waae15843b2017-05-08 21:31:20 +0200597 BN_bn2bin(key_e, cur);
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100598
599 if (hashf) {
600 struct hash_v1 pk_hash;
601 int i;
602 int ret = 0;
603
604 ret = kwb_compute_pubkey_hash(dst, &pk_hash);
605 if (ret < 0) {
606 fprintf(stderr, errmsg, keyname);
607 return ret;
608 }
609
610 fprintf(hashf, "SHA256 = ");
611 for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
612 fprintf(hashf, "%02X", pk_hash.hash[i]);
613 fprintf(hashf, "\n");
614 }
615
616 return 0;
617}
618
Pali Rohár6eb20bb2022-01-12 18:20:35 +0100619static int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig,
620 char *signame)
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100621{
622 EVP_PKEY *evp_key;
623 EVP_MD_CTX *ctx;
624 unsigned int sig_size;
625 int size;
626 int ret = 0;
627
628 evp_key = EVP_PKEY_new();
629 if (!evp_key)
630 return openssl_err("EVP_PKEY object creation failed");
631
632 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
633 ret = openssl_err("EVP key setup failed");
634 goto err_key;
635 }
636
637 size = EVP_PKEY_size(evp_key);
638 if (size > sizeof(sig->sig)) {
639 fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
640 size);
641 ret = -ENOBUFS;
642 goto err_key;
643 }
644
645 ctx = EVP_MD_CTX_create();
646 if (!ctx) {
647 ret = openssl_err("EVP context creation failed");
648 goto err_key;
649 }
650 EVP_MD_CTX_init(ctx);
651 if (!EVP_SignInit(ctx, EVP_sha256())) {
652 ret = openssl_err("Signer setup failed");
653 goto err_ctx;
654 }
655
656 if (!EVP_SignUpdate(ctx, data, datasz)) {
657 ret = openssl_err("Signing data failed");
658 goto err_ctx;
659 }
660
661 if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
662 ret = openssl_err("Could not obtain signature");
663 goto err_ctx;
664 }
665
666 EVP_MD_CTX_cleanup(ctx);
667 EVP_MD_CTX_destroy(ctx);
668 EVP_PKEY_free(evp_key);
669
670 return 0;
671
672err_ctx:
673 EVP_MD_CTX_destroy(ctx);
674err_key:
675 EVP_PKEY_free(evp_key);
676 fprintf(stderr, "Failed to create %s signature\n", signame);
677 return ret;
678}
679
Pali Rohár6eb20bb2022-01-12 18:20:35 +0100680static int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
681 char *signame)
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100682{
683 EVP_PKEY *evp_key;
684 EVP_MD_CTX *ctx;
685 int size;
686 int ret = 0;
687
688 evp_key = EVP_PKEY_new();
689 if (!evp_key)
690 return openssl_err("EVP_PKEY object creation failed");
691
692 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
693 ret = openssl_err("EVP key setup failed");
694 goto err_key;
695 }
696
697 size = EVP_PKEY_size(evp_key);
698 if (size > sizeof(sig->sig)) {
699 fprintf(stderr, "Invalid signature size (%d bytes)\n",
700 size);
701 ret = -EINVAL;
702 goto err_key;
703 }
704
705 ctx = EVP_MD_CTX_create();
706 if (!ctx) {
707 ret = openssl_err("EVP context creation failed");
708 goto err_key;
709 }
710 EVP_MD_CTX_init(ctx);
711 if (!EVP_VerifyInit(ctx, EVP_sha256())) {
712 ret = openssl_err("Verifier setup failed");
713 goto err_ctx;
714 }
715
716 if (!EVP_VerifyUpdate(ctx, data, datasz)) {
717 ret = openssl_err("Hashing data failed");
718 goto err_ctx;
719 }
720
Young Xiao22515122019-04-17 17:20:24 +0800721 if (EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key) != 1) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100722 ret = openssl_err("Could not verify signature");
723 goto err_ctx;
724 }
725
726 EVP_MD_CTX_cleanup(ctx);
727 EVP_MD_CTX_destroy(ctx);
728 EVP_PKEY_free(evp_key);
729
730 return 0;
731
732err_ctx:
733 EVP_MD_CTX_destroy(ctx);
734err_key:
735 EVP_PKEY_free(evp_key);
736 fprintf(stderr, "Failed to verify %s signature\n", signame);
737 return ret;
738}
739
Pali Rohár6eb20bb2022-01-12 18:20:35 +0100740static int kwb_sign_and_verify(RSA *key, void *data, int datasz,
741 struct sig_v1 *sig, char *signame)
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100742{
743 if (kwb_sign(key, data, datasz, sig, signame) < 0)
744 return -1;
745
746 if (kwb_verify(key, data, datasz, sig, signame) < 0)
747 return -1;
748
749 return 0;
750}
751
752
Pali Rohár6eb20bb2022-01-12 18:20:35 +0100753static int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100754{
755 struct hash_v1 kak_pub_hash;
756 struct image_cfg_element *e;
757 unsigned int fuse_line;
758 int i, idx;
759 uint8_t *ptr;
760 uint32_t val;
761 int ret = 0;
762
763 if (!out || !sec_hdr)
764 return -EINVAL;
765
766 ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
767 if (ret < 0)
768 goto done;
769
770 fprintf(out, "# burn KAK pub key hash\n");
771 ptr = kak_pub_hash.hash;
772 for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
773 fprintf(out, "fuse prog -y %u 0 ", fuse_line);
774
775 for (i = 4; i-- > 0;)
776 fprintf(out, "%02hx", (ushort)ptr[i]);
777 ptr += 4;
778 fprintf(out, " 00");
779
780 if (fuse_line < 30) {
781 for (i = 3; i-- > 0;)
782 fprintf(out, "%02hx", (ushort)ptr[i]);
783 ptr += 3;
784 } else {
785 fprintf(out, "000000");
786 }
787
788 fprintf(out, " 1\n");
789 }
790
791 fprintf(out, "# burn CSK selection\n");
792
793 idx = image_get_csk_index();
794 if (idx < 0 || idx > 15) {
795 ret = -EINVAL;
796 goto done;
797 }
798 if (idx > 0) {
799 for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
800 fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
801 fuse_line);
802 } else {
803 fprintf(out, "# CSK index is 0; no mods needed\n");
804 }
805
806 e = image_find_option(IMAGE_CFG_BOX_ID);
807 if (e) {
808 fprintf(out, "# set box ID\n");
809 fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
810 }
811
812 e = image_find_option(IMAGE_CFG_FLASH_ID);
813 if (e) {
814 fprintf(out, "# set flash ID\n");
815 fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
816 }
817
818 fprintf(out, "# enable secure mode ");
819 fprintf(out, "(must be the last fuse line written)\n");
820
821 val = 1;
822 e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
823 if (!e) {
824 fprintf(stderr, "ERROR: secured mode boot device not given\n");
825 ret = -EINVAL;
826 goto done;
827 }
828
829 if (e->sec_boot_dev > 0xff) {
830 fprintf(stderr, "ERROR: secured mode boot device invalid\n");
831 ret = -EINVAL;
832 goto done;
833 }
834
835 val |= (e->sec_boot_dev << 8);
836
837 fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
838
839 fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
840 for (fuse_line = 0; fuse_line < 24; ++fuse_line)
841 fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
842
843 fprintf(out, "# OK, that's all :-)\n");
844
845done:
846 return ret;
847}
848
849static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
850{
851 int ret = 0;
852 struct image_cfg_element *e;
853
854 e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
855 if (!e)
856 return 0;
857
858 if (!strcmp(e->name, "a38x")) {
859 FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
860
Heinrich Schuchardtf858bb22021-08-17 07:03:20 +0200861 if (!out) {
862 fprintf(stderr, "Couldn't open eFuse settings: '%s': %s\n",
863 "kwb_fuses_a38x.txt", strerror(errno));
864 return -ENOENT;
865 }
866
Mario Sixa1b6b0a2017-01-11 16:01:00 +0100867 kwb_dump_fuse_cmds_38x(out, sec_hdr);
868 fclose(out);
869 goto done;
870 }
871
872 ret = -ENOSYS;
873
874done:
875 return ret;
876}
877
Pali Rohár5cad2e62021-11-08 18:12:48 +0100878static size_t image_headersz_align(size_t headersz, uint8_t blockid)
879{
880 /*
881 * Header needs to be 4-byte aligned, which is already ensured by code
882 * above. Moreover UART images must have header aligned to 128 bytes
883 * (xmodem block size), NAND images to 256 bytes (ECC calculation),
884 * and SATA and SDIO images to 512 bytes (storage block size).
885 * Note that SPI images do not have to have header size aligned
886 * to 256 bytes because it is possible to read from SPI storage from
887 * any offset (read offset does not have to be aligned to block size).
888 */
889 if (blockid == IBR_HDR_UART_ID)
890 return ALIGN(headersz, 128);
891 else if (blockid == IBR_HDR_NAND_ID)
892 return ALIGN(headersz, 256);
893 else if (blockid == IBR_HDR_SATA_ID || blockid == IBR_HDR_SDIO_ID)
894 return ALIGN(headersz, 512);
895 else
896 return headersz;
897}
898
Pali Rohár851114b2021-11-08 18:12:50 +0100899static size_t image_headersz_v0(int *hasext)
900{
901 size_t headersz;
902
903 headersz = sizeof(struct main_hdr_v0);
904 if (image_count_options(IMAGE_CFG_DATA) > 0) {
905 headersz += sizeof(struct ext_hdr_v0);
906 if (hasext)
907 *hasext = 1;
908 }
909
910 return image_headersz_align(headersz, image_get_bootfrom());
911}
912
Stefan Roese4acd2d22014-10-22 12:13:23 +0200913static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
914 int payloadsz)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530915{
Stefan Roese4acd2d22014-10-22 12:13:23 +0200916 struct image_cfg_element *e;
917 size_t headersz;
918 struct main_hdr_v0 *main_hdr;
Mario Six885fba12017-01-11 16:00:55 +0100919 uint8_t *image;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200920 int has_ext = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530921
Stefan Roese4acd2d22014-10-22 12:13:23 +0200922 /*
923 * Calculate the size of the header and the size of the
924 * payload
925 */
Pali Rohár851114b2021-11-08 18:12:50 +0100926 headersz = image_headersz_v0(&has_ext);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530927
Stefan Roese4acd2d22014-10-22 12:13:23 +0200928 image = malloc(headersz);
929 if (!image) {
930 fprintf(stderr, "Cannot allocate memory for image\n");
931 return NULL;
932 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530933
Stefan Roese4acd2d22014-10-22 12:13:23 +0200934 memset(image, 0, headersz);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530935
Mario Six885fba12017-01-11 16:00:55 +0100936 main_hdr = (struct main_hdr_v0 *)image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530937
Stefan Roese4acd2d22014-10-22 12:13:23 +0200938 /* Fill in the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100939 main_hdr->blocksize =
Pali Roháre23ad5d2021-11-08 18:12:47 +0100940 cpu_to_le32(payloadsz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100941 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200942 main_hdr->ext = has_ext;
Pali Rohár01bdac62021-11-08 18:12:42 +0100943 main_hdr->version = 0;
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100944 main_hdr->destaddr = cpu_to_le32(params->addr);
945 main_hdr->execaddr = cpu_to_le32(params->ep);
Pali Rohárd1547b32021-11-08 18:12:43 +0100946 main_hdr->blockid = image_get_bootfrom();
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530947
Stefan Roese4acd2d22014-10-22 12:13:23 +0200948 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
949 if (e)
950 main_hdr->nandeccmode = e->nandeccmode;
951 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
952 if (e)
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100953 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200954 main_hdr->checksum = image_checksum8(image,
955 sizeof(struct main_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530956
Pali Rohár5c617102021-11-08 18:12:51 +0100957 /*
958 * For SATA srcaddr is specified in number of sectors starting from
959 * sector 0. The main header is stored at sector number 1.
960 * This expects the sector size to be 512 bytes.
961 * Header size is already aligned.
962 */
963 if (main_hdr->blockid == IBR_HDR_SATA_ID)
964 main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1);
965
966 /*
967 * For SDIO srcaddr is specified in number of sectors starting from
968 * sector 0. The main header is stored at sector number 0.
969 * This expects sector size to be 512 bytes.
970 * Header size is already aligned.
971 */
972 if (main_hdr->blockid == IBR_HDR_SDIO_ID)
973 main_hdr->srcaddr = cpu_to_le32(headersz / 512);
974
975 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
976 if (main_hdr->blockid == IBR_HDR_PEX_ID)
977 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
978
Stefan Roese4acd2d22014-10-22 12:13:23 +0200979 /* Generate the ext header */
980 if (has_ext) {
Mario Sixe89016c2017-01-11 16:00:56 +0100981 struct ext_hdr_v0 *ext_hdr;
Stefan Roese4acd2d22014-10-22 12:13:23 +0200982 int cfgi, datai;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530983
Mario Six885fba12017-01-11 16:00:55 +0100984 ext_hdr = (struct ext_hdr_v0 *)
985 (image + sizeof(struct main_hdr_v0));
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100986 ext_hdr->offset = cpu_to_le32(0x40);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530987
Stefan Roese4acd2d22014-10-22 12:13:23 +0200988 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
989 e = &image_cfg[cfgi];
990 if (e->type != IMAGE_CFG_DATA)
991 continue;
992
Reinhard Pfaua8840dc2015-11-29 15:48:25 +0100993 ext_hdr->rcfg[datai].raddr =
994 cpu_to_le32(e->regdata.raddr);
995 ext_hdr->rcfg[datai].rdata =
996 cpu_to_le32(e->regdata.rdata);
Stefan Roese4acd2d22014-10-22 12:13:23 +0200997 datai++;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530998 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +0530999
Stefan Roese4acd2d22014-10-22 12:13:23 +02001000 ext_hdr->checksum = image_checksum8(ext_hdr,
1001 sizeof(struct ext_hdr_v0));
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301002 }
1003
Stefan Roese4acd2d22014-10-22 12:13:23 +02001004 *imagesz = headersz;
1005 return image;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301006}
1007
Mario Sixe93cf532017-01-11 16:00:57 +01001008static size_t image_headersz_v1(int *hasext)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301009{
Pali Rohárd737d5d2022-01-12 18:20:37 +01001010 struct image_cfg_element *binarye, *e;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001011 unsigned int count;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001012 size_t headersz;
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001013 int cfgi;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301014
Stefan Roese4acd2d22014-10-22 12:13:23 +02001015 /*
1016 * Calculate the size of the header and the size of the
1017 * payload
1018 */
1019 headersz = sizeof(struct main_hdr_v1);
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301020
Pali Roháre58f08b2021-10-21 16:46:07 +02001021 if (image_get_csk_index() >= 0) {
1022 headersz += sizeof(struct secure_hdr_v1);
1023 if (hasext)
1024 *hasext = 1;
1025 }
1026
Pali Rohárd737d5d2022-01-12 18:20:37 +01001027 count = 0;
1028 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1029 e = &image_cfg[cfgi];
1030
1031 if (e->type == IMAGE_CFG_DATA)
1032 count++;
1033
Pali Rohár3db9c412022-01-12 18:20:38 +01001034 if (e->type == IMAGE_CFG_DATA_DELAY ||
1035 (e->type == IMAGE_CFG_BINARY && count > 0)) {
Pali Rohárd737d5d2022-01-12 18:20:37 +01001036 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
1037 count = 0;
1038 }
1039 }
Pali Rohár02ba70a2021-07-23 11:14:11 +02001040 if (count > 0)
1041 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
1042
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001043 for (cfgi = 0; cfgi < cfgn; cfgi++) {
Mario Sixe89016c2017-01-11 16:00:56 +01001044 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001045 struct stat s;
1046
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001047 binarye = &image_cfg[cfgi];
1048 if (binarye->type != IMAGE_CFG_BINARY)
1049 continue;
1050
Stefan Roese4acd2d22014-10-22 12:13:23 +02001051 ret = stat(binarye->binary.file, &s);
1052 if (ret < 0) {
Andreas Bießmanne5f1a582014-10-24 23:39:11 +02001053 char cwd[PATH_MAX];
1054 char *dir = cwd;
1055
1056 memset(cwd, 0, sizeof(cwd));
1057 if (!getcwd(cwd, sizeof(cwd))) {
1058 dir = "current working directory";
1059 perror("getcwd() failed");
1060 }
1061
Stefan Roese4acd2d22014-10-22 12:13:23 +02001062 fprintf(stderr,
1063 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
1064 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
Pali Rohár3d7b93d2021-07-23 11:14:35 +02001065 "image for your board. Use 'dumpimage -T kwbimage -p 0' to extract it from an existing image.\n",
Andreas Bießmanne5f1a582014-10-24 23:39:11 +02001066 binarye->binary.file, dir);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001067 return 0;
1068 }
1069
Pali Roháre58f08b2021-10-21 16:46:07 +02001070 headersz += sizeof(struct opt_hdr_v1) + sizeof(uint32_t) +
1071 (binarye->binary.nargs) * sizeof(uint32_t);
1072 headersz = ALIGN(headersz, 16);
1073 headersz += ALIGN(s.st_size, 4) + sizeof(uint32_t);
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001074 if (hasext)
1075 *hasext = 1;
1076 }
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001077
Pali Rohár5cad2e62021-11-08 18:12:48 +01001078 return image_headersz_align(headersz, image_get_bootfrom());
Stefan Roese4acd2d22014-10-22 12:13:23 +02001079}
1080
Pali Rohár6eb20bb2022-01-12 18:20:35 +01001081static int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
1082 struct image_cfg_element *binarye,
1083 struct main_hdr_v1 *main_hdr)
Mario Six79066ef2017-01-11 16:00:58 +01001084{
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001085 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur;
Pali Roháre58f08b2021-10-21 16:46:07 +02001086 uint32_t add_args;
1087 uint32_t offset;
Mario Six79066ef2017-01-11 16:00:58 +01001088 uint32_t *args;
1089 size_t binhdrsz;
1090 struct stat s;
1091 int argi;
1092 FILE *bin;
1093 int ret;
1094
Mario Six79066ef2017-01-11 16:00:58 +01001095 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1096
1097 bin = fopen(binarye->binary.file, "r");
1098 if (!bin) {
1099 fprintf(stderr, "Cannot open binary file %s\n",
1100 binarye->binary.file);
1101 return -1;
1102 }
1103
Mario Six1f6c8a52017-02-13 10:11:55 +01001104 if (fstat(fileno(bin), &s)) {
1105 fprintf(stderr, "Cannot stat binary file %s\n",
1106 binarye->binary.file);
1107 goto err_close;
1108 }
Mario Six79066ef2017-01-11 16:00:58 +01001109
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001110 *cur += sizeof(struct opt_hdr_v1);
Mario Six79066ef2017-01-11 16:00:58 +01001111
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001112 args = (uint32_t *)*cur;
Mario Six79066ef2017-01-11 16:00:58 +01001113 *args = cpu_to_le32(binarye->binary.nargs);
1114 args++;
1115 for (argi = 0; argi < binarye->binary.nargs; argi++)
1116 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1117
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001118 *cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
Mario Six79066ef2017-01-11 16:00:58 +01001119
Pali Roháre58f08b2021-10-21 16:46:07 +02001120 /*
1121 * ARM executable code inside the BIN header on some mvebu platforms
1122 * (e.g. A370, AXP) must always be aligned with the 128-bit boundary.
1123 * This requirement can be met by inserting dummy arguments into
1124 * BIN header, if needed.
1125 */
1126 offset = *cur - (uint8_t *)main_hdr;
1127 add_args = ((16 - offset % 16) % 16) / sizeof(uint32_t);
1128 if (add_args) {
1129 *(args - 1) = cpu_to_le32(binarye->binary.nargs + add_args);
1130 *cur += add_args * sizeof(uint32_t);
1131 }
1132
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001133 ret = fread(*cur, s.st_size, 1, bin);
Mario Six79066ef2017-01-11 16:00:58 +01001134 if (ret != 1) {
1135 fprintf(stderr,
1136 "Could not read binary image %s\n",
1137 binarye->binary.file);
Mario Six1f6c8a52017-02-13 10:11:55 +01001138 goto err_close;
Mario Six79066ef2017-01-11 16:00:58 +01001139 }
1140
1141 fclose(bin);
1142
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001143 *cur += ALIGN(s.st_size, 4);
Mario Six79066ef2017-01-11 16:00:58 +01001144
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001145 *((uint32_t *)*cur) = 0x00000000;
1146 **next_ext = 1;
1147 *next_ext = *cur;
Mario Six79066ef2017-01-11 16:00:58 +01001148
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001149 *cur += sizeof(uint32_t);
Mario Six79066ef2017-01-11 16:00:58 +01001150
Pali Roháre58f08b2021-10-21 16:46:07 +02001151 binhdrsz = sizeof(struct opt_hdr_v1) +
1152 (binarye->binary.nargs + add_args + 2) * sizeof(uint32_t) +
1153 ALIGN(s.st_size, 4);
1154 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1155 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1156
Mario Six79066ef2017-01-11 16:00:58 +01001157 return 0;
Mario Six1f6c8a52017-02-13 10:11:55 +01001158
1159err_close:
1160 fclose(bin);
1161
1162 return -1;
Mario Six79066ef2017-01-11 16:00:58 +01001163}
1164
Pali Rohár6eb20bb2022-01-12 18:20:35 +01001165static int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001166{
1167 FILE *hashf;
1168 int res;
1169
1170 hashf = fopen("pub_kak_hash.txt", "w");
Heinrich Schuchardtf858bb22021-08-17 07:03:20 +02001171 if (!hashf) {
1172 fprintf(stderr, "Couldn't open hash file: '%s': %s\n",
1173 "pub_kak_hash.txt", strerror(errno));
1174 return 1;
1175 }
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001176
1177 res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1178
1179 fclose(hashf);
1180
1181 return res < 0 ? 1 : 0;
1182}
1183
Pali Rohár6eb20bb2022-01-12 18:20:35 +01001184static int kwb_sign_csk_with_kak(struct image_tool_params *params,
1185 struct secure_hdr_v1 *secure_hdr, RSA *csk)
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001186{
1187 RSA *kak = NULL;
1188 RSA *kak_pub = NULL;
1189 int csk_idx = image_get_csk_index();
1190 struct sig_v1 tmp_sig;
1191
Heinrich Schuchardtf0317d72021-08-17 07:11:58 +02001192 if (csk_idx < 0 || csk_idx > 15) {
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001193 fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1194 return 1;
1195 }
1196
1197 if (kwb_load_kak(params, &kak) < 0)
1198 return 1;
1199
1200 if (export_pub_kak_hash(kak, secure_hdr))
1201 return 1;
1202
1203 if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1204 return 1;
1205
1206 if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1207 return 1;
1208
1209 if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1210 sizeof(secure_hdr->csk) +
1211 sizeof(secure_hdr->csksig),
1212 &tmp_sig, "CSK") < 0)
1213 return 1;
1214
1215 if (kwb_verify(kak_pub, &secure_hdr->csk,
1216 sizeof(secure_hdr->csk) +
1217 sizeof(secure_hdr->csksig),
1218 &tmp_sig, "CSK (2)") < 0)
1219 return 1;
1220
1221 secure_hdr->csksig = tmp_sig;
1222
1223 return 0;
1224}
1225
Pali Rohár6eb20bb2022-01-12 18:20:35 +01001226static int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr,
1227 int payloadsz, size_t headersz, uint8_t *image,
1228 struct secure_hdr_v1 *secure_hdr)
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001229{
1230 struct image_cfg_element *e_jtagdelay;
1231 struct image_cfg_element *e_boxid;
1232 struct image_cfg_element *e_flashid;
1233 RSA *csk = NULL;
1234 unsigned char *image_ptr;
1235 size_t image_size;
1236 struct sig_v1 tmp_sig;
1237 bool specialized_img = image_get_spezialized_img();
1238
1239 kwb_msg("Create secure header content\n");
1240
1241 e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1242 e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1243 e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1244
1245 if (kwb_load_csk(params, &csk) < 0)
1246 return 1;
1247
1248 secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1249 secure_hdr->headersz_msb = 0;
1250 secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1251 if (e_jtagdelay)
1252 secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1253 if (e_boxid && specialized_img)
1254 secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1255 if (e_flashid && specialized_img)
1256 secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1257
1258 if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1259 return 1;
1260
1261 image_ptr = ptr + headersz;
1262 image_size = payloadsz - headersz;
1263
1264 if (kwb_sign_and_verify(csk, image_ptr, image_size,
1265 &secure_hdr->imgsig, "image") < 0)
1266 return 1;
1267
1268 if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0)
1269 return 1;
1270
1271 secure_hdr->hdrsig = tmp_sig;
1272
1273 kwb_dump_fuse_cmds(secure_hdr);
1274
1275 return 0;
1276}
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001277
Pali Rohár9ac1def2022-01-12 18:20:36 +01001278static void finish_register_set_header_v1(uint8_t **cur, uint8_t **next_ext,
1279 struct register_set_hdr_v1 *register_set_hdr,
1280 int *datai, uint8_t delay)
1281{
1282 int size = sizeof(struct register_set_hdr_v1) + 8 * (*datai) + 4;
1283
1284 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1285 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1286 register_set_hdr->headersz_msb = size >> 16;
1287 register_set_hdr->data[*datai].last_entry.delay = delay;
1288 *cur += size;
1289 **next_ext = 1;
1290 *next_ext = &register_set_hdr->data[*datai].last_entry.next;
1291 *datai = 0;
1292}
1293
Stefan Roese4acd2d22014-10-22 12:13:23 +02001294static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001295 uint8_t *ptr, int payloadsz)
Stefan Roese4acd2d22014-10-22 12:13:23 +02001296{
Mario Six79066ef2017-01-11 16:00:58 +01001297 struct image_cfg_element *e;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001298 struct main_hdr_v1 *main_hdr;
Pali Rohár2b0980c2021-11-08 18:12:49 +01001299 struct opt_hdr_v1 *ohdr;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001300 struct register_set_hdr_v1 *register_set_hdr;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001301 struct secure_hdr_v1 *secure_hdr = NULL;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001302 size_t headersz;
Mario Six885fba12017-01-11 16:00:55 +01001303 uint8_t *image, *cur;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001304 int hasext = 0;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001305 uint8_t *next_ext = NULL;
Pali Rohár9ac1def2022-01-12 18:20:36 +01001306 int cfgi, datai;
Pali Rohár3db9c412022-01-12 18:20:38 +01001307 uint8_t delay;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001308
1309 /*
1310 * Calculate the size of the header and the size of the
1311 * payload
1312 */
Mario Sixe93cf532017-01-11 16:00:57 +01001313 headersz = image_headersz_v1(&hasext);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001314 if (headersz == 0)
1315 return NULL;
1316
1317 image = malloc(headersz);
1318 if (!image) {
1319 fprintf(stderr, "Cannot allocate memory for image\n");
1320 return NULL;
1321 }
1322
1323 memset(image, 0, headersz);
1324
Mario Six885fba12017-01-11 16:00:55 +01001325 main_hdr = (struct main_hdr_v1 *)image;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001326 cur = image;
1327 cur += sizeof(struct main_hdr_v1);
1328 next_ext = &main_hdr->ext;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001329
1330 /* Fill the main header */
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001331 main_hdr->blocksize =
Pali Roháre23ad5d2021-11-08 18:12:47 +01001332 cpu_to_le32(payloadsz);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001333 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001334 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
Pali Rohárcc3443f2021-07-23 11:14:06 +02001335 main_hdr->destaddr = cpu_to_le32(params->addr);
Reinhard Pfaua8840dc2015-11-29 15:48:25 +01001336 main_hdr->execaddr = cpu_to_le32(params->ep);
1337 main_hdr->srcaddr = cpu_to_le32(headersz);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001338 main_hdr->ext = hasext;
1339 main_hdr->version = 1;
Pali Rohárd1547b32021-11-08 18:12:43 +01001340 main_hdr->blockid = image_get_bootfrom();
1341
Stefan Roese4acd2d22014-10-22 12:13:23 +02001342 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1343 if (e)
1344 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
Pali Rohár2fdba4f2021-10-22 12:37:46 +02001345 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
1346 if (e)
1347 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001348 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1349 if (e)
1350 main_hdr->nandbadblklocation = e->nandbadblklocation;
Chris Packham4bdb5472016-11-09 22:07:45 +13001351 e = image_find_option(IMAGE_CFG_BAUDRATE);
1352 if (e)
Pali Rohár12f2c032021-11-08 18:12:41 +01001353 main_hdr->options |= baudrate_to_option(e->baudrate);
1354 e = image_find_option(IMAGE_CFG_UART_PORT);
1355 if (e)
1356 main_hdr->options |= (e->uart_port & 3) << 3;
1357 e = image_find_option(IMAGE_CFG_UART_MPP);
1358 if (e)
1359 main_hdr->options |= (e->uart_mpp & 7) << 5;
Chris Packham2611c052016-11-09 22:21:45 +13001360 e = image_find_option(IMAGE_CFG_DEBUG);
1361 if (e)
1362 main_hdr->flags = e->debug ? 0x1 : 0;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001363
Pali Rohár501a54a2021-07-23 11:13:59 +02001364 /*
1365 * For SATA srcaddr is specified in number of sectors starting from
1366 * sector 0. The main header is stored at sector number 1.
1367 * This expects the sector size to be 512 bytes.
1368 * Header size is already aligned.
1369 */
1370 if (main_hdr->blockid == IBR_HDR_SATA_ID)
1371 main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1);
1372
1373 /*
1374 * For SDIO srcaddr is specified in number of sectors starting from
1375 * sector 0. The main header is stored at sector number 0.
1376 * This expects sector size to be 512 bytes.
1377 * Header size is already aligned.
1378 */
1379 if (main_hdr->blockid == IBR_HDR_SDIO_ID)
1380 main_hdr->srcaddr = cpu_to_le32(headersz / 512);
1381
1382 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1383 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1384 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1385
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001386 if (image_get_csk_index() >= 0) {
1387 /*
1388 * only reserve the space here; we fill the header later since
1389 * we need the header to be complete to compute the signatures
1390 */
1391 secure_hdr = (struct secure_hdr_v1 *)cur;
1392 cur += sizeof(struct secure_hdr_v1);
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001393 *next_ext = 1;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001394 next_ext = &secure_hdr->next;
1395 }
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001396
Pali Rohár02ba70a2021-07-23 11:14:11 +02001397 datai = 0;
Pali Rohár02ba70a2021-07-23 11:14:11 +02001398 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1399 e = &image_cfg[cfgi];
Pali Rohárf63c5832021-07-23 11:14:12 +02001400 if (e->type != IMAGE_CFG_DATA &&
Pali Rohár3db9c412022-01-12 18:20:38 +01001401 e->type != IMAGE_CFG_DATA_DELAY &&
1402 e->type != IMAGE_CFG_BINARY)
Pali Rohár02ba70a2021-07-23 11:14:11 +02001403 continue;
Pali Rohár3db9c412022-01-12 18:20:38 +01001404
Pali Rohárd737d5d2022-01-12 18:20:37 +01001405 if (datai == 0)
1406 register_set_hdr = (struct register_set_hdr_v1 *)cur;
Pali Rohár3db9c412022-01-12 18:20:38 +01001407
1408 /* If delay is not specified, use the smallest possible value. */
1409 if (e->type == IMAGE_CFG_DATA_DELAY)
1410 delay = e->regdata_delay;
1411 else
1412 delay = REGISTER_SET_HDR_OPT_DELAY_MS(0);
1413
1414 /*
1415 * DATA_DELAY command is the last entry in the register set
1416 * header and BINARY command inserts new binary header.
1417 * Therefore BINARY command requires to finish register set
1418 * header if some DATA command was specified. And DATA_DELAY
1419 * command automatically finish register set header even when
1420 * there was no DATA command.
1421 */
1422 if (e->type == IMAGE_CFG_DATA_DELAY ||
1423 (e->type == IMAGE_CFG_BINARY && datai != 0))
Pali Rohár9ac1def2022-01-12 18:20:36 +01001424 finish_register_set_header_v1(&cur, &next_ext, register_set_hdr,
Pali Rohár3db9c412022-01-12 18:20:38 +01001425 &datai, delay);
1426
1427 if (e->type == IMAGE_CFG_DATA) {
1428 register_set_hdr->data[datai].entry.address =
1429 cpu_to_le32(e->regdata.raddr);
1430 register_set_hdr->data[datai].entry.value =
1431 cpu_to_le32(e->regdata.rdata);
1432 datai++;
Pali Rohárf63c5832021-07-23 11:14:12 +02001433 }
Pali Rohár3db9c412022-01-12 18:20:38 +01001434
1435 if (e->type == IMAGE_CFG_BINARY) {
1436 if (add_binary_header_v1(&cur, &next_ext, e, main_hdr))
1437 return NULL;
1438 }
Pali Rohár02ba70a2021-07-23 11:14:11 +02001439 }
1440 if (datai != 0) {
Pali Rohár9ac1def2022-01-12 18:20:36 +01001441 /* Set delay to the smallest possible value. */
Pali Rohár3db9c412022-01-12 18:20:38 +01001442 delay = REGISTER_SET_HDR_OPT_DELAY_MS(0);
Pali Rohár9ac1def2022-01-12 18:20:36 +01001443 finish_register_set_header_v1(&cur, &next_ext, register_set_hdr,
Pali Rohár3db9c412022-01-12 18:20:38 +01001444 &datai, delay);
Pali Rohárd9fb82c2021-07-23 11:14:09 +02001445 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001446
Pali Roháre23ad5d2021-11-08 18:12:47 +01001447 if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz + headersz,
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001448 headersz, image, secure_hdr))
1449 return NULL;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001450
Stefan Roese4acd2d22014-10-22 12:13:23 +02001451 *imagesz = headersz;
Pali Rohár2b0980c2021-11-08 18:12:49 +01001452
1453 /* Fill the real header size without padding into the main header */
1454 headersz = sizeof(*main_hdr);
1455 for_each_opt_hdr_v1 (ohdr, main_hdr)
1456 headersz += opt_hdr_v1_size(ohdr);
1457 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
1458 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
1459
Pierre Bourdon9203c732021-12-25 20:50:19 +01001460 /* Calculate and set the header checksum */
1461 main_hdr->checksum = image_checksum8(main_hdr, headersz);
1462
Stefan Roese4acd2d22014-10-22 12:13:23 +02001463 return image;
1464}
1465
Pali Rohár6eb20bb2022-01-12 18:20:35 +01001466static int recognize_keyword(char *keyword)
Mario Six4991b4f2017-01-11 16:00:59 +01001467{
1468 int kw_id;
1469
1470 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1471 if (!strcmp(keyword, id_strs[kw_id]))
1472 return kw_id;
1473
1474 return 0;
1475}
1476
Stefan Roese4acd2d22014-10-22 12:13:23 +02001477static int image_create_config_parse_oneline(char *line,
1478 struct image_cfg_element *el)
1479{
Mario Six4991b4f2017-01-11 16:00:59 +01001480 char *keyword, *saveptr, *value1, *value2;
1481 char delimiters[] = " \t";
1482 int keyword_id, ret, argi;
1483 char *unknown_msg = "Ignoring unknown line '%s'\n";
Stefan Roese4acd2d22014-10-22 12:13:23 +02001484
Mario Six4991b4f2017-01-11 16:00:59 +01001485 keyword = strtok_r(line, delimiters, &saveptr);
1486 keyword_id = recognize_keyword(keyword);
Mario Six94490a42017-01-11 16:00:54 +01001487
Mario Six4991b4f2017-01-11 16:00:59 +01001488 if (!keyword_id) {
1489 fprintf(stderr, unknown_msg, line);
1490 return 0;
1491 }
1492
1493 el->type = keyword_id;
1494
1495 value1 = strtok_r(NULL, delimiters, &saveptr);
1496
1497 if (!value1) {
1498 fprintf(stderr, "Parameter missing in line '%s'\n", line);
1499 return -1;
1500 }
1501
1502 switch (keyword_id) {
1503 case IMAGE_CFG_VERSION:
1504 el->version = atoi(value1);
1505 break;
Pali Roháraf496052022-01-12 18:20:40 +01001506 case IMAGE_CFG_CPU:
1507 if (strcmp(value1, "FEROCEON") == 0)
1508 el->cpu_sheeva = 0;
1509 else if (strcmp(value1, "SHEEVA") == 0)
1510 el->cpu_sheeva = 1;
1511 else if (strcmp(value1, "A9") == 0)
1512 el->cpu_sheeva = 0;
1513 else {
1514 fprintf(stderr, "Invalid CPU %s\n", value1);
1515 return -1;
1516 }
1517 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001518 case IMAGE_CFG_BOOT_FROM:
1519 ret = image_boot_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001520
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001521 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001522 fprintf(stderr, "Invalid boot media '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001523 return -1;
1524 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001525 el->bootfrom = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001526 break;
1527 case IMAGE_CFG_NAND_BLKSZ:
1528 el->nandblksz = strtoul(value1, NULL, 16);
1529 break;
1530 case IMAGE_CFG_NAND_BADBLK_LOCATION:
1531 el->nandbadblklocation = strtoul(value1, NULL, 16);
1532 break;
1533 case IMAGE_CFG_NAND_ECC_MODE:
1534 ret = image_nand_ecc_mode_id(value1);
Mario Six94490a42017-01-11 16:00:54 +01001535
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001536 if (ret < 0) {
Mario Six4991b4f2017-01-11 16:00:59 +01001537 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001538 return -1;
1539 }
Andreas Bießmannf411b8f2014-10-24 23:25:52 +02001540 el->nandeccmode = ret;
Mario Six4991b4f2017-01-11 16:00:59 +01001541 break;
1542 case IMAGE_CFG_NAND_PAGESZ:
1543 el->nandpagesz = strtoul(value1, NULL, 16);
1544 break;
1545 case IMAGE_CFG_BINARY:
1546 argi = 0;
Mario Six94490a42017-01-11 16:00:54 +01001547
Mario Six4991b4f2017-01-11 16:00:59 +01001548 el->binary.file = strdup(value1);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001549 while (1) {
Mario Six4991b4f2017-01-11 16:00:59 +01001550 char *value = strtok_r(NULL, delimiters, &saveptr);
1551
Stefan Roese4acd2d22014-10-22 12:13:23 +02001552 if (!value)
1553 break;
1554 el->binary.args[argi] = strtoul(value, NULL, 16);
1555 argi++;
1556 if (argi >= BINARY_MAX_ARGS) {
1557 fprintf(stderr,
Mario Six4991b4f2017-01-11 16:00:59 +01001558 "Too many arguments for BINARY\n");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001559 return -1;
1560 }
1561 }
1562 el->binary.nargs = argi;
Mario Six4991b4f2017-01-11 16:00:59 +01001563 break;
1564 case IMAGE_CFG_DATA:
1565 value2 = strtok_r(NULL, delimiters, &saveptr);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001566
1567 if (!value1 || !value2) {
1568 fprintf(stderr,
1569 "Invalid number of arguments for DATA\n");
1570 return -1;
1571 }
1572
Stefan Roese4acd2d22014-10-22 12:13:23 +02001573 el->regdata.raddr = strtoul(value1, NULL, 16);
1574 el->regdata.rdata = strtoul(value2, NULL, 16);
Mario Six4991b4f2017-01-11 16:00:59 +01001575 break;
Pali Rohárf63c5832021-07-23 11:14:12 +02001576 case IMAGE_CFG_DATA_DELAY:
1577 if (!strcmp(value1, "SDRAM_SETUP"))
1578 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP;
1579 else
1580 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_MS(strtoul(value1, NULL, 10));
1581 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001582 case IMAGE_CFG_BAUDRATE:
1583 el->baudrate = strtoul(value1, NULL, 10);
1584 break;
Pali Rohár12f2c032021-11-08 18:12:41 +01001585 case IMAGE_CFG_UART_PORT:
1586 el->uart_port = strtoul(value1, NULL, 16);
1587 break;
1588 case IMAGE_CFG_UART_MPP:
1589 el->uart_mpp = strtoul(value1, NULL, 16);
1590 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001591 case IMAGE_CFG_DEBUG:
1592 el->debug = strtoul(value1, NULL, 10);
1593 break;
Mario Sixa1b6b0a2017-01-11 16:01:00 +01001594 case IMAGE_CFG_KAK:
1595 el->key_name = strdup(value1);
1596 break;
1597 case IMAGE_CFG_CSK:
1598 el->key_name = strdup(value1);
1599 break;
1600 case IMAGE_CFG_CSK_INDEX:
1601 el->csk_idx = strtol(value1, NULL, 0);
1602 break;
1603 case IMAGE_CFG_JTAG_DELAY:
1604 el->jtag_delay = strtoul(value1, NULL, 0);
1605 break;
1606 case IMAGE_CFG_BOX_ID:
1607 el->boxid = strtoul(value1, NULL, 0);
1608 break;
1609 case IMAGE_CFG_FLASH_ID:
1610 el->flashid = strtoul(value1, NULL, 0);
1611 break;
1612 case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1613 el->sec_specialized_img = true;
1614 break;
1615 case IMAGE_CFG_SEC_COMMON_IMG:
1616 el->sec_specialized_img = false;
1617 break;
1618 case IMAGE_CFG_SEC_BOOT_DEV:
1619 el->sec_boot_dev = strtoul(value1, NULL, 0);
1620 break;
1621 case IMAGE_CFG_SEC_FUSE_DUMP:
1622 el->name = strdup(value1);
1623 break;
Mario Six4991b4f2017-01-11 16:00:59 +01001624 default:
1625 fprintf(stderr, unknown_msg, line);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001626 }
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301627
1628 return 0;
1629}
1630
Stefan Roese4acd2d22014-10-22 12:13:23 +02001631/*
1632 * Parse the configuration file 'fcfg' into the array of configuration
1633 * elements 'image_cfg', and return the number of configuration
1634 * elements in 'cfgn'.
1635 */
1636static int image_create_config_parse(FILE *fcfg)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301637{
Stefan Roese4acd2d22014-10-22 12:13:23 +02001638 int ret;
1639 int cfgi = 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301640
Stefan Roese4acd2d22014-10-22 12:13:23 +02001641 /* Parse the configuration file */
1642 while (!feof(fcfg)) {
1643 char *line;
1644 char buf[256];
1645
1646 /* Read the current line */
1647 memset(buf, 0, sizeof(buf));
1648 line = fgets(buf, sizeof(buf), fcfg);
1649 if (!line)
1650 break;
1651
1652 /* Ignore useless lines */
1653 if (line[0] == '\n' || line[0] == '#')
1654 continue;
1655
1656 /* Strip final newline */
1657 if (line[strlen(line) - 1] == '\n')
1658 line[strlen(line) - 1] = 0;
1659
1660 /* Parse the current line */
1661 ret = image_create_config_parse_oneline(line,
1662 &image_cfg[cfgi]);
1663 if (ret)
1664 return ret;
1665
1666 cfgi++;
1667
1668 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1669 fprintf(stderr,
1670 "Too many configuration elements in .cfg file\n");
1671 return -1;
1672 }
1673 }
1674
1675 cfgn = cfgi;
1676 return 0;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301677}
1678
Stefan Roese4acd2d22014-10-22 12:13:23 +02001679static int image_get_version(void)
1680{
1681 struct image_cfg_element *e;
1682
1683 e = image_find_option(IMAGE_CFG_VERSION);
1684 if (!e)
1685 return -1;
1686
1687 return e->version;
1688}
1689
Stefan Roese4acd2d22014-10-22 12:13:23 +02001690static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
1691 struct image_tool_params *params)
1692{
1693 FILE *fcfg;
1694 void *image = NULL;
1695 int version;
Łukasz Majewski93e93712014-11-21 09:22:43 +01001696 size_t headersz = 0;
Pali Roháre23ad5d2021-11-08 18:12:47 +01001697 size_t datasz;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001698 uint32_t checksum;
Pali Roháre23ad5d2021-11-08 18:12:47 +01001699 struct stat s;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001700 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001701
Pali Roháre23ad5d2021-11-08 18:12:47 +01001702 /*
1703 * Do not use sbuf->st_size as it contains size with padding.
1704 * We need original image data size, so stat original file.
1705 */
1706 if (stat(params->datafile, &s)) {
1707 fprintf(stderr, "Could not stat data file %s: %s\n",
1708 params->datafile, strerror(errno));
1709 exit(EXIT_FAILURE);
1710 }
1711 datasz = ALIGN(s.st_size, 4);
1712
Stefan Roese4acd2d22014-10-22 12:13:23 +02001713 fcfg = fopen(params->imagename, "r");
1714 if (!fcfg) {
1715 fprintf(stderr, "Could not open input file %s\n",
1716 params->imagename);
1717 exit(EXIT_FAILURE);
1718 }
1719
1720 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1721 sizeof(struct image_cfg_element));
1722 if (!image_cfg) {
1723 fprintf(stderr, "Cannot allocate memory\n");
1724 fclose(fcfg);
1725 exit(EXIT_FAILURE);
1726 }
1727
1728 memset(image_cfg, 0,
1729 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1730 rewind(fcfg);
1731
1732 ret = image_create_config_parse(fcfg);
1733 fclose(fcfg);
1734 if (ret) {
1735 free(image_cfg);
1736 exit(EXIT_FAILURE);
1737 }
1738
1739 version = image_get_version();
Stefan Roese934a5292014-10-28 11:32:24 +01001740 switch (version) {
1741 /*
1742 * Fallback to version 0 if no version is provided in the
1743 * cfg file
1744 */
1745 case -1:
1746 case 0:
Pali Roháre23ad5d2021-11-08 18:12:47 +01001747 image = image_create_v0(&headersz, params, datasz + 4);
Stefan Roese934a5292014-10-28 11:32:24 +01001748 break;
1749
1750 case 1:
Pali Roháre23ad5d2021-11-08 18:12:47 +01001751 image = image_create_v1(&headersz, params, ptr, datasz + 4);
Stefan Roese934a5292014-10-28 11:32:24 +01001752 break;
1753
1754 default:
1755 fprintf(stderr, "Unsupported version %d\n", version);
1756 free(image_cfg);
1757 exit(EXIT_FAILURE);
1758 }
Stefan Roese4acd2d22014-10-22 12:13:23 +02001759
1760 if (!image) {
1761 fprintf(stderr, "Could not create image\n");
1762 free(image_cfg);
1763 exit(EXIT_FAILURE);
1764 }
1765
1766 free(image_cfg);
1767
Pali Roháre23ad5d2021-11-08 18:12:47 +01001768 /* Build and add image data checksum */
Pali Rohár37cb9c12021-07-23 11:13:56 +02001769 checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + headersz,
Pali Roháre23ad5d2021-11-08 18:12:47 +01001770 datasz));
1771 memcpy((uint8_t *)ptr + headersz + datasz, &checksum, sizeof(uint32_t));
Stefan Roese4acd2d22014-10-22 12:13:23 +02001772
1773 /* Finally copy the header into the image area */
1774 memcpy(ptr, image, headersz);
1775
1776 free(image);
1777}
1778
1779static void kwbimage_print_header(const void *ptr)
1780{
1781 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Marek Behún732c9302021-08-18 00:59:15 +02001782 struct opt_hdr_v1 *ohdr;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001783
1784 printf("Image Type: MVEBU Boot from %s Image\n",
1785 image_boot_mode_name(mhdr->blockid));
Marek Behúnacb0b382021-09-24 23:07:00 +02001786 printf("Image version:%d\n", kwbimage_version(ptr));
Pali Rohár34dcf952021-07-23 11:14:04 +02001787
Marek Behún732c9302021-08-18 00:59:15 +02001788 for_each_opt_hdr_v1 (ohdr, mhdr) {
1789 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
1790 printf("BIN Hdr Size: ");
1791 genimg_print_size(opt_hdr_v1_size(ohdr) - 12 -
1792 4 * ohdr->data[0]);
Pali Rohár34dcf952021-07-23 11:14:04 +02001793 }
1794 }
Marek Behún732c9302021-08-18 00:59:15 +02001795
Gerald Kerma26f195c2014-10-31 01:03:27 +01001796 printf("Data Size: ");
Stefan Roese4acd2d22014-10-22 12:13:23 +02001797 genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
1798 printf("Load Address: %08x\n", mhdr->destaddr);
1799 printf("Entry Point: %08x\n", mhdr->execaddr);
1800}
1801
1802static int kwbimage_check_image_types(uint8_t type)
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301803{
1804 if (type == IH_TYPE_KWBIMAGE)
1805 return EXIT_SUCCESS;
Mario Six94490a42017-01-11 16:00:54 +01001806
1807 return EXIT_FAILURE;
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05301808}
1809
Stefan Roese4acd2d22014-10-22 12:13:23 +02001810static int kwbimage_verify_header(unsigned char *ptr, int image_size,
1811 struct image_tool_params *params)
1812{
Marek Behúnfe2fd732021-09-24 23:07:01 +02001813 size_t header_size = kwbheader_size(ptr);
Pali Rohár700ea982021-11-08 18:12:44 +01001814 uint8_t blockid;
1815 uint32_t offset;
1816 uint32_t size;
Marek Behúnfe2fd732021-09-24 23:07:01 +02001817 uint8_t csum;
Alexander Graf6cd56782018-03-15 11:14:19 +01001818
1819 if (header_size > image_size)
1820 return -FDT_ERR_BADSTRUCTURE;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001821
Baruch Siachdb7cd4ed2017-07-04 20:23:40 +03001822 if (!main_hdr_checksum_ok(ptr))
Stefan Roese4acd2d22014-10-22 12:13:23 +02001823 return -FDT_ERR_BADSTRUCTURE;
1824
1825 /* Only version 0 extended header has checksum */
Marek Behúnacb0b382021-09-24 23:07:00 +02001826 if (kwbimage_version(ptr) == 0) {
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001827 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Mario Sixe89016c2017-01-11 16:00:56 +01001828
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001829 if (mhdr->ext & 0x1) {
Marek Behúnfe2fd732021-09-24 23:07:01 +02001830 struct ext_hdr_v0 *ext_hdr = (void *)(mhdr + 1);
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001831
Marek Behúnfe2fd732021-09-24 23:07:01 +02001832 csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1);
1833 if (csum != ext_hdr->checksum)
Pali Rohárfe2c0e22021-07-23 11:14:01 +02001834 return -FDT_ERR_BADSTRUCTURE;
1835 }
Pali Rohár700ea982021-11-08 18:12:44 +01001836
1837 blockid = mhdr->blockid;
1838 offset = le32_to_cpu(mhdr->srcaddr);
1839 size = le32_to_cpu(mhdr->blocksize);
Marek Behúnacb0b382021-09-24 23:07:00 +02001840 } else if (kwbimage_version(ptr) == 1) {
Pali Rohár93804452021-07-23 11:14:02 +02001841 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Marek Behún732c9302021-08-18 00:59:15 +02001842 const uint8_t *mhdr_end;
1843 struct opt_hdr_v1 *ohdr;
Pali Rohár93804452021-07-23 11:14:02 +02001844
Marek Behún732c9302021-08-18 00:59:15 +02001845 mhdr_end = (uint8_t *)mhdr + header_size;
1846 for_each_opt_hdr_v1 (ohdr, ptr)
1847 if (!opt_hdr_v1_valid_size(ohdr, mhdr_end))
1848 return -FDT_ERR_BADSTRUCTURE;
Pali Roháre0c243c2021-07-23 11:14:03 +02001849
Pali Rohár700ea982021-11-08 18:12:44 +01001850 blockid = mhdr->blockid;
Pali Roháre0c243c2021-07-23 11:14:03 +02001851 offset = le32_to_cpu(mhdr->srcaddr);
Pali Roháre0c243c2021-07-23 11:14:03 +02001852 size = le32_to_cpu(mhdr->blocksize);
Pali Rohárb9840562021-08-11 10:14:14 +02001853 } else {
1854 return -FDT_ERR_BADSTRUCTURE;
Pali Rohár93804452021-07-23 11:14:02 +02001855 }
1856
Pali Rohár700ea982021-11-08 18:12:44 +01001857 /*
1858 * For SATA srcaddr is specified in number of sectors.
1859 * The main header is must be stored at sector number 1.
1860 * This expects that sector size is 512 bytes and recalculates
1861 * data offset to bytes relative to the main header.
1862 */
1863 if (blockid == IBR_HDR_SATA_ID) {
1864 if (offset < 1)
1865 return -FDT_ERR_BADSTRUCTURE;
1866 offset -= 1;
1867 offset *= 512;
1868 }
1869
1870 /*
1871 * For SDIO srcaddr is specified in number of sectors.
1872 * This expects that sector size is 512 bytes and recalculates
1873 * data offset to bytes.
1874 */
1875 if (blockid == IBR_HDR_SDIO_ID)
1876 offset *= 512;
1877
1878 /*
1879 * For PCIe srcaddr is always set to 0xFFFFFFFF.
1880 * This expects that data starts after all headers.
1881 */
1882 if (blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
1883 offset = header_size;
1884
1885 if (offset > image_size || offset % 4 != 0)
1886 return -FDT_ERR_BADSTRUCTURE;
1887
1888 if (size < 4 || offset + size > image_size || size % 4 != 0)
1889 return -FDT_ERR_BADSTRUCTURE;
1890
1891 if (image_checksum32(ptr + offset, size - 4) !=
1892 *(uint32_t *)(ptr + offset + size - 4))
1893 return -FDT_ERR_BADSTRUCTURE;
1894
Stefan Roese4acd2d22014-10-22 12:13:23 +02001895 return 0;
1896}
1897
1898static int kwbimage_generate(struct image_tool_params *params,
1899 struct image_type_params *tparams)
1900{
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001901 FILE *fcfg;
Pali Rohár37cb9c12021-07-23 11:13:56 +02001902 struct stat s;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001903 int alloc_len;
Pali Rohárc934aad2021-07-23 11:13:57 +02001904 int bootfrom;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001905 int version;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001906 void *hdr;
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001907 int ret;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001908
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001909 fcfg = fopen(params->imagename, "r");
1910 if (!fcfg) {
1911 fprintf(stderr, "Could not open input file %s\n",
1912 params->imagename);
1913 exit(EXIT_FAILURE);
1914 }
1915
Pali Rohár37cb9c12021-07-23 11:13:56 +02001916 if (stat(params->datafile, &s)) {
1917 fprintf(stderr, "Could not stat data file %s: %s\n",
1918 params->datafile, strerror(errno));
1919 exit(EXIT_FAILURE);
1920 }
1921
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001922 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1923 sizeof(struct image_cfg_element));
1924 if (!image_cfg) {
1925 fprintf(stderr, "Cannot allocate memory\n");
1926 fclose(fcfg);
1927 exit(EXIT_FAILURE);
1928 }
1929
1930 memset(image_cfg, 0,
1931 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1932 rewind(fcfg);
1933
1934 ret = image_create_config_parse(fcfg);
1935 fclose(fcfg);
1936 if (ret) {
1937 free(image_cfg);
1938 exit(EXIT_FAILURE);
1939 }
1940
Pali Rohárc934aad2021-07-23 11:13:57 +02001941 bootfrom = image_get_bootfrom();
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001942 version = image_get_version();
1943 switch (version) {
1944 /*
1945 * Fallback to version 0 if no version is provided in the
1946 * cfg file
1947 */
1948 case -1:
1949 case 0:
Pali Rohár851114b2021-11-08 18:12:50 +01001950 alloc_len = image_headersz_v0(NULL);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001951 break;
1952
1953 case 1:
Mario Sixe93cf532017-01-11 16:00:57 +01001954 alloc_len = image_headersz_v1(NULL);
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001955 break;
1956
1957 default:
1958 fprintf(stderr, "Unsupported version %d\n", version);
1959 free(image_cfg);
1960 exit(EXIT_FAILURE);
Stefan Roese4acd2d22014-10-22 12:13:23 +02001961 }
1962
Patrick Wildt6cbf7ed2017-05-10 22:18:54 +02001963 free(image_cfg);
1964
Stefan Roese4acd2d22014-10-22 12:13:23 +02001965 hdr = malloc(alloc_len);
1966 if (!hdr) {
1967 fprintf(stderr, "%s: malloc return failure: %s\n",
1968 params->cmdname, strerror(errno));
1969 exit(EXIT_FAILURE);
1970 }
1971
1972 memset(hdr, 0, alloc_len);
1973 tparams->header_size = alloc_len;
1974 tparams->hdr = hdr;
1975
Stefan Roese77720852015-11-24 09:14:59 +01001976 /*
1977 * The resulting image needs to be 4-byte aligned. At least
1978 * the Marvell hdrparser tool complains if its unaligned.
Pali Rohár37cb9c12021-07-23 11:13:56 +02001979 * After the image data is stored 4-byte checksum.
Pali Rohár188099e2021-11-08 18:12:46 +01001980 * Final UART image must be aligned to 128 bytes.
Pali Rohárc934aad2021-07-23 11:13:57 +02001981 * Final SPI and NAND images must be aligned to 256 bytes.
Pali Rohár501a54a2021-07-23 11:13:59 +02001982 * Final SATA and SDIO images must be aligned to 512 bytes.
Stefan Roese77720852015-11-24 09:14:59 +01001983 */
Pali Rohárc934aad2021-07-23 11:13:57 +02001984 if (bootfrom == IBR_HDR_SPI_ID || bootfrom == IBR_HDR_NAND_ID)
1985 return 4 + (256 - (alloc_len + s.st_size + 4) % 256) % 256;
Pali Rohár501a54a2021-07-23 11:13:59 +02001986 else if (bootfrom == IBR_HDR_SATA_ID || bootfrom == IBR_HDR_SDIO_ID)
1987 return 4 + (512 - (alloc_len + s.st_size + 4) % 512) % 512;
Pali Rohár188099e2021-11-08 18:12:46 +01001988 else if (bootfrom == IBR_HDR_UART_ID)
1989 return 4 + (128 - (alloc_len + s.st_size + 4) % 128) % 128;
Pali Rohárc934aad2021-07-23 11:13:57 +02001990 else
1991 return 4 + (4 - s.st_size % 4) % 4;
Stefan Roese4acd2d22014-10-22 12:13:23 +02001992}
1993
Pali Roháraa6943c2021-07-23 11:14:34 +02001994static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params)
1995{
1996 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Marek Behúnfe2fd732021-09-24 23:07:01 +02001997 size_t header_size = kwbheader_size(ptr);
Marek Behún732c9302021-08-18 00:59:15 +02001998 struct opt_hdr_v1 *ohdr;
Pali Roháraa6943c2021-07-23 11:14:34 +02001999 int idx = params->pflag;
2000 int cur_idx = 0;
2001 uint32_t offset;
2002 ulong image;
2003 ulong size;
2004
Marek Behún732c9302021-08-18 00:59:15 +02002005 for_each_opt_hdr_v1 (ohdr, ptr) {
2006 if (ohdr->headertype != OPT_HDR_V1_BINARY_TYPE)
2007 continue;
Pali Roháraa6943c2021-07-23 11:14:34 +02002008
Marek Behún732c9302021-08-18 00:59:15 +02002009 if (idx == cur_idx) {
2010 image = (ulong)&ohdr->data[4 + 4 * ohdr->data[0]];
2011 size = opt_hdr_v1_size(ohdr) - 12 - 4 * ohdr->data[0];
2012 goto extract;
Pali Roháraa6943c2021-07-23 11:14:34 +02002013 }
Marek Behún732c9302021-08-18 00:59:15 +02002014
2015 ++cur_idx;
Pali Roháraa6943c2021-07-23 11:14:34 +02002016 }
2017
2018 if (idx != cur_idx) {
2019 printf("Image %d is not present\n", idx);
2020 return -1;
2021 }
2022
2023 offset = le32_to_cpu(mhdr->srcaddr);
2024
2025 if (mhdr->blockid == IBR_HDR_SATA_ID) {
2026 offset -= 1;
2027 offset *= 512;
2028 }
2029
2030 if (mhdr->blockid == IBR_HDR_SDIO_ID)
2031 offset *= 512;
2032
2033 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
2034 offset = header_size;
2035
2036 image = (ulong)((uint8_t *)ptr + offset);
2037 size = le32_to_cpu(mhdr->blocksize) - 4;
2038
2039extract:
2040 return imagetool_save_subimage(params->outfile, image, size);
2041}
2042
Stefan Roese4acd2d22014-10-22 12:13:23 +02002043/*
2044 * Report Error if xflag is set in addition to default
2045 */
2046static int kwbimage_check_params(struct image_tool_params *params)
2047{
Pali Roháraa6943c2021-07-23 11:14:34 +02002048 if (!params->iflag && (!params->imagename || !strlen(params->imagename))) {
Mario Six94490a42017-01-11 16:00:54 +01002049 char *msg = "Configuration file for kwbimage creation omitted";
2050
2051 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
Pali Rohár56087c12021-11-08 18:12:45 +01002052 return 1;
Stefan Roese4acd2d22014-10-22 12:13:23 +02002053 }
2054
2055 return (params->dflag && (params->fflag || params->lflag)) ||
2056 (params->fflag && (params->dflag || params->lflag)) ||
2057 (params->lflag && (params->dflag || params->fflag)) ||
Pali Roháraa6943c2021-07-23 11:14:34 +02002058 (params->xflag);
Stefan Roese4acd2d22014-10-22 12:13:23 +02002059}
2060
Prafulla Wadaskaraa0c7a82009-09-07 15:05:02 +05302061/*
2062 * kwbimage type parameters definition
2063 */
Guilherme Maciel Ferreiraa93648d2015-01-15 02:48:07 -02002064U_BOOT_IMAGE_TYPE(
2065 kwbimage,
2066 "Marvell MVEBU Boot Image support",
2067 0,
2068 NULL,
2069 kwbimage_check_params,
2070 kwbimage_verify_header,
2071 kwbimage_print_header,
2072 kwbimage_set_header,
Pali Roháraa6943c2021-07-23 11:14:34 +02002073 kwbimage_extract_subimage,
Guilherme Maciel Ferreiraa93648d2015-01-15 02:48:07 -02002074 kwbimage_check_image_types,
2075 NULL,
2076 kwbimage_generate
2077);