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