blob: 2041a7a29aa91b184bc1bcbe263c5f04edf54430 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Konstantin Porotchkin97d26782016-12-08 12:22:28 +02002/*
3 * Copyright (C) 2016 Marvell International Ltd.
Konstantin Porotchkin97d26782016-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 Glass0af6e2d2019-08-01 09:46:52 -060010#include <env.h>
Simon Glass85f13782019-12-28 10:45:03 -070011#include <image.h>
Konstantin Porotchkin97d26782016-12-08 12:22:28 +020012#include <vsprintf.h>
13#include <errno.h>
14#include <dm.h>
15
16#include <spi_flash.h>
17#include <spi.h>
18#include <nand.h>
19#include <usb.h>
20#include <fs.h>
21#include <mmc.h>
Konstantin Porotchkina89c0552017-01-08 16:52:06 +020022#ifdef CONFIG_BLK
23#include <blk.h>
24#endif
Konstantin Porotchkin97d26782016-12-08 12:22:28 +020025#include <u-boot/sha1.h>
26#include <u-boot/sha256.h>
27
28#ifndef CONFIG_SYS_MMC_ENV_DEV
29#define CONFIG_SYS_MMC_ENV_DEV 0
30#endif
31
32#if defined(CONFIG_ARMADA_8K)
33#define MAIN_HDR_MAGIC 0xB105B002
34
35struct mvebu_image_header {
36 u32 magic; /* 0-3 */
37 u32 prolog_size; /* 4-7 */
38 u32 prolog_checksum; /* 8-11 */
39 u32 boot_image_size; /* 12-15 */
40 u32 boot_image_checksum; /* 16-19 */
41 u32 rsrvd0; /* 20-23 */
42 u32 load_addr; /* 24-27 */
43 u32 exec_addr; /* 28-31 */
44 u8 uart_cfg; /* 32 */
45 u8 baudrate; /* 33 */
46 u8 ext_count; /* 34 */
47 u8 aux_flags; /* 35 */
48 u32 io_arg_0; /* 36-39 */
49 u32 io_arg_1; /* 40-43 */
50 u32 io_arg_2; /* 43-47 */
51 u32 io_arg_3; /* 48-51 */
52 u32 rsrvd1; /* 52-55 */
53 u32 rsrvd2; /* 56-59 */
54 u32 rsrvd3; /* 60-63 */
55};
56#elif defined(CONFIG_ARMADA_3700) /* A3700 */
57#define HASH_SUM_LEN 16
58#define IMAGE_VERSION_3_6_0 0x030600
59#define IMAGE_VERSION_3_5_0 0x030500
60
61struct common_tim_data {
62 u32 version;
63 u32 identifier;
64 u32 trusted;
65 u32 issue_date;
66 u32 oem_unique_id;
67 u32 reserved[5]; /* Reserve 20 bytes */
68 u32 boot_flash_sign;
69 u32 num_images;
70 u32 num_keys;
71 u32 size_of_reserved;
72};
73
74struct mvebu_image_info {
75 u32 image_id;
76 u32 next_image_id;
77 u32 flash_entry_addr;
78 u32 load_addr;
79 u32 image_size;
80 u32 image_size_to_hash;
81 u32 hash_algorithm_id;
82 u32 hash[HASH_SUM_LEN]; /* Reserve 512 bits for the hash */
83 u32 partition_number;
84 u32 enc_algorithm_id;
85 u32 encrypt_start_offset;
86 u32 encrypt_size;
87};
88#endif /* CONFIG_ARMADA_XXX */
89
90struct bubt_dev {
91 char name[8];
92 size_t (*read)(const char *file_name);
93 int (*write)(size_t image_size);
94 int (*active)(void);
95};
96
97static ulong get_load_addr(void)
98{
99 const char *addr_str;
100 unsigned long addr;
101
Simon Glass64b723f2017-08-03 12:22:12 -0600102 addr_str = env_get("loadaddr");
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200103 if (addr_str)
104 addr = simple_strtoul(addr_str, NULL, 16);
105 else
106 addr = CONFIG_SYS_LOAD_ADDR;
107
108 return addr;
109}
110
111/********************************************************************
112 * eMMC services
113 ********************************************************************/
Jean-Jacques Hiblotd0531672018-01-04 15:23:32 +0100114#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(MMC_WRITE)
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200115static int mmc_burn_image(size_t image_size)
116{
117 struct mmc *mmc;
118 lbaint_t start_lba;
119 lbaint_t blk_count;
120 ulong blk_written;
121 int err;
122 const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
Konstantin Porotchkina89c0552017-01-08 16:52:06 +0200123#ifdef CONFIG_BLK
124 struct blk_desc *blk_desc;
125#endif
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200126 mmc = find_mmc_device(mmc_dev_num);
127 if (!mmc) {
128 printf("No SD/MMC/eMMC card found\n");
129 return -ENOMEDIUM;
130 }
131
132 err = mmc_init(mmc);
133 if (err) {
134 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
135 mmc_dev_num);
136 return err;
137 }
138
139#ifdef CONFIG_SYS_MMC_ENV_PART
140 if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) {
141 err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART);
142 if (err) {
143 printf("MMC partition switch failed\n");
144 return err;
145 }
146 }
147#endif
148
149 /* SD reserves LBA-0 for MBR and boots from LBA-1,
150 * MMC/eMMC boots from LBA-0
151 */
152 start_lba = IS_SD(mmc) ? 1 : 0;
Konstantin Porotchkina89c0552017-01-08 16:52:06 +0200153#ifdef CONFIG_BLK
154 blk_count = image_size / mmc->write_bl_len;
155 if (image_size % mmc->write_bl_len)
156 blk_count += 1;
157
158 blk_desc = mmc_get_blk_desc(mmc);
159 if (!blk_desc) {
160 printf("Error - failed to obtain block descriptor\n");
161 return -ENODEV;
162 }
163 blk_written = blk_dwrite(blk_desc, start_lba, blk_count,
164 (void *)get_load_addr());
165#else
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200166 blk_count = image_size / mmc->block_dev.blksz;
167 if (image_size % mmc->block_dev.blksz)
168 blk_count += 1;
169
170 blk_written = mmc->block_dev.block_write(mmc_dev_num,
Konstantin Porotchkina89c0552017-01-08 16:52:06 +0200171 start_lba, blk_count,
172 (void *)get_load_addr());
173#endif /* CONFIG_BLK */
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200174 if (blk_written != blk_count) {
175 printf("Error - written %#lx blocks\n", blk_written);
176 return -ENOSPC;
177 }
178 printf("Done!\n");
179
180#ifdef CONFIG_SYS_MMC_ENV_PART
181 if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART)
182 mmc_switch_part(mmc_dev_num, mmc->part_num);
183#endif
184
185 return 0;
186}
187
188static size_t mmc_read_file(const char *file_name)
189{
190 loff_t act_read = 0;
191 int rc;
192 struct mmc *mmc;
193 const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
194
195 mmc = find_mmc_device(mmc_dev_num);
196 if (!mmc) {
197 printf("No SD/MMC/eMMC card found\n");
198 return 0;
199 }
200
201 if (mmc_init(mmc)) {
202 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
203 mmc_dev_num);
204 return 0;
205 }
206
207 /* Load from data partition (0) */
208 if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) {
209 printf("Error: MMC 0 not found\n");
210 return 0;
211 }
212
213 /* Perfrom file read */
214 rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
215 if (rc)
216 return 0;
217
218 return act_read;
219}
220
221static int is_mmc_active(void)
222{
223 return 1;
224}
225#else /* CONFIG_DM_MMC */
226static int mmc_burn_image(size_t image_size)
227{
228 return -ENODEV;
229}
230
231static size_t mmc_read_file(const char *file_name)
232{
233 return 0;
234}
235
236static int is_mmc_active(void)
237{
238 return 0;
239}
240#endif /* CONFIG_DM_MMC */
241
242/********************************************************************
243 * SPI services
244 ********************************************************************/
245#ifdef CONFIG_SPI_FLASH
246static int spi_burn_image(size_t image_size)
247{
248 int ret;
249 struct spi_flash *flash;
250 u32 erase_bytes;
251
252 /* Probe the SPI bus to get the flash device */
253 flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
254 CONFIG_ENV_SPI_CS,
255 CONFIG_SF_DEFAULT_SPEED,
256 CONFIG_SF_DEFAULT_MODE);
257 if (!flash) {
258 printf("Failed to probe SPI Flash\n");
259 return -ENOMEDIUM;
260 }
261
262#ifdef CONFIG_SPI_FLASH_PROTECTION
263 spi_flash_protect(flash, 0);
264#endif
265 erase_bytes = image_size +
266 (flash->erase_size - image_size % flash->erase_size);
267 printf("Erasing %d bytes (%d blocks) at offset 0 ...",
268 erase_bytes, erase_bytes / flash->erase_size);
269 ret = spi_flash_erase(flash, 0, erase_bytes);
270 if (ret)
271 printf("Error!\n");
272 else
273 printf("Done!\n");
274
275 printf("Writing %d bytes from 0x%lx to offset 0 ...",
276 (int)image_size, get_load_addr());
277 ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr());
278 if (ret)
279 printf("Error!\n");
280 else
281 printf("Done!\n");
282
283#ifdef CONFIG_SPI_FLASH_PROTECTION
284 spi_flash_protect(flash, 1);
285#endif
286
287 return ret;
288}
289
290static int is_spi_active(void)
291{
292 return 1;
293}
294
295#else /* CONFIG_SPI_FLASH */
296static int spi_burn_image(size_t image_size)
297{
298 return -ENODEV;
299}
300
301static int is_spi_active(void)
302{
303 return 0;
304}
305#endif /* CONFIG_SPI_FLASH */
306
307/********************************************************************
308 * NAND services
309 ********************************************************************/
310#ifdef CONFIG_CMD_NAND
311static int nand_burn_image(size_t image_size)
312{
Konstantin Porotchkinc6db27b2017-03-28 18:16:56 +0300313 int ret;
314 uint32_t block_size;
Grygorii Strashko4a240bc2017-06-26 19:13:02 -0500315 struct mtd_info *mtd;
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200316
Grygorii Strashko4a240bc2017-06-26 19:13:02 -0500317 mtd = get_nand_dev_by_index(nand_curr_device);
318 if (!mtd) {
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200319 puts("\nno devices available\n");
320 return -ENOMEDIUM;
321 }
Grygorii Strashko4a240bc2017-06-26 19:13:02 -0500322 block_size = mtd->erasesize;
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200323
324 /* Align U-Boot size to currently used blocksize */
325 image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
326
327 /* Erase the U-BOOT image space */
328 printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
Grygorii Strashko4a240bc2017-06-26 19:13:02 -0500329 ret = nand_erase(mtd, 0, image_size);
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200330 if (ret) {
331 printf("Error!\n");
332 goto error;
333 }
334 printf("Done!\n");
335
336 /* Write the image to flash */
Konstantin Porotchkinc6db27b2017-03-28 18:16:56 +0300337 printf("Writing %d bytes from 0x%lx to offset 0 ... ",
338 (int)image_size, get_load_addr());
Grygorii Strashko4a240bc2017-06-26 19:13:02 -0500339 ret = nand_write(mtd, 0, &image_size, (void *)get_load_addr());
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200340 if (ret)
341 printf("Error!\n");
342 else
343 printf("Done!\n");
344
345error:
346 return ret;
347}
348
349static int is_nand_active(void)
350{
351 return 1;
352}
353
354#else /* CONFIG_CMD_NAND */
355static int nand_burn_image(size_t image_size)
356{
357 return -ENODEV;
358}
359
360static int is_nand_active(void)
361{
362 return 0;
363}
364#endif /* CONFIG_CMD_NAND */
365
366/********************************************************************
367 * USB services
368 ********************************************************************/
369#if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK)
370static size_t usb_read_file(const char *file_name)
371{
372 loff_t act_read = 0;
373 struct udevice *dev;
374 int rc;
375
376 usb_stop();
377
378 if (usb_init() < 0) {
379 printf("Error: usb_init failed\n");
380 return 0;
381 }
382
383 /* Try to recognize storage devices immediately */
384 blk_first_device(IF_TYPE_USB, &dev);
385 if (!dev) {
386 printf("Error: USB storage device not found\n");
387 return 0;
388 }
389
390 /* Always load from usb 0 */
391 if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
392 printf("Error: USB 0 not found\n");
393 return 0;
394 }
395
396 /* Perfrom file read */
397 rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
398 if (rc)
399 return 0;
400
401 return act_read;
402}
403
404static int is_usb_active(void)
405{
406 return 1;
407}
408
409#else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
410static size_t usb_read_file(const char *file_name)
411{
412 return 0;
413}
414
415static int is_usb_active(void)
416{
417 return 0;
418}
419#endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
420
421/********************************************************************
422 * Network services
423 ********************************************************************/
424#ifdef CONFIG_CMD_NET
425static size_t tftp_read_file(const char *file_name)
426{
Simon Glass892265d2019-12-28 10:45:02 -0700427 /*
428 * update global variable image_load_addr before tftp file from network
429 */
430 image_load_addr = get_load_addr();
Konstantin Porotchkin97d26782016-12-08 12:22:28 +0200431 return net_loop(TFTPGET);
432}
433
434static int is_tftp_active(void)
435{
436 return 1;
437}
438
439#else
440static size_t tftp_read_file(const char *file_name)
441{
442 return 0;
443}
444
445static int is_tftp_active(void)
446{
447 return 0;
448}
449#endif /* CONFIG_CMD_NET */
450
451enum bubt_devices {
452 BUBT_DEV_NET = 0,
453 BUBT_DEV_USB,
454 BUBT_DEV_MMC,
455 BUBT_DEV_SPI,
456 BUBT_DEV_NAND,
457
458 BUBT_MAX_DEV
459};
460
461struct bubt_dev bubt_devs[BUBT_MAX_DEV] = {
462 {"tftp", tftp_read_file, NULL, is_tftp_active},
463 {"usb", usb_read_file, NULL, is_usb_active},
464 {"mmc", mmc_read_file, mmc_burn_image, is_mmc_active},
465 {"spi", NULL, spi_burn_image, is_spi_active},
466 {"nand", NULL, nand_burn_image, is_nand_active},
467};
468
469static int bubt_write_file(struct bubt_dev *dst, size_t image_size)
470{
471 if (!dst->write) {
472 printf("Error: Write not supported on device %s\n", dst->name);
473 return -ENOTSUPP;
474 }
475
476 return dst->write(image_size);
477}
478
479#if defined(CONFIG_ARMADA_8K)
480u32 do_checksum32(u32 *start, int32_t len)
481{
482 u32 sum = 0;
483 u32 *startp = start;
484
485 do {
486 sum += *startp;
487 startp++;
488 len -= 4;
489 } while (len > 0);
490
491 return sum;
492}
493
494static int check_image_header(void)
495{
496 struct mvebu_image_header *hdr =
497 (struct mvebu_image_header *)get_load_addr();
498 u32 header_len = hdr->prolog_size;
499 u32 checksum;
500 u32 checksum_ref = hdr->prolog_checksum;
501
502 /*
503 * For now compare checksum, and magic. Later we can
504 * verify more stuff on the header like interface type, etc
505 */
506 if (hdr->magic != MAIN_HDR_MAGIC) {
507 printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n",
508 hdr->magic, MAIN_HDR_MAGIC);
509 return -ENOEXEC;
510 }
511
512 /* The checksum value is discarded from checksum calculation */
513 hdr->prolog_checksum = 0;
514
515 checksum = do_checksum32((u32 *)hdr, header_len);
516 if (checksum != checksum_ref) {
517 printf("Error: Bad Image checksum. 0x%x != 0x%x\n",
518 checksum, checksum_ref);
519 return -ENOEXEC;
520 }
521
522 /* Restore the checksum before writing */
523 hdr->prolog_checksum = checksum_ref;
524 printf("Image checksum...OK!\n");
525
526 return 0;
527}
528#elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */
529static int check_image_header(void)
530{
531 struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr();
532 int image_num;
533 u8 hash_160_output[SHA1_SUM_LEN];
534 u8 hash_256_output[SHA256_SUM_LEN];
535 sha1_context hash1_text;
536 sha256_context hash256_text;
537 u8 *hash_output;
538 u32 hash_algorithm_id;
539 u32 image_size_to_hash;
540 u32 flash_entry_addr;
541 u32 *hash_value;
542 u32 internal_hash[HASH_SUM_LEN];
543 const u8 *buff;
544 u32 num_of_image = hdr->num_images;
545 u32 version = hdr->version;
546 u32 trusted = hdr->trusted;
547
548 /* bubt checksum validation only supports nontrusted images */
549 if (trusted == 1) {
550 printf("bypass image validation, ");
551 printf("only untrusted image is supported now\n");
552 return 0;
553 }
554 /* only supports image version 3.5 and 3.6 */
555 if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) {
556 printf("Error: Unsupported Image version = 0x%08x\n", version);
557 return -ENOEXEC;
558 }
559 /* validate images hash value */
560 for (image_num = 0; image_num < num_of_image; image_num++) {
561 struct mvebu_image_info *info =
562 (struct mvebu_image_info *)(get_load_addr() +
563 sizeof(struct common_tim_data) +
564 image_num * sizeof(struct mvebu_image_info));
565 hash_algorithm_id = info->hash_algorithm_id;
566 image_size_to_hash = info->image_size_to_hash;
567 flash_entry_addr = info->flash_entry_addr;
568 hash_value = info->hash;
569 buff = (const u8 *)(get_load_addr() + flash_entry_addr);
570
571 if (image_num == 0) {
572 /*
573 * The first image includes hash values in its content.
574 * For hash calculation, we need to save the original
575 * hash values to a local variable that will be
576 * copied back for comparsion and set all zeros to
577 * the orignal hash values for calculating new value.
578 * First image original format :
579 * x...x (datum1) x...x(orig. hash values) x...x(datum2)
580 * Replaced first image format :
581 * x...x (datum1) 0...0(hash values) x...x(datum2)
582 */
583 memcpy(internal_hash, hash_value,
584 sizeof(internal_hash));
585 memset(hash_value, 0, sizeof(internal_hash));
586 }
587 if (image_size_to_hash == 0) {
588 printf("Warning: Image_%d hash checksum is disabled, ",
589 image_num);
590 printf("skip the image validation.\n");
591 continue;
592 }
593 switch (hash_algorithm_id) {
594 case SHA1_SUM_LEN:
595 sha1_starts(&hash1_text);
596 sha1_update(&hash1_text, buff, image_size_to_hash);
597 sha1_finish(&hash1_text, hash_160_output);
598 hash_output = hash_160_output;
599 break;
600 case SHA256_SUM_LEN:
601 sha256_starts(&hash256_text);
602 sha256_update(&hash256_text, buff, image_size_to_hash);
603 sha256_finish(&hash256_text, hash_256_output);
604 hash_output = hash_256_output;
605 break;
606 default:
607 printf("Error: Unsupported hash_algorithm_id = %d\n",
608 hash_algorithm_id);
609 return -ENOEXEC;
610 }
611 if (image_num == 0)
612 memcpy(hash_value, internal_hash,
613 sizeof(internal_hash));
614 if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) {
615 printf("Error: Image_%d checksum is not correct\n",
616 image_num);
617 return -ENOEXEC;
618 }
619 }
620 printf("Image checksum...OK!\n");
621
622 return 0;
623}
624
625#else /* Not ARMADA? */
626static int check_image_header(void)
627{
628 printf("bubt cmd does not support this SoC device or family!\n");
629 return -ENOEXEC;
630}
631#endif
632
633static int bubt_verify(size_t image_size)
634{
635 int err;
636
637 /* Check a correct image header exists */
638 err = check_image_header();
639 if (err) {
640 printf("Error: Image header verification failed\n");
641 return err;
642 }
643
644 return 0;
645}
646
647static int bubt_read_file(struct bubt_dev *src)
648{
649 size_t image_size;
650
651 if (!src->read) {
652 printf("Error: Read not supported on device \"%s\"\n",
653 src->name);
654 return 0;
655 }
656
657 image_size = src->read(net_boot_file_name);
658 if (image_size <= 0) {
659 printf("Error: Failed to read file %s from %s\n",
660 net_boot_file_name, src->name);
661 return 0;
662 }
663
664 return image_size;
665}
666
667static int bubt_is_dev_active(struct bubt_dev *dev)
668{
669 if (!dev->active) {
670 printf("Device \"%s\" not supported by U-BOOT image\n",
671 dev->name);
672 return 0;
673 }
674
675 if (!dev->active()) {
676 printf("Device \"%s\" is inactive\n", dev->name);
677 return 0;
678 }
679
680 return 1;
681}
682
683struct bubt_dev *find_bubt_dev(char *dev_name)
684{
685 int dev;
686
687 for (dev = 0; dev < BUBT_MAX_DEV; dev++) {
688 if (strcmp(bubt_devs[dev].name, dev_name) == 0)
689 return &bubt_devs[dev];
690 }
691
692 return 0;
693}
694
695#define DEFAULT_BUBT_SRC "tftp"
696
697#ifndef DEFAULT_BUBT_DST
698#ifdef CONFIG_MVEBU_SPI_BOOT
699#define DEFAULT_BUBT_DST "spi"
700#elif defined(CONFIG_MVEBU_NAND_BOOT)
701#define DEFAULT_BUBT_DST "nand"
702#elif defined(CONFIG_MVEBU_MMC_BOOT)
703#define DEFAULT_BUBT_DST "mmc"
704else
705#define DEFAULT_BUBT_DST "error"
706#endif
707#endif /* DEFAULT_BUBT_DST */
708
709int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
710{
711 struct bubt_dev *src, *dst;
712 size_t image_size;
713 char src_dev_name[8];
714 char dst_dev_name[8];
715 char *name;
716 int err;
717
718 if (argc < 2)
719 copy_filename(net_boot_file_name,
720 CONFIG_MVEBU_UBOOT_DFLT_NAME,
721 sizeof(net_boot_file_name));
722 else
723 copy_filename(net_boot_file_name, argv[1],
724 sizeof(net_boot_file_name));
725
726 if (argc >= 3) {
727 strncpy(dst_dev_name, argv[2], 8);
728 } else {
729 name = DEFAULT_BUBT_DST;
730 strncpy(dst_dev_name, name, 8);
731 }
732
733 if (argc >= 4)
734 strncpy(src_dev_name, argv[3], 8);
735 else
736 strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8);
737
738 /* Figure out the destination device */
739 dst = find_bubt_dev(dst_dev_name);
740 if (!dst) {
741 printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
742 return -EINVAL;
743 }
744
745 if (!bubt_is_dev_active(dst))
746 return -ENODEV;
747
748 /* Figure out the source device */
749 src = find_bubt_dev(src_dev_name);
750 if (!src) {
751 printf("Error: Unknown source \"%s\"\n", src_dev_name);
752 return 1;
753 }
754
755 if (!bubt_is_dev_active(src))
756 return -ENODEV;
757
758 printf("Burning U-BOOT image \"%s\" from \"%s\" to \"%s\"\n",
759 net_boot_file_name, src->name, dst->name);
760
761 image_size = bubt_read_file(src);
762 if (!image_size)
763 return -EIO;
764
765 err = bubt_verify(image_size);
766 if (err)
767 return err;
768
769 err = bubt_write_file(dst, image_size);
770 if (err)
771 return err;
772
773 return 0;
774}
775
776U_BOOT_CMD(
777 bubt, 4, 0, do_bubt_cmd,
778 "Burn a u-boot image to flash",
779 "[file-name] [destination [source]]\n"
780 "\t-file-name The image file name to burn. Default = flash-image.bin\n"
781 "\t-destination Flash to burn to [spi, nand, mmc]. Default = active boot device\n"
782 "\t-source The source to load image from [tftp, usb, mmc]. Default = tftp\n"
783 "Examples:\n"
784 "\tbubt - Burn flash-image.bin from tftp to active boot device\n"
785 "\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
786 "\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n"
787
788);