blob: d1cbced28fc3c11b2e64bbc2e6de0d9f6a955259 [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
Pali Rohárbeddea82021-09-24 23:07:02 +02004 * supports Kirkwood, Dove, Armada 370, Armada XP, Armada 375, Armada 38x and
5 * Armada 39x
Stefan Roese3b8b19d2014-10-22 12:13:23 +02006 *
7 * (C) Copyright 2013 Thomas Petazzoni
8 * <thomas.petazzoni@free-electrons.com>
Pali Rohárbc7bf642022-02-17 10:43:40 +01009 *
10 * (C) Copyright 2022 Pali Rohár <pali@kernel.org>
Prafulla Wadaskar07329412009-09-07 15:05:02 +053011 */
12
Heinrich Schuchardt43ee8012021-12-18 11:25:12 +010013#define OPENSSL_API_COMPAT 0x10101000L
14
Guilherme Maciel Ferreira8ed4d1c2013-12-01 12:43:10 -070015#include "imagetool.h"
Andreas Bießmann7abec5b2014-10-24 23:39:11 +020016#include <limits.h>
Prafulla Wadaskar07329412009-09-07 15:05:02 +053017#include <image.h>
Mario Six10d14492017-01-11 16:01:00 +010018#include <stdarg.h>
Stefan Roese3b8b19d2014-10-22 12:13:23 +020019#include <stdint.h>
Prafulla Wadaskar07329412009-09-07 15:05:02 +053020#include "kwbimage.h"
21
Jelle van der Waae0e55592017-05-08 21:31:20 +020022#include <openssl/bn.h>
Mario Six10d14492017-01-11 16:01:00 +010023#include <openssl/rsa.h>
24#include <openssl/pem.h>
25#include <openssl/err.h>
26#include <openssl/evp.h>
Jelle van der Waae0e55592017-05-08 21:31:20 +020027
Jonathan Gray237d0592018-02-21 02:59:01 +110028#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
29 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
Jelle van der Waae0e55592017-05-08 21:31:20 +020030static void RSA_get0_key(const RSA *r,
31 const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
32{
33 if (n != NULL)
34 *n = r->n;
35 if (e != NULL)
36 *e = r->e;
37 if (d != NULL)
38 *d = r->d;
39}
40
Jonathan Gray237d0592018-02-21 02:59:01 +110041#elif !defined(LIBRESSL_VERSION_NUMBER)
Jelle van der Waae0e55592017-05-08 21:31:20 +020042void EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
43{
44 EVP_MD_CTX_reset(ctx);
45}
46#endif
Mario Six10d14492017-01-11 16:01:00 +010047
Pali Roháre581f192022-02-17 10:43:36 +010048/* fls - find last (most-significant) bit set in 4-bit integer */
49static inline int fls4(int num)
50{
51 if (num & 0x8)
52 return 4;
53 else if (num & 0x4)
54 return 3;
55 else if (num & 0x2)
56 return 2;
57 else if (num & 0x1)
58 return 1;
59 else
60 return 0;
61}
62
Stefan Roese3b8b19d2014-10-22 12:13:23 +020063static struct image_cfg_element *image_cfg;
64static int cfgn;
Mario Six10d14492017-01-11 16:01:00 +010065static int verbose_mode;
Stefan Roese3b8b19d2014-10-22 12:13:23 +020066
67struct boot_mode {
68 unsigned int id;
69 const char *name;
70};
71
Mario Six10d14492017-01-11 16:01:00 +010072/*
73 * SHA2-256 hash
74 */
75struct hash_v1 {
76 uint8_t hash[32];
77};
78
Stefan Roese3b8b19d2014-10-22 12:13:23 +020079struct boot_mode boot_modes[] = {
Pali Rohár611a16b2021-08-11 10:14:17 +020080 { IBR_HDR_I2C_ID, "i2c" },
81 { IBR_HDR_SPI_ID, "spi" },
82 { IBR_HDR_NAND_ID, "nand" },
83 { IBR_HDR_SATA_ID, "sata" },
84 { IBR_HDR_PEX_ID, "pex" },
85 { IBR_HDR_UART_ID, "uart" },
86 { IBR_HDR_SDIO_ID, "sdio" },
Stefan Roese3b8b19d2014-10-22 12:13:23 +020087 {},
Prafulla Wadaskar07329412009-09-07 15:05:02 +053088};
89
Stefan Roese3b8b19d2014-10-22 12:13:23 +020090struct nand_ecc_mode {
91 unsigned int id;
92 const char *name;
93};
94
95struct nand_ecc_mode nand_ecc_modes[] = {
Pali Rohár611a16b2021-08-11 10:14:17 +020096 { IBR_HDR_ECC_DEFAULT, "default" },
97 { IBR_HDR_ECC_FORCED_HAMMING, "hamming" },
98 { IBR_HDR_ECC_FORCED_RS, "rs" },
99 { IBR_HDR_ECC_DISABLED, "disabled" },
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200100 {},
101};
102
103/* Used to identify an undefined execution or destination address */
104#define ADDR_INVALID ((uint32_t)-1)
105
Pali Rohár13b70402021-07-23 11:14:07 +0200106#define BINARY_MAX_ARGS 255
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200107
108/* In-memory representation of a line of the configuration file */
Mario Six62da6762017-01-11 16:00:59 +0100109
110enum image_cfg_type {
111 IMAGE_CFG_VERSION = 0x1,
112 IMAGE_CFG_BOOT_FROM,
113 IMAGE_CFG_DEST_ADDR,
114 IMAGE_CFG_EXEC_ADDR,
115 IMAGE_CFG_NAND_BLKSZ,
116 IMAGE_CFG_NAND_BADBLK_LOCATION,
117 IMAGE_CFG_NAND_ECC_MODE,
118 IMAGE_CFG_NAND_PAGESZ,
Pali Rohár15c893782023-03-29 21:25:56 +0200119 IMAGE_CFG_SATA_BLKSZ,
Pali Rohár6b76c1c2022-01-12 18:20:40 +0100120 IMAGE_CFG_CPU,
Mario Six62da6762017-01-11 16:00:59 +0100121 IMAGE_CFG_BINARY,
Mario Six62da6762017-01-11 16:00:59 +0100122 IMAGE_CFG_DATA,
Pali Rohárc0cfd1a2021-07-23 11:14:12 +0200123 IMAGE_CFG_DATA_DELAY,
Mario Six62da6762017-01-11 16:00:59 +0100124 IMAGE_CFG_BAUDRATE,
Pali Rohárd8840942021-11-08 18:12:41 +0100125 IMAGE_CFG_UART_PORT,
126 IMAGE_CFG_UART_MPP,
Mario Six62da6762017-01-11 16:00:59 +0100127 IMAGE_CFG_DEBUG,
Mario Six10d14492017-01-11 16:01:00 +0100128 IMAGE_CFG_KAK,
129 IMAGE_CFG_CSK,
130 IMAGE_CFG_CSK_INDEX,
131 IMAGE_CFG_JTAG_DELAY,
132 IMAGE_CFG_BOX_ID,
133 IMAGE_CFG_FLASH_ID,
134 IMAGE_CFG_SEC_COMMON_IMG,
135 IMAGE_CFG_SEC_SPECIALIZED_IMG,
136 IMAGE_CFG_SEC_BOOT_DEV,
137 IMAGE_CFG_SEC_FUSE_DUMP,
Mario Six62da6762017-01-11 16:00:59 +0100138
139 IMAGE_CFG_COUNT
140} type;
141
142static const char * const id_strs[] = {
143 [IMAGE_CFG_VERSION] = "VERSION",
144 [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
145 [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
146 [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
147 [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
148 [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
149 [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
150 [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
Pali Rohár15c893782023-03-29 21:25:56 +0200151 [IMAGE_CFG_SATA_BLKSZ] = "SATA_BLKSZ",
Pali Rohár6b76c1c2022-01-12 18:20:40 +0100152 [IMAGE_CFG_CPU] = "CPU",
Mario Six62da6762017-01-11 16:00:59 +0100153 [IMAGE_CFG_BINARY] = "BINARY",
Mario Six62da6762017-01-11 16:00:59 +0100154 [IMAGE_CFG_DATA] = "DATA",
Pali Rohárc0cfd1a2021-07-23 11:14:12 +0200155 [IMAGE_CFG_DATA_DELAY] = "DATA_DELAY",
Mario Six62da6762017-01-11 16:00:59 +0100156 [IMAGE_CFG_BAUDRATE] = "BAUDRATE",
Pali Rohárd8840942021-11-08 18:12:41 +0100157 [IMAGE_CFG_UART_PORT] = "UART_PORT",
158 [IMAGE_CFG_UART_MPP] = "UART_MPP",
Mario Six62da6762017-01-11 16:00:59 +0100159 [IMAGE_CFG_DEBUG] = "DEBUG",
Mario Six10d14492017-01-11 16:01:00 +0100160 [IMAGE_CFG_KAK] = "KAK",
161 [IMAGE_CFG_CSK] = "CSK",
162 [IMAGE_CFG_CSK_INDEX] = "CSK_INDEX",
163 [IMAGE_CFG_JTAG_DELAY] = "JTAG_DELAY",
164 [IMAGE_CFG_BOX_ID] = "BOX_ID",
165 [IMAGE_CFG_FLASH_ID] = "FLASH_ID",
166 [IMAGE_CFG_SEC_COMMON_IMG] = "SEC_COMMON_IMG",
167 [IMAGE_CFG_SEC_SPECIALIZED_IMG] = "SEC_SPECIALIZED_IMG",
168 [IMAGE_CFG_SEC_BOOT_DEV] = "SEC_BOOT_DEV",
169 [IMAGE_CFG_SEC_FUSE_DUMP] = "SEC_FUSE_DUMP"
Mario Six62da6762017-01-11 16:00:59 +0100170};
171
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200172struct image_cfg_element {
Mario Six62da6762017-01-11 16:00:59 +0100173 enum image_cfg_type type;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200174 union {
175 unsigned int version;
Pali Rohár6b76c1c2022-01-12 18:20:40 +0100176 unsigned int cpu_sheeva;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200177 unsigned int bootfrom;
178 struct {
179 const char *file;
Pali Rohárfc719962022-01-12 18:20:41 +0100180 unsigned int loadaddr;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200181 unsigned int args[BINARY_MAX_ARGS];
182 unsigned int nargs;
183 } binary;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200184 unsigned int dstaddr;
185 unsigned int execaddr;
186 unsigned int nandblksz;
187 unsigned int nandbadblklocation;
188 unsigned int nandeccmode;
189 unsigned int nandpagesz;
Pali Rohár15c893782023-03-29 21:25:56 +0200190 unsigned int satablksz;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200191 struct ext_hdr_v0_reg regdata;
Pali Rohárc0cfd1a2021-07-23 11:14:12 +0200192 unsigned int regdata_delay;
Chris Packham883bf452016-11-09 22:07:45 +1300193 unsigned int baudrate;
Pali Rohárd8840942021-11-08 18:12:41 +0100194 unsigned int uart_port;
195 unsigned int uart_mpp;
Chris Packham1e0728a2016-11-09 22:21:45 +1300196 unsigned int debug;
Mario Six10d14492017-01-11 16:01:00 +0100197 const char *key_name;
198 int csk_idx;
199 uint8_t jtag_delay;
200 uint32_t boxid;
201 uint32_t flashid;
202 bool sec_specialized_img;
203 unsigned int sec_boot_dev;
204 const char *name;
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200205 };
206};
207
208#define IMAGE_CFG_ELEMENT_MAX 256
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530209
210/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200211 * Utility functions to manipulate boot mode and ecc modes (convert
212 * them back and forth between description strings and the
213 * corresponding numerical identifiers).
214 */
215
216static const char *image_boot_mode_name(unsigned int id)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530217{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200218 int i;
Mario Sixd6009d72017-01-11 16:00:54 +0100219
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200220 for (i = 0; boot_modes[i].name; i++)
221 if (boot_modes[i].id == id)
222 return boot_modes[i].name;
223 return NULL;
224}
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530225
Pali Rohár31376142022-01-12 18:20:35 +0100226static int image_boot_mode_id(const char *boot_mode_name)
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200227{
228 int i;
Mario Sixd6009d72017-01-11 16:00:54 +0100229
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200230 for (i = 0; boot_modes[i].name; i++)
231 if (!strcmp(boot_modes[i].name, boot_mode_name))
232 return boot_modes[i].id;
233
234 return -1;
235}
236
Pali Rohár3d015782022-01-12 18:20:50 +0100237static const char *image_nand_ecc_mode_name(unsigned int id)
238{
239 int i;
240
241 for (i = 0; nand_ecc_modes[i].name; i++)
242 if (nand_ecc_modes[i].id == id)
243 return nand_ecc_modes[i].name;
244
245 return NULL;
246}
247
Pali Rohár31376142022-01-12 18:20:35 +0100248static int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200249{
250 int i;
Mario Sixd6009d72017-01-11 16:00:54 +0100251
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200252 for (i = 0; nand_ecc_modes[i].name; i++)
253 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
254 return nand_ecc_modes[i].id;
255 return -1;
256}
257
258static struct image_cfg_element *
259image_find_option(unsigned int optiontype)
260{
261 int i;
262
263 for (i = 0; i < cfgn; i++) {
264 if (image_cfg[i].type == optiontype)
265 return &image_cfg[i];
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530266 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200267
268 return NULL;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530269}
270
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200271static unsigned int
272image_count_options(unsigned int optiontype)
273{
274 int i;
275 unsigned int count = 0;
276
277 for (i = 0; i < cfgn; i++)
278 if (image_cfg[i].type == optiontype)
279 count++;
280
281 return count;
282}
283
Mario Six10d14492017-01-11 16:01:00 +0100284static int image_get_csk_index(void)
285{
286 struct image_cfg_element *e;
287
288 e = image_find_option(IMAGE_CFG_CSK_INDEX);
289 if (!e)
290 return -1;
291
292 return e->csk_idx;
293}
294
295static bool image_get_spezialized_img(void)
296{
297 struct image_cfg_element *e;
298
299 e = image_find_option(IMAGE_CFG_SEC_SPECIALIZED_IMG);
300 if (!e)
301 return false;
302
303 return e->sec_specialized_img;
304}
305
Pali Rohár1e2d7fb2021-11-08 18:12:43 +0100306static int image_get_bootfrom(void)
307{
308 struct image_cfg_element *e;
309
310 e = image_find_option(IMAGE_CFG_BOOT_FROM);
311 if (!e)
312 /* fallback to SPI if no BOOT_FROM is not provided */
313 return IBR_HDR_SPI_ID;
314
315 return e->bootfrom;
316}
317
Pali Rohár6b76c1c2022-01-12 18:20:40 +0100318static int image_is_cpu_sheeva(void)
319{
320 struct image_cfg_element *e;
321
322 e = image_find_option(IMAGE_CFG_CPU);
323 if (!e)
324 return 0;
325
326 return e->cpu_sheeva;
327}
328
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530329/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200330 * Compute a 8-bit checksum of a memory area. This algorithm follows
331 * the requirements of the Marvell SoC BootROM specifications.
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530332 */
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200333static uint8_t image_checksum8(void *start, uint32_t len)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530334{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200335 uint8_t csum = 0;
336 uint8_t *p = start;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530337
338 /* check len and return zero checksum if invalid */
339 if (!len)
340 return 0;
341
342 do {
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200343 csum += *p;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530344 p++;
345 } while (--len);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200346
347 return csum;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530348}
349
Baruch Siach4a5b99b2017-07-04 20:23:40 +0300350/*
351 * Verify checksum over a complete header that includes the checksum field.
352 * Return 1 when OK, otherwise 0.
353 */
354static int main_hdr_checksum_ok(void *hdr)
355{
356 /* Offsets of checksum in v0 and v1 headers are the same */
357 struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
358 uint8_t checksum;
359
Marek Behúnd1b0b032021-09-24 23:07:01 +0200360 checksum = image_checksum8(hdr, kwbheader_size_for_csum(hdr));
Baruch Siach4a5b99b2017-07-04 20:23:40 +0300361 /* Calculated checksum includes the header checksum field. Compensate
362 * for that.
363 */
364 checksum -= main_hdr->checksum;
365
366 return checksum == main_hdr->checksum;
367}
368
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200369static uint32_t image_checksum32(void *start, uint32_t len)
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530370{
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200371 uint32_t csum = 0;
372 uint32_t *p = start;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530373
374 /* check len and return zero checksum if invalid */
375 if (!len)
376 return 0;
377
378 if (len % sizeof(uint32_t)) {
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200379 fprintf(stderr, "Length %d is not in multiple of %zu\n",
380 len, sizeof(uint32_t));
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530381 return 0;
382 }
383
384 do {
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200385 csum += *p;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530386 p++;
387 len -= sizeof(uint32_t);
388 } while (len > 0);
Stefan Roese3b8b19d2014-10-22 12:13:23 +0200389
390 return csum;
Prafulla Wadaskar07329412009-09-07 15:05:02 +0530391}
392
Pali Rohár3d015782022-01-12 18:20:50 +0100393static unsigned int options_to_baudrate(uint8_t options)
394{
395 switch (options & 0x7) {
396 case MAIN_HDR_V1_OPT_BAUD_2400:
397 return 2400;
398 case MAIN_HDR_V1_OPT_BAUD_4800:
399 return 4800;
400 case MAIN_HDR_V1_OPT_BAUD_9600:
401 return 9600;
402 case MAIN_HDR_V1_OPT_BAUD_19200:
403 return 19200;
404 case MAIN_HDR_V1_OPT_BAUD_38400:
405 return 38400;
406 case MAIN_HDR_V1_OPT_BAUD_57600:
407 return 57600;
408 case MAIN_HDR_V1_OPT_BAUD_115200:
409 return 115200;
410 case MAIN_HDR_V1_OPT_BAUD_DEFAULT:
411 default:
412 return 0;
413 }
414}
415
Chris Packham883bf452016-11-09 22:07:45 +1300416static uint8_t baudrate_to_option(unsigned int baudrate)
417{
418 switch (baudrate) {
419 case 2400:
420 return MAIN_HDR_V1_OPT_BAUD_2400;
421 case 4800:
422 return MAIN_HDR_V1_OPT_BAUD_4800;
423 case 9600:
424 return MAIN_HDR_V1_OPT_BAUD_9600;
425 case 19200:
426 return MAIN_HDR_V1_OPT_BAUD_19200;
427 case 38400:
428 return MAIN_HDR_V1_OPT_BAUD_38400;
429 case 57600:
430 return MAIN_HDR_V1_OPT_BAUD_57600;
431 case 115200:
432 return MAIN_HDR_V1_OPT_BAUD_115200;
433 default:
434 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
435 }
436}
437
Mario Six10d14492017-01-11 16:01:00 +0100438static void kwb_msg(const char *fmt, ...)
439{
440 if (verbose_mode) {
441 va_list ap;
442
443 va_start(ap, fmt);
444 vfprintf(stdout, fmt, ap);
445 va_end(ap);
446 }
447}
448
449static int openssl_err(const char *msg)
450{
451 unsigned long ssl_err = ERR_get_error();
452
453 fprintf(stderr, "%s", msg);
454 fprintf(stderr, ": %s\n",
455 ERR_error_string(ssl_err, 0));
456
457 return -1;
458}
459
460static int kwb_load_rsa_key(const char *keydir, const char *name, RSA **p_rsa)
461{
462 char path[PATH_MAX];
463 RSA *rsa;
464 FILE *f;
465
466 if (!keydir)
467 keydir = ".";
468
469 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
470 f = fopen(path, "r");
471 if (!f) {
472 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
473 path, strerror(errno));
474 return -ENOENT;
475 }
476
477 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, "");
478 if (!rsa) {
479 openssl_err("Failure reading private key");
480 fclose(f);
481 return -EPROTO;
482 }
483 fclose(f);
484 *p_rsa = rsa;
485
486 return 0;
487}
488
489static int kwb_load_cfg_key(struct image_tool_params *params,
490 unsigned int cfg_option, const char *key_name,
491 RSA **p_key)
492{
493 struct image_cfg_element *e_key;
494 RSA *key;
495 int res;
496
497 *p_key = NULL;
498
499 e_key = image_find_option(cfg_option);
500 if (!e_key) {
501 fprintf(stderr, "%s not configured\n", key_name);
502 return -ENOENT;
503 }
504
505 res = kwb_load_rsa_key(params->keydir, e_key->key_name, &key);
506 if (res < 0) {
507 fprintf(stderr, "Failed to load %s\n", key_name);
508 return -ENOENT;
509 }
510
511 *p_key = key;
512
513 return 0;
514}
515
516static int kwb_load_kak(struct image_tool_params *params, RSA **p_kak)
517{
518 return kwb_load_cfg_key(params, IMAGE_CFG_KAK, "KAK", p_kak);
519}
520
521static int kwb_load_csk(struct image_tool_params *params, RSA **p_csk)
522{
523 return kwb_load_cfg_key(params, IMAGE_CFG_CSK, "CSK", p_csk);
524}
525
526static int kwb_compute_pubkey_hash(struct pubkey_der_v1 *pk,
527 struct hash_v1 *hash)
528{
529 EVP_MD_CTX *ctx;
530 unsigned int key_size;
531 unsigned int hash_size;
532 int ret = 0;
533
534 if (!pk || !hash || pk->key[0] != 0x30 || pk->key[1] != 0x82)
535 return -EINVAL;
536
537 key_size = (pk->key[2] << 8) + pk->key[3] + 4;
538
539 ctx = EVP_MD_CTX_create();
540 if (!ctx)
541 return openssl_err("EVP context creation failed");
542
543 EVP_MD_CTX_init(ctx);
544 if (!EVP_DigestInit(ctx, EVP_sha256())) {
545 ret = openssl_err("Digest setup failed");
546 goto hash_err_ctx;
547 }
548
549 if (!EVP_DigestUpdate(ctx, pk->key, key_size)) {
550 ret = openssl_err("Hashing data failed");
551 goto hash_err_ctx;
552 }
553
554 if (!EVP_DigestFinal(ctx, hash->hash, &hash_size)) {
555 ret = openssl_err("Could not obtain hash");
556 goto hash_err_ctx;
557 }
558
559 EVP_MD_CTX_cleanup(ctx);
560
561hash_err_ctx:
562 EVP_MD_CTX_destroy(ctx);
563 return ret;
564}
565
566static int kwb_import_pubkey(RSA **key, struct pubkey_der_v1 *src, char *keyname)
567{
568 RSA *rsa;
569 const unsigned char *ptr;
570
571 if (!key || !src)
572 goto fail;
573
574 ptr = src->key;
575 rsa = d2i_RSAPublicKey(key, &ptr, sizeof(src->key));
576 if (!rsa) {
577 openssl_err("error decoding public key");
578 goto fail;
579 }
580
581 return 0;
582fail:
583 fprintf(stderr, "Failed to decode %s pubkey\n", keyname);
584 return -EINVAL;
585}
586
587static int kwb_export_pubkey(RSA *key, struct pubkey_der_v1 *dst, FILE *hashf,
588 char *keyname)
589{
590 int size_exp, size_mod, size_seq;
Jelle van der Waae0e55592017-05-08 21:31:20 +0200591 const BIGNUM *key_e, *key_n;
Mario Six10d14492017-01-11 16:01:00 +0100592 uint8_t *cur;
593 char *errmsg = "Failed to encode %s\n";
594
Jelle van der Waae0e55592017-05-08 21:31:20 +0200595 RSA_get0_key(key, NULL, &key_e, NULL);
596 RSA_get0_key(key, &key_n, NULL, NULL);
597
598 if (!key || !key_e || !key_n || !dst) {
Mario Six10d14492017-01-11 16:01:00 +0100599 fprintf(stderr, "export pk failed: (%p, %p, %p, %p)",
Jelle van der Waae0e55592017-05-08 21:31:20 +0200600 key, key_e, key_n, dst);
Mario Six10d14492017-01-11 16:01:00 +0100601 fprintf(stderr, errmsg, keyname);
602 return -EINVAL;
603 }
604
605 /*
606 * According to the specs, the key should be PKCS#1 DER encoded.
607 * But unfortunately the really required encoding seems to be different;
608 * it violates DER...! (But it still conformes to BER.)
609 * (Length always in long form w/ 2 byte length code; no leading zero
610 * when MSB of first byte is set...)
611 * So we cannot use the encoding func provided by OpenSSL and have to
612 * do the encoding manually.
613 */
614
Jelle van der Waae0e55592017-05-08 21:31:20 +0200615 size_exp = BN_num_bytes(key_e);
616 size_mod = BN_num_bytes(key_n);
Mario Six10d14492017-01-11 16:01:00 +0100617 size_seq = 4 + size_mod + 4 + size_exp;
618
619 if (size_mod > 256) {
620 fprintf(stderr, "export pk failed: wrong mod size: %d\n",
621 size_mod);
622 fprintf(stderr, errmsg, keyname);
623 return -EINVAL;
624 }
625
626 if (4 + size_seq > sizeof(dst->key)) {
Marek Behúnf7b7f7c2021-09-24 23:06:38 +0200627 fprintf(stderr, "export pk failed: seq too large (%d, %zu)\n",
Mario Six10d14492017-01-11 16:01:00 +0100628 4 + size_seq, sizeof(dst->key));
629 fprintf(stderr, errmsg, keyname);
630 return -ENOBUFS;
631 }
632
633 cur = dst->key;
634
635 /* PKCS#1 (RFC3447) RSAPublicKey structure */
636 *cur++ = 0x30; /* SEQUENCE */
637 *cur++ = 0x82;
638 *cur++ = (size_seq >> 8) & 0xFF;
639 *cur++ = size_seq & 0xFF;
640 /* Modulus */
641 *cur++ = 0x02; /* INTEGER */
642 *cur++ = 0x82;
643 *cur++ = (size_mod >> 8) & 0xFF;
644 *cur++ = size_mod & 0xFF;
Jelle van der Waae0e55592017-05-08 21:31:20 +0200645 BN_bn2bin(key_n, cur);
Mario Six10d14492017-01-11 16:01:00 +0100646 cur += size_mod;
647 /* Exponent */
648 *cur++ = 0x02; /* INTEGER */
649 *cur++ = 0x82;
650 *cur++ = (size_exp >> 8) & 0xFF;
651 *cur++ = size_exp & 0xFF;
Jelle van der Waae0e55592017-05-08 21:31:20 +0200652 BN_bn2bin(key_e, cur);
Mario Six10d14492017-01-11 16:01:00 +0100653
654 if (hashf) {
655 struct hash_v1 pk_hash;
656 int i;
657 int ret = 0;
658
659 ret = kwb_compute_pubkey_hash(dst, &pk_hash);
660 if (ret < 0) {
661 fprintf(stderr, errmsg, keyname);
662 return ret;
663 }
664
665 fprintf(hashf, "SHA256 = ");
666 for (i = 0 ; i < sizeof(pk_hash.hash); ++i)
667 fprintf(hashf, "%02X", pk_hash.hash[i]);
668 fprintf(hashf, "\n");
669 }
670
671 return 0;
672}
673
Pali Rohár31376142022-01-12 18:20:35 +0100674static int kwb_sign(RSA *key, void *data, int datasz, struct sig_v1 *sig,
675 char *signame)
Mario Six10d14492017-01-11 16:01:00 +0100676{
677 EVP_PKEY *evp_key;
678 EVP_MD_CTX *ctx;
679 unsigned int sig_size;
680 int size;
681 int ret = 0;
682
683 evp_key = EVP_PKEY_new();
684 if (!evp_key)
685 return openssl_err("EVP_PKEY object creation failed");
686
687 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
688 ret = openssl_err("EVP key setup failed");
689 goto err_key;
690 }
691
692 size = EVP_PKEY_size(evp_key);
693 if (size > sizeof(sig->sig)) {
694 fprintf(stderr, "Buffer to small for signature (%d bytes)\n",
695 size);
696 ret = -ENOBUFS;
697 goto err_key;
698 }
699
700 ctx = EVP_MD_CTX_create();
701 if (!ctx) {
702 ret = openssl_err("EVP context creation failed");
703 goto err_key;
704 }
705 EVP_MD_CTX_init(ctx);
706 if (!EVP_SignInit(ctx, EVP_sha256())) {
707 ret = openssl_err("Signer setup failed");
708 goto err_ctx;
709 }
710
711 if (!EVP_SignUpdate(ctx, data, datasz)) {
712 ret = openssl_err("Signing data failed");
713 goto err_ctx;
714 }
715
716 if (!EVP_SignFinal(ctx, sig->sig, &sig_size, evp_key)) {
717 ret = openssl_err("Could not obtain signature");
718 goto err_ctx;
719 }
720
721 EVP_MD_CTX_cleanup(ctx);
722 EVP_MD_CTX_destroy(ctx);
723 EVP_PKEY_free(evp_key);
724
725 return 0;
726
727err_ctx:
728 EVP_MD_CTX_destroy(ctx);
729err_key:
730 EVP_PKEY_free(evp_key);
731 fprintf(stderr, "Failed to create %s signature\n", signame);
732 return ret;
733}
734
Pali Rohár31376142022-01-12 18:20:35 +0100735static int kwb_verify(RSA *key, void *data, int datasz, struct sig_v1 *sig,
736 char *signame)
Mario Six10d14492017-01-11 16:01:00 +0100737{
738 EVP_PKEY *evp_key;
739 EVP_MD_CTX *ctx;
740 int size;
741 int ret = 0;
742
743 evp_key = EVP_PKEY_new();
744 if (!evp_key)
745 return openssl_err("EVP_PKEY object creation failed");
746
747 if (!EVP_PKEY_set1_RSA(evp_key, key)) {
748 ret = openssl_err("EVP key setup failed");
749 goto err_key;
750 }
751
752 size = EVP_PKEY_size(evp_key);
753 if (size > sizeof(sig->sig)) {
754 fprintf(stderr, "Invalid signature size (%d bytes)\n",
755 size);
756 ret = -EINVAL;
757 goto err_key;
758 }
759
760 ctx = EVP_MD_CTX_create();
761 if (!ctx) {
762 ret = openssl_err("EVP context creation failed");
763 goto err_key;
764 }
765 EVP_MD_CTX_init(ctx);
766 if (!EVP_VerifyInit(ctx, EVP_sha256())) {
767 ret = openssl_err("Verifier setup failed");
768 goto err_ctx;
769 }
770
771 if (!EVP_VerifyUpdate(ctx, data, datasz)) {
772 ret = openssl_err("Hashing data failed");
773 goto err_ctx;
774 }
775
Young Xiaoda575f52019-04-17 17:20:24 +0800776 if (EVP_VerifyFinal(ctx, sig->sig, sizeof(sig->sig), evp_key) != 1) {
Mario Six10d14492017-01-11 16:01:00 +0100777 ret = openssl_err("Could not verify signature");
778 goto err_ctx;
779 }
780
781 EVP_MD_CTX_cleanup(ctx);
782 EVP_MD_CTX_destroy(ctx);
783 EVP_PKEY_free(evp_key);
784
785 return 0;
786
787err_ctx:
788 EVP_MD_CTX_destroy(ctx);
789err_key:
790 EVP_PKEY_free(evp_key);
791 fprintf(stderr, "Failed to verify %s signature\n", signame);
792 return ret;
793}
794
Pali Rohár31376142022-01-12 18:20:35 +0100795static int kwb_sign_and_verify(RSA *key, void *data, int datasz,
796 struct sig_v1 *sig, char *signame)
Mario Six10d14492017-01-11 16:01:00 +0100797{
798 if (kwb_sign(key, data, datasz, sig, signame) < 0)
799 return -1;
800
801 if (kwb_verify(key, data, datasz, sig, signame) < 0)
802 return -1;
803
804 return 0;
805}
806
Pali Rohár31376142022-01-12 18:20:35 +0100807static int kwb_dump_fuse_cmds_38x(FILE *out, struct secure_hdr_v1 *sec_hdr)
Mario Six10d14492017-01-11 16:01:00 +0100808{
809 struct hash_v1 kak_pub_hash;
810 struct image_cfg_element *e;
811 unsigned int fuse_line;
812 int i, idx;
813 uint8_t *ptr;
814 uint32_t val;
815 int ret = 0;
816
817 if (!out || !sec_hdr)
818 return -EINVAL;
819
820 ret = kwb_compute_pubkey_hash(&sec_hdr->kak, &kak_pub_hash);
821 if (ret < 0)
822 goto done;
823
824 fprintf(out, "# burn KAK pub key hash\n");
825 ptr = kak_pub_hash.hash;
826 for (fuse_line = 26; fuse_line <= 30; ++fuse_line) {
827 fprintf(out, "fuse prog -y %u 0 ", fuse_line);
828
829 for (i = 4; i-- > 0;)
830 fprintf(out, "%02hx", (ushort)ptr[i]);
831 ptr += 4;
832 fprintf(out, " 00");
833
834 if (fuse_line < 30) {
835 for (i = 3; i-- > 0;)
836 fprintf(out, "%02hx", (ushort)ptr[i]);
837 ptr += 3;
838 } else {
839 fprintf(out, "000000");
840 }
841
842 fprintf(out, " 1\n");
843 }
844
845 fprintf(out, "# burn CSK selection\n");
846
847 idx = image_get_csk_index();
848 if (idx < 0 || idx > 15) {
849 ret = -EINVAL;
850 goto done;
851 }
852 if (idx > 0) {
853 for (fuse_line = 31; fuse_line < 31 + idx; ++fuse_line)
854 fprintf(out, "fuse prog -y %u 0 00000001 00000000 1\n",
855 fuse_line);
856 } else {
857 fprintf(out, "# CSK index is 0; no mods needed\n");
858 }
859
860 e = image_find_option(IMAGE_CFG_BOX_ID);
861 if (e) {
862 fprintf(out, "# set box ID\n");
863 fprintf(out, "fuse prog -y 48 0 %08x 00000000 1\n", e->boxid);
864 }
865
866 e = image_find_option(IMAGE_CFG_FLASH_ID);
867 if (e) {
868 fprintf(out, "# set flash ID\n");
869 fprintf(out, "fuse prog -y 47 0 %08x 00000000 1\n", e->flashid);
870 }
871
872 fprintf(out, "# enable secure mode ");
873 fprintf(out, "(must be the last fuse line written)\n");
874
875 val = 1;
876 e = image_find_option(IMAGE_CFG_SEC_BOOT_DEV);
877 if (!e) {
878 fprintf(stderr, "ERROR: secured mode boot device not given\n");
879 ret = -EINVAL;
880 goto done;
881 }
882
883 if (e->sec_boot_dev > 0xff) {
884 fprintf(stderr, "ERROR: secured mode boot device invalid\n");
885 ret = -EINVAL;
886 goto done;
887 }
888
889 val |= (e->sec_boot_dev << 8);
890
891 fprintf(out, "fuse prog -y 24 0 %08x 0103e0a9 1\n", val);
892
893 fprintf(out, "# lock (unused) fuse lines (0-23)s\n");
894 for (fuse_line = 0; fuse_line < 24; ++fuse_line)
895 fprintf(out, "fuse prog -y %u 2 1\n", fuse_line);
896
897 fprintf(out, "# OK, that's all :-)\n");
898
899done:
900 return ret;
901}
902
903static int kwb_dump_fuse_cmds(struct secure_hdr_v1 *sec_hdr)
904{
905 int ret = 0;
906 struct image_cfg_element *e;
907
908 e = image_find_option(IMAGE_CFG_SEC_FUSE_DUMP);
909 if (!e)
910 return 0;
911
912 if (!strcmp(e->name, "a38x")) {
913 FILE *out = fopen("kwb_fuses_a38x.txt", "w+");
914
Heinrich Schuchardt379ec092021-08-17 07:03:20 +0200915 if (!out) {
916 fprintf(stderr, "Couldn't open eFuse settings: '%s': %s\n",
917 "kwb_fuses_a38x.txt", strerror(errno));
918 return -ENOENT;
919 }
920
Mario Six10d14492017-01-11 16:01:00 +0100921 kwb_dump_fuse_cmds_38x(out, sec_hdr);
922 fclose(out);
923 goto done;
924 }
925
926 ret = -ENOSYS;
927
928done:
929 return ret;
930}
931
Pali Rohárc6178dc2023-01-18 21:42:40 +0100932static int image_fill_xip_header(void *image, struct image_tool_params *params)
933{
934 struct main_hdr_v1 *main_hdr = image; /* kwbimage v0 and v1 have same XIP members */
935 int version = kwbimage_version(image);
936 uint32_t srcaddr = le32_to_cpu(main_hdr->srcaddr);
937 uint32_t startaddr = 0;
938
939 if (main_hdr->blockid != IBR_HDR_SPI_ID) {
940 fprintf(stderr, "XIP is supported only for SPI images\n");
941 return 0;
942 }
943
944 if (version == 0 &&
945 params->addr >= 0xE8000000 && params->addr < 0xEFFFFFFF &&
946 params->ep >= 0xE8000000 && params->ep < 0xEFFFFFFF) {
947 /* Load and Execute address is in SPI address space (kwbimage v0) */
948 startaddr = 0xE8000000;
949 } else if (version != 0 &&
950 params->addr >= 0xD4000000 && params->addr < 0xD7FFFFFF &&
951 params->ep >= 0xD4000000 && params->ep < 0xD7FFFFFF) {
952 /* Load and Execute address is in SPI address space (kwbimage v1) */
953 startaddr = 0xD4000000;
954 } else if (version != 0 &&
955 params->addr >= 0xD8000000 && params->addr < 0xDFFFFFFF &&
956 params->ep >= 0xD8000000 && params->ep < 0xDFFFFFFF) {
957 /* Load and Execute address is in Device bus space (kwbimage v1) */
958 startaddr = 0xD8000000;
959 } else if (params->addr != 0x0) {
960 /* Load address is non-zero */
961 if (version == 0)
962 fprintf(stderr, "XIP Load Address or XIP Entry Point is not in SPI address space\n");
963 else
964 fprintf(stderr, "XIP Load Address or XIP Entry Point is not in SPI nor in Device bus address space\n");
965 return 0;
966 }
967
968 /*
969 * For XIP destaddr must be set to 0xFFFFFFFF and
970 * execaddr relative to the start of XIP memory address space.
971 */
972 main_hdr->destaddr = cpu_to_le32(0xFFFFFFFF);
973
974 if (startaddr == 0) {
975 /*
976 * mkimage's --load-address 0x0 means that binary is Position
977 * Independent and in this case mkimage's --entry-point address
978 * is relative offset from beginning of the data part of image.
979 */
980 main_hdr->execaddr = cpu_to_le32(srcaddr + params->ep);
981 } else {
982 /* The lowest possible load address is after the header at srcaddr. */
983 if (params->addr - startaddr < srcaddr) {
984 fprintf(stderr,
985 "Invalid XIP Load Address 0x%08x.\n"
986 "The lowest address for this configuration is 0x%08x.\n",
987 params->addr, (unsigned)(startaddr + srcaddr));
988 return 0;
989 }
990 main_hdr->srcaddr = cpu_to_le32(params->addr - startaddr);
991 main_hdr->execaddr = cpu_to_le32(params->ep - startaddr);
992 }
993
994 return 1;
995}
996
Pali Rohár15c893782023-03-29 21:25:56 +0200997static unsigned int image_get_satablksz(void)
998{
999 struct image_cfg_element *e;
1000 e = image_find_option(IMAGE_CFG_SATA_BLKSZ);
1001 return e ? e->satablksz : 512;
1002}
1003
Pali Rohár14c05962021-11-08 18:12:48 +01001004static size_t image_headersz_align(size_t headersz, uint8_t blockid)
1005{
1006 /*
1007 * Header needs to be 4-byte aligned, which is already ensured by code
1008 * above. Moreover UART images must have header aligned to 128 bytes
1009 * (xmodem block size), NAND images to 256 bytes (ECC calculation),
Pali Rohár15c893782023-03-29 21:25:56 +02001010 * SDIO images to 512 bytes (SDHC/SDXC fixed block size) and SATA
1011 * images to specified storage block size (default 512 bytes).
Pali Rohár14c05962021-11-08 18:12:48 +01001012 * Note that SPI images do not have to have header size aligned
1013 * to 256 bytes because it is possible to read from SPI storage from
1014 * any offset (read offset does not have to be aligned to block size).
1015 */
1016 if (blockid == IBR_HDR_UART_ID)
1017 return ALIGN(headersz, 128);
1018 else if (blockid == IBR_HDR_NAND_ID)
1019 return ALIGN(headersz, 256);
Pali Rohár15c893782023-03-29 21:25:56 +02001020 else if (blockid == IBR_HDR_SDIO_ID)
Pali Rohár14c05962021-11-08 18:12:48 +01001021 return ALIGN(headersz, 512);
Pali Rohár15c893782023-03-29 21:25:56 +02001022 else if (blockid == IBR_HDR_SATA_ID)
1023 return ALIGN(headersz, image_get_satablksz());
Pali Rohár14c05962021-11-08 18:12:48 +01001024 else
1025 return headersz;
1026}
1027
Pali Rohárecb3ca72021-11-08 18:12:50 +01001028static size_t image_headersz_v0(int *hasext)
1029{
1030 size_t headersz;
1031
1032 headersz = sizeof(struct main_hdr_v0);
1033 if (image_count_options(IMAGE_CFG_DATA) > 0) {
1034 headersz += sizeof(struct ext_hdr_v0);
1035 if (hasext)
1036 *hasext = 1;
1037 }
1038
Pali Rohár534c2f82023-01-29 15:00:45 +01001039 return headersz;
Pali Rohárecb3ca72021-11-08 18:12:50 +01001040}
1041
Pali Rohár3528adf2023-01-29 13:17:21 +01001042static void *image_create_v0(size_t *dataoff, struct image_tool_params *params,
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001043 int payloadsz)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301044{
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001045 struct image_cfg_element *e;
1046 size_t headersz;
1047 struct main_hdr_v0 *main_hdr;
Mario Six7497cd62017-01-11 16:00:55 +01001048 uint8_t *image;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001049 int has_ext = 0;
1050
1051 /*
Pali Rohár534c2f82023-01-29 15:00:45 +01001052 * Calculate the size of the header and the offset of the
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001053 * payload
1054 */
Pali Rohárecb3ca72021-11-08 18:12:50 +01001055 headersz = image_headersz_v0(&has_ext);
Pali Rohár534c2f82023-01-29 15:00:45 +01001056 *dataoff = image_headersz_align(headersz, image_get_bootfrom());
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001057
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001058 image = malloc(headersz);
1059 if (!image) {
1060 fprintf(stderr, "Cannot allocate memory for image\n");
1061 return NULL;
1062 }
1063
1064 memset(image, 0, headersz);
1065
Mario Six7497cd62017-01-11 16:00:55 +01001066 main_hdr = (struct main_hdr_v0 *)image;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301067
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001068 /* Fill in the main header */
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001069 main_hdr->blocksize =
Pali Rohárdce60c52021-11-08 18:12:47 +01001070 cpu_to_le32(payloadsz);
Pali Rohár534c2f82023-01-29 15:00:45 +01001071 main_hdr->srcaddr = cpu_to_le32(*dataoff);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001072 main_hdr->ext = has_ext;
Pali Rohárc990f942021-11-08 18:12:42 +01001073 main_hdr->version = 0;
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001074 main_hdr->destaddr = cpu_to_le32(params->addr);
1075 main_hdr->execaddr = cpu_to_le32(params->ep);
Pali Rohár1e2d7fb2021-11-08 18:12:43 +01001076 main_hdr->blockid = image_get_bootfrom();
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301077
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001078 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
1079 if (e)
1080 main_hdr->nandeccmode = e->nandeccmode;
Pali Rohár94671fd2022-02-17 10:43:38 +01001081 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1082 if (e)
1083 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001084 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
1085 if (e)
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001086 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Pali Rohár94671fd2022-02-17 10:43:38 +01001087 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1088 if (e)
1089 main_hdr->nandbadblklocation = e->nandbadblklocation;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301090
Pali Rohár15c893782023-03-29 21:25:56 +02001091 /* For SATA srcaddr is specified in number of sectors. */
1092 if (main_hdr->blockid == IBR_HDR_SATA_ID) {
1093 params->bl_len = image_get_satablksz();
1094 main_hdr->srcaddr = cpu_to_le32(le32_to_cpu(main_hdr->srcaddr) / params->bl_len);
1095 }
Pali Rohárf8f134d2021-11-08 18:12:51 +01001096
Pali Rohárf8f134d2021-11-08 18:12:51 +01001097 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1098 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1099 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1100
Pali Rohárc6178dc2023-01-18 21:42:40 +01001101 if (params->xflag) {
1102 if (!image_fill_xip_header(main_hdr, params)) {
1103 free(image);
1104 return NULL;
1105 }
1106 *dataoff = le32_to_cpu(main_hdr->srcaddr);
1107 }
1108
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001109 /* Generate the ext header */
1110 if (has_ext) {
Mario Six6f273632017-01-11 16:00:56 +01001111 struct ext_hdr_v0 *ext_hdr;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001112 int cfgi, datai;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301113
Mario Six7497cd62017-01-11 16:00:55 +01001114 ext_hdr = (struct ext_hdr_v0 *)
1115 (image + sizeof(struct main_hdr_v0));
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001116 ext_hdr->offset = cpu_to_le32(0x40);
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301117
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001118 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
1119 e = &image_cfg[cfgi];
1120 if (e->type != IMAGE_CFG_DATA)
1121 continue;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301122
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001123 ext_hdr->rcfg[datai].raddr =
1124 cpu_to_le32(e->regdata.raddr);
1125 ext_hdr->rcfg[datai].rdata =
1126 cpu_to_le32(e->regdata.rdata);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001127 datai++;
1128 }
1129
1130 ext_hdr->checksum = image_checksum8(ext_hdr,
1131 sizeof(struct ext_hdr_v0));
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301132 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301133
Pali Rohár11dbb552023-01-09 01:35:13 +01001134 main_hdr->checksum = image_checksum8(image,
1135 sizeof(struct main_hdr_v0));
1136
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001137 return image;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301138}
1139
Mario Six855cf9e2017-01-11 16:00:57 +01001140static size_t image_headersz_v1(int *hasext)
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001141{
Pali Rohárfc719962022-01-12 18:20:41 +01001142 struct image_cfg_element *e;
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001143 unsigned int count;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001144 size_t headersz;
Pali Rohárfc719962022-01-12 18:20:41 +01001145 int cpu_sheeva;
1146 struct stat s;
Pali Roháre0a6dc72021-07-23 11:14:09 +02001147 int cfgi;
Pali Rohárfc719962022-01-12 18:20:41 +01001148 int ret;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301149
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001150 headersz = sizeof(struct main_hdr_v1);
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301151
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001152 if (image_get_csk_index() >= 0) {
1153 headersz += sizeof(struct secure_hdr_v1);
1154 if (hasext)
1155 *hasext = 1;
1156 }
1157
Pali Rohárfc719962022-01-12 18:20:41 +01001158 cpu_sheeva = image_is_cpu_sheeva();
1159
Pali Rohárd8683252022-01-12 18:20:37 +01001160 count = 0;
1161 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1162 e = &image_cfg[cfgi];
1163
1164 if (e->type == IMAGE_CFG_DATA)
1165 count++;
1166
Pali Rohárfeae5e02022-01-12 18:20:38 +01001167 if (e->type == IMAGE_CFG_DATA_DELAY ||
1168 (e->type == IMAGE_CFG_BINARY && count > 0)) {
Pali Rohárd8683252022-01-12 18:20:37 +01001169 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
1170 count = 0;
1171 }
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001172
Pali Rohárfc719962022-01-12 18:20:41 +01001173 if (e->type != IMAGE_CFG_BINARY)
Pali Roháre0a6dc72021-07-23 11:14:09 +02001174 continue;
1175
Pali Rohárfc719962022-01-12 18:20:41 +01001176 ret = stat(e->binary.file, &s);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001177 if (ret < 0) {
Andreas Bießmann7abec5b2014-10-24 23:39:11 +02001178 char cwd[PATH_MAX];
1179 char *dir = cwd;
1180
1181 memset(cwd, 0, sizeof(cwd));
1182 if (!getcwd(cwd, sizeof(cwd))) {
1183 dir = "current working directory";
1184 perror("getcwd() failed");
1185 }
1186
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001187 fprintf(stderr,
1188 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
1189 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
Pali Rohár74bf2392022-02-17 10:43:39 +01001190 "image for your board. Use 'dumpimage -T kwbimage -p 1' to extract it from an existing image.\n",
Pali Rohárfc719962022-01-12 18:20:41 +01001191 e->binary.file, dir);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001192 return 0;
1193 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301194
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001195 headersz += sizeof(struct opt_hdr_v1) + sizeof(uint32_t) +
Pali Rohárfc719962022-01-12 18:20:41 +01001196 (e->binary.nargs) * sizeof(uint32_t);
1197
1198 if (e->binary.loadaddr) {
1199 /*
1200 * BootROM loads kwbimage header (in which the
1201 * executable code is also stored) to address
1202 * 0x40004000 or 0x40000000. Thus there is
1203 * restriction for the load address of the N-th
1204 * BINARY image.
1205 */
1206 unsigned int base_addr, low_addr, high_addr;
1207
1208 base_addr = cpu_sheeva ? 0x40004000 : 0x40000000;
1209 low_addr = base_addr + headersz;
1210 high_addr = low_addr +
1211 (BINARY_MAX_ARGS - e->binary.nargs) * sizeof(uint32_t);
1212
1213 if (cpu_sheeva && e->binary.loadaddr % 16) {
1214 fprintf(stderr,
1215 "Invalid LOAD_ADDRESS 0x%08x for BINARY %s with %d args.\n"
1216 "Address for CPU SHEEVA must be 16-byte aligned.\n",
1217 e->binary.loadaddr, e->binary.file, e->binary.nargs);
1218 return 0;
1219 }
1220
1221 if (e->binary.loadaddr % 4 || e->binary.loadaddr < low_addr ||
1222 e->binary.loadaddr > high_addr) {
1223 fprintf(stderr,
1224 "Invalid LOAD_ADDRESS 0x%08x for BINARY %s with %d args.\n"
1225 "Address must be 4-byte aligned and in range 0x%08x-0x%08x.\n",
1226 e->binary.loadaddr, e->binary.file,
1227 e->binary.nargs, low_addr, high_addr);
1228 return 0;
1229 }
1230 headersz = e->binary.loadaddr - base_addr;
Pali Rohár22529eb2022-01-12 18:20:46 +01001231 } else if (cpu_sheeva) {
Pali Rohárfc719962022-01-12 18:20:41 +01001232 headersz = ALIGN(headersz, 16);
Pali Rohár22529eb2022-01-12 18:20:46 +01001233 } else {
1234 headersz = ALIGN(headersz, 4);
Pali Rohárfc719962022-01-12 18:20:41 +01001235 }
1236
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001237 headersz += ALIGN(s.st_size, 4) + sizeof(uint32_t);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001238 if (hasext)
1239 *hasext = 1;
1240 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301241
Pali Rohárfc719962022-01-12 18:20:41 +01001242 if (count > 0)
1243 headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4;
1244
Pali Rohár0e8a0262023-03-23 20:57:51 +01001245 /*
1246 * For all images except UART, headersz stored in header itself should
1247 * contains header size without padding. For UART image BootROM rounds
1248 * down headersz to multiply of 128 bytes. Therefore align UART headersz
1249 * to multiply of 128 bytes to ensure that remaining UART header bytes
1250 * are not ignored by BootROM.
1251 */
1252 if (image_get_bootfrom() == IBR_HDR_UART_ID)
1253 headersz = ALIGN(headersz, 128);
1254
Pali Rohár534c2f82023-01-29 15:00:45 +01001255 return headersz;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001256}
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301257
Pali Rohár31376142022-01-12 18:20:35 +01001258static int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext,
1259 struct image_cfg_element *binarye,
1260 struct main_hdr_v1 *main_hdr)
Mario Six030ca162017-01-11 16:00:58 +01001261{
Pali Roháre0a6dc72021-07-23 11:14:09 +02001262 struct opt_hdr_v1 *hdr = (struct opt_hdr_v1 *)*cur;
Pali Rohárfc719962022-01-12 18:20:41 +01001263 uint32_t base_addr;
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001264 uint32_t add_args;
1265 uint32_t offset;
Mario Six030ca162017-01-11 16:00:58 +01001266 uint32_t *args;
1267 size_t binhdrsz;
Pali Rohárfc719962022-01-12 18:20:41 +01001268 int cpu_sheeva;
Mario Six030ca162017-01-11 16:00:58 +01001269 struct stat s;
1270 int argi;
1271 FILE *bin;
1272 int ret;
1273
Mario Six030ca162017-01-11 16:00:58 +01001274 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
1275
1276 bin = fopen(binarye->binary.file, "r");
1277 if (!bin) {
1278 fprintf(stderr, "Cannot open binary file %s\n",
1279 binarye->binary.file);
1280 return -1;
1281 }
1282
Mario Sixe3edf162017-02-13 10:11:55 +01001283 if (fstat(fileno(bin), &s)) {
1284 fprintf(stderr, "Cannot stat binary file %s\n",
1285 binarye->binary.file);
1286 goto err_close;
1287 }
Mario Six030ca162017-01-11 16:00:58 +01001288
Pali Roháre0a6dc72021-07-23 11:14:09 +02001289 *cur += sizeof(struct opt_hdr_v1);
Mario Six030ca162017-01-11 16:00:58 +01001290
Pali Roháre0a6dc72021-07-23 11:14:09 +02001291 args = (uint32_t *)*cur;
Mario Six030ca162017-01-11 16:00:58 +01001292 *args = cpu_to_le32(binarye->binary.nargs);
1293 args++;
1294 for (argi = 0; argi < binarye->binary.nargs; argi++)
1295 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
1296
Pali Roháre0a6dc72021-07-23 11:14:09 +02001297 *cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
Mario Six030ca162017-01-11 16:00:58 +01001298
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001299 /*
Pali Rohár22529eb2022-01-12 18:20:46 +01001300 * ARM executable code inside the BIN header on platforms with Sheeva
1301 * CPU (A370 and AXP) must always be aligned with the 128-bit boundary.
Pali Rohárfc719962022-01-12 18:20:41 +01001302 * In the case when this code is not position independent (e.g. ARM
1303 * SPL), it must be placed at fixed load and execute address.
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001304 * This requirement can be met by inserting dummy arguments into
1305 * BIN header, if needed.
1306 */
Pali Rohárfc719962022-01-12 18:20:41 +01001307 cpu_sheeva = image_is_cpu_sheeva();
1308 base_addr = cpu_sheeva ? 0x40004000 : 0x40000000;
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001309 offset = *cur - (uint8_t *)main_hdr;
Pali Rohárfc719962022-01-12 18:20:41 +01001310 if (binarye->binary.loadaddr)
1311 add_args = (binarye->binary.loadaddr - base_addr - offset) / sizeof(uint32_t);
Pali Rohár22529eb2022-01-12 18:20:46 +01001312 else if (cpu_sheeva)
Pali Rohárfc719962022-01-12 18:20:41 +01001313 add_args = ((16 - offset % 16) % 16) / sizeof(uint32_t);
Pali Rohár22529eb2022-01-12 18:20:46 +01001314 else
1315 add_args = 0;
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001316 if (add_args) {
1317 *(args - 1) = cpu_to_le32(binarye->binary.nargs + add_args);
1318 *cur += add_args * sizeof(uint32_t);
1319 }
1320
Pali Roháre0a6dc72021-07-23 11:14:09 +02001321 ret = fread(*cur, s.st_size, 1, bin);
Mario Six030ca162017-01-11 16:00:58 +01001322 if (ret != 1) {
1323 fprintf(stderr,
1324 "Could not read binary image %s\n",
1325 binarye->binary.file);
Mario Sixe3edf162017-02-13 10:11:55 +01001326 goto err_close;
Mario Six030ca162017-01-11 16:00:58 +01001327 }
1328
1329 fclose(bin);
1330
Pali Roháre0a6dc72021-07-23 11:14:09 +02001331 *cur += ALIGN(s.st_size, 4);
Mario Six030ca162017-01-11 16:00:58 +01001332
Pali Roháre0a6dc72021-07-23 11:14:09 +02001333 *((uint32_t *)*cur) = 0x00000000;
1334 **next_ext = 1;
1335 *next_ext = *cur;
Mario Six030ca162017-01-11 16:00:58 +01001336
Pali Roháre0a6dc72021-07-23 11:14:09 +02001337 *cur += sizeof(uint32_t);
Mario Six030ca162017-01-11 16:00:58 +01001338
Pali Rohár46ebc0e2021-10-21 16:46:07 +02001339 binhdrsz = sizeof(struct opt_hdr_v1) +
1340 (binarye->binary.nargs + add_args + 2) * sizeof(uint32_t) +
1341 ALIGN(s.st_size, 4);
1342 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
1343 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
1344
Mario Six030ca162017-01-11 16:00:58 +01001345 return 0;
Mario Sixe3edf162017-02-13 10:11:55 +01001346
1347err_close:
1348 fclose(bin);
1349
1350 return -1;
Mario Six030ca162017-01-11 16:00:58 +01001351}
Mario Six10d14492017-01-11 16:01:00 +01001352
Pali Rohár31376142022-01-12 18:20:35 +01001353static int export_pub_kak_hash(RSA *kak, struct secure_hdr_v1 *secure_hdr)
Mario Six10d14492017-01-11 16:01:00 +01001354{
1355 FILE *hashf;
1356 int res;
1357
1358 hashf = fopen("pub_kak_hash.txt", "w");
Heinrich Schuchardt379ec092021-08-17 07:03:20 +02001359 if (!hashf) {
1360 fprintf(stderr, "Couldn't open hash file: '%s': %s\n",
1361 "pub_kak_hash.txt", strerror(errno));
1362 return 1;
1363 }
Mario Six10d14492017-01-11 16:01:00 +01001364
1365 res = kwb_export_pubkey(kak, &secure_hdr->kak, hashf, "KAK");
1366
1367 fclose(hashf);
1368
1369 return res < 0 ? 1 : 0;
1370}
1371
Pali Rohár31376142022-01-12 18:20:35 +01001372static int kwb_sign_csk_with_kak(struct image_tool_params *params,
1373 struct secure_hdr_v1 *secure_hdr, RSA *csk)
Mario Six10d14492017-01-11 16:01:00 +01001374{
1375 RSA *kak = NULL;
1376 RSA *kak_pub = NULL;
1377 int csk_idx = image_get_csk_index();
1378 struct sig_v1 tmp_sig;
1379
Heinrich Schuchardtd8f0f1a2021-08-17 07:11:58 +02001380 if (csk_idx < 0 || csk_idx > 15) {
Mario Six10d14492017-01-11 16:01:00 +01001381 fprintf(stderr, "Invalid CSK index %d\n", csk_idx);
1382 return 1;
1383 }
1384
1385 if (kwb_load_kak(params, &kak) < 0)
1386 return 1;
1387
1388 if (export_pub_kak_hash(kak, secure_hdr))
1389 return 1;
1390
1391 if (kwb_import_pubkey(&kak_pub, &secure_hdr->kak, "KAK") < 0)
1392 return 1;
1393
1394 if (kwb_export_pubkey(csk, &secure_hdr->csk[csk_idx], NULL, "CSK") < 0)
1395 return 1;
1396
1397 if (kwb_sign_and_verify(kak, &secure_hdr->csk,
1398 sizeof(secure_hdr->csk) +
1399 sizeof(secure_hdr->csksig),
1400 &tmp_sig, "CSK") < 0)
1401 return 1;
1402
1403 if (kwb_verify(kak_pub, &secure_hdr->csk,
1404 sizeof(secure_hdr->csk) +
1405 sizeof(secure_hdr->csksig),
1406 &tmp_sig, "CSK (2)") < 0)
1407 return 1;
1408
1409 secure_hdr->csksig = tmp_sig;
1410
1411 return 0;
1412}
1413
Pali Rohárd8298f02023-01-29 13:08:10 +01001414static int add_secure_header_v1(struct image_tool_params *params, uint8_t *image_ptr,
1415 size_t image_size, uint8_t *header_ptr, size_t headersz,
Pali Rohár31376142022-01-12 18:20:35 +01001416 struct secure_hdr_v1 *secure_hdr)
Mario Six10d14492017-01-11 16:01:00 +01001417{
1418 struct image_cfg_element *e_jtagdelay;
1419 struct image_cfg_element *e_boxid;
1420 struct image_cfg_element *e_flashid;
1421 RSA *csk = NULL;
Mario Six10d14492017-01-11 16:01:00 +01001422 struct sig_v1 tmp_sig;
1423 bool specialized_img = image_get_spezialized_img();
1424
1425 kwb_msg("Create secure header content\n");
1426
1427 e_jtagdelay = image_find_option(IMAGE_CFG_JTAG_DELAY);
1428 e_boxid = image_find_option(IMAGE_CFG_BOX_ID);
1429 e_flashid = image_find_option(IMAGE_CFG_FLASH_ID);
1430
1431 if (kwb_load_csk(params, &csk) < 0)
1432 return 1;
1433
1434 secure_hdr->headertype = OPT_HDR_V1_SECURE_TYPE;
1435 secure_hdr->headersz_msb = 0;
1436 secure_hdr->headersz_lsb = cpu_to_le16(sizeof(struct secure_hdr_v1));
1437 if (e_jtagdelay)
1438 secure_hdr->jtag_delay = e_jtagdelay->jtag_delay;
1439 if (e_boxid && specialized_img)
1440 secure_hdr->boxid = cpu_to_le32(e_boxid->boxid);
1441 if (e_flashid && specialized_img)
1442 secure_hdr->flashid = cpu_to_le32(e_flashid->flashid);
1443
1444 if (kwb_sign_csk_with_kak(params, secure_hdr, csk))
1445 return 1;
1446
Pali Rohár55e827c2023-01-29 14:33:36 +01001447 if (kwb_sign_and_verify(csk, image_ptr, image_size - 4,
Mario Six10d14492017-01-11 16:01:00 +01001448 &secure_hdr->imgsig, "image") < 0)
1449 return 1;
1450
Pali Rohárd8298f02023-01-29 13:08:10 +01001451 if (kwb_sign_and_verify(csk, header_ptr, headersz, &tmp_sig, "header") < 0)
Mario Six10d14492017-01-11 16:01:00 +01001452 return 1;
1453
1454 secure_hdr->hdrsig = tmp_sig;
1455
1456 kwb_dump_fuse_cmds(secure_hdr);
1457
1458 return 0;
1459}
Mario Six030ca162017-01-11 16:00:58 +01001460
Pali Rohára82a7d62022-01-12 18:20:36 +01001461static void finish_register_set_header_v1(uint8_t **cur, uint8_t **next_ext,
1462 struct register_set_hdr_v1 *register_set_hdr,
1463 int *datai, uint8_t delay)
1464{
1465 int size = sizeof(struct register_set_hdr_v1) + 8 * (*datai) + 4;
1466
1467 register_set_hdr->headertype = OPT_HDR_V1_REGISTER_TYPE;
1468 register_set_hdr->headersz_lsb = cpu_to_le16(size & 0xFFFF);
1469 register_set_hdr->headersz_msb = size >> 16;
1470 register_set_hdr->data[*datai].last_entry.delay = delay;
1471 *cur += size;
1472 **next_ext = 1;
1473 *next_ext = &register_set_hdr->data[*datai].last_entry.next;
1474 *datai = 0;
1475}
1476
Pali Rohár3528adf2023-01-29 13:17:21 +01001477static void *image_create_v1(size_t *dataoff, struct image_tool_params *params,
Mario Six10d14492017-01-11 16:01:00 +01001478 uint8_t *ptr, int payloadsz)
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001479{
Mario Six030ca162017-01-11 16:00:58 +01001480 struct image_cfg_element *e;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001481 struct main_hdr_v1 *main_hdr;
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001482 struct register_set_hdr_v1 *register_set_hdr;
Mario Six10d14492017-01-11 16:01:00 +01001483 struct secure_hdr_v1 *secure_hdr = NULL;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001484 size_t headersz;
Mario Six7497cd62017-01-11 16:00:55 +01001485 uint8_t *image, *cur;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001486 int hasext = 0;
Mario Six10d14492017-01-11 16:01:00 +01001487 uint8_t *next_ext = NULL;
Pali Rohára82a7d62022-01-12 18:20:36 +01001488 int cfgi, datai;
Pali Rohárfeae5e02022-01-12 18:20:38 +01001489 uint8_t delay;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301490
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001491 /*
Pali Rohár534c2f82023-01-29 15:00:45 +01001492 * Calculate the size of the header and the offset of the
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001493 * payload
1494 */
Mario Six855cf9e2017-01-11 16:00:57 +01001495 headersz = image_headersz_v1(&hasext);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001496 if (headersz == 0)
1497 return NULL;
Pali Rohár534c2f82023-01-29 15:00:45 +01001498 *dataoff = image_headersz_align(headersz, image_get_bootfrom());
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301499
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001500 image = malloc(headersz);
1501 if (!image) {
1502 fprintf(stderr, "Cannot allocate memory for image\n");
1503 return NULL;
1504 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301505
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001506 memset(image, 0, headersz);
1507
Mario Six7497cd62017-01-11 16:00:55 +01001508 main_hdr = (struct main_hdr_v1 *)image;
Mario Six10d14492017-01-11 16:01:00 +01001509 cur = image;
1510 cur += sizeof(struct main_hdr_v1);
1511 next_ext = &main_hdr->ext;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001512
1513 /* Fill the main header */
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001514 main_hdr->blocksize =
Pali Rohárdce60c52021-11-08 18:12:47 +01001515 cpu_to_le32(payloadsz);
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001516 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001517 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
Pali Rohárf8171a52021-07-23 11:14:06 +02001518 main_hdr->destaddr = cpu_to_le32(params->addr);
Reinhard Pfau3efeaae2015-11-29 15:48:25 +01001519 main_hdr->execaddr = cpu_to_le32(params->ep);
Pali Rohár534c2f82023-01-29 15:00:45 +01001520 main_hdr->srcaddr = cpu_to_le32(*dataoff);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001521 main_hdr->ext = hasext;
1522 main_hdr->version = 1;
Pali Rohár1e2d7fb2021-11-08 18:12:43 +01001523 main_hdr->blockid = image_get_bootfrom();
1524
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001525 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
1526 if (e)
1527 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
Pali Rohárbf9a89e2021-10-22 12:37:46 +02001528 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
1529 if (e)
1530 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001531 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
1532 if (e)
1533 main_hdr->nandbadblklocation = e->nandbadblklocation;
Chris Packham883bf452016-11-09 22:07:45 +13001534 e = image_find_option(IMAGE_CFG_BAUDRATE);
1535 if (e)
Pali Rohárd8840942021-11-08 18:12:41 +01001536 main_hdr->options |= baudrate_to_option(e->baudrate);
1537 e = image_find_option(IMAGE_CFG_UART_PORT);
1538 if (e)
1539 main_hdr->options |= (e->uart_port & 3) << 3;
1540 e = image_find_option(IMAGE_CFG_UART_MPP);
1541 if (e)
1542 main_hdr->options |= (e->uart_mpp & 7) << 5;
Chris Packham1e0728a2016-11-09 22:21:45 +13001543 e = image_find_option(IMAGE_CFG_DEBUG);
1544 if (e)
1545 main_hdr->flags = e->debug ? 0x1 : 0;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001546
Pali Rohár15c893782023-03-29 21:25:56 +02001547 /* For SATA srcaddr is specified in number of sectors. */
1548 if (main_hdr->blockid == IBR_HDR_SATA_ID) {
1549 params->bl_len = image_get_satablksz();
1550 main_hdr->srcaddr = cpu_to_le32(le32_to_cpu(main_hdr->srcaddr) / params->bl_len);
1551 }
Pali Rohár6f6f65e2021-07-23 11:13:59 +02001552
Pali Rohár6f6f65e2021-07-23 11:13:59 +02001553 /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */
1554 if (main_hdr->blockid == IBR_HDR_PEX_ID)
1555 main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF);
1556
Pali Rohárc6178dc2023-01-18 21:42:40 +01001557 if (params->xflag) {
1558 if (!image_fill_xip_header(main_hdr, params)) {
1559 free(image);
1560 return NULL;
1561 }
1562 *dataoff = le32_to_cpu(main_hdr->srcaddr);
1563 }
1564
Mario Six10d14492017-01-11 16:01:00 +01001565 if (image_get_csk_index() >= 0) {
1566 /*
1567 * only reserve the space here; we fill the header later since
1568 * we need the header to be complete to compute the signatures
1569 */
1570 secure_hdr = (struct secure_hdr_v1 *)cur;
1571 cur += sizeof(struct secure_hdr_v1);
Pali Roháre0a6dc72021-07-23 11:14:09 +02001572 *next_ext = 1;
Mario Six10d14492017-01-11 16:01:00 +01001573 next_ext = &secure_hdr->next;
1574 }
Mario Six10d14492017-01-11 16:01:00 +01001575
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001576 datai = 0;
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001577 for (cfgi = 0; cfgi < cfgn; cfgi++) {
1578 e = &image_cfg[cfgi];
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001579 if (e->type != IMAGE_CFG_DATA &&
Pali Rohárfeae5e02022-01-12 18:20:38 +01001580 e->type != IMAGE_CFG_DATA_DELAY &&
1581 e->type != IMAGE_CFG_BINARY)
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001582 continue;
Pali Rohárfeae5e02022-01-12 18:20:38 +01001583
Pali Rohárd8683252022-01-12 18:20:37 +01001584 if (datai == 0)
1585 register_set_hdr = (struct register_set_hdr_v1 *)cur;
Pali Rohárfeae5e02022-01-12 18:20:38 +01001586
1587 /* If delay is not specified, use the smallest possible value. */
1588 if (e->type == IMAGE_CFG_DATA_DELAY)
1589 delay = e->regdata_delay;
1590 else
1591 delay = REGISTER_SET_HDR_OPT_DELAY_MS(0);
1592
1593 /*
1594 * DATA_DELAY command is the last entry in the register set
1595 * header and BINARY command inserts new binary header.
1596 * Therefore BINARY command requires to finish register set
1597 * header if some DATA command was specified. And DATA_DELAY
1598 * command automatically finish register set header even when
1599 * there was no DATA command.
1600 */
1601 if (e->type == IMAGE_CFG_DATA_DELAY ||
1602 (e->type == IMAGE_CFG_BINARY && datai != 0))
Pali Rohára82a7d62022-01-12 18:20:36 +01001603 finish_register_set_header_v1(&cur, &next_ext, register_set_hdr,
Pali Rohárfeae5e02022-01-12 18:20:38 +01001604 &datai, delay);
1605
1606 if (e->type == IMAGE_CFG_DATA) {
1607 register_set_hdr->data[datai].entry.address =
1608 cpu_to_le32(e->regdata.raddr);
1609 register_set_hdr->data[datai].entry.value =
1610 cpu_to_le32(e->regdata.rdata);
1611 datai++;
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001612 }
Pali Rohárfeae5e02022-01-12 18:20:38 +01001613
1614 if (e->type == IMAGE_CFG_BINARY) {
1615 if (add_binary_header_v1(&cur, &next_ext, e, main_hdr))
1616 return NULL;
1617 }
Pali Rohárfbe10ac2021-07-23 11:14:11 +02001618 }
1619 if (datai != 0) {
Pali Rohára82a7d62022-01-12 18:20:36 +01001620 /* Set delay to the smallest possible value. */
Pali Rohárfeae5e02022-01-12 18:20:38 +01001621 delay = REGISTER_SET_HDR_OPT_DELAY_MS(0);
Pali Rohára82a7d62022-01-12 18:20:36 +01001622 finish_register_set_header_v1(&cur, &next_ext, register_set_hdr,
Pali Rohárfeae5e02022-01-12 18:20:38 +01001623 &datai, delay);
Pali Roháre0a6dc72021-07-23 11:14:09 +02001624 }
Mario Six10d14492017-01-11 16:01:00 +01001625
Pali Rohár534c2f82023-01-29 15:00:45 +01001626 if (secure_hdr && add_secure_header_v1(params, ptr + *dataoff, payloadsz,
Pali Rohárd8298f02023-01-29 13:08:10 +01001627 image, headersz, secure_hdr))
Mario Six10d14492017-01-11 16:01:00 +01001628 return NULL;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001629
Pierre Bourdon3fb703d2021-12-25 20:50:19 +01001630 /* Calculate and set the header checksum */
1631 main_hdr->checksum = image_checksum8(main_hdr, headersz);
1632
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001633 return image;
1634}
1635
Pali Rohár31376142022-01-12 18:20:35 +01001636static int recognize_keyword(char *keyword)
Mario Six62da6762017-01-11 16:00:59 +01001637{
1638 int kw_id;
1639
1640 for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
1641 if (!strcmp(keyword, id_strs[kw_id]))
1642 return kw_id;
1643
1644 return 0;
1645}
1646
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001647static int image_create_config_parse_oneline(char *line,
1648 struct image_cfg_element *el)
1649{
Mario Six62da6762017-01-11 16:00:59 +01001650 char *keyword, *saveptr, *value1, *value2;
1651 char delimiters[] = " \t";
1652 int keyword_id, ret, argi;
1653 char *unknown_msg = "Ignoring unknown line '%s'\n";
1654
1655 keyword = strtok_r(line, delimiters, &saveptr);
1656 keyword_id = recognize_keyword(keyword);
1657
1658 if (!keyword_id) {
1659 fprintf(stderr, unknown_msg, line);
1660 return 0;
1661 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001662
Mario Six62da6762017-01-11 16:00:59 +01001663 el->type = keyword_id;
Mario Sixd6009d72017-01-11 16:00:54 +01001664
Mario Six62da6762017-01-11 16:00:59 +01001665 value1 = strtok_r(NULL, delimiters, &saveptr);
1666
1667 if (!value1) {
1668 fprintf(stderr, "Parameter missing in line '%s'\n", line);
1669 return -1;
1670 }
1671
1672 switch (keyword_id) {
1673 case IMAGE_CFG_VERSION:
1674 el->version = atoi(value1);
1675 break;
Pali Rohár6b76c1c2022-01-12 18:20:40 +01001676 case IMAGE_CFG_CPU:
1677 if (strcmp(value1, "FEROCEON") == 0)
1678 el->cpu_sheeva = 0;
1679 else if (strcmp(value1, "SHEEVA") == 0)
1680 el->cpu_sheeva = 1;
1681 else if (strcmp(value1, "A9") == 0)
1682 el->cpu_sheeva = 0;
1683 else {
1684 fprintf(stderr, "Invalid CPU %s\n", value1);
1685 return -1;
1686 }
1687 break;
Mario Six62da6762017-01-11 16:00:59 +01001688 case IMAGE_CFG_BOOT_FROM:
1689 ret = image_boot_mode_id(value1);
Mario Sixd6009d72017-01-11 16:00:54 +01001690
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001691 if (ret < 0) {
Mario Six62da6762017-01-11 16:00:59 +01001692 fprintf(stderr, "Invalid boot media '%s'\n", value1);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001693 return -1;
1694 }
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001695 el->bootfrom = ret;
Mario Six62da6762017-01-11 16:00:59 +01001696 break;
1697 case IMAGE_CFG_NAND_BLKSZ:
1698 el->nandblksz = strtoul(value1, NULL, 16);
1699 break;
1700 case IMAGE_CFG_NAND_BADBLK_LOCATION:
1701 el->nandbadblklocation = strtoul(value1, NULL, 16);
1702 break;
1703 case IMAGE_CFG_NAND_ECC_MODE:
1704 ret = image_nand_ecc_mode_id(value1);
Mario Sixd6009d72017-01-11 16:00:54 +01001705
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001706 if (ret < 0) {
Mario Six62da6762017-01-11 16:00:59 +01001707 fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001708 return -1;
1709 }
Andreas Bießmann4c40e352014-10-24 23:25:52 +02001710 el->nandeccmode = ret;
Mario Six62da6762017-01-11 16:00:59 +01001711 break;
1712 case IMAGE_CFG_NAND_PAGESZ:
1713 el->nandpagesz = strtoul(value1, NULL, 16);
1714 break;
Pali Rohár15c893782023-03-29 21:25:56 +02001715 case IMAGE_CFG_SATA_BLKSZ:
1716 el->satablksz = strtoul(value1, NULL, 0);
1717 if (el->satablksz & (el->satablksz-1)) {
1718 fprintf(stderr, "Invalid SATA block size '%s'\n", value1);
1719 return -1;
1720 }
1721 break;
Mario Six62da6762017-01-11 16:00:59 +01001722 case IMAGE_CFG_BINARY:
1723 argi = 0;
Mario Sixd6009d72017-01-11 16:00:54 +01001724
Mario Six62da6762017-01-11 16:00:59 +01001725 el->binary.file = strdup(value1);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001726 while (1) {
Mario Six62da6762017-01-11 16:00:59 +01001727 char *value = strtok_r(NULL, delimiters, &saveptr);
Pali Rohárfc719962022-01-12 18:20:41 +01001728 char *endptr;
Mario Six62da6762017-01-11 16:00:59 +01001729
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001730 if (!value)
1731 break;
Pali Rohárfc719962022-01-12 18:20:41 +01001732
1733 if (!strcmp(value, "LOAD_ADDRESS")) {
1734 value = strtok_r(NULL, delimiters, &saveptr);
1735 if (!value) {
1736 fprintf(stderr,
1737 "Missing address argument for BINARY LOAD_ADDRESS\n");
1738 return -1;
1739 }
1740 el->binary.loadaddr = strtoul(value, &endptr, 16);
1741 if (*endptr) {
1742 fprintf(stderr,
1743 "Invalid argument '%s' for BINARY LOAD_ADDRESS\n",
1744 value);
1745 return -1;
1746 }
1747 value = strtok_r(NULL, delimiters, &saveptr);
1748 if (value) {
1749 fprintf(stderr,
1750 "Unexpected argument '%s' after BINARY LOAD_ADDRESS\n",
1751 value);
1752 return -1;
1753 }
1754 break;
1755 }
1756
1757 el->binary.args[argi] = strtoul(value, &endptr, 16);
1758 if (*endptr) {
1759 fprintf(stderr, "Invalid argument '%s' for BINARY\n", value);
1760 return -1;
1761 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001762 argi++;
1763 if (argi >= BINARY_MAX_ARGS) {
1764 fprintf(stderr,
Mario Six62da6762017-01-11 16:00:59 +01001765 "Too many arguments for BINARY\n");
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001766 return -1;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301767 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301768 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001769 el->binary.nargs = argi;
Mario Six62da6762017-01-11 16:00:59 +01001770 break;
1771 case IMAGE_CFG_DATA:
1772 value2 = strtok_r(NULL, delimiters, &saveptr);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001773
1774 if (!value1 || !value2) {
1775 fprintf(stderr,
1776 "Invalid number of arguments for DATA\n");
1777 return -1;
1778 }
1779
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001780 el->regdata.raddr = strtoul(value1, NULL, 16);
1781 el->regdata.rdata = strtoul(value2, NULL, 16);
Mario Six62da6762017-01-11 16:00:59 +01001782 break;
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001783 case IMAGE_CFG_DATA_DELAY:
1784 if (!strcmp(value1, "SDRAM_SETUP"))
1785 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP;
1786 else
1787 el->regdata_delay = REGISTER_SET_HDR_OPT_DELAY_MS(strtoul(value1, NULL, 10));
Pali Rohár80e2ee12022-01-12 18:20:48 +01001788 if (el->regdata_delay > 255) {
1789 fprintf(stderr, "Maximal DATA_DELAY is 255\n");
1790 return -1;
1791 }
Pali Rohárc0cfd1a2021-07-23 11:14:12 +02001792 break;
Mario Six62da6762017-01-11 16:00:59 +01001793 case IMAGE_CFG_BAUDRATE:
1794 el->baudrate = strtoul(value1, NULL, 10);
1795 break;
Pali Rohárd8840942021-11-08 18:12:41 +01001796 case IMAGE_CFG_UART_PORT:
1797 el->uart_port = strtoul(value1, NULL, 16);
1798 break;
1799 case IMAGE_CFG_UART_MPP:
1800 el->uart_mpp = strtoul(value1, NULL, 16);
1801 break;
Mario Six62da6762017-01-11 16:00:59 +01001802 case IMAGE_CFG_DEBUG:
1803 el->debug = strtoul(value1, NULL, 10);
1804 break;
Mario Six10d14492017-01-11 16:01:00 +01001805 case IMAGE_CFG_KAK:
1806 el->key_name = strdup(value1);
1807 break;
1808 case IMAGE_CFG_CSK:
1809 el->key_name = strdup(value1);
1810 break;
1811 case IMAGE_CFG_CSK_INDEX:
1812 el->csk_idx = strtol(value1, NULL, 0);
1813 break;
1814 case IMAGE_CFG_JTAG_DELAY:
1815 el->jtag_delay = strtoul(value1, NULL, 0);
1816 break;
1817 case IMAGE_CFG_BOX_ID:
1818 el->boxid = strtoul(value1, NULL, 0);
1819 break;
1820 case IMAGE_CFG_FLASH_ID:
1821 el->flashid = strtoul(value1, NULL, 0);
1822 break;
1823 case IMAGE_CFG_SEC_SPECIALIZED_IMG:
1824 el->sec_specialized_img = true;
1825 break;
1826 case IMAGE_CFG_SEC_COMMON_IMG:
1827 el->sec_specialized_img = false;
1828 break;
1829 case IMAGE_CFG_SEC_BOOT_DEV:
1830 el->sec_boot_dev = strtoul(value1, NULL, 0);
1831 break;
1832 case IMAGE_CFG_SEC_FUSE_DUMP:
1833 el->name = strdup(value1);
1834 break;
Mario Six62da6762017-01-11 16:00:59 +01001835 default:
1836 fprintf(stderr, unknown_msg, line);
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301837 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301838
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001839 return 0;
1840}
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301841
1842/*
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001843 * Parse the configuration file 'fcfg' into the array of configuration
1844 * elements 'image_cfg', and return the number of configuration
1845 * elements in 'cfgn'.
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301846 */
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001847static int image_create_config_parse(FILE *fcfg)
1848{
1849 int ret;
1850 int cfgi = 0;
1851
1852 /* Parse the configuration file */
1853 while (!feof(fcfg)) {
1854 char *line;
1855 char buf[256];
1856
1857 /* Read the current line */
1858 memset(buf, 0, sizeof(buf));
1859 line = fgets(buf, sizeof(buf), fcfg);
1860 if (!line)
1861 break;
1862
1863 /* Ignore useless lines */
1864 if (line[0] == '\n' || line[0] == '#')
1865 continue;
1866
1867 /* Strip final newline */
1868 if (line[strlen(line) - 1] == '\n')
1869 line[strlen(line) - 1] = 0;
1870
1871 /* Parse the current line */
1872 ret = image_create_config_parse_oneline(line,
1873 &image_cfg[cfgi]);
1874 if (ret)
1875 return ret;
1876
1877 cfgi++;
1878
1879 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
1880 fprintf(stderr,
1881 "Too many configuration elements in .cfg file\n");
1882 return -1;
1883 }
1884 }
1885
1886 cfgn = cfgi;
1887 return 0;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301888}
1889
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001890static int image_get_version(void)
1891{
1892 struct image_cfg_element *e;
1893
1894 e = image_find_option(IMAGE_CFG_VERSION);
1895 if (!e)
1896 return -1;
1897
1898 return e->version;
1899}
1900
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001901static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
Guilherme Maciel Ferreira8ed4d1c2013-12-01 12:43:10 -07001902 struct image_tool_params *params)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301903{
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001904 FILE *fcfg;
1905 void *image = NULL;
1906 int version;
Pali Rohár3528adf2023-01-29 13:17:21 +01001907 size_t dataoff = 0;
Pali Rohárdce60c52021-11-08 18:12:47 +01001908 size_t datasz;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301909 uint32_t checksum;
Pali Rohárdce60c52021-11-08 18:12:47 +01001910 struct stat s;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001911 int ret;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301912
Pali Rohár15c893782023-03-29 21:25:56 +02001913 params->bl_len = 1;
1914
Pali Rohárdce60c52021-11-08 18:12:47 +01001915 /*
1916 * Do not use sbuf->st_size as it contains size with padding.
1917 * We need original image data size, so stat original file.
1918 */
Pali Rohár3e4756b2023-01-21 20:11:28 +01001919 if (params->skipcpy) {
1920 s.st_size = 0;
1921 } else if (stat(params->datafile, &s)) {
Pali Rohárdce60c52021-11-08 18:12:47 +01001922 fprintf(stderr, "Could not stat data file %s: %s\n",
1923 params->datafile, strerror(errno));
1924 exit(EXIT_FAILURE);
1925 }
1926 datasz = ALIGN(s.st_size, 4);
1927
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001928 fcfg = fopen(params->imagename, "r");
1929 if (!fcfg) {
1930 fprintf(stderr, "Could not open input file %s\n",
1931 params->imagename);
1932 exit(EXIT_FAILURE);
1933 }
1934
1935 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
1936 sizeof(struct image_cfg_element));
1937 if (!image_cfg) {
1938 fprintf(stderr, "Cannot allocate memory\n");
1939 fclose(fcfg);
1940 exit(EXIT_FAILURE);
1941 }
1942
1943 memset(image_cfg, 0,
1944 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
1945 rewind(fcfg);
1946
1947 ret = image_create_config_parse(fcfg);
1948 fclose(fcfg);
1949 if (ret) {
1950 free(image_cfg);
1951 exit(EXIT_FAILURE);
1952 }
1953
1954 version = image_get_version();
Stefan Roese933918c2014-10-28 11:32:24 +01001955 switch (version) {
1956 /*
1957 * Fallback to version 0 if no version is provided in the
1958 * cfg file
1959 */
1960 case -1:
1961 case 0:
Pali Rohár3528adf2023-01-29 13:17:21 +01001962 image = image_create_v0(&dataoff, params, datasz + 4);
Stefan Roese933918c2014-10-28 11:32:24 +01001963 break;
1964
1965 case 1:
Pali Rohár3528adf2023-01-29 13:17:21 +01001966 image = image_create_v1(&dataoff, params, ptr, datasz + 4);
Stefan Roese933918c2014-10-28 11:32:24 +01001967 break;
1968
1969 default:
1970 fprintf(stderr, "Unsupported version %d\n", version);
1971 free(image_cfg);
1972 exit(EXIT_FAILURE);
1973 }
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301974
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001975 if (!image) {
1976 fprintf(stderr, "Could not create image\n");
1977 free(image_cfg);
1978 exit(EXIT_FAILURE);
1979 }
1980
1981 free(image_cfg);
1982
Pali Rohárdce60c52021-11-08 18:12:47 +01001983 /* Build and add image data checksum */
Pali Rohár3528adf2023-01-29 13:17:21 +01001984 checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + dataoff,
Pali Rohárdce60c52021-11-08 18:12:47 +01001985 datasz));
Pali Rohár3528adf2023-01-29 13:17:21 +01001986 memcpy((uint8_t *)ptr + dataoff + datasz, &checksum, sizeof(uint32_t));
Prafulla Wadaskar07329412009-09-07 15:05:02 +05301987
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001988 /* Finally copy the header into the image area */
Pali Rohár534c2f82023-01-29 15:00:45 +01001989 memcpy(ptr, image, kwbheader_size(image));
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001990
1991 free(image);
1992}
1993
Pali Rohár0ed41e22023-03-29 21:25:54 +02001994static void kwbimage_print_header(const void *ptr, struct image_tool_params *params)
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001995{
1996 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Pali Roháre581f192022-02-17 10:43:36 +01001997 struct bin_hdr_v0 *bhdr;
Marek Behúnb1a76502021-08-18 00:59:15 +02001998 struct opt_hdr_v1 *ohdr;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02001999
2000 printf("Image Type: MVEBU Boot from %s Image\n",
2001 image_boot_mode_name(mhdr->blockid));
Marek Behúnfa9caec2021-09-24 23:07:00 +02002002 printf("Image version:%d\n", kwbimage_version(ptr));
Pali Rohárcd614ad2021-07-23 11:14:04 +02002003
Marek Behúnb1a76502021-08-18 00:59:15 +02002004 for_each_opt_hdr_v1 (ohdr, mhdr) {
2005 if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
Pali Rohár6e16d392022-01-12 18:20:49 +01002006 printf("BIN Img Size: ");
Marek Behúnb1a76502021-08-18 00:59:15 +02002007 genimg_print_size(opt_hdr_v1_size(ohdr) - 12 -
2008 4 * ohdr->data[0]);
Pali Rohárd8386e62023-01-08 23:27:11 +01002009 printf("BIN Img Offs: ");
2010 genimg_print_size(((uint8_t *)ohdr - (uint8_t *)mhdr) +
2011 8 + 4 * ohdr->data[0]);
Pali Rohárcd614ad2021-07-23 11:14:04 +02002012 }
2013 }
Marek Behúnb1a76502021-08-18 00:59:15 +02002014
Pali Roháre581f192022-02-17 10:43:36 +01002015 for_each_bin_hdr_v0(bhdr, mhdr) {
2016 printf("BIN Img Size: ");
2017 genimg_print_size(le32_to_cpu(bhdr->size));
2018 printf("BIN Img Addr: %08x\n", le32_to_cpu(bhdr->destaddr));
2019 printf("BIN Img Entr: %08x\n", le32_to_cpu(bhdr->execaddr));
2020 }
2021
Gerald Kerma8f9e5832014-10-31 01:03:27 +01002022 printf("Data Size: ");
Pali Rohárdc9c9632023-01-08 13:56:42 +01002023 genimg_print_size(le32_to_cpu(mhdr->blocksize) - sizeof(uint32_t));
Pali Roháreb543d02023-01-08 13:58:26 +01002024 printf("Data Offset: ");
2025 if (mhdr->blockid == IBR_HDR_SATA_ID)
Pali Rohár15c893782023-03-29 21:25:56 +02002026 printf("%u Sector%s (LBA) = ", le32_to_cpu(mhdr->srcaddr),
Pali Roháreb543d02023-01-08 13:58:26 +01002027 le32_to_cpu(mhdr->srcaddr) != 1 ? "s" : "");
Pali Rohár15c893782023-03-29 21:25:56 +02002028 genimg_print_size(le32_to_cpu(mhdr->srcaddr) * params->bl_len);
2029 if (mhdr->blockid == IBR_HDR_SATA_ID)
2030 printf("Sector Size: %u Bytes\n", params->bl_len);
Pali Rohárc6178dc2023-01-18 21:42:40 +01002031 if (mhdr->blockid == IBR_HDR_SPI_ID && le32_to_cpu(mhdr->destaddr) == 0xFFFFFFFF) {
2032 printf("Load Address: XIP\n");
2033 printf("Execute Offs: %08x\n", le32_to_cpu(mhdr->execaddr));
2034 } else {
2035 printf("Load Address: %08x\n", le32_to_cpu(mhdr->destaddr));
2036 printf("Entry Point: %08x\n", le32_to_cpu(mhdr->execaddr));
2037 }
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002038}
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302039
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002040static int kwbimage_check_image_types(uint8_t type)
2041{
2042 if (type == IH_TYPE_KWBIMAGE)
2043 return EXIT_SUCCESS;
Mario Sixd6009d72017-01-11 16:00:54 +01002044
2045 return EXIT_FAILURE;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302046}
2047
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002048static int kwbimage_verify_header(unsigned char *ptr, int image_size,
2049 struct image_tool_params *params)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302050{
Marek Behúnd1b0b032021-09-24 23:07:01 +02002051 size_t header_size = kwbheader_size(ptr);
Pali Rohár17414cb2021-11-08 18:12:44 +01002052 uint8_t blockid;
2053 uint32_t offset;
2054 uint32_t size;
Marek Behúnd1b0b032021-09-24 23:07:01 +02002055 uint8_t csum;
Pali Rohár15c893782023-03-29 21:25:56 +02002056 int blksz;
Alexander Graf22e87fc2018-03-15 11:14:19 +01002057
Pali Rohár55f9e492022-09-18 18:39:18 +02002058 if (header_size > 192*1024)
2059 return -FDT_ERR_BADSTRUCTURE;
2060
Alexander Graf22e87fc2018-03-15 11:14:19 +01002061 if (header_size > image_size)
2062 return -FDT_ERR_BADSTRUCTURE;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302063
Baruch Siach4a5b99b2017-07-04 20:23:40 +03002064 if (!main_hdr_checksum_ok(ptr))
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002065 return -FDT_ERR_BADSTRUCTURE;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302066
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002067 /* Only version 0 extended header has checksum */
Marek Behúnfa9caec2021-09-24 23:07:00 +02002068 if (kwbimage_version(ptr) == 0) {
Pali Rohár03345b92021-07-23 11:14:01 +02002069 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
Pali Roháre581f192022-02-17 10:43:36 +01002070 struct ext_hdr_v0 *ext_hdr;
2071 struct bin_hdr_v0 *bhdr;
Pali Rohára98cc272021-08-11 10:14:15 +02002072
Pali Roháre581f192022-02-17 10:43:36 +01002073 for_each_ext_hdr_v0(ext_hdr, ptr) {
Marek Behúnd1b0b032021-09-24 23:07:01 +02002074 csum = image_checksum8(ext_hdr, sizeof(*ext_hdr) - 1);
2075 if (csum != ext_hdr->checksum)
Pali Rohár03345b92021-07-23 11:14:01 +02002076 return -FDT_ERR_BADSTRUCTURE;
2077 }
Pali Rohár17414cb2021-11-08 18:12:44 +01002078
Pali Roháre581f192022-02-17 10:43:36 +01002079 for_each_bin_hdr_v0(bhdr, ptr) {
2080 csum = image_checksum8(bhdr, (uint8_t *)&bhdr->checksum - (uint8_t *)bhdr - 1);
2081 if (csum != bhdr->checksum)
2082 return -FDT_ERR_BADSTRUCTURE;
2083
2084 if (bhdr->offset > sizeof(*bhdr) || bhdr->offset % 4 != 0)
2085 return -FDT_ERR_BADSTRUCTURE;
2086
2087 if (bhdr->offset + bhdr->size + 4 > sizeof(*bhdr) || bhdr->size % 4 != 0)
2088 return -FDT_ERR_BADSTRUCTURE;
2089
2090 if (image_checksum32((uint8_t *)bhdr + bhdr->offset, bhdr->size) !=
2091 *(uint32_t *)((uint8_t *)bhdr + bhdr->offset + bhdr->size))
2092 return -FDT_ERR_BADSTRUCTURE;
2093 }
2094
Pali Rohár17414cb2021-11-08 18:12:44 +01002095 blockid = mhdr->blockid;
2096 offset = le32_to_cpu(mhdr->srcaddr);
2097 size = le32_to_cpu(mhdr->blocksize);
Marek Behúnfa9caec2021-09-24 23:07:00 +02002098 } else if (kwbimage_version(ptr) == 1) {
Pali Rohárfdb575a2021-07-23 11:14:02 +02002099 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Marek Behúnb1a76502021-08-18 00:59:15 +02002100 const uint8_t *mhdr_end;
2101 struct opt_hdr_v1 *ohdr;
Pali Rohárfdb575a2021-07-23 11:14:02 +02002102
Marek Behúnb1a76502021-08-18 00:59:15 +02002103 mhdr_end = (uint8_t *)mhdr + header_size;
2104 for_each_opt_hdr_v1 (ohdr, ptr)
2105 if (!opt_hdr_v1_valid_size(ohdr, mhdr_end))
2106 return -FDT_ERR_BADSTRUCTURE;
Pali Rohár48bc68c2021-07-23 11:14:03 +02002107
Pali Rohár17414cb2021-11-08 18:12:44 +01002108 blockid = mhdr->blockid;
Pali Rohár48bc68c2021-07-23 11:14:03 +02002109 offset = le32_to_cpu(mhdr->srcaddr);
Pali Rohár17414cb2021-11-08 18:12:44 +01002110 size = le32_to_cpu(mhdr->blocksize);
2111 } else {
2112 return -FDT_ERR_BADSTRUCTURE;
2113 }
Pali Rohár48bc68c2021-07-23 11:14:03 +02002114
Pali Rohár15c893782023-03-29 21:25:56 +02002115 if (size < 4 || size % 4 != 0)
2116 return -FDT_ERR_BADSTRUCTURE;
2117
Pali Rohár17414cb2021-11-08 18:12:44 +01002118 /*
2119 * For SATA srcaddr is specified in number of sectors.
Pali Rohár15c893782023-03-29 21:25:56 +02002120 * Try all possible sector sizes which are power of two,
2121 * at least 512 bytes and up to the 32 kB.
Pali Rohár17414cb2021-11-08 18:12:44 +01002122 */
Pali Rohár15c893782023-03-29 21:25:56 +02002123 if (blockid == IBR_HDR_SATA_ID) {
2124 for (blksz = 512; blksz < 0x10000; blksz *= 2) {
2125 if (offset * blksz > image_size || offset * blksz + size > image_size)
2126 break;
2127
2128 if (image_checksum32(ptr + offset * blksz, size - 4) ==
2129 *(uint32_t *)(ptr + offset * blksz + size - 4)) {
2130 params->bl_len = blksz;
2131 return 0;
2132 }
2133 }
2134
2135 return -FDT_ERR_BADSTRUCTURE;
2136 }
Pali Rohár48bc68c2021-07-23 11:14:03 +02002137
Pali Rohár17414cb2021-11-08 18:12:44 +01002138 /*
Pali Rohár17414cb2021-11-08 18:12:44 +01002139 * For PCIe srcaddr is always set to 0xFFFFFFFF.
2140 * This expects that data starts after all headers.
2141 */
2142 if (blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
2143 offset = header_size;
Pali Rohár48bc68c2021-07-23 11:14:03 +02002144
Pali Rohár15c893782023-03-29 21:25:56 +02002145 if (offset % 4 != 0 || offset > image_size || offset + size > image_size)
Pali Rohár17414cb2021-11-08 18:12:44 +01002146 return -FDT_ERR_BADSTRUCTURE;
Pali Rohár48bc68c2021-07-23 11:14:03 +02002147
Pali Rohár17414cb2021-11-08 18:12:44 +01002148 if (image_checksum32(ptr + offset, size - 4) !=
2149 *(uint32_t *)(ptr + offset + size - 4))
Pali Rohár010e2522021-08-11 10:14:14 +02002150 return -FDT_ERR_BADSTRUCTURE;
Pali Rohárfdb575a2021-07-23 11:14:02 +02002151
Pali Rohár15c893782023-03-29 21:25:56 +02002152 params->bl_len = 1;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302153 return 0;
2154}
2155
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002156static int kwbimage_generate(struct image_tool_params *params,
2157 struct image_type_params *tparams)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302158{
Patrick Wildtef84f822017-05-10 22:18:54 +02002159 FILE *fcfg;
Pali Rohárcfb60a92021-07-23 11:13:56 +02002160 struct stat s;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002161 int alloc_len;
Pali Rohár04785152021-07-23 11:13:57 +02002162 int bootfrom;
Patrick Wildtef84f822017-05-10 22:18:54 +02002163 int version;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002164 void *hdr;
Patrick Wildtef84f822017-05-10 22:18:54 +02002165 int ret;
Pali Rohár5a5e5462023-03-29 21:25:55 +02002166 int align, size;
Pali Rohár15c893782023-03-29 21:25:56 +02002167 unsigned int satablksz;
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302168
Patrick Wildtef84f822017-05-10 22:18:54 +02002169 fcfg = fopen(params->imagename, "r");
2170 if (!fcfg) {
2171 fprintf(stderr, "Could not open input file %s\n",
2172 params->imagename);
2173 exit(EXIT_FAILURE);
2174 }
2175
Pali Rohár3e4756b2023-01-21 20:11:28 +01002176 if (params->skipcpy) {
2177 s.st_size = 0;
2178 } else if (stat(params->datafile, &s)) {
Pali Rohárcfb60a92021-07-23 11:13:56 +02002179 fprintf(stderr, "Could not stat data file %s: %s\n",
2180 params->datafile, strerror(errno));
2181 exit(EXIT_FAILURE);
2182 }
2183
Patrick Wildtef84f822017-05-10 22:18:54 +02002184 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
2185 sizeof(struct image_cfg_element));
2186 if (!image_cfg) {
2187 fprintf(stderr, "Cannot allocate memory\n");
2188 fclose(fcfg);
2189 exit(EXIT_FAILURE);
2190 }
2191
2192 memset(image_cfg, 0,
2193 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
2194 rewind(fcfg);
2195
2196 ret = image_create_config_parse(fcfg);
2197 fclose(fcfg);
2198 if (ret) {
2199 free(image_cfg);
2200 exit(EXIT_FAILURE);
2201 }
2202
Pali Rohár04785152021-07-23 11:13:57 +02002203 bootfrom = image_get_bootfrom();
Patrick Wildtef84f822017-05-10 22:18:54 +02002204 version = image_get_version();
Pali Rohár15c893782023-03-29 21:25:56 +02002205 satablksz = image_get_satablksz();
Patrick Wildtef84f822017-05-10 22:18:54 +02002206 switch (version) {
2207 /*
2208 * Fallback to version 0 if no version is provided in the
2209 * cfg file
2210 */
2211 case -1:
2212 case 0:
Pali Rohárecb3ca72021-11-08 18:12:50 +01002213 alloc_len = image_headersz_v0(NULL);
Patrick Wildtef84f822017-05-10 22:18:54 +02002214 break;
2215
2216 case 1:
Mario Six855cf9e2017-01-11 16:00:57 +01002217 alloc_len = image_headersz_v1(NULL);
Pali Rohár4bfc16e2022-01-12 18:20:42 +01002218 if (!alloc_len) {
2219 free(image_cfg);
2220 exit(EXIT_FAILURE);
2221 }
Pali Rohár08c51742022-01-12 18:20:43 +01002222 if (alloc_len > 192*1024) {
2223 fprintf(stderr, "Header is too big (%u bytes), maximal kwbimage header size is %u bytes\n", alloc_len, 192*1024);
2224 free(image_cfg);
2225 exit(EXIT_FAILURE);
2226 }
Patrick Wildtef84f822017-05-10 22:18:54 +02002227 break;
2228
2229 default:
2230 fprintf(stderr, "Unsupported version %d\n", version);
2231 free(image_cfg);
2232 exit(EXIT_FAILURE);
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002233 }
2234
Pali Rohár534c2f82023-01-29 15:00:45 +01002235 alloc_len = image_headersz_align(alloc_len, image_get_bootfrom());
2236
Patrick Wildtef84f822017-05-10 22:18:54 +02002237 free(image_cfg);
2238
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002239 hdr = malloc(alloc_len);
2240 if (!hdr) {
2241 fprintf(stderr, "%s: malloc return failure: %s\n",
2242 params->cmdname, strerror(errno));
2243 exit(EXIT_FAILURE);
2244 }
2245
2246 memset(hdr, 0, alloc_len);
2247 tparams->header_size = alloc_len;
2248 tparams->hdr = hdr;
2249
Pali Rohár3e4756b2023-01-21 20:11:28 +01002250 /*
Pali Rohár15c893782023-03-29 21:25:56 +02002251 * Final SATA images must be aligned to disk block size.
2252 * Final SDIO images must be aligned to 512 bytes.
Pali Rohár5a5e5462023-03-29 21:25:55 +02002253 * Final SPI and NAND images must be aligned to 256 bytes.
2254 * Final UART image must be aligned to 128 bytes.
2255 */
Pali Rohár15c893782023-03-29 21:25:56 +02002256 if (bootfrom == IBR_HDR_SATA_ID)
2257 align = satablksz;
2258 else if (bootfrom == IBR_HDR_SDIO_ID)
Pali Rohár5a5e5462023-03-29 21:25:55 +02002259 align = 512;
2260 else if (bootfrom == IBR_HDR_SPI_ID || bootfrom == IBR_HDR_NAND_ID)
2261 align = 256;
2262 else if (bootfrom == IBR_HDR_UART_ID)
2263 align = 128;
2264 else
2265 align = 4;
2266
2267 /*
2268 * The resulting image needs to be 4-byte aligned. At least
2269 * the Marvell hdrparser tool complains if its unaligned.
2270 * After the image data is stored 4-byte checksum.
2271 */
2272 size = 4 + (align - (alloc_len + s.st_size + 4) % align) % align;
2273
2274 /*
Pali Rohár3e4756b2023-01-21 20:11:28 +01002275 * This function should return aligned size of the datafile.
2276 * When skipcpy is set (datafile is skipped) then return value of this
2277 * function is ignored, so we have to put required kwbimage aligning
2278 * into the preallocated header size.
2279 */
2280 if (params->skipcpy) {
Pali Rohár5a5e5462023-03-29 21:25:55 +02002281 tparams->header_size += size;
Pali Rohár3e4756b2023-01-21 20:11:28 +01002282 return 0;
2283 } else {
Pali Rohár5a5e5462023-03-29 21:25:55 +02002284 return size;
Pali Rohár3e4756b2023-01-21 20:11:28 +01002285 }
2286}
2287
Pali Rohár3d015782022-01-12 18:20:50 +01002288static int kwbimage_generate_config(void *ptr, struct image_tool_params *params)
2289{
2290 struct main_hdr_v0 *mhdr0 = (struct main_hdr_v0 *)ptr;
2291 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
2292 size_t header_size = kwbheader_size(ptr);
2293 struct register_set_hdr_v1 *regset_hdr;
2294 struct ext_hdr_v0_reg *regdata;
2295 struct ext_hdr_v0 *ehdr0;
Pali Roháre581f192022-02-17 10:43:36 +01002296 struct bin_hdr_v0 *bhdr0;
Pali Rohár3d015782022-01-12 18:20:50 +01002297 struct opt_hdr_v1 *ohdr;
Pali Rohárc68fca12023-01-08 13:53:48 +01002298 int regset_count;
Pali Roháre581f192022-02-17 10:43:36 +01002299 int params_count;
Pali Rohár3d015782022-01-12 18:20:50 +01002300 unsigned offset;
Pali Roháre581f192022-02-17 10:43:36 +01002301 int is_v0_ext;
Pali Rohár3d015782022-01-12 18:20:50 +01002302 int cur_idx;
2303 int version;
2304 FILE *f;
2305 int i;
2306
2307 f = fopen(params->outfile, "w");
2308 if (!f) {
2309 fprintf(stderr, "Can't open \"%s\": %s\n", params->outfile, strerror(errno));
2310 return -1;
2311 }
2312
2313 version = kwbimage_version(ptr);
2314
Pali Roháre581f192022-02-17 10:43:36 +01002315 is_v0_ext = 0;
2316 if (version == 0) {
2317 if (mhdr0->ext > 1 || mhdr0->bin ||
2318 ((ehdr0 = ext_hdr_v0_first(ptr)) &&
2319 (ehdr0->match_addr || ehdr0->match_mask || ehdr0->match_value)))
2320 is_v0_ext = 1;
2321 }
2322
Pali Rohár3d015782022-01-12 18:20:50 +01002323 if (version != 0)
2324 fprintf(f, "VERSION %d\n", version);
2325
2326 fprintf(f, "BOOT_FROM %s\n", image_boot_mode_name(mhdr->blockid) ?: "<unknown>");
2327
2328 if (version == 0 && mhdr->blockid == IBR_HDR_NAND_ID)
2329 fprintf(f, "NAND_ECC_MODE %s\n", image_nand_ecc_mode_name(mhdr0->nandeccmode));
2330
2331 if (mhdr->blockid == IBR_HDR_NAND_ID)
Pali Rohárf248c702023-01-14 14:31:00 +01002332 fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)le16_to_cpu(mhdr->nandpagesize));
Pali Rohár3d015782022-01-12 18:20:50 +01002333
Pali Rohárbb4f3a72023-01-08 16:22:34 +01002334 if (mhdr->blockid == IBR_HDR_NAND_ID && (version != 0 || is_v0_ext || mhdr->nandblocksize != 0)) {
Pali Rohár975ad212023-01-14 13:42:14 +01002335 if (mhdr->nandblocksize != 0) /* block size explicitly set in 64 kB unit */
2336 fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize * 64*1024);
2337 else if (le16_to_cpu(mhdr->nandpagesize) > 512)
2338 fprintf(f, "NAND_BLKSZ 0x10000\n"); /* large page NAND flash = 64 kB block size */
2339 else
2340 fprintf(f, "NAND_BLKSZ 0x4000\n"); /* small page NAND flash = 16 kB block size */
2341 }
Pali Roháre581f192022-02-17 10:43:36 +01002342
Pali Rohárec19f952023-01-14 14:46:09 +01002343 if (mhdr->blockid == IBR_HDR_NAND_ID && (version != 0 || is_v0_ext))
Pali Rohár3d015782022-01-12 18:20:50 +01002344 fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation);
Pali Rohár3d015782022-01-12 18:20:50 +01002345
2346 if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID)
2347 fprintf(f, "SATA_PIO_MODE %u\n", (unsigned)mhdr0->satapiomode);
2348
Pali Rohár15c893782023-03-29 21:25:56 +02002349 if (mhdr->blockid == IBR_HDR_SATA_ID)
2350 fprintf(f, "SATA_BLKSZ %u\n", params->bl_len);
2351
Pali Rohár3d015782022-01-12 18:20:50 +01002352 /*
2353 * Addresses and sizes which are specified by mkimage command line
2354 * arguments and not in kwbimage config file
2355 */
2356
2357 if (version != 0)
2358 fprintf(f, "#HEADER_SIZE 0x%x\n",
2359 ((unsigned)mhdr->headersz_msb << 8) | le16_to_cpu(mhdr->headersz_lsb));
2360
2361 fprintf(f, "#SRC_ADDRESS 0x%x\n", le32_to_cpu(mhdr->srcaddr));
2362 fprintf(f, "#BLOCK_SIZE 0x%x\n", le32_to_cpu(mhdr->blocksize));
2363 fprintf(f, "#DEST_ADDRESS 0x%08x\n", le32_to_cpu(mhdr->destaddr));
2364 fprintf(f, "#EXEC_ADDRESS 0x%08x\n", le32_to_cpu(mhdr->execaddr));
2365
2366 if (version != 0) {
2367 if (options_to_baudrate(mhdr->options))
2368 fprintf(f, "BAUDRATE %u\n", options_to_baudrate(mhdr->options));
2369 if (options_to_baudrate(mhdr->options) ||
2370 ((mhdr->options >> 3) & 0x3) || ((mhdr->options >> 5) & 0x7)) {
2371 fprintf(f, "UART_PORT %u\n", (unsigned)((mhdr->options >> 3) & 0x3));
2372 fprintf(f, "UART_MPP 0x%x\n", (unsigned)((mhdr->options >> 5) & 0x7));
2373 }
2374 if (mhdr->flags & 0x1)
2375 fprintf(f, "DEBUG 1\n");
2376 }
2377
2378 cur_idx = 1;
2379 for_each_opt_hdr_v1(ohdr, ptr) {
2380 if (ohdr->headertype == OPT_HDR_V1_SECURE_TYPE) {
2381 fprintf(f, "#SECURE_HEADER\n");
2382 } else if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) {
2383 fprintf(f, "BINARY binary%d.bin", cur_idx);
2384 for (i = 0; i < ohdr->data[0]; i++)
2385 fprintf(f, " 0x%x", le32_to_cpu(((uint32_t *)ohdr->data)[i + 1]));
2386 offset = (unsigned)((uint8_t *)ohdr - (uint8_t *)mhdr) + 8 + 4 * ohdr->data[0];
2387 fprintf(f, " LOAD_ADDRESS 0x%08x\n", 0x40000000 + offset);
2388 fprintf(f, " # for CPU SHEEVA: LOAD_ADDRESS 0x%08x\n", 0x40004000 + offset);
2389 cur_idx++;
2390 } else if (ohdr->headertype == OPT_HDR_V1_REGISTER_TYPE) {
2391 regset_hdr = (struct register_set_hdr_v1 *)ohdr;
Pali Rohárc68fca12023-01-08 13:53:48 +01002392 if (opt_hdr_v1_size(ohdr) > sizeof(*ohdr))
2393 regset_count = (opt_hdr_v1_size(ohdr) - sizeof(*ohdr)) /
2394 sizeof(regset_hdr->data[0].entry);
2395 else
2396 regset_count = 0;
2397 for (i = 0; i < regset_count; i++)
Pali Rohár3d015782022-01-12 18:20:50 +01002398 fprintf(f, "DATA 0x%08x 0x%08x\n",
2399 le32_to_cpu(regset_hdr->data[i].entry.address),
2400 le32_to_cpu(regset_hdr->data[i].entry.value));
Pali Rohárc68fca12023-01-08 13:53:48 +01002401 if (regset_count > 0) {
2402 if (regset_hdr->data[regset_count-1].last_entry.delay !=
2403 REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP)
Pali Rohár3d015782022-01-12 18:20:50 +01002404 fprintf(f, "DATA_DELAY %u\n",
Pali Rohárc68fca12023-01-08 13:53:48 +01002405 (unsigned)regset_hdr->data[regset_count-1].last_entry.delay);
Pali Rohár3d015782022-01-12 18:20:50 +01002406 else
2407 fprintf(f, "DATA_DELAY SDRAM_SETUP\n");
2408 }
2409 }
2410 }
2411
Pali Roháre581f192022-02-17 10:43:36 +01002412 if (version == 0 && !is_v0_ext && le16_to_cpu(mhdr0->ddrinitdelay))
2413 fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)le16_to_cpu(mhdr0->ddrinitdelay));
2414
2415 for_each_ext_hdr_v0(ehdr0, ptr) {
2416 if (is_v0_ext) {
2417 fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
2418 le32_to_cpu(ehdr0->match_addr),
2419 le32_to_cpu(ehdr0->match_mask),
2420 le32_to_cpu(ehdr0->match_value));
2421 if (ehdr0->rsvd1[0] || ehdr0->rsvd1[1] || ehdr0->rsvd1[2] ||
2422 ehdr0->rsvd1[3] || ehdr0->rsvd1[4] || ehdr0->rsvd1[5] ||
2423 ehdr0->rsvd1[6] || ehdr0->rsvd1[7])
2424 fprintf(f, "#DDR_RSVD1 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
2425 ehdr0->rsvd1[0], ehdr0->rsvd1[1], ehdr0->rsvd1[2],
2426 ehdr0->rsvd1[3], ehdr0->rsvd1[4], ehdr0->rsvd1[5],
2427 ehdr0->rsvd1[6], ehdr0->rsvd1[7]);
2428 if (ehdr0->rsvd2[0] || ehdr0->rsvd2[1] || ehdr0->rsvd2[2] ||
2429 ehdr0->rsvd2[3] || ehdr0->rsvd2[4] || ehdr0->rsvd2[5] ||
2430 ehdr0->rsvd2[6])
2431 fprintf(f, "#DDR_RSVD2 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
2432 ehdr0->rsvd2[0], ehdr0->rsvd2[1], ehdr0->rsvd2[2],
2433 ehdr0->rsvd2[3], ehdr0->rsvd2[4], ehdr0->rsvd2[5],
2434 ehdr0->rsvd2[6]);
2435 if (ehdr0->ddrwritetype)
2436 fprintf(f, "DDR_WRITE_TYPE %u\n", (unsigned)ehdr0->ddrwritetype);
2437 if (ehdr0->ddrresetmpp)
2438 fprintf(f, "DDR_RESET_MPP 0x%x\n", (unsigned)ehdr0->ddrresetmpp);
2439 if (ehdr0->ddrclkenmpp)
2440 fprintf(f, "DDR_CLKEN_MPP 0x%x\n", (unsigned)ehdr0->ddrclkenmpp);
2441 if (ehdr0->ddrinitdelay)
2442 fprintf(f, "DDR_INIT_DELAY %u\n", (unsigned)ehdr0->ddrinitdelay);
2443 }
2444
Pali Rohár3d015782022-01-12 18:20:50 +01002445 if (ehdr0->offset) {
2446 for (regdata = (struct ext_hdr_v0_reg *)((uint8_t *)ptr + ehdr0->offset);
Pali Rohár0e129b82022-02-13 01:04:33 +01002447 (uint8_t *)regdata < (uint8_t *)ptr + header_size &&
2448 (regdata->raddr || regdata->rdata);
Pali Rohár3d015782022-01-12 18:20:50 +01002449 regdata++)
2450 fprintf(f, "DATA 0x%08x 0x%08x\n", le32_to_cpu(regdata->raddr),
2451 le32_to_cpu(regdata->rdata));
Pali Rohár0e129b82022-02-13 01:04:33 +01002452 if ((uint8_t *)regdata != (uint8_t *)ptr + ehdr0->offset)
2453 fprintf(f, "DATA 0x0 0x0\n");
Pali Rohár3d015782022-01-12 18:20:50 +01002454 }
Pali Roháre581f192022-02-17 10:43:36 +01002455
2456 if (le32_to_cpu(ehdr0->enddelay))
2457 fprintf(f, "DATA_DELAY %u\n", le32_to_cpu(ehdr0->enddelay));
2458 else if (is_v0_ext)
2459 fprintf(f, "DATA_DELAY SDRAM_SETUP\n");
Pali Rohár3d015782022-01-12 18:20:50 +01002460 }
2461
Pali Roháre581f192022-02-17 10:43:36 +01002462 cur_idx = 1;
2463 for_each_bin_hdr_v0(bhdr0, ptr) {
2464 fprintf(f, "\nMATCH ADDRESS 0x%08x MASK 0x%08x VALUE 0x%08x\n",
2465 le32_to_cpu(bhdr0->match_addr),
2466 le32_to_cpu(bhdr0->match_mask),
2467 le32_to_cpu(bhdr0->match_value));
2468
2469 fprintf(f, "BINARY binary%d.bin", cur_idx);
2470 params_count = fls4(bhdr0->params_flags & 0xF);
2471 for (i = 0; i < params_count; i++)
2472 fprintf(f, " 0x%x", (bhdr0->params[i] & (1 << i)) ? bhdr0->params[i] : 0);
2473 fprintf(f, " LOAD_ADDRESS 0x%08x", le32_to_cpu(bhdr0->destaddr));
2474 fprintf(f, " EXEC_ADDRESS 0x%08x", le32_to_cpu(bhdr0->execaddr));
2475 fprintf(f, "\n");
2476
2477 fprintf(f, "#BINARY_OFFSET 0x%x\n", le32_to_cpu(bhdr0->offset));
2478 fprintf(f, "#BINARY_SIZE 0x%x\n", le32_to_cpu(bhdr0->size));
2479
2480 if (bhdr0->rsvd1)
2481 fprintf(f, "#BINARY_RSVD1 0x%x\n", (unsigned)bhdr0->rsvd1);
2482 if (bhdr0->rsvd2)
2483 fprintf(f, "#BINARY_RSVD2 0x%x\n", (unsigned)bhdr0->rsvd2);
2484
2485 cur_idx++;
2486 }
Pali Rohár3d015782022-01-12 18:20:50 +01002487
2488 /* Undocumented reserved fields */
2489
2490 if (version == 0 && (mhdr0->rsvd1[0] || mhdr0->rsvd1[1] || mhdr0->rsvd1[2]))
2491 fprintf(f, "#RSVD1 0x%x 0x%x 0x%x\n", (unsigned)mhdr0->rsvd1[0],
2492 (unsigned)mhdr0->rsvd1[1], (unsigned)mhdr0->rsvd1[2]);
2493
Pali Rohár3d015782022-01-12 18:20:50 +01002494 if (version == 0 && le16_to_cpu(mhdr0->rsvd2))
2495 fprintf(f, "#RSVD2 0x%x\n", (unsigned)le16_to_cpu(mhdr0->rsvd2));
2496
2497 if (version != 0 && mhdr->reserved4)
2498 fprintf(f, "#RESERVED4 0x%x\n", (unsigned)mhdr->reserved4);
2499
2500 if (version != 0 && mhdr->reserved5)
2501 fprintf(f, "#RESERVED5 0x%x\n", (unsigned)le16_to_cpu(mhdr->reserved5));
2502
2503 fclose(f);
2504
2505 return 0;
2506}
2507
Pali Rohár5ec2c582021-07-23 11:14:34 +02002508static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params)
2509{
2510 struct main_hdr_v1 *mhdr = (struct main_hdr_v1 *)ptr;
Marek Behúnd1b0b032021-09-24 23:07:01 +02002511 size_t header_size = kwbheader_size(ptr);
Pali Roháre581f192022-02-17 10:43:36 +01002512 struct bin_hdr_v0 *bhdr;
Marek Behúnb1a76502021-08-18 00:59:15 +02002513 struct opt_hdr_v1 *ohdr;
Pali Rohár5ec2c582021-07-23 11:14:34 +02002514 int idx = params->pflag;
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002515 int cur_idx;
Pali Rohár5ec2c582021-07-23 11:14:34 +02002516 uint32_t offset;
2517 ulong image;
2518 ulong size;
2519
Pali Rohár3d015782022-01-12 18:20:50 +01002520 /* Generate kwbimage config file when '-p -1' is specified */
2521 if (idx == -1)
2522 return kwbimage_generate_config(ptr, params);
2523
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002524 image = 0;
2525 size = 0;
Pali Rohár5ec2c582021-07-23 11:14:34 +02002526
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002527 if (idx == 0) {
2528 /* Extract data image when -p is not specified or when '-p 0' is specified */
2529 offset = le32_to_cpu(mhdr->srcaddr);
Marek Behúnb1a76502021-08-18 00:59:15 +02002530
Pali Rohár90e47002023-01-21 13:34:55 +01002531 if (mhdr->blockid == IBR_HDR_SATA_ID)
Pali Rohár15c893782023-03-29 21:25:56 +02002532 offset *= params->bl_len;
Pali Rohár5ec2c582021-07-23 11:14:34 +02002533
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002534 if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
2535 offset = header_size;
Pali Rohár5ec2c582021-07-23 11:14:34 +02002536
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002537 image = (ulong)((uint8_t *)ptr + offset);
2538 size = le32_to_cpu(mhdr->blocksize) - 4;
2539 } else {
2540 /* Extract N-th binary header executabe image when other '-p N' is specified */
2541 cur_idx = 1;
2542 for_each_opt_hdr_v1(ohdr, ptr) {
2543 if (ohdr->headertype != OPT_HDR_V1_BINARY_TYPE)
2544 continue;
Pali Rohár5ec2c582021-07-23 11:14:34 +02002545
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002546 if (idx == cur_idx) {
2547 image = (ulong)&ohdr->data[4 + 4 * ohdr->data[0]];
2548 size = opt_hdr_v1_size(ohdr) - 12 - 4 * ohdr->data[0];
2549 break;
2550 }
Pali Rohár5ec2c582021-07-23 11:14:34 +02002551
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002552 ++cur_idx;
2553 }
Pali Roháre581f192022-02-17 10:43:36 +01002554 for_each_bin_hdr_v0(bhdr, ptr) {
2555 if (idx == cur_idx) {
2556 image = (ulong)bhdr + bhdr->offset;
2557 size = bhdr->size;
2558 break;
2559 }
2560 ++cur_idx;
2561 }
Pali Rohár5ec2c582021-07-23 11:14:34 +02002562
Pali Rohár7e18d0a2022-01-12 18:20:53 +01002563 if (!image) {
2564 fprintf(stderr, "Argument -p %d is invalid\n", idx);
2565 fprintf(stderr, "Available subimages:\n");
2566 fprintf(stderr, " -p -1 - kwbimage config file\n");
2567 fprintf(stderr, " -p 0 - data image\n");
2568 if (cur_idx - 1 > 0)
2569 fprintf(stderr, " -p N - Nth binary header image (totally: %d)\n",
2570 cur_idx - 1);
2571 return -1;
2572 }
2573 }
Pali Rohár5ec2c582021-07-23 11:14:34 +02002574
Pali Rohár5ec2c582021-07-23 11:14:34 +02002575 return imagetool_save_subimage(params->outfile, image, size);
2576}
2577
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002578static int kwbimage_check_params(struct image_tool_params *params)
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302579{
Pali Rohár2dbaf402022-02-17 10:43:37 +01002580 if (!params->lflag && !params->iflag && !params->pflag &&
Pali Rohára0722ce2022-01-12 18:20:54 +01002581 (!params->imagename || !strlen(params->imagename))) {
Mario Sixd6009d72017-01-11 16:00:54 +01002582 char *msg = "Configuration file for kwbimage creation omitted";
2583
2584 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
Pali Rohárac0c3482021-11-08 18:12:45 +01002585 return 1;
Stefan Roese3b8b19d2014-10-22 12:13:23 +02002586 }
2587
Pali Rohár3e4756b2023-01-21 20:11:28 +01002588 return (params->dflag && (params->fflag || params->lflag || params->skipcpy)) ||
Pali Rohár6d5ed692023-01-21 13:00:21 +01002589 (params->fflag) ||
Pali Rohárc6178dc2023-01-18 21:42:40 +01002590 (params->lflag && (params->dflag || params->fflag));
Prafulla Wadaskar07329412009-09-07 15:05:02 +05302591}
2592
2593/*
2594 * kwbimage type parameters definition
2595 */
Guilherme Maciel Ferreira28be1cf2015-01-15 02:48:07 -02002596U_BOOT_IMAGE_TYPE(
2597 kwbimage,
2598 "Marvell MVEBU Boot Image support",
2599 0,
2600 NULL,
2601 kwbimage_check_params,
2602 kwbimage_verify_header,
2603 kwbimage_print_header,
2604 kwbimage_set_header,
Pali Rohár5ec2c582021-07-23 11:14:34 +02002605 kwbimage_extract_subimage,
Guilherme Maciel Ferreira28be1cf2015-01-15 02:48:07 -02002606 kwbimage_check_image_types,
2607 NULL,
2608 kwbimage_generate
2609);