Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-marvell into next

- mvebu: Various fixes in SPL / kwboot / kwbimage (Pali)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 16c5e72..cdb1776 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -331,7 +331,7 @@
 	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 @@
 	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 @@
 	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 @@
 	imply SPL_LIBDISK_SUPPORT
 	select SPL_BOOTROM_SUPPORT
 
+config MVEBU_SPL_BOOT_DEVICE_PEX
+	bool "PCI Express"
+	select SPL_BOOTROM_SUPPORT
+
 config MVEBU_SPL_BOOT_DEVICE_UART
 	bool "UART"
 	select SPL_BOOTROM_SUPPORT
 
 endchoice
 
+config MVEBU_SPL_NAND_BADBLK_LOCATION
+	hex "NAND Bad block indicator location"
+	depends on MVEBU_SPL_BOOT_DEVICE_NAND
+	range 0x0 0x1
+	help
+	  Value 0x0 = SLC flash = BBI at page 0 or page 1
+	  Value 0x1 = MLC flash = BBI at last page in the block
+
 config MVEBU_EFUSE
 	bool "Enable eFuse support"
 	depends on HAVE_MVEBU_EFUSE
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index a9f506c..90f8833 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -50,16 +50,29 @@
 ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI),)
 	KWB_CFG_BOOT_FROM=spi
 endif
+ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_NAND),)
+	KWB_CFG_BOOT_FROM=nand
+endif
 ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC),)
 	KWB_CFG_BOOT_FROM=sdio
 endif
 ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SATA),)
 	KWB_CFG_BOOT_FROM=sata
 endif
+ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_PEX),)
+	KWB_CFG_BOOT_FROM=pex
+endif
 ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_UART),)
 	KWB_CFG_BOOT_FROM=uart
 endif
 
+ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_NAND),)
+KWB_REPLACE += NAND_PAGE_SIZE NAND_BLKSZ NAND_BADBLK_LOCATION
+KWB_CFG_NAND_PAGE_SIZE = $(CONFIG_SYS_NAND_PAGE_SIZE)
+KWB_CFG_NAND_BLKSZ = $(CONFIG_SYS_NAND_BLOCK_SIZE)
+KWB_CFG_NAND_BADBLK_LOCATION = $(CONFIG_MVEBU_SPL_NAND_BADBLK_LOCATION)
+endif
+
 ifneq ($(CONFIG_SECURED_MODE_IMAGE),)
 KWB_REPLACE += CSK_INDEX
 KWB_CFG_CSK_INDEX = $(CONFIG_SECURED_MODE_CSK_INDEX)
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 329d136..bbe167e 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -25,7 +25,7 @@
 	{ 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 @@
 #endif
 };
 
