[PATCH V2 1/2] spl: mmc: Factor out eMMC boot partition selection code

Factor out eMMC boot partition selection code into default_spl_mmc_emmc_boot_partition() function and implement weak spl_mmc_emmc_boot_partition(), so that architecture or board code can override the eMMC boot partition selection.
Signed-off-by: Marek Vasut marex@denx.de Cc: Faiz Abbas faiz_abbas@ti.com Cc: Harald Seiler hws@denx.de Cc: Lokesh Vutla lokeshvutla@ti.com Cc: Simon Glass sjg@chromium.org Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com --- V2: Update comments --- common/spl/spl_mmc.c | 37 ++++++++++++++++++++++++------------- include/spl.h | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-)
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index add2785b4e3..2377d0937d1 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -324,6 +324,29 @@ unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return raw_sect; }
+int default_spl_mmc_emmc_boot_partition(struct mmc *mmc) +{ + int part; +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION + part = CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION; +#else + /* + * We need to check what the partition is configured to. + * 1 and 2 match up to boot0 / boot1 and 7 is user data + * which is the first physical partition (0). + */ + part = (mmc->part_config >> 3) & PART_ACCESS_MASK; + if (part == 7) + part = 0; +#endif + return part; +} + +int __weak spl_mmc_emmc_boot_partition(struct mmc *mmc) +{ + return default_spl_mmc_emmc_boot_partition(mmc); +} + int spl_mmc_load(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, const char *filename, @@ -355,19 +378,7 @@ int spl_mmc_load(struct spl_image_info *spl_image, err = -EINVAL; switch (boot_mode) { case MMCSD_MODE_EMMCBOOT: -#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION - part = CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION; -#else - /* - * We need to check what the partition is configured to. - * 1 and 2 match up to boot0 / boot1 and 7 is user data - * which is the first physical partition (0). - */ - part = (mmc->part_config >> 3) & PART_ACCESS_MASK; - - if (part == 7) - part = 0; -#endif + part = spl_mmc_emmc_boot_partition(mmc);
if (CONFIG_IS_ENABLED(MMC_TINY)) err = mmc_switch_part(mmc, part); diff --git a/include/spl.h b/include/spl.h index cee9a42ddb5..c643943482d 100644 --- a/include/spl.h +++ b/include/spl.h @@ -357,6 +357,29 @@ u32 spl_mmc_boot_mode(const u32 boot_device); * If not overridden, it is weakly defined in common/spl/spl_mmc.c. */ int spl_mmc_boot_partition(const u32 boot_device); + +struct mmc; +/** + * default_spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot from. + * mmc: Pointer for the mmc device structure + * + * This function should return the eMMC boot partition number which + * the SPL should load U-Boot from (on the given boot_device). + */ +int default_spl_mmc_emmc_boot_partition(struct mmc *mmc); + +/** + * spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot from. + * mmc: Pointer for the mmc device structure + * + * This function should return the eMMC boot partition number which + * the SPL should load U-Boot from (on the given boot_device). + * + * If not overridden, it is weakly defined in common/spl/spl_mmc.c + * and calls default_spl_mmc_emmc_boot_partition(); + */ +int spl_mmc_emmc_boot_partition(struct mmc *mmc); + void spl_set_bd(void);
/**

In case the iMX8M boot from eMMC boot partition and the primary image is corrupted, the BootROM is capable of starting a secondary image in the other eMMC boot partition as a fallback.
However, the BootROM leaves the eMMC BOOT_PARTITION_ENABLE setting as it was, i.e. pointing to the boot partition containing the corrupted image, and the BootROM does not provide any indication that this sort of fallback occured.
According to AN12853 i.MX ROMs Log Events, Rev. 0, May 2020, it is possible to determine whether fallback event occurred by parsing the ROM event log. In case ROM event ID 0x51 is present, fallback event did occur.
This patch implements ROM event log parsing and search for event ID 0x51 for all iMX8M SoCs, and based on that corrects the eMMC boot partition selection. This way, the SPL loads the remaining boot components from the same eMMC boot partition from which it was started, even in case of the fallback.
Signed-off-by: Marek Vasut marex@denx.de Cc: Faiz Abbas faiz_abbas@ti.com Cc: Harald Seiler hws@denx.de Cc: Lokesh Vutla lokeshvutla@ti.com Cc: Simon Glass sjg@chromium.org Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com --- V2: Return detected partition when the end of ROM event log is reached. --- arch/arm/mach-imx/imx8m/soc.c | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 0c44022a6dc..f8ff4332d86 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -571,6 +571,67 @@ enum boot_device get_boot_device(void) } #endif
+#if defined(CONFIG_IMX8M) +#include <spl.h> +int spl_mmc_emmc_boot_partition(struct mmc *mmc) +{ + u32 *rom_log_addr = (u32 *)0x9e0; + u32 *rom_log; + u8 event_id; + int i, part; + + part = default_spl_mmc_emmc_boot_partition(mmc); + + /* If the ROM event log pointer is not valid. */ + if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 || + *rom_log_addr & 0x3) + return part; + + /* Parse the ROM event ID version 2 log */ + rom_log = (u32 *)(uintptr_t)(*rom_log_addr); + for (i = 0; i < 128; i++) { + event_id = rom_log[i] >> 24; + switch (event_id) { + case 0x00: /* End of list */ + return part; + /* Log entries with 1 parameter, skip 1 */ + case 0x80: /* Start to perform the device initialization */ + case 0x81: /* The boot device initialization completes */ + case 0x8f: /* The boot device initialization fails */ + case 0x90: /* Start to read data from boot device */ + case 0x91: /* Reading data from boot device completes */ + case 0x9f: /* Reading data from boot device fails */ + i += 1; + continue; + /* Log entries with 2 parameters, skip 2 */ + case 0xa0: /* Image authentication result */ + case 0xc0: /* Jump to the boot image soon */ + i += 2; + continue; + /* Boot from the secondary boot image */ + case 0x51: + /* + * Swap the eMMC boot partitions in case there was a + * fallback event (i.e. primary image was corrupted + * and that corruption was recognized by the BootROM), + * so the SPL loads the rest of the U-Boot from the + * correct eMMC boot partition, since the BootROM + * leaves the boot partition set to the corrupted one. + */ + if (part == 1) + part = 2; + else if (part == 2) + part = 1; + continue; + default: + continue; + } + } + + return part; +} +#endif + bool is_usb_boot(void) { return get_boot_device() == USB_BOOT;

