mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-marvell into next
- mvebu: Various fixes in SPL / kwboot / kwbimage (Pali)
This commit is contained in:
commit
49cba67852
22 changed files with 937 additions and 279 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
* This expects that sector size is 512 bytes.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
253
cmd/mvebu/bubt.c
253
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;
|
||||
|
@ -290,6 +334,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
|
||||
********************************************************************/
|
||||
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
83
configs/clearfog_sata_defconfig
Normal file
83
configs/clearfog_sata_defconfig
Normal file
|
@ -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
|
92
configs/db-88f6820-amc_nand_defconfig
Normal file
92
configs/db-88f6820-amc_nand_defconfig
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
297
tools/kwbimage.c
297
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);
|
||||
|
@ -2154,6 +2201,22 @@ static int kwbimage_generate(struct image_tool_params *params,
|
|||
tparams->header_size = alloc_len;
|
||||
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.
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
200
tools/kwboot.c
200
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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue