blob: 276069a0efc275b53b45f7a20564e5afb52c5550 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +02002/*
3 * Copyright (C) 2016 Marvell International Ltd.
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +02004 * https://spdx.org/licenses
5 */
6
7#include <config.h>
8#include <common.h>
9#include <command.h>
Simon Glass7b51b572019-08-01 09:46:52 -060010#include <env.h>
Simon Glassb79fdc72020-05-10 11:39:54 -060011#include <flash.h>
Simon Glass8e8ccfe2019-12-28 10:45:03 -070012#include <image.h>
Simon Glass90526e92020-05-10 11:39:56 -060013#include <net.h>
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +020014#include <vsprintf.h>
15#include <errno.h>
16#include <dm.h>
17
18#include <spi_flash.h>
19#include <spi.h>
20#include <nand.h>
21#include <usb.h>
22#include <fs.h>
23#include <mmc.h>
Konstantin Porotchkine559ef12017-01-08 16:52:06 +020024#ifdef CONFIG_BLK
25#include <blk.h>
26#endif
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +020027#include <u-boot/sha1.h>
28#include <u-boot/sha256.h>
Pali Rohár93c13582022-07-26 16:11:58 +020029#include <u-boot/sha512.h>
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +020030
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +020031#if defined(CONFIG_ARMADA_8K)
32#define MAIN_HDR_MAGIC 0xB105B002
33
34struct mvebu_image_header {
35 u32 magic; /* 0-3 */
36 u32 prolog_size; /* 4-7 */
37 u32 prolog_checksum; /* 8-11 */
38 u32 boot_image_size; /* 12-15 */
39 u32 boot_image_checksum; /* 16-19 */
40 u32 rsrvd0; /* 20-23 */
41 u32 load_addr; /* 24-27 */
42 u32 exec_addr; /* 28-31 */
43 u8 uart_cfg; /* 32 */
44 u8 baudrate; /* 33 */
45 u8 ext_count; /* 34 */
46 u8 aux_flags; /* 35 */
47 u32 io_arg_0; /* 36-39 */
48 u32 io_arg_1; /* 40-43 */
49 u32 io_arg_2; /* 43-47 */
50 u32 io_arg_3; /* 48-51 */
51 u32 rsrvd1; /* 52-55 */
52 u32 rsrvd2; /* 56-59 */
53 u32 rsrvd3; /* 60-63 */
54};
55#elif defined(CONFIG_ARMADA_3700) /* A3700 */
56#define HASH_SUM_LEN 16
57#define IMAGE_VERSION_3_6_0 0x030600
58#define IMAGE_VERSION_3_5_0 0x030500
59
Pali Rohár5d2f7d32022-07-26 16:11:56 +020060struct tim_boot_flash_sign {
61 unsigned int id;
62 const char *name;
63};
64
65struct tim_boot_flash_sign tim_boot_flash_signs[] = {
66 { 0x454d4d08, "mmc" },
67 { 0x454d4d0b, "mmc" },
68 { 0x5350490a, "spi" },
69 { 0x5350491a, "nand" },
70 { 0x55415223, "uart" },
71 { 0x53415432, "sata" },
72 {},
73};
74
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +020075struct common_tim_data {
76 u32 version;
77 u32 identifier;
78 u32 trusted;
79 u32 issue_date;
80 u32 oem_unique_id;
81 u32 reserved[5]; /* Reserve 20 bytes */
82 u32 boot_flash_sign;
83 u32 num_images;
84 u32 num_keys;
85 u32 size_of_reserved;
86};
87
88struct mvebu_image_info {
89 u32 image_id;
90 u32 next_image_id;
91 u32 flash_entry_addr;
92 u32 load_addr;
93 u32 image_size;
94 u32 image_size_to_hash;
95 u32 hash_algorithm_id;
96 u32 hash[HASH_SUM_LEN]; /* Reserve 512 bits for the hash */
97 u32 partition_number;
98 u32 enc_algorithm_id;
99 u32 encrypt_start_offset;
100 u32 encrypt_size;
101};
Pali Rohár5d2f7d32022-07-26 16:11:56 +0200102#elif defined(CONFIG_ARMADA_32BIT)
Joel Johnson8ec6db72020-04-17 09:38:04 -0600103
Pali Rohár7af368f2021-10-22 12:41:10 +0200104/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */
Joel Johnson8ec6db72020-04-17 09:38:04 -0600105struct a38x_main_hdr_v1 {
106 u8 blockid; /* 0x0 */
107 u8 flags; /* 0x1 */
Pali Rohár33cdd9e2021-10-22 12:37:48 +0200108 u16 nandpagesize; /* 0x2-0x3 */
Joel Johnson8ec6db72020-04-17 09:38:04 -0600109 u32 blocksize; /* 0x4-0x7 */
110 u8 version; /* 0x8 */
111 u8 headersz_msb; /* 0x9 */
112 u16 headersz_lsb; /* 0xA-0xB */
113 u32 srcaddr; /* 0xC-0xF */
114 u32 destaddr; /* 0x10-0x13 */
115 u32 execaddr; /* 0x14-0x17 */
116 u8 options; /* 0x18 */
117 u8 nandblocksize; /* 0x19 */
118 u8 nandbadblklocation; /* 0x1A */
119 u8 reserved4; /* 0x1B */
120 u16 reserved5; /* 0x1C-0x1D */
121 u8 ext; /* 0x1E */
122 u8 checksum; /* 0x1F */
123};
Joel Johnson658854a2020-04-17 09:38:06 -0600124
125struct a38x_boot_mode {
126 unsigned int id;
127 const char *name;
128};
129
130/* The blockid header field values used to indicate boot device of image */
131struct a38x_boot_mode a38x_boot_modes[] = {
132 { 0x4D, "i2c" },
133 { 0x5A, "spi" },
134 { 0x69, "uart" },
135 { 0x78, "sata" },
136 { 0x8B, "nand" },
137 { 0x9C, "pex" },
138 { 0xAE, "mmc" },
139 {},
140};
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200141
Pali Rohár5d2f7d32022-07-26 16:11:56 +0200142#endif
143
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200144struct bubt_dev {
145 char name[8];
146 size_t (*read)(const char *file_name);
147 int (*write)(size_t image_size);
148 int (*active)(void);
149};
150
151static ulong get_load_addr(void)
152{
153 const char *addr_str;
154 unsigned long addr;
155
Simon Glass00caae62017-08-03 12:22:12 -0600156 addr_str = env_get("loadaddr");
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200157 if (addr_str)
Simon Glass7e5f4602021-07-24 09:03:29 -0600158 addr = hextoul(addr_str, NULL);
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200159 else
160 addr = CONFIG_SYS_LOAD_ADDR;
161
162 return addr;
163}
164
165/********************************************************************
166 * eMMC services
167 ********************************************************************/
Jean-Jacques Hiblotd6400c32018-01-04 15:23:32 +0100168#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(MMC_WRITE)
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200169static int mmc_burn_image(size_t image_size)
170{
171 struct mmc *mmc;
172 lbaint_t start_lba;
173 lbaint_t blk_count;
174 ulong blk_written;
175 int err;
176 const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
Konstantin Porotchkine559ef12017-01-08 16:52:06 +0200177#ifdef CONFIG_BLK
178 struct blk_desc *blk_desc;
179#endif
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200180 mmc = find_mmc_device(mmc_dev_num);
181 if (!mmc) {
182 printf("No SD/MMC/eMMC card found\n");
183 return -ENOMEDIUM;
184 }
185
186 err = mmc_init(mmc);
187 if (err) {
188 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
189 mmc_dev_num);
190 return err;
191 }
192
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200193 /* SD reserves LBA-0 for MBR and boots from LBA-1,
194 * MMC/eMMC boots from LBA-0
195 */
196 start_lba = IS_SD(mmc) ? 1 : 0;
Konstantin Porotchkine559ef12017-01-08 16:52:06 +0200197#ifdef CONFIG_BLK
198 blk_count = image_size / mmc->write_bl_len;
199 if (image_size % mmc->write_bl_len)
200 blk_count += 1;
201
202 blk_desc = mmc_get_blk_desc(mmc);
203 if (!blk_desc) {
204 printf("Error - failed to obtain block descriptor\n");
205 return -ENODEV;
206 }
207 blk_written = blk_dwrite(blk_desc, start_lba, blk_count,
208 (void *)get_load_addr());
209#else
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200210 blk_count = image_size / mmc->block_dev.blksz;
211 if (image_size % mmc->block_dev.blksz)
212 blk_count += 1;
213
214 blk_written = mmc->block_dev.block_write(mmc_dev_num,
Konstantin Porotchkine559ef12017-01-08 16:52:06 +0200215 start_lba, blk_count,
216 (void *)get_load_addr());
217#endif /* CONFIG_BLK */
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200218 if (blk_written != blk_count) {
219 printf("Error - written %#lx blocks\n", blk_written);
220 return -ENOSPC;
221 }
222 printf("Done!\n");
223
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200224 return 0;
225}
226
227static size_t mmc_read_file(const char *file_name)
228{
229 loff_t act_read = 0;
230 int rc;
231 struct mmc *mmc;
232 const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
233
234 mmc = find_mmc_device(mmc_dev_num);
235 if (!mmc) {
236 printf("No SD/MMC/eMMC card found\n");
237 return 0;
238 }
239
240 if (mmc_init(mmc)) {
241 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
242 mmc_dev_num);
243 return 0;
244 }
245
246 /* Load from data partition (0) */
247 if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) {
248 printf("Error: MMC 0 not found\n");
249 return 0;
250 }
251
252 /* Perfrom file read */
253 rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
254 if (rc)
255 return 0;
256
257 return act_read;
258}
259
260static int is_mmc_active(void)
261{
262 return 1;
263}
264#else /* CONFIG_DM_MMC */
265static int mmc_burn_image(size_t image_size)
266{
267 return -ENODEV;
268}
269
270static size_t mmc_read_file(const char *file_name)
271{
272 return 0;
273}
274
275static int is_mmc_active(void)
276{
277 return 0;
278}
279#endif /* CONFIG_DM_MMC */
280
281/********************************************************************
282 * SPI services
283 ********************************************************************/
284#ifdef CONFIG_SPI_FLASH
285static int spi_burn_image(size_t image_size)
286{
287 int ret;
288 struct spi_flash *flash;
289 u32 erase_bytes;
290
291 /* Probe the SPI bus to get the flash device */
Tom Rini7e6a6fd2021-12-11 14:55:48 -0500292 flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
293 CONFIG_SF_DEFAULT_CS,
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200294 CONFIG_SF_DEFAULT_SPEED,
295 CONFIG_SF_DEFAULT_MODE);
296 if (!flash) {
297 printf("Failed to probe SPI Flash\n");
298 return -ENOMEDIUM;
299 }
300
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200301 erase_bytes = image_size +
302 (flash->erase_size - image_size % flash->erase_size);
303 printf("Erasing %d bytes (%d blocks) at offset 0 ...",
304 erase_bytes, erase_bytes / flash->erase_size);
305 ret = spi_flash_erase(flash, 0, erase_bytes);
306 if (ret)
307 printf("Error!\n");
308 else
309 printf("Done!\n");
310
311 printf("Writing %d bytes from 0x%lx to offset 0 ...",
312 (int)image_size, get_load_addr());
313 ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr());
314 if (ret)
315 printf("Error!\n");
316 else
317 printf("Done!\n");
318
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200319 return ret;
320}
321
322static int is_spi_active(void)
323{
324 return 1;
325}
326
327#else /* CONFIG_SPI_FLASH */
328static int spi_burn_image(size_t image_size)
329{
330 return -ENODEV;
331}
332
333static int is_spi_active(void)
334{
335 return 0;
336}
337#endif /* CONFIG_SPI_FLASH */
338
339/********************************************************************
340 * NAND services
341 ********************************************************************/
342#ifdef CONFIG_CMD_NAND
343static int nand_burn_image(size_t image_size)
344{
Konstantin Porotchkinf2ca24d2017-03-28 18:16:56 +0300345 int ret;
346 uint32_t block_size;
Grygorii Strashko7021c7e2017-06-26 19:13:02 -0500347 struct mtd_info *mtd;
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200348
Grygorii Strashko7021c7e2017-06-26 19:13:02 -0500349 mtd = get_nand_dev_by_index(nand_curr_device);
350 if (!mtd) {
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200351 puts("\nno devices available\n");
352 return -ENOMEDIUM;
353 }
Grygorii Strashko7021c7e2017-06-26 19:13:02 -0500354 block_size = mtd->erasesize;
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200355
356 /* Align U-Boot size to currently used blocksize */
357 image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
358
Joel Johnsonf41b85e2020-04-17 09:38:05 -0600359 /* Erase the U-Boot image space */
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200360 printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
Grygorii Strashko7021c7e2017-06-26 19:13:02 -0500361 ret = nand_erase(mtd, 0, image_size);
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200362 if (ret) {
363 printf("Error!\n");
364 goto error;
365 }
366 printf("Done!\n");
367
368 /* Write the image to flash */
Konstantin Porotchkinf2ca24d2017-03-28 18:16:56 +0300369 printf("Writing %d bytes from 0x%lx to offset 0 ... ",
370 (int)image_size, get_load_addr());
Grygorii Strashko7021c7e2017-06-26 19:13:02 -0500371 ret = nand_write(mtd, 0, &image_size, (void *)get_load_addr());
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200372 if (ret)
373 printf("Error!\n");
374 else
375 printf("Done!\n");
376
377error:
378 return ret;
379}
380
381static int is_nand_active(void)
382{
383 return 1;
384}
385
386#else /* CONFIG_CMD_NAND */
387static int nand_burn_image(size_t image_size)
388{
389 return -ENODEV;
390}
391
392static int is_nand_active(void)
393{
394 return 0;
395}
396#endif /* CONFIG_CMD_NAND */
397
398/********************************************************************
399 * USB services
400 ********************************************************************/
401#if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK)
402static size_t usb_read_file(const char *file_name)
403{
404 loff_t act_read = 0;
405 struct udevice *dev;
406 int rc;
407
408 usb_stop();
409
410 if (usb_init() < 0) {
411 printf("Error: usb_init failed\n");
412 return 0;
413 }
414
415 /* Try to recognize storage devices immediately */
416 blk_first_device(IF_TYPE_USB, &dev);
417 if (!dev) {
418 printf("Error: USB storage device not found\n");
419 return 0;
420 }
421
422 /* Always load from usb 0 */
423 if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
424 printf("Error: USB 0 not found\n");
425 return 0;
426 }
427
428 /* Perfrom file read */
429 rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
430 if (rc)
431 return 0;
432
433 return act_read;
434}
435
436static int is_usb_active(void)
437{
438 return 1;
439}
440
441#else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
442static size_t usb_read_file(const char *file_name)
443{
444 return 0;
445}
446
447static int is_usb_active(void)
448{
449 return 0;
450}
451#endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
452
453/********************************************************************
454 * Network services
455 ********************************************************************/
456#ifdef CONFIG_CMD_NET
457static size_t tftp_read_file(const char *file_name)
458{
Pali Rohár4b9521f2022-07-26 16:11:57 +0200459 int ret;
460
Simon Glassbb872dd2019-12-28 10:45:02 -0700461 /*
462 * update global variable image_load_addr before tftp file from network
463 */
464 image_load_addr = get_load_addr();
Pali Rohár4b9521f2022-07-26 16:11:57 +0200465 ret = net_loop(TFTPGET);
466 return ret > 0 ? ret : 0;
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200467}
468
469static int is_tftp_active(void)
470{
471 return 1;
472}
473
474#else
475static size_t tftp_read_file(const char *file_name)
476{
477 return 0;
478}
479
480static int is_tftp_active(void)
481{
482 return 0;
483}
484#endif /* CONFIG_CMD_NET */
485
486enum bubt_devices {
487 BUBT_DEV_NET = 0,
488 BUBT_DEV_USB,
489 BUBT_DEV_MMC,
490 BUBT_DEV_SPI,
491 BUBT_DEV_NAND,
492
493 BUBT_MAX_DEV
494};
495
496struct bubt_dev bubt_devs[BUBT_MAX_DEV] = {
497 {"tftp", tftp_read_file, NULL, is_tftp_active},
498 {"usb", usb_read_file, NULL, is_usb_active},
499 {"mmc", mmc_read_file, mmc_burn_image, is_mmc_active},
500 {"spi", NULL, spi_burn_image, is_spi_active},
501 {"nand", NULL, nand_burn_image, is_nand_active},
502};
503
504static int bubt_write_file(struct bubt_dev *dst, size_t image_size)
505{
506 if (!dst->write) {
507 printf("Error: Write not supported on device %s\n", dst->name);
508 return -ENOTSUPP;
509 }
510
511 return dst->write(image_size);
512}
513
514#if defined(CONFIG_ARMADA_8K)
515u32 do_checksum32(u32 *start, int32_t len)
516{
517 u32 sum = 0;
518 u32 *startp = start;
519
520 do {
521 sum += *startp;
522 startp++;
523 len -= 4;
524 } while (len > 0);
525
526 return sum;
527}
528
529static int check_image_header(void)
530{
531 struct mvebu_image_header *hdr =
532 (struct mvebu_image_header *)get_load_addr();
533 u32 header_len = hdr->prolog_size;
534 u32 checksum;
535 u32 checksum_ref = hdr->prolog_checksum;
536
537 /*
538 * For now compare checksum, and magic. Later we can
539 * verify more stuff on the header like interface type, etc
540 */
541 if (hdr->magic != MAIN_HDR_MAGIC) {
542 printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n",
543 hdr->magic, MAIN_HDR_MAGIC);
544 return -ENOEXEC;
545 }
546
547 /* The checksum value is discarded from checksum calculation */
548 hdr->prolog_checksum = 0;
549
550 checksum = do_checksum32((u32 *)hdr, header_len);
551 if (checksum != checksum_ref) {
552 printf("Error: Bad Image checksum. 0x%x != 0x%x\n",
553 checksum, checksum_ref);
554 return -ENOEXEC;
555 }
556
557 /* Restore the checksum before writing */
558 hdr->prolog_checksum = checksum_ref;
559 printf("Image checksum...OK!\n");
560
561 return 0;
562}
563#elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */
564static int check_image_header(void)
565{
566 struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr();
567 int image_num;
568 u8 hash_160_output[SHA1_SUM_LEN];
569 u8 hash_256_output[SHA256_SUM_LEN];
Pali Rohár93c13582022-07-26 16:11:58 +0200570 u8 hash_512_output[SHA512_SUM_LEN];
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200571 sha1_context hash1_text;
572 sha256_context hash256_text;
Pali Rohár93c13582022-07-26 16:11:58 +0200573 sha512_context hash512_text;
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200574 u8 *hash_output;
575 u32 hash_algorithm_id;
576 u32 image_size_to_hash;
577 u32 flash_entry_addr;
578 u32 *hash_value;
579 u32 internal_hash[HASH_SUM_LEN];
580 const u8 *buff;
581 u32 num_of_image = hdr->num_images;
582 u32 version = hdr->version;
583 u32 trusted = hdr->trusted;
584
585 /* bubt checksum validation only supports nontrusted images */
586 if (trusted == 1) {
587 printf("bypass image validation, ");
588 printf("only untrusted image is supported now\n");
589 return 0;
590 }
591 /* only supports image version 3.5 and 3.6 */
592 if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) {
593 printf("Error: Unsupported Image version = 0x%08x\n", version);
594 return -ENOEXEC;
595 }
596 /* validate images hash value */
597 for (image_num = 0; image_num < num_of_image; image_num++) {
598 struct mvebu_image_info *info =
599 (struct mvebu_image_info *)(get_load_addr() +
600 sizeof(struct common_tim_data) +
601 image_num * sizeof(struct mvebu_image_info));
602 hash_algorithm_id = info->hash_algorithm_id;
603 image_size_to_hash = info->image_size_to_hash;
604 flash_entry_addr = info->flash_entry_addr;
605 hash_value = info->hash;
606 buff = (const u8 *)(get_load_addr() + flash_entry_addr);
607
608 if (image_num == 0) {
609 /*
610 * The first image includes hash values in its content.
611 * For hash calculation, we need to save the original
612 * hash values to a local variable that will be
613 * copied back for comparsion and set all zeros to
614 * the orignal hash values for calculating new value.
615 * First image original format :
616 * x...x (datum1) x...x(orig. hash values) x...x(datum2)
617 * Replaced first image format :
618 * x...x (datum1) 0...0(hash values) x...x(datum2)
619 */
620 memcpy(internal_hash, hash_value,
621 sizeof(internal_hash));
622 memset(hash_value, 0, sizeof(internal_hash));
623 }
624 if (image_size_to_hash == 0) {
625 printf("Warning: Image_%d hash checksum is disabled, ",
626 image_num);
627 printf("skip the image validation.\n");
628 continue;
629 }
630 switch (hash_algorithm_id) {
631 case SHA1_SUM_LEN:
632 sha1_starts(&hash1_text);
633 sha1_update(&hash1_text, buff, image_size_to_hash);
634 sha1_finish(&hash1_text, hash_160_output);
635 hash_output = hash_160_output;
636 break;
637 case SHA256_SUM_LEN:
638 sha256_starts(&hash256_text);
639 sha256_update(&hash256_text, buff, image_size_to_hash);
640 sha256_finish(&hash256_text, hash_256_output);
641 hash_output = hash_256_output;
642 break;
Pali Rohár93c13582022-07-26 16:11:58 +0200643 case SHA512_SUM_LEN:
644 sha512_starts(&hash512_text);
645 sha512_update(&hash512_text, buff, image_size_to_hash);
646 sha512_finish(&hash512_text, hash_512_output);
647 hash_output = hash_512_output;
648 break;
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200649 default:
650 printf("Error: Unsupported hash_algorithm_id = %d\n",
651 hash_algorithm_id);
652 return -ENOEXEC;
653 }
654 if (image_num == 0)
655 memcpy(hash_value, internal_hash,
656 sizeof(internal_hash));
657 if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) {
658 printf("Error: Image_%d checksum is not correct\n",
659 image_num);
660 return -ENOEXEC;
661 }
662 }
663 printf("Image checksum...OK!\n");
664
665 return 0;
666}
Pali Rohár5d2f7d32022-07-26 16:11:56 +0200667#elif defined(CONFIG_ARMADA_32BIT)
Joel Johnson8ec6db72020-04-17 09:38:04 -0600668static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h)
669{
670 if (h->version == 1)
671 return (h->headersz_msb << 16) | le16_to_cpu(h->headersz_lsb);
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200672
Joel Johnson8ec6db72020-04-17 09:38:04 -0600673 printf("Error: Invalid A38x image (header version 0x%x unknown)!\n",
674 h->version);
675 return 0;
676}
677
678static uint8_t image_checksum8(const void *start, size_t len)
679{
680 u8 csum = 0;
681 const u8 *p = start;
682
683 while (len) {
684 csum += *p;
685 ++p;
686 --len;
687 }
688
689 return csum;
690}
691
692static int check_image_header(void)
693{
694 u8 checksum;
695 const struct a38x_main_hdr_v1 *hdr =
696 (struct a38x_main_hdr_v1 *)get_load_addr();
697 const size_t image_size = a38x_header_size(hdr);
698
699 if (!image_size)
700 return -ENOEXEC;
701
702 checksum = image_checksum8(hdr, image_size);
703 checksum -= hdr->checksum;
704 if (checksum != hdr->checksum) {
705 printf("Error: Bad A38x image checksum. 0x%x != 0x%x\n",
706 checksum, hdr->checksum);
707 return -ENOEXEC;
708 }
709
710 printf("Image checksum...OK!\n");
711 return 0;
712}
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200713#else /* Not ARMADA? */
714static int check_image_header(void)
715{
716 printf("bubt cmd does not support this SoC device or family!\n");
717 return -ENOEXEC;
718}
719#endif
720
Joel Johnson658854a2020-04-17 09:38:06 -0600721static int bubt_check_boot_mode(const struct bubt_dev *dst)
722{
Pali Rohár5d2f7d32022-07-26 16:11:56 +0200723#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT)
724 int mode;
725#if defined(CONFIG_ARMADA_3700)
726 const struct tim_boot_flash_sign *boot_modes = tim_boot_flash_signs;
727 const struct common_tim_data *hdr =
728 (struct common_tim_data *)get_load_addr();
729 u32 id = hdr->boot_flash_sign;
730#elif defined(CONFIG_ARMADA_32BIT)
731 const struct a38x_boot_mode *boot_modes = a38x_boot_modes;
732 const struct a38x_main_hdr_v1 *hdr =
733 (struct a38x_main_hdr_v1 *)get_load_addr();
734 u32 id = hdr->blockid;
735#endif
Joel Johnson658854a2020-04-17 09:38:06 -0600736
Pali Rohár5d2f7d32022-07-26 16:11:56 +0200737 for (mode = 0; boot_modes[mode].name; mode++) {
738 if (boot_modes[mode].id == id)
739 break;
Joel Johnson658854a2020-04-17 09:38:06 -0600740 }
Pali Rohár5d2f7d32022-07-26 16:11:56 +0200741
742 if (!boot_modes[mode].name) {
743 printf("Error: unknown boot device in image header: 0x%x\n", id);
744 return -ENOEXEC;
745 }
746
747 if (strcmp(boot_modes[mode].name, dst->name) == 0)
748 return 0;
749
750 printf("Error: image meant to be booted from \"%s\", not \"%s\"!\n",
751 boot_modes[mode].name, dst->name);
752 return -ENOEXEC;
753#else
754 return 0;
755#endif
Joel Johnson658854a2020-04-17 09:38:06 -0600756}
757
758static int bubt_verify(const struct bubt_dev *dst)
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200759{
760 int err;
761
762 /* Check a correct image header exists */
763 err = check_image_header();
764 if (err) {
765 printf("Error: Image header verification failed\n");
766 return err;
767 }
768
Joel Johnson658854a2020-04-17 09:38:06 -0600769 err = bubt_check_boot_mode(dst);
770 if (err) {
771 printf("Error: Image boot mode verification failed\n");
772 return err;
773 }
774
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200775 return 0;
776}
777
778static int bubt_read_file(struct bubt_dev *src)
779{
780 size_t image_size;
781
782 if (!src->read) {
783 printf("Error: Read not supported on device \"%s\"\n",
784 src->name);
785 return 0;
786 }
787
788 image_size = src->read(net_boot_file_name);
789 if (image_size <= 0) {
790 printf("Error: Failed to read file %s from %s\n",
791 net_boot_file_name, src->name);
792 return 0;
793 }
794
795 return image_size;
796}
797
798static int bubt_is_dev_active(struct bubt_dev *dev)
799{
800 if (!dev->active) {
Joel Johnsonf41b85e2020-04-17 09:38:05 -0600801 printf("Device \"%s\" not supported by U-Boot image\n",
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200802 dev->name);
803 return 0;
804 }
805
806 if (!dev->active()) {
807 printf("Device \"%s\" is inactive\n", dev->name);
808 return 0;
809 }
810
811 return 1;
812}
813
814struct bubt_dev *find_bubt_dev(char *dev_name)
815{
816 int dev;
817
818 for (dev = 0; dev < BUBT_MAX_DEV; dev++) {
819 if (strcmp(bubt_devs[dev].name, dev_name) == 0)
820 return &bubt_devs[dev];
821 }
822
823 return 0;
824}
825
826#define DEFAULT_BUBT_SRC "tftp"
827
828#ifndef DEFAULT_BUBT_DST
829#ifdef CONFIG_MVEBU_SPI_BOOT
830#define DEFAULT_BUBT_DST "spi"
831#elif defined(CONFIG_MVEBU_NAND_BOOT)
832#define DEFAULT_BUBT_DST "nand"
833#elif defined(CONFIG_MVEBU_MMC_BOOT)
834#define DEFAULT_BUBT_DST "mmc"
Konstantin Porotchkin9f27bcc2021-03-17 18:53:43 +0200835#else
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200836#define DEFAULT_BUBT_DST "error"
837#endif
838#endif /* DEFAULT_BUBT_DST */
839
Simon Glass09140112020-05-10 11:40:03 -0600840int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200841{
842 struct bubt_dev *src, *dst;
843 size_t image_size;
844 char src_dev_name[8];
845 char dst_dev_name[8];
846 char *name;
847 int err;
848
849 if (argc < 2)
850 copy_filename(net_boot_file_name,
851 CONFIG_MVEBU_UBOOT_DFLT_NAME,
852 sizeof(net_boot_file_name));
853 else
854 copy_filename(net_boot_file_name, argv[1],
855 sizeof(net_boot_file_name));
856
857 if (argc >= 3) {
858 strncpy(dst_dev_name, argv[2], 8);
859 } else {
860 name = DEFAULT_BUBT_DST;
861 strncpy(dst_dev_name, name, 8);
862 }
863
864 if (argc >= 4)
865 strncpy(src_dev_name, argv[3], 8);
866 else
867 strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8);
868
869 /* Figure out the destination device */
870 dst = find_bubt_dev(dst_dev_name);
871 if (!dst) {
872 printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
873 return -EINVAL;
874 }
875
876 if (!bubt_is_dev_active(dst))
877 return -ENODEV;
878
879 /* Figure out the source device */
880 src = find_bubt_dev(src_dev_name);
881 if (!src) {
882 printf("Error: Unknown source \"%s\"\n", src_dev_name);
883 return 1;
884 }
885
886 if (!bubt_is_dev_active(src))
887 return -ENODEV;
888
Joel Johnsonf41b85e2020-04-17 09:38:05 -0600889 printf("Burning U-Boot image \"%s\" from \"%s\" to \"%s\"\n",
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200890 net_boot_file_name, src->name, dst->name);
891
892 image_size = bubt_read_file(src);
893 if (!image_size)
894 return -EIO;
895
Joel Johnson658854a2020-04-17 09:38:06 -0600896 err = bubt_verify(dst);
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200897 if (err)
898 return err;
899
900 err = bubt_write_file(dst, image_size);
901 if (err)
902 return err;
903
904 return 0;
905}
906
907U_BOOT_CMD(
908 bubt, 4, 0, do_bubt_cmd,
909 "Burn a u-boot image to flash",
910 "[file-name] [destination [source]]\n"
Pali Rohár32771532021-01-27 11:56:02 +0100911 "\t-file-name The image file name to burn. Default = " CONFIG_MVEBU_UBOOT_DFLT_NAME "\n"
912 "\t-destination Flash to burn to [spi, nand, mmc]. Default = " DEFAULT_BUBT_DST "\n"
913 "\t-source The source to load image from [tftp, usb, mmc]. Default = " DEFAULT_BUBT_SRC "\n"
Konstantin Porotchkinfa61ef62016-12-08 12:22:28 +0200914 "Examples:\n"
915 "\tbubt - Burn flash-image.bin from tftp to active boot device\n"
916 "\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
917 "\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n"
918
919);