+/* SPI0 CS0 Flash of size MBUS_SPI_SIZE is mapped to address MBUS_SPI_BASE */
+#if CONFIG_ENV_SPI_BUS == 0 && CONFIG_ENV_SPI_CS == 0 && \
+    CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE <= MBUS_SPI_SIZE
+void *env_sf_get_env_addr(void)
+{
+	return (void *)MBUS_SPI_BASE + CONFIG_ENV_OFFSET;
+}
+#endif
+
 void lowlevel_init(void)
 {
 	/*
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index c17c244..904e715 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -66,17 +66,38 @@
 /*
  * Default Device Address MAP BAR values
  */
+#ifdef CONFIG_SPL_BUILD
+#ifdef CONFIG_ARMADA_38X
+#define MBUS_PCI_MEM_BASE	0x88000000
+#define MBUS_PCI_MEM_SIZE	((3 * 128) << 20)
+#else
+#define MBUS_PCI_MEM_BASE	0x80000000
+#define MBUS_PCI_MEM_SIZE	((4 * 128) << 20)
+#endif
+#else
 #define MBUS_PCI_MAX_PORTS	6
 #define MBUS_PCI_MEM_BASE	MVEBU_SDRAM_SIZE_MAX
 #define MBUS_PCI_MEM_SIZE	((MBUS_PCI_MAX_PORTS * 128) << 20)
 #define MBUS_PCI_IO_BASE	0xF1100000
 #define MBUS_PCI_IO_SIZE	((MBUS_PCI_MAX_PORTS * 64) << 10)
+#endif
+#ifdef CONFIG_SPL_BUILD
+#define MBUS_SPI_BASE		0xD4000000
+#define MBUS_SPI_SIZE		(64 << 20)
+#else
 #define MBUS_SPI_BASE		0xF4000000
 #define MBUS_SPI_SIZE		(8 << 20)
+#endif
+#ifndef CONFIG_SPL_BUILD
 #define MBUS_DFX_BASE		0xF6000000
 #define MBUS_DFX_SIZE		(1 << 20)
+#endif
 #define MBUS_BOOTROM_BASE	0xF8000000
+#ifdef CONFIG_SPL_BUILD
+#define MBUS_BOOTROM_SIZE	(128 << 20)
+#else
 #define MBUS_BOOTROM_SIZE	(8 << 20)
+#endif
 
 struct mbus_win {
 	u32 base;
diff --git a/arch/arm/mach-mvebu/kwbimage.cfg.in b/arch/arm/mach-mvebu/kwbimage.cfg.in
index ccb0997..90cf00c 100644
--- a/arch/arm/mach-mvebu/kwbimage.cfg.in
+++ b/arch/arm/mach-mvebu/kwbimage.cfg.in
@@ -11,6 +11,11 @@
 # Boot Media configurations
 #@BOOT_FROM
 
+# NAND configuration
+#@NAND_PAGE_SIZE
+#@NAND_BLKSZ
+#@NAND_BADBLK_LOCATION
+
 # Enable BootROM output via DEBUG flag on SoCs which require it
 #@DEBUG
 
diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
index 943ae01..3349f4e 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
@@ -53,7 +53,7 @@
  */
 u8 serdes_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 @@
 	if (sys_env_device_rev_get() == MV_88F68XX_Z1_ID)
 		return MV_SERDES_REV_1_2;
 
-	/* for A39x-Z1, A38x-A0 */
+	/* for A38x-A0 */
 	return MV_SERDES_REV_2_1;
 }
 
diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
index dd229e1..6925a9d 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
+++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
@@ -15,12 +15,12 @@
 #define SET_BIT(data, bit)		((data) | (0x1 << (bit)))
 #define CLEAR_BIT(data, bit)		((data) & (~(0x1 << (bit))))
 
-#define MAX_SERDES_LANES		7	/* as in a39x */
+#define MAX_SERDES_LANES		7
 
 /* Serdes revision */
 /* Serdes revision 1.2 (for A38x-Z1) */
 #define MV_SERDES_REV_1_2		0x0
-/* Serdes revision 2.1 (for A39x-Z1, A38x-A0) */
+/* Serdes revision 2.1 (for A38x-A0) */
 #define MV_SERDES_REV_2_1		0x1
 #define MV_SERDES_REV_NA		0xff
 
diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
index 950680a..fb8ec11 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
@@ -145,10 +145,6 @@
 		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 @@
 	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 @@
  */
 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 @@
 
 	g_dev_id = reg_read(DEVICE_SAMPLE_AT_RESET1_REG);
 	g_dev_id = g_dev_id >> SAR_DEV_ID_OFFS & SAR_DEV_ID_MASK;
-	printf("Detected Device ID %s\n", device_id_str[g_dev_id]);
+	printf("Detected Device ID %s\n", g_dev_id < 4 ? device_id_str[g_dev_id] : "NONE");
 
 	return g_dev_id;
 }
diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
index 94c43b4..20039f7 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
+++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
@@ -198,22 +198,6 @@
 #define A38X_MV_MARVELL_BOARD_NUM	(A38X_MV_MAX_MARVELL_BOARD_ID - \
 					 A38X_MARVELL_BOARD_ID_BASE)
 
-/* Customer boards for A39x */
-#define A39X_CUSTOMER_BOARD_ID_BASE	0x20
-#define A39X_CUSTOMER_BOARD_ID0		(A39X_CUSTOMER_BOARD_ID_BASE + 0)
-#define A39X_CUSTOMER_BOARD_ID1		(A39X_CUSTOMER_BOARD_ID_BASE + 1)
-#define A39X_MV_MAX_CUSTOMER_BOARD_ID	(A39X_CUSTOMER_BOARD_ID_BASE + 2)
-#define A39X_MV_CUSTOMER_BOARD_NUM	(A39X_MV_MAX_CUSTOMER_BOARD_ID - \
-					 A39X_CUSTOMER_BOARD_ID_BASE)
-
-/* Marvell boards for A39x */
-#define A39X_MARVELL_BOARD_ID_BASE	0x30
-#define A39X_DB_69XX_ID			(A39X_MARVELL_BOARD_ID_BASE + 0)
-#define A39X_RD_69XX_ID			(A39X_MARVELL_BOARD_ID_BASE + 1)
-#define A39X_MV_MAX_MARVELL_BOARD_ID	(A39X_MARVELL_BOARD_ID_BASE + 2)
-#define A39X_MV_MARVELL_BOARD_NUM	(A39X_MV_MAX_MARVELL_BOARD_ID - \
-					 A39X_MARVELL_BOARD_ID_BASE)
-
 #define CUTOMER_BOARD_ID_BASE		A38X_CUSTOMER_BOARD_ID_BASE
 #define CUSTOMER_BOARD_ID0		A38X_CUSTOMER_BOARD_ID0
 #define CUSTOMER_BOARD_ID1		A38X_CUSTOMER_BOARD_ID1
@@ -236,8 +220,6 @@
 #define MV_88F68XX_Z1_ID		0x0
 #define MV_88F68XX_A0_ID		0x4
 #define MV_88F68XX_B0_ID		0xa
-/* A39x revisions */
-#define MV_88F69XX_Z1_ID		0x2
 
 #define MPP_CONTROL_REG(id)		(0x18000 + (id * 4))
 #define GPP_DATA_OUT_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x00)
