- mvebu: Various fixes in SPL / kwboot / kwbimage (Pali)
This commit is contained in:
Tom Rini 2023-03-01 11:00:22 -05:00
commit 49cba67852
22 changed files with 937 additions and 279 deletions

View file

@ -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

View file

@ -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)

View file

@ -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)
{
/*

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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,

View file

@ -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;

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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");

View 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

View 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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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));
}
/*

View file

@ -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) {

View file

@ -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