In case the iMX8M boot from eMMC boot partition and the primary image is corrupted, the BootROM is capable of starting a secondary image in the other eMMC boot partition as a fallback. However, the BootROM leaves the eMMC BOOT_PARTITION_ENABLE setting as it was, i.e. pointing to the boot partition containing the corrupted image, and the BootROM does not provide any indication that this sort of fallback occured. According to AN12853 i.MX ROMs Log Events, Rev. 0, May 2020, it is possible to determine whether fallback event occurred by parsing the ROM event log. In case ROM event ID 0x51 is present, fallback event did occur. This patch implements ROM event log parsing and search for event ID 0x51 for all iMX8M SoCs, and based on that corrects the eMMC boot partition selection. This way, the SPL loads the remaining boot components from the same eMMC boot partition from which it was started, even in case of the fallback. Signed-off-by: Marek Vasut marex@denx.de Cc: Faiz Abbas faiz_abbas@ti.com Cc: Harald Seiler hws@denx.de Cc: Lokesh Vutla lokeshvutla@ti.com Cc: Simon Glass sjg@chromium.org Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

On 7/3/21 11:55 AM, Marek Vasut wrote:
Factor out eMMC boot partition selection code into default_spl_mmc_emmc_boot_partition() function and implement weak spl_mmc_emmc_boot_partition(), so that architecture or board code can override the eMMC boot partition selection.
Signed-off-by: Marek Vasut marex@denx.de Cc: Faiz Abbas faiz_abbas@ti.com Cc: Harald Seiler hws@denx.de Cc: Lokesh Vutla lokeshvutla@ti.com Cc: Simon Glass sjg@chromium.org Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
V2: Update comments
common/spl/spl_mmc.c | 37 ++++++++++++++++++++++++------------- include/spl.h | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-)
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index add2785b4e3..2377d0937d1 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -324,6 +324,29 @@ unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return raw_sect; }
+int default_spl_mmc_emmc_boot_partition(struct mmc *mmc) +{
- int part;
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION
- part = CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION;
+#else
- /*
* We need to check what the partition is configured to.
* 1 and 2 match up to boot0 / boot1 and 7 is user data
* which is the first physical partition (0).
*/
- part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
- if (part == 7)
part = 0;
+#endif
- return part;
+}
+int __weak spl_mmc_emmc_boot_partition(struct mmc *mmc) +{
- return default_spl_mmc_emmc_boot_partition(mmc);
+}
int spl_mmc_load(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, const char *filename, @@ -355,19 +378,7 @@ int spl_mmc_load(struct spl_image_info *spl_image, err = -EINVAL; switch (boot_mode) { case MMCSD_MODE_EMMCBOOT: -#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION
part = CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION;
-#else
/*
* We need to check what the partition is configured to.
* 1 and 2 match up to boot0 / boot1 and 7 is user data
* which is the first physical partition (0).
*/
part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
if (part == 7)
part = 0;
-#endif
part = spl_mmc_emmc_boot_partition(mmc);
if (CONFIG_IS_ENABLED(MMC_TINY)) err = mmc_switch_part(mmc, part);
diff --git a/include/spl.h b/include/spl.h index cee9a42ddb5..c643943482d 100644 --- a/include/spl.h +++ b/include/spl.h @@ -357,6 +357,29 @@ u32 spl_mmc_boot_mode(const u32 boot_device);
- If not overridden, it is weakly defined in common/spl/spl_mmc.c.
*/ int spl_mmc_boot_partition(const u32 boot_device);
+struct mmc; +/**
- default_spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot from.
- mmc: Pointer for the mmc device structure
- This function should return the eMMC boot partition number which
- the SPL should load U-Boot from (on the given boot_device).
- */
+int default_spl_mmc_emmc_boot_partition(struct mmc *mmc);
+/**
- spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot from.
- mmc: Pointer for the mmc device structure
- This function should return the eMMC boot partition number which
- the SPL should load U-Boot from (on the given boot_device).
- If not overridden, it is weakly defined in common/spl/spl_mmc.c
- and calls default_spl_mmc_emmc_boot_partition();
- */
+int spl_mmc_emmc_boot_partition(struct mmc *mmc);
void spl_set_bd(void);
/**

Factor out eMMC boot partition selection code into default_spl_mmc_emmc_boot_partition() function and implement weak spl_mmc_emmc_boot_partition(), so that architecture or board code can override the eMMC boot partition selection. Signed-off-by: Marek Vasut marex@denx.de Cc: Faiz Abbas faiz_abbas@ti.com Cc: Harald Seiler hws@denx.de Cc: Lokesh Vutla lokeshvutla@ti.com Cc: Simon Glass sjg@chromium.org Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic
participants (3)
-
Jaehoon Chung
-
Marek Vasut
-
sbabic@denx.de