@@ -257,19 +239,12 @@
 #define MV_6811_DEV_ID		0x6811
 #define MV_6820_DEV_ID		0x6820
 #define MV_6828_DEV_ID		0x6828
-/* Armada 39x Family */
-#define MV_6920_DEV_ID		0x6920
-#define MV_6928_DEV_ID		0x6928
 
 enum {
 	MV_6810,
 	MV_6820,
 	MV_6811,
 	MV_6828,
-	MV_NONE,
-	MV_6920,
-	MV_6928,
-	MV_MAX_DEV_ID,
 };
 
 #define MV_6820_INDEX			0
@@ -277,17 +252,12 @@
 #define MV_6811_INDEX			2
 #define MV_6828_INDEX			3
 
-#define MV_6920_INDEX			0
-#define MV_6928_INDEX			1
-
 #define MAX_DEV_ID_NUM			4
 
 #define MV_6820_INDEX			0
 #define MV_6810_INDEX			1
 #define MV_6811_INDEX			2
 #define MV_6828_INDEX			3
-#define MV_6920_INDEX			0
-#define MV_6928_INDEX			1
 
 enum unit_id {
 	PEX_UNIT_ID,
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index 4245992..6b8c72a 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -33,21 +33,44 @@
 #endif
 
 /*
- * When loading U-Boot via SPL from eMMC (in Marvell terminology SDIO), the
- * kwbimage main header is stored at sector 0. U-Boot SPL needs to parse this
- * header and figure out at which sector the U-Boot proper binary is stored.
- * Partition booting is therefore not supported and CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
- * and CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET need to point to the
- * kwbimage main header.
+ * When loading U-Boot via SPL from eMMC, the kwbimage main header is stored at
+ * sector 0 and either on HW boot partition or on data partition. Choice of HW
+ * partition depends on what is configured in eMMC EXT_CSC register.
+ * When loading U-Boot via SPL from SD card, the kwbimage main header is stored
+ * at sector 1.
+ * Therefore MBR/GPT partition booting, fixed sector number and fixed eMMC HW
+ * partition number are unsupported due to limitation of Marvell BootROM.
+ * Correct sector number must be determined as runtime in mvebu SPL code based
+ * on the detected boot source. Otherwise U-Boot SPL would not be able to load
+ * U-Boot proper.
+ * Runtime mvebu SPL sector calculation code expects:
+ * - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET=0
+ * - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0
  */
 #ifdef CONFIG_SPL_MMC
+#ifdef CONFIG_SYS_MMCSD_FS_BOOT
+#error CONFIG_SYS_MMCSD_FS_BOOT is unsupported
+#endif
+#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
+#error CONFIG_SYS_MMCSD_FS_BOOT_PARTITION is unsupported
+#endif
+#ifdef CONFIG_SUPPORT_EMMC_BOOT_OVERRIDE_PART_CONFIG
+#error CONFIG_SUPPORT_EMMC_BOOT_OVERRIDE_PART_CONFIG is unsupported
+#endif
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION
+#error CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION is unsupported
+#endif
 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
 #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION is unsupported
 #endif
-#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) && CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR != 0
+#ifndef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+#error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR must be enabled for SD/eMMC boot support
+#endif
+#if !defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) || \
+    CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR != 0
 #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR must be set to 0
 #endif
-#if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET) && \
+#if !defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET) || \
     CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET != 0
 #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET must be set to 0
 #endif
@@ -98,7 +121,12 @@
 #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 @@
 	}
 
 	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 @@
 
 	/*
 	 * For SATA srcaddr is specified in number of sectors.
-	 * The main header is must be stored at sector number 1.
-	 * This expects that sector size is 512 bytes and recalculates
-	 * data offset to bytes relative to the main header.
-	 */
-	if (IS_ENABLED(CONFIG_SPL_SATA) && mhdr->blockid == IBR_HDR_SATA_ID) {
-		if (spl_image->offset < 1) {
-			printf("ERROR: Wrong srcaddr (0x%08x) in SATA kwbimage\n",
-			       spl_image->offset);
-			return -EINVAL;
-		}
-		spl_image->offset -= 1;
-		spl_image->offset *= 512;
-	}
-
-	/*
-	 * For SDIO (eMMC) srcaddr is specified in number of sectors.
-	 * This expects that sector size is 512 bytes and recalculates
-	 * data offset to bytes.
+	 * This expects that sector size is 512 bytes.
 	 */
-	if (IS_ENABLED(CONFIG_SPL_MMC) && mhdr->blockid == IBR_HDR_SDIO_ID)
+	if (IS_ENABLED(CONFIG_SPL_SATA) && mhdr->blockid == IBR_HDR_SATA_ID)
 		spl_image->offset *= 512;
 
 	if (spl_image->offset % 4 != 0) {
@@ -299,19 +308,6 @@
 	hang();
 }
 
