[PATCH 20/30] imx: iamge-container: support secondary container

Peng Fan (OSS) peng.fan at oss.nxp.com
Fri Jun 2 08:45:57 CEST 2023


From: Peng Fan <peng.fan at nxp.com>

Add the support for loading image from secondary container set on
iMX8QM B0, iMX8QXP C0.

Using the SCFW API to get container set index, if it is the secondary
boot, get the offset from fuse and apply to offset of current container
set beginning for loading.

Also override the emmc boot partition to check secondary boot and switch
to the other boot part.

This patch is modified from NXP downstream:
imx8: Fix the fuse used by secondary container offset
imx: container: Skip container set check for ROM API
imx8: spl: Support booting from secondary container set

Signed-off-by: Ye Li <ye.li at nxp.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 arch/arm/mach-imx/image-container.c | 94 ++++++++++++++++++++++++++---
 1 file changed, 87 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c
index 745de130630..5f188ab32d1 100644
--- a/arch/arm/mach-imx/image-container.c
+++ b/arch/arm/mach-imx/image-container.c
@@ -22,6 +22,25 @@
 #define QSPI_NOR_DEV	3
 #define ROM_API_DEV	4
 
+/* The unit of second image offset number which provision by the fuse bits */
+#define SND_IMG_OFF_UNIT    (0x100000UL)
+
+/*
+ * If num = 0, off = (2 ^ 2) * 1MB
+ * else If num = 2, off = (2 ^ 0) * 1MB
+ * else off = (2 ^ num) * 1MB
+ */
+#define SND_IMG_NUM_TO_OFF(num) \
+	((1UL << ((0 == (num)) ? 2 : (2 == (num)) ? 0 : (num))) * SND_IMG_OFF_UNIT)
+
+#define GET_SND_IMG_NUM(fuse) (((fuse) >> 24) & 0x1F)
+
+#if defined(CONFIG_IMX8QM)
+#define FUSE_IMG_SET_OFF_WORD 464
+#elif defined(CONFIG_IMX8QXP)
+#define FUSE_IMG_SET_OFF_WORD 720
+#endif
+
 int get_container_size(ulong addr, u16 *header_length)
 {
 	struct container_hdr *phdr;
@@ -136,15 +155,53 @@ static int get_dev_container_size(void *dev, int dev_type, unsigned long offset,
 	return ret;
 }
 
+static bool check_secondary_cnt_set(unsigned long *set_off)
+{
+#if IS_ENABLED(CONFIG_ARCH_IMX8)
+	int ret;
+	u8 set_id = 1;
+	u32 fuse_val = 0;
+
+	if (!(is_imx8qxp() && is_soc_rev(CHIP_REV_B))) {
+		ret = sc_misc_get_boot_container(-1, &set_id);
+		if (ret)
+			return false;
+		/* Secondary boot */
+		if (set_id == 2) {
+			ret = sc_misc_otp_fuse_read(-1, FUSE_IMG_SET_OFF_WORD, &fuse_val);
+			if (!ret) {
+				if (set_off)
+					*set_off = SND_IMG_NUM_TO_OFF(GET_SND_IMG_NUM(fuse_val));
+				return true;
+			}
+		}
+	}
+#endif
+
+	return false;
+}
+
 static unsigned long get_boot_device_offset(void *dev, int dev_type)
 {
-	unsigned long offset = 0;
+	unsigned long offset = 0, sec_set_off = 0;
+	bool sec_boot = false;
+
+	if (dev_type == ROM_API_DEV) {
+		offset = (unsigned long)dev;
+		return offset;
+	}
+
+	sec_boot = check_secondary_cnt_set(&sec_set_off);
+	if (sec_boot)
+		printf("Secondary set selected\n");
+	else
+		printf("Primary set selected\n");
 
 	if (dev_type == MMC_DEV) {
 		struct mmc *mmc = (struct mmc *)dev;
 
 		if (IS_SD(mmc) || mmc->part_config == MMCPART_NOAVAILABLE) {
-			offset = CONTAINER_HDR_MMCSD_OFFSET;
+			offset = sec_boot ? sec_set_off : CONTAINER_HDR_MMCSD_OFFSET;
 		} else {
 			u8 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
 
@@ -154,19 +211,23 @@ static unsigned long get_boot_device_offset(void *dev, int dev_type)
 				else
 					offset = CONTAINER_HDR_EMMC_OFFSET;
 			} else {
-				offset = CONTAINER_HDR_MMCSD_OFFSET;
+				offset = sec_boot ? sec_set_off : CONTAINER_HDR_MMCSD_OFFSET;
 			}
 		}
 	} else if (dev_type == QSPI_DEV) {
-		offset = CONTAINER_HDR_QSPI_OFFSET;
+		offset = sec_boot ? (sec_set_off + CONTAINER_HDR_QSPI_OFFSET) :
+			CONTAINER_HDR_QSPI_OFFSET;
 	} else if (dev_type == NAND_DEV) {
-		offset = CONTAINER_HDR_NAND_OFFSET;
+		offset = sec_boot ? (sec_set_off + CONTAINER_HDR_NAND_OFFSET) :
+			CONTAINER_HDR_NAND_OFFSET;
 	} else if (dev_type == QSPI_NOR_DEV) {
 		offset = CONTAINER_HDR_QSPI_OFFSET + 0x08000000;
-	} else if (dev_type == ROM_API_DEV) {
-		offset = (unsigned long)dev;
+	} else {
+		printf("Not supported dev_type: %d\n", dev_type);
 	}
 
+	debug("container set offset 0x%lx\n", offset);
+
 	return offset;
 }
 
@@ -227,6 +288,25 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
 
 	return end / mmc->read_bl_len;
 }
+
+int spl_mmc_emmc_boot_partition(struct mmc *mmc)
+{
+	int part;
+
+	part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
+	if (part == 1 || part == 2) {
+		unsigned long sec_set_off = 0;
+		bool sec_boot = false;
+
+		sec_boot = check_secondary_cnt_set(&sec_set_off);
+		if (sec_boot)
+			part = (part == 1) ? 2 : 1;
+	} else if (part == 7) {
+		part = 0;
+	}
+
+	return part;
+}
 #endif
 
 #ifdef CONFIG_SPL_NAND_SUPPORT
-- 
2.40.0



More information about the U-Boot mailing list