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