-/*
- * SPI0 CS0 Flash is mapped to address range 0xD4000000 - 0xD7FFFFFF by BootROM.
- * Proper U-Boot removes this direct mapping. So it is available only in SPL.
- */
-#if defined(CONFIG_SPL_ENV_IS_IN_SPI_FLASH) && \
-    CONFIG_ENV_SPI_BUS == 0 && CONFIG_ENV_SPI_CS == 0 && \
-    CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE <= 64*1024*1024
-void *env_sf_get_env_addr(void)
-{
-	return (void *)0xD4000000 + CONFIG_ENV_OFFSET;
-}
-#endif
-
 void board_init_f(ulong dummy)
 {
 	int ret;
diff --git a/cmd/mvebu/Kconfig b/cmd/mvebu/Kconfig
index 9ec3aa9..e83a982 100644
--- a/cmd/mvebu/Kconfig
+++ b/cmd/mvebu/Kconfig
@@ -3,8 +3,12 @@
 
 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 @@
 
 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 @@
 	  For details about bubt command please see the documentation
 	  in doc/mvebu/cmd/bubt.txt
 
+config MVEBU_SATA_BOOT
+	bool "SATA flash boot"
+	depends on SCSI
+	help
+	  Enable boot from SATA disk.
+	  Allow usage of SATA disk as a target for "bubt" command
+	  For details about bubt command please see the documentation
+	  in doc/mvebu/cmd/bubt.txt
+
 endchoice
 
 config MVEBU_UBOOT_DFLT_NAME
 	string "Default image name for bubt command"
+	default BUILD_TARGET if ARMADA_32BIT && BUILD_TARGET != ""
 	default "flash-image.bin"
 	help
 	  This option should contain a default file name to be used with
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c
index 1efbe2e..49797b2 100644
--- a/cmd/mvebu/bubt.c
+++ b/cmd/mvebu/bubt.c
@@ -19,6 +19,7 @@
 #include <spi_flash.h>
 #include <spi.h>
 #include <nand.h>
+#include <scsi.h>
 #include <usb.h>
 #include <fs.h>
 #include <mmc.h>
@@ -189,6 +190,11 @@
 #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");
@@ -201,6 +207,38 @@
 		       mmc_dev_num);
 		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 @@
 	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 @@
 						 start_lba, blk_count,
 						 (void *)get_load_addr());
 #endif /* CONFIG_BLK */
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+#ifdef CONFIG_BLK
+	err = blk_dselect_hwpart(blk_desc, orig_part);
+#else
+	err = mmc_switch_part(mmc, orig_part);
+#endif
+	if (err)
+		printf("Error - MMC failed to switch back to original partition\n");
+#endif
+
 	if (blk_written != blk_count) {
 		printf("Error - written %#lx blocks\n", blk_written);
 		return -ENOSPC;
@@ -291,6 +335,143 @@
 #endif /* CONFIG_DM_MMC */
 
 /********************************************************************
+ *     SATA services
+ ********************************************************************/
+#if defined(CONFIG_SCSI) && defined(CONFIG_BLK)
+static int sata_burn_image(size_t image_size)
+{
+#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT)
+	lbaint_t	start_lba;
+	lbaint_t	blk_count;
+	ulong		blk_written;
+	struct blk_desc *blk_desc;
+#ifdef CONFIG_ARMADA_3700
+	struct disk_partition info;
+	int		part;
+#endif
+
+	scsi_scan(false);
+
+	blk_desc = blk_get_devnum_by_uclass_id(UCLASS_SCSI, 0);
+	if (!blk_desc)
+		return -ENODEV;
+
+#ifdef CONFIG_ARMADA_3700
+	/*
+	 * 64-bit Armada 3700 BootROM loads SATA firmware from
+	 * GPT 'Marvell Armada 3700 Boot partition' or from
+	 * MBR 'M' (0x4d) partition.
+	 */
+	switch (blk_desc->part_type) {
+	case PART_TYPE_DOS:
+		for (part = 1; part <= 4; part++) {
+			info.sys_ind = 0;
+			if (part_get_info(blk_desc, part, &info))
+				continue;
+			if (info.sys_ind == 'M')
+				break;
+		}
+		if (part > 4) {
+			printf("Error - cannot find MBR 'M' (0x4d) partition on SATA disk\n");
+			return -ENODEV;
+		}
+		start_lba = info.start;
+		break;
+	case PART_TYPE_EFI:
+		for (part = 1; part <= 64; part++) {
+			info.type_guid[0] = 0;
+			if (part_get_info(blk_desc, part, &info))
+				continue;
+			/* Check for GPT type GUID of 'Marvell Armada 3700 Boot partition' */
+			if (strcmp(info.type_guid, "6828311A-BA55-42A4-BCDE-A89BB5EDECAE") == 0)
+				break;
+		}
+		if (part > 64) {
+			printf("Error - cannot find GPT 'Marvell Armada 3700 Boot partition' on SATA disk\n");
+			return -ENODEV;
+		}
+		start_lba = info.start;
+		break;
+	default:
+		printf("Error - no partitions on SATA disk\n");
+		return -ENODEV;
+	}
+#else
+	/* 32-bit Armada BootROM loads SATA firmware from the sector 1. */
+	start_lba = 1;
+#endif
+
+	blk_count = image_size / blk_desc->blksz;
+	if (image_size % blk_desc->blksz)
+		blk_count += 1;
+
+	blk_written = blk_dwrite(blk_desc, start_lba, blk_count,
+				 (void *)get_load_addr());
+
+	if (blk_written != blk_count) {
+		printf("Error - written %#lx blocks\n", blk_written);
+		return -ENOSPC;
+	}
+
+	printf("Done!\n");
+	return 0;
+#else
+	return -ENODEV;
+#endif
+}
+
+static size_t sata_read_file(const char *file_name)
+{
+	loff_t act_read = 0;
+	struct udevice *dev;
+	int rc;
+
+	/* try to recognize storage devices immediately */
+	scsi_scan(false);
+
+	/* Try to recognize storage devices immediately */
+	blk_first_device(UCLASS_SCSI, &dev);
+	if (!dev) {
+		printf("Error: SATA device not found\n");
+		return 0;
+	}
+
+	/* Always load from scsi 0 */
+	if (fs_set_blk_dev("scsi", "0", FS_TYPE_ANY)) {
+		printf("Error: SATA 0 not found\n");
+		return 0;
+	}
+
+	/* Perfrom file read */
+	rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
+	if (rc)
+		return 0;
+
+	return act_read;
+}
+
+static int is_sata_active(void)
+{
+	return 1;
+}
+#else /* CONFIG_SCSI */
+static int sata_burn_image(size_t image_size)
+{
+	return -ENODEV;
+}
+
+static size_t sata_read_file(const char *file_name)
+{
+	return 0;
+}
+
+static int is_sata_active(void)
+{
+	return 0;
+}
+#endif /* CONFIG_SCSI */
+
+/********************************************************************
  *     SPI services
  ********************************************************************/
 #ifdef CONFIG_SPI_FLASH
@@ -499,16 +680,18 @@
 	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 @@
 }
 
 #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 @@
 {
 	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 @@
 		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 @@
 	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,17 +925,8 @@
 	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;
+	if (hdr->blockid == 0x78) /* SATA id */
 		offset *= 512;
-	}
-
-	if (hdr->blockid == 0xAE) /* SDIO id */
-		offset *= 512;
 
 	if (offset % 4 != 0 || size < 4 || size % 4 != 0) {
 		printf("Error: Bad A38x image blocksize.\n");
@@ -770,7 +948,7 @@
 #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 @@
 			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 @@
 }
 #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 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 @@
 	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 @@
 #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 @@
 	"Burn a u-boot image to flash",
 	"[file-name] [destination [source]]\n"
 	"\t-file-name     The image file name to burn. Default = " CONFIG_MVEBU_UBOOT_DFLT_NAME "\n"
