diff options
-rw-r--r-- | arch/arm/mach-mvebu/Kconfig | 23 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/Makefile | 13 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/cpu.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/include/mach/cpu.h | 21 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/kwbimage.cfg.in | 5 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h | 30 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/spl.c | 84 | ||||
-rw-r--r-- | cmd/mvebu/Kconfig | 18 | ||||
-rw-r--r-- | cmd/mvebu/bubt.c | 253 | ||||
-rw-r--r-- | common/spl/Kconfig | 9 | ||||
-rw-r--r-- | common/spl/spl_mmc.c | 12 | ||||
-rw-r--r-- | configs/clearfog_sata_defconfig | 83 | ||||
-rw-r--r-- | configs/db-88f6820-amc_nand_defconfig | 92 | ||||
-rw-r--r-- | doc/kwboot.1 | 3 | ||||
-rw-r--r-- | doc/mvebu/cmd/bubt.txt | 25 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/Kconfig | 4 | ||||
-rw-r--r-- | tools/kwbimage.c | 297 | ||||
-rw-r--r-- | tools/kwboot.c | 200 | ||||
-rw-r--r-- | tools/mkimage.c | 11 |
22 files changed, 937 insertions, 279 deletions
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 16c5e72..cdb1776 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -331,7 +331,7 @@ choice depends on SPL config MVEBU_SPL_BOOT_DEVICE_SPI - bool "SPI NOR flash" + bool "NOR flash (SPI or parallel)" imply ENV_IS_IN_SPI_FLASH imply SPL_DM_SPI imply SPL_SPI_FLASH_SUPPORT @@ -339,8 +339,13 @@ config MVEBU_SPL_BOOT_DEVICE_SPI imply SPL_SPI select SPL_BOOTROM_SUPPORT +config MVEBU_SPL_BOOT_DEVICE_NAND + bool "NAND flash (SPI or parallel)" + select MTD_RAW_NAND + select SPL_BOOTROM_SUPPORT + config MVEBU_SPL_BOOT_DEVICE_MMC - bool "SDIO/MMC card" + bool "eMMC or SD card" imply ENV_IS_IN_MMC # GPIO needed for eMMC/SD card presence detection imply SPL_DM_GPIO @@ -348,6 +353,8 @@ config MVEBU_SPL_BOOT_DEVICE_MMC imply SPL_GPIO imply SPL_LIBDISK_SUPPORT imply SPL_MMC + select SUPPORT_EMMC_BOOT if SPL_MMC + select SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR if SPL_MMC select SPL_BOOTROM_SUPPORT config MVEBU_SPL_BOOT_DEVICE_SATA @@ -356,12 +363,24 @@ config MVEBU_SPL_BOOT_DEVICE_SATA imply SPL_LIBDISK_SUPPORT select SPL_BOOTROM_SUPPORT +config MVEBU_SPL_BOOT_DEVICE_PEX + bool "PCI Express" + select SPL_BOOTROM_SUPPORT + config MVEBU_SPL_BOOT_DEVICE_UART bool "UART" select SPL_BOOTROM_SUPPORT endchoice +config MVEBU_SPL_NAND_BADBLK_LOCATION + hex "NAND Bad block indicator location" + depends on MVEBU_SPL_BOOT_DEVICE_NAND + range 0x0 0x1 + help + Value 0x0 = SLC flash = BBI at page 0 or page 1 + Value 0x1 = MLC flash = BBI at last page in the block + config MVEBU_EFUSE bool "Enable eFuse support" depends on HAVE_MVEBU_EFUSE diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index a9f506c..90f8833 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -50,16 +50,29 @@ KWB_REPLACE += BOOT_FROM ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI),) KWB_CFG_BOOT_FROM=spi endif +ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_NAND),) + KWB_CFG_BOOT_FROM=nand +endif ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC),) KWB_CFG_BOOT_FROM=sdio endif ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SATA),) KWB_CFG_BOOT_FROM=sata endif +ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_PEX),) + KWB_CFG_BOOT_FROM=pex +endif ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_UART),) KWB_CFG_BOOT_FROM=uart endif +ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_NAND),) +KWB_REPLACE += NAND_PAGE_SIZE NAND_BLKSZ NAND_BADBLK_LOCATION +KWB_CFG_NAND_PAGE_SIZE = $(CONFIG_SYS_NAND_PAGE_SIZE) +KWB_CFG_NAND_BLKSZ = $(CONFIG_SYS_NAND_BLOCK_SIZE) +KWB_CFG_NAND_BADBLK_LOCATION = $(CONFIG_MVEBU_SPL_NAND_BADBLK_LOCATION) +endif + ifneq ($(CONFIG_SECURED_MODE_IMAGE),) KWB_REPLACE += CSK_INDEX KWB_CFG_CSK_INDEX = $(CONFIG_SECURED_MODE_CSK_INDEX) diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 329d136..bbe167e 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -25,7 +25,7 @@ static const struct mbus_win windows[] = { { MBUS_SPI_BASE, MBUS_SPI_SIZE, CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPIFLASH }, - /* NOR */ + /* BootROM */ { MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE, CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM }, @@ -35,6 +35,15 @@ static const struct mbus_win windows[] = { #endif }; +/* SPI0 CS0 Flash of size MBUS_SPI_SIZE is mapped to address MBUS_SPI_BASE */ +#if CONFIG_ENV_SPI_BUS == 0 && CONFIG_ENV_SPI_CS == 0 && \ + CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE <= MBUS_SPI_SIZE +void *env_sf_get_env_addr(void) +{ + return (void *)MBUS_SPI_BASE + CONFIG_ENV_OFFSET; +} +#endif + void lowlevel_init(void) { /* diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h index c17c244..904e715 100644 --- a/arch/arm/mach-mvebu/include/mach/cpu.h +++ b/arch/arm/mach-mvebu/include/mach/cpu.h @@ -66,17 +66,38 @@ enum cpu_attrib { /* * Default Device Address MAP BAR values */ +#ifdef CONFIG_SPL_BUILD +#ifdef CONFIG_ARMADA_38X +#define MBUS_PCI_MEM_BASE 0x88000000 +#define MBUS_PCI_MEM_SIZE ((3 * 128) << 20) +#else +#define MBUS_PCI_MEM_BASE 0x80000000 +#define MBUS_PCI_MEM_SIZE ((4 * 128) << 20) +#endif +#else #define MBUS_PCI_MAX_PORTS 6 #define MBUS_PCI_MEM_BASE MVEBU_SDRAM_SIZE_MAX #define MBUS_PCI_MEM_SIZE ((MBUS_PCI_MAX_PORTS * 128) << 20) #define MBUS_PCI_IO_BASE 0xF1100000 #define MBUS_PCI_IO_SIZE ((MBUS_PCI_MAX_PORTS * 64) << 10) +#endif +#ifdef CONFIG_SPL_BUILD +#define MBUS_SPI_BASE 0xD4000000 +#define MBUS_SPI_SIZE (64 << 20) +#else #define MBUS_SPI_BASE 0xF4000000 #define MBUS_SPI_SIZE (8 << 20) +#endif +#ifndef CONFIG_SPL_BUILD #define MBUS_DFX_BASE 0xF6000000 #define MBUS_DFX_SIZE (1 << 20) +#endif #define MBUS_BOOTROM_BASE 0xF8000000 +#ifdef CONFIG_SPL_BUILD +#define MBUS_BOOTROM_SIZE (128 << 20) +#else #define MBUS_BOOTROM_SIZE (8 << 20) +#endif struct mbus_win { u32 base; diff --git a/arch/arm/mach-mvebu/kwbimage.cfg.in b/arch/arm/mach-mvebu/kwbimage.cfg.in index ccb0997..90cf00c 100644 --- a/arch/arm/mach-mvebu/kwbimage.cfg.in +++ b/arch/arm/mach-mvebu/kwbimage.cfg.in @@ -11,6 +11,11 @@ VERSION 1 # Boot Media configurations #@BOOT_FROM +# NAND configuration +#@NAND_PAGE_SIZE +#@NAND_BLKSZ +#@NAND_BADBLK_LOCATION + # Enable BootROM output via DEBUG flag on SoCs which require it #@DEBUG diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c index 943ae01..3349f4e 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c +++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c @@ -53,7 +53,7 @@ u8 serdes_lane_in_use_count[MAX_UNITS_ID][MAX_UNIT_NUMB] = { */ u8 serdes_unit_count[MAX_UNITS_ID] = { 0 }; -/* Selector mapping for A380-A0 and A390-Z1 */ +/* Selector mapping for A380-A0 */ u8 selectors_serdes_rev2_map[LAST_SERDES_TYPE][MAX_SERDES_LANES] = { /* 0 1 2 3 4 5 6 */ { 0x1, 0x1, NA, NA, NA, NA, NA }, /* PEX0 */ @@ -812,7 +812,7 @@ u8 hws_ctrl_serdes_rev_get(void) if (sys_env_device_rev_get() == MV_88F68XX_Z1_ID) return MV_SERDES_REV_1_2; - /* for A39x-Z1, A38x-A0 */ + /* for A38x-A0 */ return MV_SERDES_REV_2_1; } diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h index dd229e1..6925a9d 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h +++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h @@ -15,12 +15,12 @@ #define SET_BIT(data, bit) ((data) | (0x1 << (bit))) #define CLEAR_BIT(data, bit) ((data) & (~(0x1 << (bit)))) -#define MAX_SERDES_LANES 7 /* as in a39x */ +#define MAX_SERDES_LANES 7 /* Serdes revision */ /* Serdes revision 1.2 (for A38x-Z1) */ #define MV_SERDES_REV_1_2 0x0 -/* Serdes revision 2.1 (for A39x-Z1, A38x-A0) */ +/* Serdes revision 2.1 (for A38x-A0) */ #define MV_SERDES_REV_2_1 0x1 #define MV_SERDES_REV_NA 0xff diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c index 950680a..fb8ec11 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c +++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c @@ -145,10 +145,6 @@ u32 sys_env_id_index_get(u32 ctrl_model) return MV_6811_INDEX; case MV_6828_DEV_ID: return MV_6828_INDEX; - case MV_6920_DEV_ID: - return MV_6920_INDEX; - case MV_6928_DEV_ID: - return MV_6928_INDEX; default: return MV_6820_INDEX; } @@ -183,11 +179,9 @@ u16 sys_env_model_get(void) case MV_6810_DEV_ID: case MV_6811_DEV_ID: case MV_6828_DEV_ID: - case MV_6920_DEV_ID: - case MV_6928_DEV_ID: return ctrl_id; default: - /* Device ID Default for A38x: 6820 , for A39x: 6920 */ + /* Device ID Default for A38x: 6820 */ default_ctrl_id = MV_6820_DEV_ID; printf("%s: Error retrieving device ID (%x), using default ID = %x\n", __func__, ctrl_id, default_ctrl_id); @@ -201,8 +195,8 @@ u16 sys_env_model_get(void) */ u32 sys_env_device_id_get(void) { - char *device_id_str[7] = { - "6810", "6820", "6811", "6828", "NONE", "6920", "6928" + char *device_id_str[4] = { + "6810", "6820", "6811", "6828", }; if (g_dev_id != -1) @@ -210,7 +204,7 @@ u32 sys_env_device_id_get(void) g_dev_id = reg_read(DEVICE_SAMPLE_AT_RESET1_REG); g_dev_id = g_dev_id >> SAR_DEV_ID_OFFS & SAR_DEV_ID_MASK; - printf("Detected Device ID %s\n", device_id_str[g_dev_id]); + printf("Detected Device ID %s\n", g_dev_id < 4 ? device_id_str[g_dev_id] : "NONE"); return g_dev_id; } diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h index 94c43b4..20039f7 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h +++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h @@ -198,22 +198,6 @@ #define A38X_MV_MARVELL_BOARD_NUM (A38X_MV_MAX_MARVELL_BOARD_ID - \ A38X_MARVELL_BOARD_ID_BASE) -/* Customer boards for A39x */ -#define A39X_CUSTOMER_BOARD_ID_BASE 0x20 -#define A39X_CUSTOMER_BOARD_ID0 (A39X_CUSTOMER_BOARD_ID_BASE + 0) -#define A39X_CUSTOMER_BOARD_ID1 (A39X_CUSTOMER_BOARD_ID_BASE + 1) -#define A39X_MV_MAX_CUSTOMER_BOARD_ID (A39X_CUSTOMER_BOARD_ID_BASE + 2) -#define A39X_MV_CUSTOMER_BOARD_NUM (A39X_MV_MAX_CUSTOMER_BOARD_ID - \ - A39X_CUSTOMER_BOARD_ID_BASE) - -/* Marvell boards for A39x */ -#define A39X_MARVELL_BOARD_ID_BASE 0x30 -#define A39X_DB_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 0) -#define A39X_RD_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 1) -#define A39X_MV_MAX_MARVELL_BOARD_ID (A39X_MARVELL_BOARD_ID_BASE + 2) -#define A39X_MV_MARVELL_BOARD_NUM (A39X_MV_MAX_MARVELL_BOARD_ID - \ - A39X_MARVELL_BOARD_ID_BASE) - #define CUTOMER_BOARD_ID_BASE A38X_CUSTOMER_BOARD_ID_BASE #define CUSTOMER_BOARD_ID0 A38X_CUSTOMER_BOARD_ID0 #define CUSTOMER_BOARD_ID1 A38X_CUSTOMER_BOARD_ID1 @@ -236,8 +220,6 @@ #define MV_88F68XX_Z1_ID 0x0 #define MV_88F68XX_A0_ID 0x4 #define MV_88F68XX_B0_ID 0xa -/* A39x revisions */ -#define MV_88F69XX_Z1_ID 0x2 #define MPP_CONTROL_REG(id) (0x18000 + (id * 4)) #define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00) @@ -257,19 +239,12 @@ #define MV_6811_DEV_ID 0x6811 #define MV_6820_DEV_ID 0x6820 #define MV_6828_DEV_ID 0x6828 -/* Armada 39x Family */ -#define MV_6920_DEV_ID 0x6920 -#define MV_6928_DEV_ID 0x6928 enum { MV_6810, MV_6820, MV_6811, MV_6828, - MV_NONE, - MV_6920, - MV_6928, - MV_MAX_DEV_ID, }; #define MV_6820_INDEX 0 @@ -277,17 +252,12 @@ enum { #define MV_6811_INDEX 2 #define MV_6828_INDEX 3 -#define MV_6920_INDEX 0 -#define MV_6928_INDEX 1 - #define MAX_DEV_ID_NUM 4 #define MV_6820_INDEX 0 #define MV_6810_INDEX 1 #define MV_6811_INDEX 2 #define MV_6828_INDEX 3 -#define MV_6920_INDEX 0 -#define MV_6928_INDEX 1 enum unit_id { PEX_UNIT_ID, diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 4245992..6b8c72a 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -33,21 +33,44 @@ #endif /* - * When loading U-Boot via SPL from eMMC (in Marvell terminology SDIO), the - * kwbimage main header is stored at sector 0. U-Boot SPL needs to parse this - * header and figure out at which sector the U-Boot proper binary is stored. - * Partition booting is therefore not supported and CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - * and CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET need to point to the - * kwbimage main header. + * When loading U-Boot via SPL from eMMC, the kwbimage main header is stored at + * sector 0 and either on HW boot partition or on data partition. Choice of HW + * partition depends on what is configured in eMMC EXT_CSC register. + * When loading U-Boot via SPL from SD card, the kwbimage main header is stored + * at sector 1. + * Therefore MBR/GPT partition booting, fixed sector number and fixed eMMC HW + * partition number are unsupported due to limitation of Marvell BootROM. + * Correct sector number must be determined as runtime in mvebu SPL code based + * on the detected boot source. Otherwise U-Boot SPL would not be able to load + * U-Boot proper. + * Runtime mvebu SPL sector calculation code expects: + * - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET=0 + * - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0 */ #ifdef CONFIG_SPL_MMC +#ifdef CONFIG_SYS_MMCSD_FS_BOOT +#error CONFIG_SYS_MMCSD_FS_BOOT is unsupported +#endif +#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION +#error CONFIG_SYS_MMCSD_FS_BOOT_PARTITION is unsupported +#endif +#ifdef CONFIG_SUPPORT_EMMC_BOOT_OVERRIDE_PART_CONFIG +#error CONFIG_SUPPORT_EMMC_BOOT_OVERRIDE_PART_CONFIG is unsupported +#endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION +#error CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION is unsupported +#endif #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION is unsupported #endif -#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) && CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR != 0 +#ifndef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR +#error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR must be enabled for SD/eMMC boot support +#endif +#if !defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) || \ + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR != 0 #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR must be set to 0 #endif -#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET) && \ +#if !defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET) || \ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET != 0 #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET must be set to 0 #endif @@ -98,7 +121,12 @@ struct kwbimage_main_hdr_v1 { #ifdef CONFIG_SPL_MMC u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) { - return MMCSD_MODE_RAW; + return IS_SD(mmc) ? MMCSD_MODE_RAW : MMCSD_MODE_EMMCBOOT; +} +unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) +{ + return IS_SD(mmc) ? 1 : 0; } #endif @@ -169,9 +197,7 @@ int spl_parse_board_header(struct spl_image_info *spl_image, } if (IS_ENABLED(CONFIG_SPL_MMC) && - (bootdev->boot_device == BOOT_DEVICE_MMC1 || - bootdev->boot_device == BOOT_DEVICE_MMC2 || - bootdev->boot_device == BOOT_DEVICE_MMC2_2) && + (bootdev->boot_device == BOOT_DEVICE_MMC1) && mhdr->blockid != IBR_HDR_SDIO_ID) { printf("ERROR: Wrong blockid (0x%x) in SDIO kwbimage\n", mhdr->blockid); @@ -182,26 +208,9 @@ int spl_parse_board_header(struct spl_image_info *spl_image, /* * For SATA srcaddr is specified in number of sectors. - * The main header is must be stored at sector number 1. - * This expects that sector size is 512 bytes and recalculates - * data offset to bytes relative to the main header. - */ - if (IS_ENABLED(CONFIG_SPL_SATA) && mhdr->blockid == IBR_HDR_SATA_ID) { - if (spl_image->offset < 1) { - printf("ERROR: Wrong srcaddr (0x%08x) in SATA kwbimage\n", - spl_image->offset); - return -EINVAL; - } - spl_image->offset -= 1; - spl_image->offset *= 512; - } - - /* - * For SDIO (eMMC) srcaddr is specified in number of sectors. - * This expects that sector size is 512 bytes and recalculates - * data offset to bytes. + * This expects that sector size is 512 bytes. */ - if (IS_ENABLED(CONFIG_SPL_MMC) && mhdr->blockid == IBR_HDR_SDIO_ID) + if (IS_ENABLED(CONFIG_SPL_SATA) && mhdr->blockid == IBR_HDR_SATA_ID) spl_image->offset *= 512; if (spl_image->offset % 4 != 0) { @@ -299,19 +308,6 @@ int board_return_to_bootrom(struct spl_image_info *spl_image, hang(); } -/* - * SPI0 CS0 Flash is mapped to address range 0xD4000000 - 0xD7FFFFFF by BootROM. - * Proper U-Boot removes this direct mapping. So it is available only in SPL. - */ -#if defined(CONFIG_SPL_ENV_IS_IN_SPI_FLASH) && \ - CONFIG_ENV_SPI_BUS == 0 && CONFIG_ENV_SPI_CS == 0 && \ - CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE <= 64*1024*1024 -void *env_sf_get_env_addr(void) -{ - return (void *)0xD4000000 + CONFIG_ENV_OFFSET; -} -#endif - void board_init_f(ulong dummy) { int ret; diff --git a/cmd/mvebu/Kconfig b/cmd/mvebu/Kconfig index 9ec3aa9..e83a982 100644 --- a/cmd/mvebu/Kconfig +++ b/cmd/mvebu/Kconfig @@ -3,8 +3,12 @@ depends on ARCH_MVEBU config CMD_MVEBU_BUBT bool "bubt" + default y select SHA256 if ARMADA_3700 select SHA512 if ARMADA_3700 + select DOS_PARTITION if ARMADA_3700 + select EFI_PARTITION if ARMADA_3700 + select PARTITION_TYPE_GUID if ARMADA_3700 select MVEBU_EFUSE if ARMADA_38X || ARMADA_3700 help bubt - Burn a u-boot image to flash @@ -15,6 +19,10 @@ if CMD_MVEBU_BUBT choice prompt "Flash for image" + default MVEBU_SPI_BOOT if MVEBU_SPL_BOOT_DEVICE_SPI + default MVEBU_NAND_BOOT if MVEBU_SPL_BOOT_DEVICE_NAND + default MVEBU_MMC_BOOT if MVEBU_SPL_BOOT_DEVICE_MMC + default MVEBU_SATA_BOOT if MVEBU_SPL_BOOT_DEVICE_SATA default MVEBU_SPI_BOOT config MVEBU_NAND_BOOT @@ -44,10 +52,20 @@ config MVEBU_MMC_BOOT For details about bubt command please see the documentation in doc/mvebu/cmd/bubt.txt +config MVEBU_SATA_BOOT + bool "SATA flash boot" + depends on SCSI + help + Enable boot from SATA disk. + Allow usage of SATA disk as a target for "bubt" command + For details about bubt command please see the documentation + in doc/mvebu/cmd/bubt.txt + endchoice config MVEBU_UBOOT_DFLT_NAME string "Default image name for bubt command" + default BUILD_TARGET if ARMADA_32BIT && BUILD_TARGET != "" default "flash-image.bin" help This option should contain a default file name to be used with diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 1efbe2e..49797b2 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -19,6 +19,7 @@ #include <spi_flash.h> #include <spi.h> #include <nand.h> +#include <scsi.h> #include <usb.h> #include <fs.h> #include <mmc.h> @@ -189,6 +190,11 @@ static int mmc_burn_image(size_t image_size) #ifdef CONFIG_BLK struct blk_desc *blk_desc; #endif +#ifdef CONFIG_SUPPORT_EMMC_BOOT + u8 part; + u8 orig_part; +#endif + mmc = find_mmc_device(mmc_dev_num); if (!mmc) { printf("No SD/MMC/eMMC card found\n"); @@ -202,6 +208,38 @@ static int mmc_burn_image(size_t image_size) return err; } +#ifdef CONFIG_BLK + blk_desc = mmc_get_blk_desc(mmc); + if (!blk_desc) { + printf("Error - failed to obtain block descriptor\n"); + return -ENODEV; + } +#endif + +#ifdef CONFIG_SUPPORT_EMMC_BOOT +#ifdef CONFIG_BLK + orig_part = blk_desc->hwpart; +#else + orig_part = mmc->block_dev.hwpart; +#endif + + part = (mmc->part_config >> 3) & PART_ACCESS_MASK; + + if (part == 7) + part = 0; + +#ifdef CONFIG_BLK + err = blk_dselect_hwpart(blk_desc, part); +#else + err = mmc_switch_part(mmc, part); +#endif + + if (err) { + printf("Error - MMC partition switch failed\n"); + return err; + } +#endif + /* SD reserves LBA-0 for MBR and boots from LBA-1, * MMC/eMMC boots from LBA-0 */ @@ -211,11 +249,6 @@ static int mmc_burn_image(size_t image_size) if (image_size % mmc->write_bl_len) blk_count += 1; - blk_desc = mmc_get_blk_desc(mmc); - if (!blk_desc) { - printf("Error - failed to obtain block descriptor\n"); - return -ENODEV; - } blk_written = blk_dwrite(blk_desc, start_lba, blk_count, (void *)get_load_addr()); #else @@ -227,6 +260,17 @@ static int mmc_burn_image(size_t image_size) start_lba, blk_count, (void *)get_load_addr()); #endif /* CONFIG_BLK */ + +#ifdef CONFIG_SUPPORT_EMMC_BOOT +#ifdef CONFIG_BLK + err = blk_dselect_hwpart(blk_desc, orig_part); +#else + err = mmc_switch_part(mmc, orig_part); +#endif + if (err) + printf("Error - MMC failed to switch back to original partition\n"); +#endif + if (blk_written != blk_count) { printf("Error - written %#lx blocks\n", blk_written); return -ENOSPC; @@ -291,6 +335,143 @@ static int is_mmc_active(void) #endif /* CONFIG_DM_MMC */ /******************************************************************** + * SATA services + ********************************************************************/ +#if defined(CONFIG_SCSI) && defined(CONFIG_BLK) +static int sata_burn_image(size_t image_size) +{ +#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT) + lbaint_t start_lba; + lbaint_t blk_count; + ulong blk_written; + struct blk_desc *blk_desc; +#ifdef CONFIG_ARMADA_3700 + struct disk_partition info; + int part; +#endif + + scsi_scan(false); + + blk_desc = blk_get_devnum_by_uclass_id(UCLASS_SCSI, 0); + if (!blk_desc) + return -ENODEV; + +#ifdef CONFIG_ARMADA_3700 + /* + * 64-bit Armada 3700 BootROM loads SATA firmware from + * GPT 'Marvell Armada 3700 Boot partition' or from + * MBR 'M' (0x4d) partition. + */ + switch (blk_desc->part_type) { + case PART_TYPE_DOS: + for (part = 1; part <= 4; part++) { + info.sys_ind = 0; + if (part_get_info(blk_desc, part, &info)) + continue; + if (info.sys_ind == 'M') + break; + } + if (part > 4) { + printf("Error - cannot find MBR 'M' (0x4d) partition on SATA disk\n"); + return -ENODEV; + } + start_lba = info.start; + break; + case PART_TYPE_EFI: + for (part = 1; part <= 64; part++) { + info.type_guid[0] = 0; + if (part_get_info(blk_desc, part, &info)) + continue; + /* Check for GPT type GUID of 'Marvell Armada 3700 Boot partition' */ + if (strcmp(info.type_guid, "6828311A-BA55-42A4-BCDE-A89BB5EDECAE") == 0) + break; + } + if (part > 64) { + printf("Error - cannot find GPT 'Marvell Armada 3700 Boot partition' on SATA disk\n"); + return -ENODEV; + } + start_lba = info.start; + break; + default: + printf("Error - no partitions on SATA disk\n"); + return -ENODEV; + } +#else + /* 32-bit Armada BootROM loads SATA firmware from the sector 1. */ + start_lba = 1; +#endif + + blk_count = image_size / blk_desc->blksz; + if (image_size % blk_desc->blksz) + blk_count += 1; + + blk_written = blk_dwrite(blk_desc, start_lba, blk_count, + (void *)get_load_addr()); + + if (blk_written != blk_count) { + printf("Error - written %#lx blocks\n", blk_written); + return -ENOSPC; + } + + printf("Done!\n"); + return 0; +#else + return -ENODEV; +#endif +} + +static size_t sata_read_file(const char *file_name) +{ + loff_t act_read = 0; + struct udevice *dev; + int rc; + + /* try to recognize storage devices immediately */ + scsi_scan(false); + + /* Try to recognize storage devices immediately */ + blk_first_device(UCLASS_SCSI, &dev); + if (!dev) { + printf("Error: SATA device not found\n"); + return 0; + } + + /* Always load from scsi 0 */ + if (fs_set_blk_dev("scsi", "0", FS_TYPE_ANY)) { + printf("Error: SATA 0 not found\n"); + return 0; + } + + /* Perfrom file read */ + rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); + if (rc) + return 0; + + return act_read; +} + +static int is_sata_active(void) +{ + return 1; +} +#else /* CONFIG_SCSI */ +static int sata_burn_image(size_t image_size) +{ + return -ENODEV; +} + +static size_t sata_read_file(const char *file_name) +{ + return 0; +} + +static int is_sata_active(void) +{ + return 0; +} +#endif /* CONFIG_SCSI */ + +/******************************************************************** * SPI services ********************************************************************/ #ifdef CONFIG_SPI_FLASH @@ -499,16 +680,18 @@ enum bubt_devices { BUBT_DEV_NET = 0, BUBT_DEV_USB, BUBT_DEV_MMC, + BUBT_DEV_SATA, BUBT_DEV_SPI, BUBT_DEV_NAND, BUBT_MAX_DEV }; -struct bubt_dev bubt_devs[BUBT_MAX_DEV] = { +static struct bubt_dev bubt_devs[BUBT_MAX_DEV] = { {"tftp", tftp_read_file, NULL, is_tftp_active}, {"usb", usb_read_file, NULL, is_usb_active}, {"mmc", mmc_read_file, mmc_burn_image, is_mmc_active}, + {"sata", sata_read_file, sata_burn_image, is_sata_active}, {"spi", NULL, spi_burn_image, is_spi_active}, {"nand", NULL, nand_burn_image, is_nand_active}, }; @@ -524,7 +707,7 @@ static int bubt_write_file(struct bubt_dev *dst, size_t image_size) } #if defined(CONFIG_ARMADA_8K) -u32 do_checksum32(u32 *start, int32_t len) +static u32 do_checksum32(u32 *start, int32_t len) { u32 sum = 0; u32 *startp = start; @@ -542,9 +725,8 @@ static int check_image_header(void) { struct mvebu_image_header *hdr = (struct mvebu_image_header *)get_load_addr(); - u32 header_len = hdr->prolog_size; u32 checksum; - u32 checksum_ref = hdr->prolog_checksum; + u32 checksum_ref; /* * For now compare checksum, and magic. Later we can @@ -556,18 +738,23 @@ static int check_image_header(void) return -ENOEXEC; } - /* The checksum value is discarded from checksum calculation */ - hdr->prolog_checksum = 0; + checksum_ref = hdr->prolog_checksum; + checksum = do_checksum32((u32 *)hdr, hdr->prolog_size); + checksum -= hdr->prolog_checksum; + if (checksum != checksum_ref) { + printf("Error: Bad Prolog checksum. 0x%x != 0x%x\n", + checksum, checksum_ref); + return -ENOEXEC; + } - checksum = do_checksum32((u32 *)hdr, header_len); + checksum_ref = hdr->boot_image_checksum; + checksum = do_checksum32((u32 *)((u8 *)hdr + hdr->prolog_size), hdr->boot_image_size); if (checksum != checksum_ref) { printf("Error: Bad Image checksum. 0x%x != 0x%x\n", checksum, checksum_ref); return -ENOEXEC; } - /* Restore the checksum before writing */ - hdr->prolog_checksum = checksum_ref; printf("Image checksum...OK!\n"); return 0; @@ -722,12 +909,12 @@ static int check_image_header(void) u32 offset, size; const struct a38x_main_hdr_v1 *hdr = (struct a38x_main_hdr_v1 *)get_load_addr(); - const size_t image_size = a38x_header_size(hdr); + const size_t hdr_size = a38x_header_size(hdr); - if (!image_size) + if (!hdr_size) return -ENOEXEC; - checksum = image_checksum8(hdr, image_size); + checksum = image_checksum8(hdr, hdr_size); checksum -= hdr->checksum; if (checksum != hdr->checksum) { printf("Error: Bad A38x image header checksum. 0x%x != 0x%x\n", @@ -738,16 +925,7 @@ static int check_image_header(void) offset = le32_to_cpu(hdr->srcaddr); size = le32_to_cpu(hdr->blocksize); - if (hdr->blockid == 0x78) { /* SATA id */ - if (offset < 1) { - printf("Error: Bad A38x image srcaddr.\n"); - return -ENOEXEC; - } - offset -= 1; - offset *= 512; - } - - if (hdr->blockid == 0xAE) /* SDIO id */ + if (hdr->blockid == 0x78) /* SATA id */ offset *= 512; if (offset % 4 != 0 || size < 4 || size % 4 != 0) { @@ -770,7 +948,7 @@ static int check_image_header(void) #if defined(CONFIG_ARMADA_38X) static int a38x_image_is_secure(const struct a38x_main_hdr_v1 *hdr) { - u32 image_size = a38x_header_size(hdr); + const size_t hdr_size = a38x_header_size(hdr); struct a38x_opt_hdr_v1 *ohdr; u32 ohdr_size; @@ -791,7 +969,7 @@ static int a38x_image_is_secure(const struct a38x_main_hdr_v1 *hdr) break; ohdr = (struct a38x_opt_hdr_v1 *)((u8 *)ohdr + ohdr_size); - if ((u8 *)ohdr >= (u8 *)hdr + image_size) + if ((u8 *)ohdr >= (u8 *)hdr + hdr_size) break; } while (1); @@ -806,7 +984,7 @@ static int check_image_header(void) } #endif -#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT) +#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_38X) static u64 fuse_read_u64(u32 bank) { u32 val[2]; @@ -835,7 +1013,10 @@ static inline u8 maj3(u8 val) static int bubt_check_boot_mode(const struct bubt_dev *dst) { #if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT) - int mode, secure_mode; + int mode; +#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_38X) + int secure_mode; +#endif #if defined(CONFIG_ARMADA_3700) const struct tim_boot_flash_sign *boot_modes = tim_boot_flash_signs; const struct common_tim_data *hdr = @@ -966,7 +1147,7 @@ static int bubt_is_dev_active(struct bubt_dev *dev) return 1; } -struct bubt_dev *find_bubt_dev(char *dev_name) +static struct bubt_dev *find_bubt_dev(char *dev_name) { int dev; @@ -987,12 +1168,14 @@ struct bubt_dev *find_bubt_dev(char *dev_name) #define DEFAULT_BUBT_DST "nand" #elif defined(CONFIG_MVEBU_MMC_BOOT) #define DEFAULT_BUBT_DST "mmc" +#elif defined(CONFIG_MVEBU_SATA_BOOT) +#define DEFAULT_BUBT_DST "sata" #else #define DEFAULT_BUBT_DST "error" #endif #endif /* DEFAULT_BUBT_DST */ -int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +static int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct bubt_dev *src, *dst; size_t image_size; @@ -1064,8 +1247,8 @@ U_BOOT_CMD( "Burn a u-boot image to flash", "[file-name] [destination [source]]\n" "\t-file-name The image file name to burn. Default = " CONFIG_MVEBU_UBOOT_DFLT_NAME "\n" - "\t-destination Flash to burn to [spi, nand, mmc]. Default = " DEFAULT_BUBT_DST "\n" - "\t-source The source to load image from [tftp, usb, mmc]. Default = " DEFAULT_BUBT_SRC "\n" + "\t-destination Flash to burn to [spi, nand, mmc, sata]. Default = " DEFAULT_BUBT_DST "\n" + "\t-source The source to load image from [tftp, usb, mmc, sata]. Default = " DEFAULT_BUBT_SRC "\n" "Examples:\n" "\tbubt - Burn flash-image.bin from tftp to active boot device\n" "\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n" diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 3c2af45..2c042ad 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -816,8 +816,17 @@ config SPL_MMC this option to build the drivers in drivers/mmc as part of an SPL build. +config SYS_MMCSD_FS_BOOT + bool "MMC FS Boot mode" + depends on SPL_MMC + default y if !ARCH_MVEBU + help + Enable MMC FS Boot mode. Partition is selected by option + SYS_MMCSD_FS_BOOT_PARTITION. + config SYS_MMCSD_FS_BOOT_PARTITION int "MMC Boot Partition" + depends on SYS_MMCSD_FS_BOOT default 1 help Partition on the MMC to load U-Boot from when the MMC is being diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index e4135b2..bd5e6ad 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -272,7 +272,7 @@ int spl_start_uboot(void) } #endif -#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION +#ifdef CONFIG_SYS_MMCSD_FS_BOOT static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct mmc *mmc, @@ -341,14 +341,6 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, return err; } -#else -static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev, - struct mmc *mmc, - const char *filename) -{ - return -ENOSYS; -} #endif u32 __weak spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) @@ -481,6 +473,7 @@ int spl_mmc_load(struct spl_image_info *spl_image, return err; #endif /* If RAW mode fails, try FS mode. */ +#ifdef CONFIG_SYS_MMCSD_FS_BOOT case MMCSD_MODE_FS: debug("spl: mmc boot mode: fs\n"); @@ -489,6 +482,7 @@ int spl_mmc_load(struct spl_image_info *spl_image, return err; break; +#endif #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT default: puts("spl: mmc: wrong boot mode\n"); diff --git a/configs/clearfog_sata_defconfig b/configs/clearfog_sata_defconfig new file mode 100644 index 0000000..e9b3615 --- /dev/null +++ b/configs/clearfog_sata_defconfig @@ -0,0 +1,83 @@ +CONFIG_ARM=y +CONFIG_ARCH_CPU_INIT=y +CONFIG_SYS_THUMB_BUILD=y +CONFIG_ARCH_MVEBU=y +CONFIG_TEXT_BASE=0x00800000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_CLEARFOG=y +CONFIG_MVEBU_SPL_BOOT_DEVICE_SATA=y +CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog" +CONFIG_SPL_TEXT_BASE=0x40000030 +CONFIG_SPL_SERIAL=y +CONFIG_SPL=y +CONFIG_DEBUG_UART_BASE=0xf1012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_SYS_LOAD_ADDR=0x800000 +CONFIG_DEBUG_UART=y +CONFIG_AHCI=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000 +CONFIG_BOOTDELAY=3 +CONFIG_USE_PREBOOT=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_SPL_MAX_SIZE=0x22fd0 +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0x40023000 +CONFIG_SPL_BSS_MAX_SIZE=0x4000 +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_STACK=0x4002c000 +CONFIG_SPL_I2C=y +CONFIG_SYS_MAXARGS=32 +CONFIG_CMD_TLV_EEPROM=y +CONFIG_SPL_CMD_TLV_EEPROM=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_MVEBU_BUBT=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_MIN_ENTRIES=128 +CONFIG_ARP_TIMEOUT=200 +CONFIG_NET_RETRY_COUNT=50 +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_AHCI_MVEBU=y +CONFIG_DM_PCA953X=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +CONFIG_I2C_EEPROM=y +CONFIG_SPL_I2C_EEPROM=y +CONFIG_SUPPORT_EMMC_BOOT=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_MV=y +CONFIG_MTD=y +CONFIG_SF_DEFAULT_BUS=1 +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PHY_MARVELL=y +CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y +CONFIG_MII=y +CONFIG_MVMDIO=y +CONFIG_PCI=y +CONFIG_PCI_MVEBU=y +CONFIG_SCSI=y +CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_KIRKWOOD_SPI=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y diff --git a/configs/db-88f6820-amc_nand_defconfig b/configs/db-88f6820-amc_nand_defconfig new file mode 100644 index 0000000..e784c34 --- /dev/null +++ b/configs/db-88f6820-amc_nand_defconfig @@ -0,0 +1,92 @@ +CONFIG_ARM=y +CONFIG_ARCH_CPU_INIT=y +CONFIG_ARCH_MVEBU=y +CONFIG_TEXT_BASE=0x00800000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_DB_88F6820_AMC=y +CONFIG_MVEBU_SPL_BOOT_DEVICE_NAND=y +CONFIG_MVEBU_SPL_NAND_BADBLK_LOCATION=0x00 +CONFIG_ENV_SIZE=0x10000 +CONFIG_ENV_OFFSET=0x100000 +CONFIG_ENV_SECT_SIZE=0x40000 +CONFIG_DEFAULT_DEVICE_TREE="armada-385-db-88f6820-amc" +CONFIG_SPL_TEXT_BASE=0x40000030 +CONFIG_SPL_SERIAL=y +CONFIG_SPL=y +CONFIG_DEBUG_UART_BASE=0xf1012000 +CONFIG_DEBUG_UART_CLOCK=200000000 +CONFIG_SYS_LOAD_ADDR=0x800000 +CONFIG_DEBUG_UART=y +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000 +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_BOOTDELAY=3 +CONFIG_USE_PREBOOT=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_SPL_MAX_SIZE=0x22fd0 +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0x40023000 +CONFIG_SPL_BSS_MAX_SIZE=0x4000 +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_STACK=0x4002c000 +CONFIG_SPL_I2C=y +CONFIG_SYS_MAXARGS=96 +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_I2C=y +CONFIG_CMD_PCI=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_EFI_PARTITION=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SPI_MAX_HZ=50000000 +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_ARP_TIMEOUT=200 +CONFIG_NET_RETRY_COUNT=50 +CONFIG_SPL_OF_TRANSLATE=y +# CONFIG_SPL_BLK is not set +# CONFIG_BLOCK_CACHE is not set +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +# CONFIG_MMC is not set +CONFIG_MTD=y +CONFIG_SYS_NAND_USE_FLASH_BBT=y +CONFIG_NAND_PXA3XX=y +CONFIG_SYS_NAND_BLOCK_SIZE=0x40000 +CONFIG_SYS_NAND_ONFI_DETECTION=y +CONFIG_SYS_NAND_PAGE_SIZE=0x1000 +CONFIG_SF_DEFAULT_BUS=1 +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_PHY_MARVELL=y +CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y +CONFIG_MII=y +CONFIG_MVMDIO=y +CONFIG_PCI=y +CONFIG_PCI_MVEBU=y +CONFIG_SPL_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_KIRKWOOD_SPI=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y diff --git a/doc/kwboot.1 b/doc/kwboot.1 index a528fbb..5cda3b4 100644 --- a/doc/kwboot.1 +++ b/doc/kwboot.1 @@ -159,7 +159,8 @@ program: Instruct BootROM to enter boot Xmodem boot mode, send header of \fIu-boot-with-spl.kwb\fP kwbimage file via Xmodem at 115200 Bd, then instruct BootROM to change baudrate to 5200000 Bd, send data part of the kwbimage -file via Xmodem at high speed and finally run terminal program: +file via Xmodem at high speed, then change baudrate back to 115200 Bd, +and finally run terminal program: .IP .B kwboot -b u-boot-with-spl.kwb -B 5200000 -t /dev/ttyUSB0 diff --git a/doc/mvebu/cmd/bubt.txt b/doc/mvebu/cmd/bubt.txt index 6051243..52bd3e6 100644 --- a/doc/mvebu/cmd/bubt.txt +++ b/doc/mvebu/cmd/bubt.txt @@ -5,8 +5,8 @@ Bubt command is used to burn a new ATF image to flash device. The bubt command gets the following parameters: ATF file name, destination device and source device. bubt [file-name] [destination [source]] - file-name Image file name to burn. default = flash-image.bin - - destination Flash to burn to [spi, nand, mmc]. default = active flash - - source Source to load image from [tftp, usb]. default = tftp + - destination Flash to burn to [spi, nand, mmc, sata]. default = active flash + - source Source to load image from [tftp, usb, mmc, sata]. default = tftp Examples: bubt - Burn flash-image.bin from tftp to active flash @@ -14,8 +14,7 @@ Examples: Notes: - For the TFTP interface set serverip and ipaddr. -- To burn image to SD/eMMC device, the target is defined - by parameters CONFIG_SYS_MMC_ENV_DEV and CONFIG_SYS_MMC_ENV_PART. +- To burn image to SD/eMMC device, the target is defined by HW partition. Bubt command details (burn image step by-step) ---------------------------------------------- @@ -40,10 +39,20 @@ Notes: Number 0 is used for user data partition and should not be utilized for storing boot images and U-Boot environment in RAW mode since it will break file system structures usually located here. - The default boot partition is BOOT0. It is selected by the following parameter: - CONFIG_SYS_MMC_ENV_PART=1 - Valid values for this parameter are 1 for BOOT0 and 2 for BOOT1. - Please never use partition number 0 here! + + Currently configured boot partition can be printed by command: + # mmc partconf 0 + (search for BOOT_PARTITION_ACCESS output, number 7 is user data) + + Change it to BOOT0: + # mmc partconf 0 0 1 1 + + Change it to BOOT1: + # mmc partconf 0 0 2 2 + + Change it to user data: + # mmc partconf 0 0 7 0 + - The partition number is ignored if the target device is SD card. - The boot image offset starts at block 0 for eMMC and block 1 for SD devices. The block 0 on SD devices is left for MBR storage. diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 5b35da4..5c7b0d9 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -628,7 +628,8 @@ comment "Generic NAND options" config SYS_NAND_BLOCK_SIZE hex "NAND chip eraseblock size" - depends on ARCH_SUNXI || SPL_NAND_SUPPORT || TPL_NAND_SUPPORT + depends on ARCH_SUNXI || SPL_NAND_SUPPORT || TPL_NAND_SUPPORT || \ + MVEBU_SPL_BOOT_DEVICE_NAND depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && \ !NAND_FSL_IFC && !NAND_MT7621 help @@ -655,6 +656,7 @@ config SYS_NAND_PAGE_SIZE hex "NAND chip page size" depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \ SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \ + MVEBU_SPL_BOOT_DEVICE_NAND || \ (NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621 help diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 6abb9f2..309657a 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -927,6 +927,71 @@ done: return ret; } +static int image_fill_xip_header(void *image, struct image_tool_params *params) +{ + struct main_hdr_v1 *main_hdr = image; /* kwbimage v0 and v1 have same XIP members */ + int version = kwbimage_version(image); + uint32_t srcaddr = le32_to_cpu(main_hdr->srcaddr); + uint32_t startaddr = 0; + + if (main_hdr->blockid != IBR_HDR_SPI_ID) { + fprintf(stderr, "XIP is supported only for SPI images\n"); + return 0; + } + + if (version == 0 && + params->addr >= 0xE8000000 && params->addr < 0xEFFFFFFF && + params->ep >= 0xE8000000 && params->ep < 0xEFFFFFFF) { + /* Load and Execute address is in SPI address space (kwbimage v0) */ + startaddr = 0xE8000000; + } else if (version != 0 && + params->addr >= 0xD4000000 && params->addr < 0xD7FFFFFF && + params->ep >= 0xD4000000 && params->ep < 0xD7FFFFFF) { + /* Load and Execute address is in SPI address space (kwbimage v1) */ + startaddr = 0xD4000000; + } else if (version != 0 && + params->addr >= 0xD8000000 && params->addr < 0xDFFFFFFF && + params->ep >= 0xD8000000 && params->ep < 0xDFFFFFFF) { + /* Load and Execute address is in Device bus space (kwbimage v1) */ + startaddr = 0xD8000000; + } else if (params->addr != 0x0) { + /* Load address is non-zero */ + if (version == 0) + fprintf(stderr, "XIP Load Address or XIP Entry Point is not in SPI address space\n"); + else + fprintf(stderr, "XIP Load Address or XIP Entry Point is not in SPI nor in Device bus address space\n"); + return 0; + } + + /* + * For XIP destaddr must be set to 0xFFFFFFFF and + * execaddr relative to the start of XIP memory address space. + */ + main_hdr->destaddr = cpu_to_le32(0xFFFFFFFF); + + if (startaddr == 0) { + /* + * mkimage's --load-address 0x0 means that binary is Position + * Independent and in this case mkimage's --entry-point address + * is relative offset from beginning of the data part of image. + */ + main_hdr->execaddr = cpu_to_le32(srcaddr + params->ep); + } else { + /* The lowest possible load address is after the header at srcaddr. */ + if (params->addr - startaddr < srcaddr) { + fprintf(stderr, + "Invalid XIP Load Address 0x%08x.\n" + "The lowest address for this configuration is 0x%08x.\n", + params->addr, (unsigned)(startaddr + srcaddr)); + return 0; + } + main_hdr->srcaddr = cpu_to_le32(params->addr - startaddr); + main_hdr->execaddr = cpu_to_le32(params->ep - startaddr); + } + + return 1; +} + static size_t image_headersz_align(size_t headersz, uint8_t blockid) { /* @@ -959,10 +1024,10 @@ static size_t image_headersz_v0(int *hasext) *hasext = 1; } - return image_headersz_align(headersz, image_get_bootfrom()); + return headersz; } -static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, +static void *image_create_v0(size_t *dataoff, struct image_tool_params *params, int payloadsz) { struct image_cfg_element *e; @@ -972,10 +1037,11 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, int has_ext = 0; /* - * Calculate the size of the header and the size of the + * Calculate the size of the header and the offset of the * payload */ headersz = image_headersz_v0(&has_ext); + *dataoff = image_headersz_align(headersz, image_get_bootfrom()); image = malloc(headersz); if (!image) { @@ -990,7 +1056,7 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, /* Fill in the main header */ main_hdr->blocksize = cpu_to_le32(payloadsz); - main_hdr->srcaddr = cpu_to_le32(headersz); + main_hdr->srcaddr = cpu_to_le32(*dataoff); main_hdr->ext = has_ext; main_hdr->version = 0; main_hdr->destaddr = cpu_to_le32(params->addr); @@ -1009,31 +1075,26 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION); if (e) main_hdr->nandbadblklocation = e->nandbadblklocation; - main_hdr->checksum = image_checksum8(image, - sizeof(struct main_hdr_v0)); /* - * For SATA srcaddr is specified in number of sectors starting from - * sector 0. The main header is stored at sector number 1. + * For SATA srcaddr is specified in number of sectors. * This expects the sector size to be 512 bytes. - * Header size is already aligned. */ if (main_hdr->blockid == IBR_HDR_SATA_ID) - main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1); - - /* - * For SDIO srcaddr is specified in number of sectors starting from - * sector 0. The main header is stored at sector number 0. - * This expects sector size to be 512 bytes. - * Header size is already aligned. - */ - if (main_hdr->blockid == IBR_HDR_SDIO_ID) - main_hdr->srcaddr = cpu_to_le32(headersz / 512); + main_hdr->srcaddr = cpu_to_le32(le32_to_cpu(main_hdr->srcaddr) / 512); /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */ if (main_hdr->blockid == IBR_HDR_PEX_ID) main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF); + if (params->xflag) { + if (!image_fill_xip_header(main_hdr, params)) { + free(image); + return NULL; + } + *dataoff = le32_to_cpu(main_hdr->srcaddr); + } + /* Generate the ext header */ if (has_ext) { struct ext_hdr_v0 *ext_hdr; @@ -1059,7 +1120,9 @@ static void *image_create_v0(size_t *imagesz, struct image_tool_params *params, sizeof(struct ext_hdr_v0)); } - *imagesz = headersz; + main_hdr->checksum = image_checksum8(image, + sizeof(struct main_hdr_v0)); + return image; } @@ -1073,10 +1136,6 @@ static size_t image_headersz_v1(int *hasext) int cfgi; int ret; - /* - * Calculate the size of the header and the size of the - * payload - */ headersz = sizeof(struct main_hdr_v1); if (image_get_csk_index() >= 0) { @@ -1172,7 +1231,7 @@ static size_t image_headersz_v1(int *hasext) if (count > 0) headersz += sizeof(struct register_set_hdr_v1) + 8 * count + 4; - return image_headersz_align(headersz, image_get_bootfrom()); + return headersz; } static int add_binary_header_v1(uint8_t **cur, uint8_t **next_ext, @@ -1331,16 +1390,14 @@ static int kwb_sign_csk_with_kak(struct image_tool_params *params, return 0; } -static int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr, - int payloadsz, size_t headersz, uint8_t *image, +static int add_secure_header_v1(struct image_tool_params *params, uint8_t *image_ptr, + size_t image_size, uint8_t *header_ptr, size_t headersz, struct secure_hdr_v1 *secure_hdr) { struct image_cfg_element *e_jtagdelay; struct image_cfg_element *e_boxid; struct image_cfg_element *e_flashid; RSA *csk = NULL; - unsigned char *image_ptr; - size_t image_size; struct sig_v1 tmp_sig; bool specialized_img = image_get_spezialized_img(); @@ -1366,14 +1423,11 @@ static int add_secure_header_v1(struct image_tool_params *params, uint8_t *ptr, if (kwb_sign_csk_with_kak(params, secure_hdr, csk)) return 1; - image_ptr = ptr + headersz; - image_size = payloadsz - headersz; - - if (kwb_sign_and_verify(csk, image_ptr, image_size, + if (kwb_sign_and_verify(csk, image_ptr, image_size - 4, &secure_hdr->imgsig, "image") < 0) return 1; - if (kwb_sign_and_verify(csk, image, headersz, &tmp_sig, "header") < 0) + if (kwb_sign_and_verify(csk, header_ptr, headersz, &tmp_sig, "header") < 0) return 1; secure_hdr->hdrsig = tmp_sig; @@ -1399,12 +1453,11 @@ static void finish_register_set_header_v1(uint8_t **cur, uint8_t **next_ext, *datai = 0; } -static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, +static void *image_create_v1(size_t *dataoff, struct image_tool_params *params, uint8_t *ptr, int payloadsz) { struct image_cfg_element *e; struct main_hdr_v1 *main_hdr; - struct opt_hdr_v1 *ohdr; struct register_set_hdr_v1 *register_set_hdr; struct secure_hdr_v1 *secure_hdr = NULL; size_t headersz; @@ -1415,12 +1468,13 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, uint8_t delay; /* - * Calculate the size of the header and the size of the + * Calculate the size of the header and the offset of the * payload */ headersz = image_headersz_v1(&hasext); if (headersz == 0) return NULL; + *dataoff = image_headersz_align(headersz, image_get_bootfrom()); image = malloc(headersz); if (!image) { @@ -1442,7 +1496,7 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; main_hdr->destaddr = cpu_to_le32(params->addr); main_hdr->execaddr = cpu_to_le32(params->ep); - main_hdr->srcaddr = cpu_to_le32(headersz); + main_hdr->srcaddr = cpu_to_le32(*dataoff); main_hdr->ext = hasext; main_hdr->version = 1; main_hdr->blockid = image_get_bootfrom(); @@ -1470,27 +1524,24 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, main_hdr->flags = e->debug ? 0x1 : 0; /* - * For SATA srcaddr is specified in number of sectors starting from - * sector 0. The main header is stored at sector number 1. + * For SATA srcaddr is specified in number of sectors. * This expects the sector size to be 512 bytes. - * Header size is already aligned. */ if (main_hdr->blockid == IBR_HDR_SATA_ID) - main_hdr->srcaddr = cpu_to_le32(headersz / 512 + 1); - - /* - * For SDIO srcaddr is specified in number of sectors starting from - * sector 0. The main header is stored at sector number 0. - * This expects sector size to be 512 bytes. - * Header size is already aligned. - */ - if (main_hdr->blockid == IBR_HDR_SDIO_ID) - main_hdr->srcaddr = cpu_to_le32(headersz / 512); + main_hdr->srcaddr = cpu_to_le32(le32_to_cpu(main_hdr->srcaddr) / 512); /* For PCIe srcaddr is not used and must be set to 0xFFFFFFFF. */ if (main_hdr->blockid == IBR_HDR_PEX_ID) main_hdr->srcaddr = cpu_to_le32(0xFFFFFFFF); + if (params->xflag) { + if (!image_fill_xip_header(main_hdr, params)) { + free(image); + return NULL; + } + *dataoff = le32_to_cpu(main_hdr->srcaddr); + } + if (image_get_csk_index() >= 0) { /* * only reserve the space here; we fill the header later since @@ -1552,19 +1603,10 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, &datai, delay); } - if (secure_hdr && add_secure_header_v1(params, ptr, payloadsz + headersz, - headersz, image, secure_hdr)) + if (secure_hdr && add_secure_header_v1(params, ptr + *dataoff, payloadsz, + image, headersz, secure_hdr)) return NULL; - *imagesz = headersz; - - /* Fill the real header size without padding into the main header */ - headersz = sizeof(*main_hdr); - for_each_opt_hdr_v1 (ohdr, main_hdr) - headersz += opt_hdr_v1_size(ohdr); - main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF); - main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16; - /* Calculate and set the header checksum */ main_hdr->checksum = image_checksum8(main_hdr, headersz); @@ -1835,7 +1877,7 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, FILE *fcfg; void *image = NULL; int version; - size_t headersz = 0; + size_t dataoff = 0; size_t datasz; uint32_t checksum; struct stat s; @@ -1845,7 +1887,9 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, * Do not use sbuf->st_size as it contains size with padding. * We need original image data size, so stat original file. */ - if (stat(params->datafile, &s)) { + if (params->skipcpy) { + s.st_size = 0; + } else if (stat(params->datafile, &s)) { fprintf(stderr, "Could not stat data file %s: %s\n", params->datafile, strerror(errno)); exit(EXIT_FAILURE); @@ -1886,11 +1930,11 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, */ case -1: case 0: - image = image_create_v0(&headersz, params, datasz + 4); + image = image_create_v0(&dataoff, params, datasz + 4); break; case 1: - image = image_create_v1(&headersz, params, ptr, datasz + 4); + image = image_create_v1(&dataoff, params, ptr, datasz + 4); break; default: @@ -1908,12 +1952,12 @@ static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd, free(image_cfg); /* Build and add image data checksum */ - checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + headersz, + checksum = cpu_to_le32(image_checksum32((uint8_t *)ptr + dataoff, datasz)); - memcpy((uint8_t *)ptr + headersz + datasz, &checksum, sizeof(uint32_t)); + memcpy((uint8_t *)ptr + dataoff + datasz, &checksum, sizeof(uint32_t)); /* Finally copy the header into the image area */ - memcpy(ptr, image, headersz); + memcpy(ptr, image, kwbheader_size(image)); free(image); } @@ -1933,9 +1977,9 @@ static void kwbimage_print_header(const void *ptr) printf("BIN Img Size: "); genimg_print_size(opt_hdr_v1_size(ohdr) - 12 - 4 * ohdr->data[0]); - printf("BIN Img Offs: %08x\n", - (unsigned)((uint8_t *)ohdr - (uint8_t *)mhdr) + - 8 + 4 * ohdr->data[0]); + printf("BIN Img Offs: "); + genimg_print_size(((uint8_t *)ohdr - (uint8_t *)mhdr) + + 8 + 4 * ohdr->data[0]); } } @@ -1947,9 +1991,20 @@ static void kwbimage_print_header(const void *ptr) } printf("Data Size: "); - genimg_print_size(mhdr->blocksize - sizeof(uint32_t)); - printf("Load Address: %08x\n", mhdr->destaddr); - printf("Entry Point: %08x\n", mhdr->execaddr); + genimg_print_size(le32_to_cpu(mhdr->blocksize) - sizeof(uint32_t)); + printf("Data Offset: "); + if (mhdr->blockid == IBR_HDR_SATA_ID) + printf("%u Sector%s (LBA)\n", le32_to_cpu(mhdr->srcaddr), + le32_to_cpu(mhdr->srcaddr) != 1 ? "s" : ""); + else + genimg_print_size(le32_to_cpu(mhdr->srcaddr)); + if (mhdr->blockid == IBR_HDR_SPI_ID && le32_to_cpu(mhdr->destaddr) == 0xFFFFFFFF) { + printf("Load Address: XIP\n"); + printf("Execute Offs: %08x\n", le32_to_cpu(mhdr->execaddr)); + } else { + printf("Load Address: %08x\n", le32_to_cpu(mhdr->destaddr)); + printf("Entry Point: %08x\n", le32_to_cpu(mhdr->execaddr)); + } } static int kwbimage_check_image_types(uint8_t type) @@ -2028,23 +2083,9 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size, /* * For SATA srcaddr is specified in number of sectors. - * The main header is must be stored at sector number 1. - * This expects that sector size is 512 bytes and recalculates - * data offset to bytes relative to the main header. + * This expects that sector size is 512 bytes. */ - if (blockid == IBR_HDR_SATA_ID) { - if (offset < 1) - return -FDT_ERR_BADSTRUCTURE; - offset -= 1; - offset *= 512; - } - - /* - * For SDIO srcaddr is specified in number of sectors. - * This expects that sector size is 512 bytes and recalculates - * data offset to bytes. - */ - if (blockid == IBR_HDR_SDIO_ID) + if (blockid == IBR_HDR_SATA_ID) offset *= 512; /* @@ -2067,6 +2108,8 @@ static int kwbimage_verify_header(unsigned char *ptr, int image_size, return 0; } +static int kwbimage_align_size(int bootfrom, int alloc_len, struct stat s); + static int kwbimage_generate(struct image_tool_params *params, struct image_type_params *tparams) { @@ -2085,7 +2128,9 @@ static int kwbimage_generate(struct image_tool_params *params, exit(EXIT_FAILURE); } - if (stat(params->datafile, &s)) { + if (params->skipcpy) { + s.st_size = 0; + } else if (stat(params->datafile, &s)) { fprintf(stderr, "Could not stat data file %s: %s\n", params->datafile, strerror(errno)); exit(EXIT_FAILURE); @@ -2141,6 +2186,8 @@ static int kwbimage_generate(struct image_tool_params *params, exit(EXIT_FAILURE); } + alloc_len = image_headersz_align(alloc_len, image_get_bootfrom()); + free(image_cfg); hdr = malloc(alloc_len); @@ -2155,6 +2202,22 @@ static int kwbimage_generate(struct image_tool_params *params, tparams->hdr = hdr; /* + * This function should return aligned size of the datafile. + * When skipcpy is set (datafile is skipped) then return value of this + * function is ignored, so we have to put required kwbimage aligning + * into the preallocated header size. + */ + if (params->skipcpy) { + tparams->header_size += kwbimage_align_size(bootfrom, alloc_len, s); + return 0; + } else { + return kwbimage_align_size(bootfrom, alloc_len, s); + } +} + +static int kwbimage_align_size(int bootfrom, int alloc_len, struct stat s) +{ + /* * The resulting image needs to be 4-byte aligned. At least * the Marvell hdrparser tool complains if its unaligned. * After the image data is stored 4-byte checksum. @@ -2182,6 +2245,7 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) struct ext_hdr_v0 *ehdr0; struct bin_hdr_v0 *bhdr0; struct opt_hdr_v1 *ohdr; + int regset_count; int params_count; unsigned offset; int is_v0_ext; @@ -2215,12 +2279,18 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) fprintf(f, "NAND_ECC_MODE %s\n", image_nand_ecc_mode_name(mhdr0->nandeccmode)); if (mhdr->blockid == IBR_HDR_NAND_ID) - fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)mhdr->nandpagesize); + fprintf(f, "NAND_PAGE_SIZE 0x%x\n", (unsigned)le16_to_cpu(mhdr->nandpagesize)); - if (version != 0 && mhdr->blockid == IBR_HDR_NAND_ID) - fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize); + if (mhdr->blockid == IBR_HDR_NAND_ID && (version != 0 || is_v0_ext || mhdr->nandblocksize != 0)) { + if (mhdr->nandblocksize != 0) /* block size explicitly set in 64 kB unit */ + fprintf(f, "NAND_BLKSZ 0x%x\n", (unsigned)mhdr->nandblocksize * 64*1024); + else if (le16_to_cpu(mhdr->nandpagesize) > 512) + fprintf(f, "NAND_BLKSZ 0x10000\n"); /* large page NAND flash = 64 kB block size */ + else + fprintf(f, "NAND_BLKSZ 0x4000\n"); /* small page NAND flash = 16 kB block size */ + } - if (mhdr->blockid == IBR_HDR_NAND_ID && (mhdr->nandbadblklocation != 0 || is_v0_ext)) + if (mhdr->blockid == IBR_HDR_NAND_ID && (version != 0 || is_v0_ext)) fprintf(f, "NAND_BADBLK_LOCATION 0x%x\n", (unsigned)mhdr->nandbadblklocation); if (version == 0 && mhdr->blockid == IBR_HDR_SATA_ID) @@ -2266,18 +2336,20 @@ static int kwbimage_generate_config(void *ptr, struct image_tool_params *params) cur_idx++; } else if (ohdr->headertype == OPT_HDR_V1_REGISTER_TYPE) { regset_hdr = (struct register_set_hdr_v1 *)ohdr; - for (i = 0; - i < opt_hdr_v1_size(ohdr) - sizeof(struct opt_hdr_v1) - - sizeof(regset_hdr->data[0].last_entry); - i++) + if (opt_hdr_v1_size(ohdr) > sizeof(*ohdr)) + regset_count = (opt_hdr_v1_size(ohdr) - sizeof(*ohdr)) / + sizeof(regset_hdr->data[0].entry); + else + regset_count = 0; + for (i = 0; i < regset_count; i++) fprintf(f, "DATA 0x%08x 0x%08x\n", le32_to_cpu(regset_hdr->data[i].entry.address), le32_to_cpu(regset_hdr->data[i].entry.value)); - if (opt_hdr_v1_size(ohdr) - sizeof(struct opt_hdr_v1) >= - sizeof(regset_hdr->data[0].last_entry)) { - if (regset_hdr->data[0].last_entry.delay) + if (regset_count > 0) { + if (regset_hdr->data[regset_count-1].last_entry.delay != + REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP) fprintf(f, "DATA_DELAY %u\n", - (unsigned)regset_hdr->data[0].last_entry.delay); + (unsigned)regset_hdr->data[regset_count-1].last_entry.delay); else fprintf(f, "DATA_DELAY SDRAM_SETUP\n"); } @@ -2403,12 +2475,7 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params /* Extract data image when -p is not specified or when '-p 0' is specified */ offset = le32_to_cpu(mhdr->srcaddr); - if (mhdr->blockid == IBR_HDR_SATA_ID) { - offset -= 1; - offset *= 512; - } - - if (mhdr->blockid == IBR_HDR_SDIO_ID) + if (mhdr->blockid == IBR_HDR_SATA_ID) offset *= 512; if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF) @@ -2455,9 +2522,6 @@ static int kwbimage_extract_subimage(void *ptr, struct image_tool_params *params return imagetool_save_subimage(params->outfile, image, size); } -/* - * Report Error if xflag is set in addition to default - */ static int kwbimage_check_params(struct image_tool_params *params) { if (!params->lflag && !params->iflag && !params->pflag && @@ -2468,10 +2532,9 @@ static int kwbimage_check_params(struct image_tool_params *params) return 1; } - return (params->dflag && (params->fflag || params->lflag)) || - (params->fflag && (params->dflag || params->lflag)) || - (params->lflag && (params->dflag || params->fflag)) || - (params->xflag); + return (params->dflag && (params->fflag || params->lflag || params->skipcpy)) || + (params->fflag) || + (params->lflag && (params->dflag || params->fflag)); } /* diff --git a/tools/kwboot.c b/tools/kwboot.c index da4fe32..7c66648 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -15,6 +15,12 @@ * Processor, and High-Definition Video Decoder: Functional Specifications" * August 3, 2011. Chapter 5 "BootROM Firmware" * https://web.archive.org/web/20120130172443/https://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf + * - "88F6665, 88F6660, 88F6658, 88F6655, 88F6655F, 88F6650, 88F6650F, 88F6610, + * and 88F6610F Avanta LP Family Integrated Single/Dual CPU Ecosystem for + * Gateway (GW), Home Gateway Unit (HGU), and Single Family Unit (SFU) + * Functional Specifications" Doc. No. MV-S108952-00, Rev. A. November 7, 2013. + * Chapter 7 "Boot Flow" + * CONFIDENTIAL, no public documentation available * - "88F6710, 88F6707, and 88F6W11: ARMADA(R) 370 SoC: Functional Specifications" * May 26, 2014. Chapter 6 "BootROM Firmware". * https://web.archive.org/web/20140617183701/https://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf @@ -22,6 +28,15 @@ * Multi-Core ARMv7 Based SoC Processors: Functional Specifications" * May 29, 2014. Chapter 6 "BootROM Firmware". * https://web.archive.org/web/20180829171131/https://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf + * - "BobCat2 Control and Management Subsystem Functional Specifications" + * Doc. No. MV-S109400-00, Rev. A. December 4, 2014. + * Chapter 1.6 BootROM Firmware + * CONFIDENTIAL, no public documentation available + * - "AlleyCat3 and PONCat3 Highly Integrated 1/10 Gigabit Ethernet Switch + * Control and Management Subsystem: Functional Specifications" + * Doc. No. MV-S109693-00, Rev. A. May 20, 2014. + * Chapter 1.6 BootROM Firmware + * CONFIDENTIAL, no public documentation available * - "ARMADA(R) 375 Value-Performance Dual Core CPU System on Chip: Functional * Specifications" Doc. No. MV-S109377-00, Rev. A. September 18, 2013. * Chapter 7 "Boot Sequence" @@ -35,6 +50,72 @@ * System on Chip Functional Specifications" Doc. No. MV-S109896-00, Rev. B. * December 22, 2015. Chapter 7 "Boot Flow" * CONFIDENTIAL, no public documentation available + * - "Marvell boot image parser", Marvell U-Boot 2013.01, version 18.06. September 17, 2015. + * https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/blob/u-boot-2013.01-armada-18.06/tools/marvell/doimage_mv/hdrparser.c + * - "Marvell doimage Tool", Marvell U-Boot 2013.01, version 18.06. August 30, 2015. + * https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/blob/u-boot-2013.01-armada-18.06/tools/marvell/doimage_mv/doimage.c + * + * Storage location / offset of different image types: + * - IBR_HDR_SPI_ID (0x5A): + * SPI image can be stored at any 2 MB aligned offset in the first 16 MB of + * SPI-NOR or parallel-NOR. Despite the type name it really can be stored on + * parallel-NOR and cannot be stored on other SPI devices, like SPI-NAND. + * So it should have been named NOR image, not SPI image. This image type + * supports XIP - Execute In Place directly from NOR memory. + * + * - IBR_HDR_NAND_ID (0x8B): + * NAND image can be stored either at any 2 MB aligned offset in the first + * 16 MB of SPI-NAND or at any blocksize aligned offset in the first 64 MB + * of parallel-NAND. + * + * - IBR_HDR_PEX_ID (0x9C): + * PEX image is used for booting from PCI Express device. Source address + * stored in image is ignored by BootROM. It is not the BootROM who parses + * or loads data part of the PEX image. BootROM just configures SoC to the + * PCIe endpoint mode and let the PCIe device on the other end of the PCIe + * link (which must be in Root Complex mode) to load kwbimage into SoC's + * memory and tell BootROM physical address. + * + * - IBR_HDR_UART_ID (0x69): + * UART image can be transfered via xmodem protocol over first UART. + * + * - IBR_HDR_I2C_ID (0x4D): + * It is unknown for what kind of storage is used this image. It is not + * specified in any document from References section. + * + * - IBR_HDR_SATA_ID (0x78): + * SATA image can be stored at sector 1 (after the MBR table), sector 34 + * (after the GPT table) or at any next sector which is aligned to 2 MB and + * is in the first 16 MB of SATA disk. Note that source address in SATA image + * is stored in sector unit and not in bytes like for any other images. + * Unfortunately sector size is disk specific, in most cases it is 512 bytes + * but there are also Native 4K SATA disks which have 4096 bytes long sectors. + * + * - IBR_HDR_SDIO_ID (0xAE): + * SDIO image can be stored on different medias: + * - SD(SC) card + * - SDHC/SDXC card + * - eMMC HW boot partition + * - eMMC user data partition / MMC card + * It cannot be stored on SDIO card despite the image name. + * + * For SD(SC)/SDHC/SDXC cards, image can be stored at the same locations as + * the SATA image (sector 1, sector 34 or any 2 MB aligned sector) but within + * the first 64 MB. SDHC and SDXC cards have fixed 512 bytes long sector size. + * Old SD(SC) cards unfortunately can have also different sector sizes, mostly + * 1024 bytes long sector sizes and also can be changed at runtime. + * + * For MMC-compatible devices, image can be stored at offset 0 or at offset + * 2 MB. If MMC device supports HW boot partitions then image must be stored + * on the HW partition as is configured in the EXT_CSC register (it can be + * either boot or user data). + * + * Note that source address for SDIO image is stored in byte unit, like for + * any other images (except SATA). Marvell Functional Specifications for + * A38x and A39x SoCs say that source address is in sector units, but this + * is purely incorrect information. A385 BootROM really expects source address + * for SDIO images in bytes and also Marvell tools generate SDIO image with + * source address in byte units. */ #include "kwbimage.h" @@ -1699,6 +1780,47 @@ kwboot_img_is_secure(void *img) return 0; } +static int +kwboot_img_has_ddr_init(void *img) +{ + const struct register_set_hdr_v1 *rhdr; + const struct main_hdr_v0 *hdr0; + struct opt_hdr_v1 *ohdr; + u32 ohdrsz; + int last; + + /* + * kwbimage v0 image headers contain DDR init code either in + * extension header or in binary code header. + */ + if (kwbimage_version(img) == 0) { + hdr0 = img; + return hdr0->ext || hdr0->bin; + } + + /* + * kwbimage v1 image headers contain DDR init code either in binary + * code header or in a register set list header with SDRAM_SETUP. + */ + for_each_opt_hdr_v1 (ohdr, img) { + if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE) + return 1; + if (ohdr->headertype == OPT_HDR_V1_REGISTER_TYPE) { + rhdr = (const struct register_set_hdr_v1 *)ohdr; + ohdrsz = opt_hdr_v1_size(ohdr); + if (ohdrsz >= sizeof(*ohdr) + sizeof(rhdr->data[0].last_entry)) { + ohdrsz -= sizeof(*ohdr) + sizeof(rhdr->data[0].last_entry); + last = ohdrsz / sizeof(rhdr->data[0].entry); + if (rhdr->data[last].last_entry.delay == + REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP) + return 1; + } + } + } + + return 0; +} + static void * kwboot_img_grow_data_right(void *img, size_t *size, size_t grow) { @@ -1854,10 +1976,26 @@ _inject_baudrate_change_code(void *img, size_t *size, int for_data, } } +static const char * +kwboot_img_type(uint8_t blockid) +{ + switch (blockid) { + case IBR_HDR_I2C_ID: return "I2C"; + case IBR_HDR_SPI_ID: return "SPI"; + case IBR_HDR_NAND_ID: return "NAND"; + case IBR_HDR_SATA_ID: return "SATA"; + case IBR_HDR_PEX_ID: return "PEX"; + case IBR_HDR_UART_ID: return "UART"; + case IBR_HDR_SDIO_ID: return "SDIO"; + default: return "unknown"; + } +} + static int kwboot_img_patch(void *img, size_t *size, int baudrate) { struct main_hdr_v1 *hdr; + struct opt_hdr_v1 *ohdr; uint32_t srcaddr; uint8_t csum; size_t hdrsz; @@ -1866,8 +2004,10 @@ kwboot_img_patch(void *img, size_t *size, int baudrate) hdr = img; - if (*size < sizeof(struct main_hdr_v1)) + if (*size < sizeof(struct main_hdr_v1)) { + fprintf(stderr, "Invalid image header size\n"); goto err; + } image_ver = kwbimage_version(img); if (image_ver != 0 && image_ver != 1) { @@ -1877,24 +2017,23 @@ kwboot_img_patch(void *img, size_t *size, int baudrate) hdrsz = kwbheader_size(hdr); - if (*size < hdrsz) + if (*size < hdrsz) { + fprintf(stderr, "Invalid image header size\n"); goto err; + } + + kwboot_printv("Detected kwbimage v%d with %s boot signature\n", image_ver, kwboot_img_type(hdr->blockid)); csum = kwboot_hdr_csum8(hdr) - hdr->checksum; - if (csum != hdr->checksum) + if (csum != hdr->checksum) { + fprintf(stderr, "Image has invalid header checksum stored in image header\n"); goto err; + } srcaddr = le32_to_cpu(hdr->srcaddr); switch (hdr->blockid) { case IBR_HDR_SATA_ID: - if (srcaddr < 1) - goto err; - - hdr->srcaddr = cpu_to_le32((srcaddr - 1) * 512); - break; - - case IBR_HDR_SDIO_ID: hdr->srcaddr = cpu_to_le32(srcaddr * 512); break; @@ -1906,18 +2045,48 @@ kwboot_img_patch(void *img, size_t *size, int baudrate) case IBR_HDR_SPI_ID: if (hdr->destaddr == cpu_to_le32(0xFFFFFFFF)) { kwboot_printv("Patching destination and execution addresses from SPI/NOR XIP area to DDR area 0x00800000\n"); - hdr->destaddr = cpu_to_le32(0x00800000); - hdr->execaddr = cpu_to_le32(0x00800000); + hdr->destaddr = cpu_to_le32(0x00800000 + le32_to_cpu(hdr->srcaddr)); + hdr->execaddr = cpu_to_le32(0x00800000 + le32_to_cpu(hdr->execaddr)); } break; } - if (hdrsz > le32_to_cpu(hdr->srcaddr) || - *size < le32_to_cpu(hdr->srcaddr) + le32_to_cpu(hdr->blocksize)) + if (hdrsz > le32_to_cpu(hdr->srcaddr)) { + fprintf(stderr, "Image has invalid data offset stored in image header\n"); goto err; + } - if (kwboot_img_csum32(img) != *kwboot_img_csum32_ptr(img)) + if (*size < le32_to_cpu(hdr->srcaddr) + le32_to_cpu(hdr->blocksize)) { + fprintf(stderr, "Image has invalid data size stored in image header\n"); goto err; + } + + for_each_opt_hdr_v1 (ohdr, hdr) { + if (!opt_hdr_v1_valid_size(ohdr, (const uint8_t *)hdr + hdrsz)) { + fprintf(stderr, "Invalid optional image header\n"); + goto err; + } + } + + /* + * The 32-bit data checksum is optional for UART image. If it is not + * present (checksum detected as invalid) then grow data part of the + * image for the checksum, so it can be inserted there. + */ + if (kwboot_img_csum32(img) != *kwboot_img_csum32_ptr(img)) { + if (hdr->blockid != IBR_HDR_UART_ID) { + fprintf(stderr, "Image has invalid data checksum\n"); + goto err; + } + kwboot_img_grow_data_right(img, size, sizeof(uint32_t)); + } + + if (!kwboot_img_has_ddr_init(img) && + (le32_to_cpu(hdr->destaddr) < 0x40000000 || + le32_to_cpu(hdr->destaddr) + le32_to_cpu(hdr->blocksize) > 0x40034000)) { + fprintf(stderr, "Image does not contain DDR init code needed for UART booting\n"); + goto err; + } is_secure = kwboot_img_is_secure(img); @@ -2182,6 +2351,7 @@ main(int argc, char **argv) KWBOOT_XM_BLKSZ + sizeof(kwboot_baud_code) + sizeof(kwboot_baud_code_data_jump) + + sizeof(uint32_t) + KWBOOT_XM_BLKSZ; if (imgpath) { diff --git a/tools/mkimage.c b/tools/mkimage.c index af7b0e0..a92d9d5 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -599,7 +599,12 @@ int main(int argc, char **argv) exit (retval); } - if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT)) { + if (!params.skipcpy && params.type != IH_TYPE_MULTI && params.type != IH_TYPE_SCRIPT) { + if (!params.datafile) { + fprintf(stderr, "%s: Option -d with image data file was not specified\n", + params.cmdname); + exit(EXIT_FAILURE); + } dfd = open(params.datafile, O_RDONLY | O_BINARY); if (dfd < 0) { fprintf(stderr, "%s: Can't open %s: %s\n", @@ -860,7 +865,9 @@ copy_file (int ifd, const char *datafile, int pad) exit (EXIT_FAILURE); } - if (params.xflag) { + if (params.xflag && + (((params.type > IH_TYPE_INVALID) && (params.type < IH_TYPE_FLATDT)) || + (params.type == IH_TYPE_KERNEL_NOLOAD) || (params.type == IH_TYPE_FIRMWARE_IVT))) { unsigned char *p = NULL; /* * XIP: do not append the struct legacy_img_hdr at the |