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