-	"\t-destination   Flash to burn to [spi, nand, mmc]. Default = " DEFAULT_BUBT_DST "\n"
-	"\t-source        The source to load image from [tftp, usb, mmc]. Default = " DEFAULT_BUBT_SRC "\n"
+	"\t-destination   Flash to burn to [spi, nand, mmc, sata]. Default = " DEFAULT_BUBT_DST "\n"
+	"\t-source        The source to load image from [tftp, usb, mmc, sata]. Default = " DEFAULT_BUBT_SRC "\n"
 	"Examples:\n"
 	"\tbubt - Burn flash-image.bin from tftp to active boot device\n"
 	"\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 3c2af45..2c042ad 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -816,8 +816,17 @@
 	  this option to build the drivers in drivers/mmc as part of an SPL
 	  build.
 
+config SYS_MMCSD_FS_BOOT
+	bool "MMC FS Boot mode"
+	depends on SPL_MMC
+	default y if !ARCH_MVEBU
+	help
+	  Enable MMC FS Boot mode. Partition is selected by option
+	  SYS_MMCSD_FS_BOOT_PARTITION.
+
 config SYS_MMCSD_FS_BOOT_PARTITION
 	int "MMC Boot Partition"
+	depends on SYS_MMCSD_FS_BOOT
 	default 1
 	help
 	  Partition on the MMC to load U-Boot from when the MMC is being
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index e4135b2..bd5e6ad 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -272,7 +272,7 @@
 }
 #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 @@
 
 	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 @@
 			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 @@
 			return err;
 
 		break;
+#endif
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 	default:
 		puts("spl: mmc: wrong boot mode\n");
diff --git a/configs/clearfog_sata_defconfig b/configs/clearfog_sata_defconfig
new file mode 100644
index 0000000..e9b3615
--- /dev/null
+++ b/configs/clearfog_sata_defconfig
@@ -0,0 +1,83 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_TEXT_BASE=0x00800000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_CLEARFOG=y
+CONFIG_MVEBU_SPL_BOOT_DEVICE_SATA=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog"
+CONFIG_SPL_TEXT_BASE=0x40000030
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL=y
+CONFIG_DEBUG_UART_BASE=0xf1012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_SYS_LOAD_ADDR=0x800000
+CONFIG_DEBUG_UART=y
+CONFIG_AHCI=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
+CONFIG_BOOTDELAY=3
+CONFIG_USE_PREBOOT=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_MAX_SIZE=0x22fd0
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x40023000
+CONFIG_SPL_BSS_MAX_SIZE=0x4000
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_STACK=0x4002c000
+CONFIG_SPL_I2C=y
+CONFIG_SYS_MAXARGS=32
+CONFIG_CMD_TLV_EEPROM=y
+CONFIG_SPL_CMD_TLV_EEPROM=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_MVEBU_BUBT=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_MIN_ENTRIES=128
+CONFIG_ARP_TIMEOUT=200
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_AHCI_MVEBU=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SPL_I2C_EEPROM=y
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_MV=y
+CONFIG_MTD=y
+CONFIG_SF_DEFAULT_BUS=1
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
+CONFIG_MII=y
+CONFIG_MVMDIO=y
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_SCSI=y
+CONFIG_SPL_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_KIRKWOOD_SPI=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
diff --git a/configs/db-88f6820-amc_nand_defconfig b/configs/db-88f6820-amc_nand_defconfig
new file mode 100644
index 0000000..e784c34
--- /dev/null
+++ b/configs/db-88f6820-amc_nand_defconfig
@@ -0,0 +1,92 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_TEXT_BASE=0x00800000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_DB_88F6820_AMC=y
+CONFIG_MVEBU_SPL_BOOT_DEVICE_NAND=y
+CONFIG_MVEBU_SPL_NAND_BADBLK_LOCATION=0x00
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x100000
+CONFIG_ENV_SECT_SIZE=0x40000
+CONFIG_DEFAULT_DEVICE_TREE="armada-385-db-88f6820-amc"
+CONFIG_SPL_TEXT_BASE=0x40000030
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL=y
+CONFIG_DEBUG_UART_BASE=0xf1012000
+CONFIG_DEBUG_UART_CLOCK=200000000
+CONFIG_SYS_LOAD_ADDR=0x800000
+CONFIG_DEBUG_UART=y
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_PREBOOT=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_MAX_SIZE=0x22fd0
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x40023000
+CONFIG_SPL_BSS_MAX_SIZE=0x4000
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_STACK=0x4002c000
+CONFIG_SPL_I2C=y
+CONFIG_SYS_MAXARGS=96
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_I2C=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SPI_MAX_HZ=50000000
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ARP_TIMEOUT=200
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_SPL_OF_TRANSLATE=y
+# CONFIG_SPL_BLK is not set
+# CONFIG_BLOCK_CACHE is not set
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_SYS_NAND_USE_FLASH_BBT=y
+CONFIG_NAND_PXA3XX=y
+CONFIG_SYS_NAND_BLOCK_SIZE=0x40000
+CONFIG_SYS_NAND_ONFI_DETECTION=y
+CONFIG_SYS_NAND_PAGE_SIZE=0x1000
+CONFIG_SF_DEFAULT_BUS=1
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
+CONFIG_MII=y
+CONFIG_MVMDIO=y
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_SPL_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_KIRKWOOD_SPI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/doc/kwboot.1 b/doc/kwboot.1
index a528fbb..5cda3b4 100644
--- a/doc/kwboot.1
+++ b/doc/kwboot.1
@@ -159,7 +159,8 @@
 Instruct BootROM to enter boot Xmodem boot mode, send header of
 \fIu-boot-with-spl.kwb\fP kwbimage file via Xmodem at 115200 Bd, then instruct
 BootROM to change baudrate to 5200000 Bd, send data part of the kwbimage
-file via Xmodem at high speed and finally run terminal program:
+file via Xmodem at high speed, then change baudrate back to 115200 Bd,
+and finally run terminal program:
 .IP
 .B kwboot -b u-boot-with-spl.kwb -B 5200000 -t /dev/ttyUSB0
 
diff --git a/doc/mvebu/cmd/bubt.txt b/doc/mvebu/cmd/bubt.txt
index 6051243..52bd3e6 100644
--- a/doc/mvebu/cmd/bubt.txt
+++ b/doc/mvebu/cmd/bubt.txt
@@ -5,8 +5,8 @@
 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 @@
 
 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 @@
   Number 0 is used for user data partition and should not be utilized for storing
   boot images and U-Boot environment in RAW mode since it will break file system
   structures usually located here.
-  The default boot partition is BOOT0. It is selected by the following parameter:
-  CONFIG_SYS_MMC_ENV_PART=1
-  Valid values for this parameter are 1 for BOOT0 and 2 for BOOT1.
-  Please never use partition number 0 here!
+
+  Currently configured boot partition can be printed by command:
+  # mmc partconf 0
+  (search for BOOT_PARTITION_ACCESS output, number 7 is user data)
+
+  Change it to BOOT0:
+  # mmc partconf 0 0 1 1
+
+  Change it to BOOT1:
+  # mmc partconf 0 0 2 2
+
+  Change it to user data:
+  # mmc partconf 0 0 7 0
+
 - The partition number is ignored if the target device is SD card.
 - The boot image offset starts at block 0 for eMMC and block 1 for SD devices.
   The block 0 on SD devices is left for MBR storage.
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5b35da4..5c7b0d9 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -628,7 +628,8 @@
 
 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 @@
 	hex "NAND chip page size"
 	depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \
 		SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \
+		MVEBU_SPL_BOOT_DEVICE_NAND || \
 		(NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER
 	depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621
 	help
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 6abb9f2..309657a 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -927,6 +927,71 @@
 	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 @@
 			*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 @@
 	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 @@
 	/* 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 @@
 	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 @@
 						    sizeof(struct ext_hdr_v0));
 	}
 
+	main_hdr->checksum = image_checksum8(image,
+					     sizeof(struct main_hdr_v0));
+
-	*imagesz = headersz;
 	return image;
 }
 
@@ -1073,10 +1136,6 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	*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 @@
 	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 @@
 	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 @@
 		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 @@
 					      &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 @@
 	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 @@
 	 * 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 @@
 		 */
 	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 @@
 	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 @@
 			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 @@
 	}
 
 	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,26 +2083,12 @@
 
 	/*
 	 * 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;
+	if (blockid == IBR_HDR_SATA_ID)
 		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)
-		offset *= 512;
-
-	/*
 	 * For PCIe srcaddr is always set to 0xFFFFFFFF.
 	 * This expects that data starts after all headers.
 	 */
@@ -2067,6 +2108,8 @@
 	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 @@
 		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 @@
 		exit(EXIT_FAILURE);
 	}
 
+	alloc_len = image_headersz_align(alloc_len, image_get_bootfrom());
+
 	free(image_cfg);
 
 	hdr = malloc(alloc_len);
@@ -2154,6 +2201,22 @@
 	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 @@
 	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 @@
 		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 @@
 			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,13 +2475,8 @@
 		/* 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;
+		if (mhdr->blockid == IBR_HDR_SATA_ID)
 			offset *= 512;
-		}
-
-		if (mhdr->blockid == IBR_HDR_SDIO_ID)
-			offset *= 512;
 
 		if (mhdr->blockid == IBR_HDR_PEX_ID && offset == 0xFFFFFFFF)
 			offset = header_size;
@@ -2455,9 +2522,6 @@
 	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 @@
 		return 1;
 	}
 
-	return (params->dflag && (params->fflag || params->lflag)) ||
-		(params->fflag && (params->dflag || params->lflag)) ||
-		(params->lflag && (params->dflag || params->fflag)) ||
-		(params->xflag);
+	return (params->dflag && (params->fflag || params->lflag || params->skipcpy)) ||
+		(params->fflag) ||
+		(params->lflag && (params->dflag || params->fflag));
 }
 
 /*
diff --git a/tools/kwboot.c b/tools/kwboot.c
index da4fe32..7c66648 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -15,6 +15,12 @@
  *   Processor, and High-Definition Video Decoder: Functional Specifications"
  *   August 3, 2011. Chapter 5 "BootROM Firmware"
  *   https://web.archive.org/web/20120130172443/https://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf
+ * - "88F6665, 88F6660, 88F6658, 88F6655, 88F6655F, 88F6650, 88F6650F, 88F6610,
+ *   and 88F6610F Avanta LP Family Integrated Single/Dual CPU Ecosystem for
+ *   Gateway (GW), Home Gateway Unit (HGU), and Single Family Unit (SFU)
+ *   Functional Specifications" Doc. No. MV-S108952-00, Rev. A. November 7, 2013.
+ *   Chapter 7 "Boot Flow"
+ *   CONFIDENTIAL, no public documentation available
  * - "88F6710, 88F6707, and 88F6W11: ARMADA(R) 370 SoC: Functional Specifications"
  *   May 26, 2014. Chapter 6 "BootROM Firmware".
  *   https://web.archive.org/web/20140617183701/https://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf
@@ -22,6 +28,15 @@
  *   Multi-Core ARMv7 Based SoC Processors: Functional Specifications"
  *   May 29, 2014. Chapter 6 "BootROM Firmware".
  *   https://web.archive.org/web/20180829171131/https://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf
+ * - "BobCat2 Control and Management Subsystem Functional Specifications"
+ *   Doc. No. MV-S109400-00, Rev. A. December 4, 2014.
+ *   Chapter 1.6 BootROM Firmware
+ *   CONFIDENTIAL, no public documentation available
+ * - "AlleyCat3 and PONCat3 Highly Integrated 1/10 Gigabit Ethernet Switch
+ *   Control and Management Subsystem: Functional Specifications"
+ *   Doc. No. MV-S109693-00, Rev. A. May 20, 2014.
+ *   Chapter 1.6 BootROM Firmware
+ *   CONFIDENTIAL, no public documentation available
  * - "ARMADA(R) 375 Value-Performance Dual Core CPU System on Chip: Functional
  *   Specifications" Doc. No. MV-S109377-00, Rev. A. September 18, 2013.
  *   Chapter 7 "Boot Sequence"
@@ -35,6 +50,72 @@
  *   System on Chip Functional Specifications" Doc. No. MV-S109896-00, Rev. B.
  *   December 22, 2015. Chapter 7 "Boot Flow"
  *   CONFIDENTIAL, no public documentation available
+ * - "Marvell boot image parser", Marvell U-Boot 2013.01, version 18.06. September 17, 2015.
+ *   https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/blob/u-boot-2013.01-armada-18.06/tools/marvell/doimage_mv/hdrparser.c
+ * - "Marvell doimage Tool", Marvell U-Boot 2013.01, version 18.06. August 30, 2015.
+ *   https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/blob/u-boot-2013.01-armada-18.06/tools/marvell/doimage_mv/doimage.c
+ *
+ * Storage location / offset of different image types:
+ * - IBR_HDR_SPI_ID (0x5A):
+ *   SPI image can be stored at any 2 MB aligned offset in the first 16 MB of
+ *   SPI-NOR or parallel-NOR. Despite the type name it really can be stored on
+ *   parallel-NOR and cannot be stored on other SPI devices, like SPI-NAND.
+ *   So it should have been named NOR image, not SPI image. This image type
+ *   supports XIP - Execute In Place directly from NOR memory.
+ *
+ * - IBR_HDR_NAND_ID (0x8B):
+ *   NAND image can be stored either at any 2 MB aligned offset in the first
+ *   16 MB of SPI-NAND or at any blocksize aligned offset in the first 64 MB
+ *   of parallel-NAND.
+ *
+ * - IBR_HDR_PEX_ID (0x9C):
+ *   PEX image is used for booting from PCI Express device. Source address
+ *   stored in image is ignored by BootROM. It is not the BootROM who parses
+ *   or loads data part of the PEX image. BootROM just configures SoC to the
+ *   PCIe endpoint mode and let the PCIe device on the other end of the PCIe
+ *   link (which must be in Root Complex mode) to load kwbimage into SoC's
+ *   memory and tell BootROM physical address.
+ *
+ * - IBR_HDR_UART_ID (0x69):
+ *   UART image can be transfered via xmodem protocol over first UART.
+ *
+ * - IBR_HDR_I2C_ID (0x4D):
+ *   It is unknown for what kind of storage is used this image. It is not
+ *   specified in any document from References section.
+ *
+ * - IBR_HDR_SATA_ID (0x78):
+ *   SATA image can be stored at sector 1 (after the MBR table), sector 34
+ *   (after the GPT table) or at any next sector which is aligned to 2 MB and
+ *   is in the first 16 MB of SATA disk. Note that source address in SATA image
+ *   is stored in sector unit and not in bytes like for any other images.
+ *   Unfortunately sector size is disk specific, in most cases it is 512 bytes
+ *   but there are also Native 4K SATA disks which have 4096 bytes long sectors.
+ *
+ * - IBR_HDR_SDIO_ID (0xAE):
+ *   SDIO image can be stored on different medias:
+ *   - SD(SC) card
+ *   - SDHC/SDXC card
+ *   - eMMC HW boot partition
+ *   - eMMC user data partition / MMC card
+ *   It cannot be stored on SDIO card despite the image name.
+ *
+ *   For SD(SC)/SDHC/SDXC cards, image can be stored at the same locations as
+ *   the SATA image (sector 1, sector 34 or any 2 MB aligned sector) but within
+ *   the first 64 MB. SDHC and SDXC cards have fixed 512 bytes long sector size.
+ *   Old SD(SC) cards unfortunately can have also different sector sizes, mostly
+ *   1024 bytes long sector sizes and also can be changed at runtime.
+ *
+ *   For MMC-compatible devices, image can be stored at offset 0 or at offset
+ *   2 MB. If MMC device supports HW boot partitions then image must be stored
+ *   on the HW partition as is configured in the EXT_CSC register (it can be
+ *   either boot or user data).
+ *
+ *   Note that source address for SDIO image is stored in byte unit, like for
+ *   any other images (except SATA). Marvell Functional Specifications for
+ *   A38x and A39x SoCs say that source address is in sector units, but this
+ *   is purely incorrect information. A385 BootROM really expects source address
+ *   for SDIO images in bytes and also Marvell tools generate SDIO image with
+ *   source address in byte units.
  */
 
 #include "kwbimage.h"
@@ -1695,6 +1776,47 @@
 	for_each_opt_hdr_v1 (ohdr, img)
 		if (ohdr->headertype == OPT_HDR_V1_SECURE_TYPE)
 			return 1;
+
+	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;
 }
@@ -1854,10 +1976,26 @@
 	}
 }
 
+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 @@
 
 	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 @@
 
 	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 @@
 	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 @@
 				 KWBOOT_XM_BLKSZ +
 				 sizeof(kwboot_baud_code) +
 				 sizeof(kwboot_baud_code_data_jump) +
+				 sizeof(uint32_t) +
 				 KWBOOT_XM_BLKSZ;
 
 	if (imgpath) {
diff --git a/tools/mkimage.c b/tools/mkimage.c
index af7b0e0..a92d9d5 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -599,7 +599,12 @@
 		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 @@
 		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