ARM Sunxi Platform Development
 help / color / Atom feed
* [RESEND PATCH v2 0/3] sunxi: Improve automatic eMMC boot partition support
@ 2021-07-12 10:06 Andre Przywara
  2021-07-12 10:06 ` [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument Andre Przywara
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Andre Przywara @ 2021-07-12 10:06 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Sunil Mohan Adapa,
	linux-sunxi, u-boot

(resent to also include forgotten U-Boot list)

The Allwinner BootROM supports loading the SPL from eMMC boot partitions,
but so far the SPL support for this case was a bit lacking, as it was a
compile time decision, and even required a manual config change.
This actually got accidentally fixed in v2021.04 (c0b417b2f1a3 "sunxi:
support loading with SPL > 32KB"), but still some gaps remain: When just
enabling an eMMC boot partition, but having no bootable code there, the
BROM will just continue with booting from the user data partition, but
U-Boot does not detect this and will try to load U-Boot proper from that
boot partition.

This series fixes this, by replicating the BROMs decisions in the SPL,
to decide on the partition to continue loading from.

Patch 1/3 prepares a generic function to take an extra argument, while
patch 2/3 implements the actual algorithm.
As this now allows to always have eMMC boot support on, patch 3/3 just
activates this for a number of boards I could test it on.

I'd like to encourage other people to test this on boards with eMMC, to
enable this in the respective defconfig, maybe even centrally.

Some more details on eMMC boot partition support and how to install
U-Boot in there can be found in the linux-sunxi Wiki:
http://linux-sunxi.org/Bootable_eMMC

Cheers,
Andre

Changelog v1 .. v2:
- drop patch 1/5 (bugfix): already merged
- drop patch 3/5, as it was obsoleted by c0b417b2f1a3
- remove check for 32KB SPL limit (not applicable for H6 and beyond)
- remove extra sector offset adjustment (obsoleted by c0b417b2f1a3)

Andre Przywara (3):
  spl: mmc: extend spl_mmc_boot_mode() to take mmc argument
  sunxi: eMMC: Improve automatic boot source detection
  sunxi: defconfig: enable eMMC boot partition support

 arch/arm/mach-imx/spl.c                    |  2 +-
 arch/arm/mach-k3/am6_init.c                |  2 +-
 arch/arm/mach-k3/j721e_init.c              |  2 +-
 arch/arm/mach-omap2/boot-common.c          |  2 +-
 arch/arm/mach-rockchip/spl.c               |  2 +-
 arch/arm/mach-socfpga/spl_a10.c            |  2 +-
 arch/arm/mach-socfpga/spl_gen5.c           |  2 +-
 arch/arm/mach-stm32mp/spl.c                |  2 +-
 arch/arm/mach-sunxi/board.c                | 80 ++++++++++++++++++++++
 arch/arm/mach-uniphier/mmc-boot-mode.c     |  5 +-
 common/spl/spl_mmc.c                       |  4 +-
 configs/bananapi_m64_defconfig             |  1 +
 configs/emlid_neutis_n5_devboard_defconfig |  1 +
 configs/pine64-lts_defconfig               |  1 +
 configs/pine_h64_defconfig                 |  1 +
 include/spl.h                              |  3 +-
 16 files changed, 97 insertions(+), 15 deletions(-)

-- 
2.17.5


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument
  2021-07-12 10:06 [RESEND PATCH v2 0/3] sunxi: Improve automatic eMMC boot partition support Andre Przywara
@ 2021-07-12 10:06 ` Andre Przywara
  2021-07-20 18:32   ` Simon Glass
  2021-07-12 10:06 ` [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection Andre Przywara
  2021-07-12 10:06 ` [RESEND PATCH v2 3/3] sunxi: defconfig: enable eMMC boot partition support Andre Przywara
  2 siblings, 1 reply; 7+ messages in thread
From: Andre Przywara @ 2021-07-12 10:06 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Sunil Mohan Adapa,
	linux-sunxi, u-boot, Stefano Babic, Fabio Estevam,
	NXP i . MX U-Boot Team, Lokesh Vutla, Simon Glass,
	Philipp Tomsich, Kever Yang, Marek Vasut, Simon Goldschmidt,
	Ley Foon Tan, Patrick Delaunay, Patrice Chotard

Platforms can overwrite the weak definition of spl_mmc_boot_mode() to
determine where to load U-Boot proper from.
For most of them this is a trivial decision based on Kconfig variables,
but it might be desirable the probe the actual device to answer this
question.

Pass the pointer to the mmc struct to that function, so implementations
can make use of that.

Compile-tested for all users changed.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Stefano Babic <sbabic@denx.de>
Reviewed-by: Ley Foon Tan <ley.foon.tan@inte.com> (for SoCFPGA)
Acked-by: Lokesh Vutla <lokeshvutla@ti.com> (for OMAP and K3)
---
(resent to also include forgotten U-Boot list)

 arch/arm/mach-imx/spl.c                | 2 +-
 arch/arm/mach-k3/am6_init.c            | 2 +-
 arch/arm/mach-k3/j721e_init.c          | 2 +-
 arch/arm/mach-omap2/boot-common.c      | 2 +-
 arch/arm/mach-rockchip/spl.c           | 2 +-
 arch/arm/mach-socfpga/spl_a10.c        | 2 +-
 arch/arm/mach-socfpga/spl_gen5.c       | 2 +-
 arch/arm/mach-stm32mp/spl.c            | 2 +-
 arch/arm/mach-uniphier/mmc-boot-mode.c | 5 +----
 common/spl/spl_mmc.c                   | 4 ++--
 include/spl.h                          | 3 ++-
 11 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c
index 36033d611c9..797097b9c79 100644
--- a/arch/arm/mach-imx/spl.c
+++ b/arch/arm/mach-imx/spl.c
@@ -201,7 +201,7 @@ int g_dnl_get_board_bcd_device_number(int gcnum)
 
 #if defined(CONFIG_SPL_MMC_SUPPORT)
 /* called from spl_mmc to see type of boot mode for storage (RAW or FAT) */
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 #if defined(CONFIG_MX7) || defined(CONFIG_IMX8M) || defined(CONFIG_IMX8)
 	switch (get_boot_device()) {
diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c
index 425b3f93c86..f4b039e8a6a 100644
--- a/arch/arm/mach-k3/am6_init.c
+++ b/arch/arm/mach-k3/am6_init.c
@@ -253,7 +253,7 @@ void board_init_f(ulong dummy)
 	spl_enable_dcache();
 }
 
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 #if defined(CONFIG_SUPPORT_EMMC_BOOT)
 	u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
diff --git a/arch/arm/mach-k3/j721e_init.c b/arch/arm/mach-k3/j721e_init.c
index e9e076c9e72..fc0db2a4001 100644
--- a/arch/arm/mach-k3/j721e_init.c
+++ b/arch/arm/mach-k3/j721e_init.c
@@ -232,7 +232,7 @@ void board_init_f(ulong dummy)
 	spl_enable_dcache();
 }
 
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 	switch (boot_device) {
 	case BOOT_DEVICE_MMC1:
diff --git a/arch/arm/mach-omap2/boot-common.c b/arch/arm/mach-omap2/boot-common.c
index 1268a325038..f71fe65a0b1 100644
--- a/arch/arm/mach-omap2/boot-common.c
+++ b/arch/arm/mach-omap2/boot-common.c
@@ -189,7 +189,7 @@ u32 spl_boot_device(void)
 	return gd->arch.omap_boot_device;
 }
 
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 	return gd->arch.omap_boot_mode;
 }
diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c
index 02c40fb37ed..082a5bfb20a 100644
--- a/arch/arm/mach-rockchip/spl.c
+++ b/arch/arm/mach-rockchip/spl.c
@@ -65,7 +65,7 @@ u32 spl_boot_device(void)
 	return boot_device;
 }
 
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 	return MMCSD_MODE_RAW;
 }
diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c
index b5f43f09d19..c6dcd309bfc 100644
--- a/arch/arm/mach-socfpga/spl_a10.c
+++ b/arch/arm/mach-socfpga/spl_a10.c
@@ -94,7 +94,7 @@ u32 spl_boot_device(void)
 }
 
 #ifdef CONFIG_SPL_MMC_SUPPORT
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 #if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
 	return MMCSD_MODE_FS;
diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c
index 7c716117685..e5d1e64c449 100644
--- a/arch/arm/mach-socfpga/spl_gen5.c
+++ b/arch/arm/mach-socfpga/spl_gen5.c
@@ -53,7 +53,7 @@ u32 spl_boot_device(void)
 }
 
 #ifdef CONFIG_SPL_MMC_SUPPORT
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 #if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
 	return MMCSD_MODE_FS;
diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c
index b53659a698a..4c8085b8305 100644
--- a/arch/arm/mach-stm32mp/spl.c
+++ b/arch/arm/mach-stm32mp/spl.c
@@ -53,7 +53,7 @@ u32 spl_boot_device(void)
 	return BOOT_DEVICE_MMC1;
 }
 
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 	return MMCSD_MODE_RAW;
 }
diff --git a/arch/arm/mach-uniphier/mmc-boot-mode.c b/arch/arm/mach-uniphier/mmc-boot-mode.c
index e47e5df6480..09cad743c55 100644
--- a/arch/arm/mach-uniphier/mmc-boot-mode.c
+++ b/arch/arm/mach-uniphier/mmc-boot-mode.c
@@ -7,10 +7,8 @@
 #include <mmc.h>
 #include <spl.h>
 
-u32 spl_mmc_boot_mode(const u32 boot_device)
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
-	struct mmc *mmc;
-
 	/*
 	 * work around a bug in the Boot ROM of LD4, Pro4, and sLD8:
 	 *
@@ -24,7 +22,6 @@ u32 spl_mmc_boot_mode(const u32 boot_device)
 	 * Fixup mmc->part_config here because it is used to determine the
 	 * partition which the U-Boot image is read from.
 	 */
-	mmc = find_mmc_device(0);
 	mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK);
 	mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE;
 
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index add2785b4e3..309abaf961a 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -300,7 +300,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
 }
 #endif
 
-u32 __weak spl_mmc_boot_mode(const u32 boot_device)
+u32 __weak spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
 {
 #if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
 	return MMCSD_MODE_FS;
@@ -351,7 +351,7 @@ int spl_mmc_load(struct spl_image_info *spl_image,
 		}
 	}
 
-	boot_mode = spl_mmc_boot_mode(bootdev->boot_device);
+	boot_mode = spl_mmc_boot_mode(mmc, bootdev->boot_device);
 	err = -EINVAL;
 	switch (boot_mode) {
 	case MMCSD_MODE_EMMCBOOT:
diff --git a/include/spl.h b/include/spl.h
index cee9a42ddb5..c8f470dd5f2 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -14,6 +14,7 @@
 #include <asm/global_data.h>
 #include <asm/spl.h>
 #include <handoff.h>
+#include <mmc.h>
 
 struct blk_desc;
 struct image_header;
@@ -343,7 +344,7 @@ u32 spl_boot_device(void);
  * Note:  It is important to use the boot_device parameter instead of e.g.
  * spl_boot_device() as U-Boot is not always loaded from the same device as SPL.
  */
-u32 spl_mmc_boot_mode(const u32 boot_device);
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device);
 
 /**
  * spl_mmc_boot_partition() - MMC partition to load U-Boot from.
-- 
2.17.5


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection
  2021-07-12 10:06 [RESEND PATCH v2 0/3] sunxi: Improve automatic eMMC boot partition support Andre Przywara
  2021-07-12 10:06 ` [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument Andre Przywara
@ 2021-07-12 10:06 ` Andre Przywara
  2021-07-12 10:57   ` Jaehoon Chung
  2021-07-12 10:06 ` [RESEND PATCH v2 3/3] sunxi: defconfig: enable eMMC boot partition support Andre Przywara
  2 siblings, 1 reply; 7+ messages in thread
From: Andre Przywara @ 2021-07-12 10:06 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Sunil Mohan Adapa,
	linux-sunxi, u-boot

When the Allwinner BROM loads the SPL from an eMMC boot partition, it
sets the boot source byte to the same value as when booting from the
user data partition. This prevents us from determining the boot source
to load U-Boot proper from the proper partition for sure.

The generic SPL MMC code already looks at the enabled boot partition
number, to load U-Boot proper from the same partition, but this fails
if there is nothing bootable in this partition, as the BROM then
silently falls back to the user data partition, which the SPL misses.

To learn about the actual boot source anyway, we repeat the algorithm
the BROM used to select the boot partition in the first place:
- Test EXT_CSD[179] to check if an eMMC boot partition is enabled.
- Test EXT_CSD[177] to check for valid MMC interface settings.
- Check if BOOT_ACK is enabled.
- Check the beginning of the first sector for a valid eGON signature.
- Load the whole SPL.
- Recalculate the checksum to verify the SPL is valid.

If one of those steps fails, we bail out and continue loading from the
user data partition. Otherwise we load from the selected boot partition.

Since the boot source is needed twice in the boot process, we cache the
result of this test to avoid doing this costly test multiple times.

This allows the very same image file to be put onto an SD card, into the
eMMC user data partition or into the eMMC boot partition, and safely
loads the whole of U-Boot from there.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---

(resent to also include forgotten U-Boot list)

 arch/arm/mach-sunxi/board.c | 80 +++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index e979e426dd1..2552c34733b 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -334,6 +334,86 @@ u32 spl_boot_device(void)
 	return sunxi_get_boot_device();
 }
 
+/*
+ * When booting from an eMMC boot partition, the SPL puts the same boot
+ * source code into SRAM A1 as when loading the SPL from the normal
+ * eMMC user data partition: 0x2. So to know where we have been loaded
+ * from, we repeat the BROM algorithm here: checking for a valid eGON boot
+ * image at offset 0 of a (potentially) selected boot partition.
+ * If any of the conditions is not met, it must have been the eMMC user
+ * data partition.
+ */
+static bool sunxi_valid_emmc_boot(struct mmc *mmc)
+{
+	struct blk_desc *bd = mmc_get_blk_desc(mmc);
+	uint32_t *buffer = (void *)(uintptr_t)CONFIG_SYS_TEXT_BASE;
+	int bootpart = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
+	uint32_t spl_size, emmc_checksum, chksum = 0;
+	ulong count;
+
+	/* The BROM requires BOOT_ACK to be enabled. */
+	if (!EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config))
+		return false;
+
+	/*
+	 * The BOOT_BUS_CONDITION register must be 4-bit SDR, with (0x09)
+	 * or without (0x01) high speed timings.
+	 */
+	if ((mmc->ext_csd[EXT_CSD_BOOT_BUS_WIDTH] & 0x1b) != 0x01 &&
+	    (mmc->ext_csd[EXT_CSD_BOOT_BUS_WIDTH] & 0x1b) != 0x09)
+		return false;
+
+	/* Partition 0 is the user data partition, bootpart must be 1 or 2. */
+	if (bootpart != 1 && bootpart != 2)
+		return false;
+
+	mmc_switch_part(mmc, bootpart);
+
+	/* Read the first block to do some sanity checks on the eGON header. */
+	count = blk_dread(bd, 0, 1, buffer);
+	if (count != 1 || !is_boot0_magic(buffer + 1))
+		return false;
+
+	/* Read the rest of the SPL now we know it's halfway sane. */
+	spl_size = buffer[4];
+	count = blk_dread(bd, 1, DIV_ROUND_UP(spl_size, bd->blksz) - 1,
+			  buffer + bd->blksz / 4);
+
+	/* Save the checksum and replace it with the "stamp value". */
+	emmc_checksum = buffer[3];
+	buffer[3] = 0x5f0a6c39;
+
+	/* The checksum is a simple ignore-carry addition of all words. */
+	for (count = 0; count < spl_size / 4; count++)
+		chksum += buffer[count];
+
+	debug("eMMC boot part SPL checksum: stored: 0x%08x, computed: 0x%08x\n",
+	       emmc_checksum, chksum);
+
+	return emmc_checksum == chksum;
+}
+
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
+{
+	static u32 result = ~0;
+
+	if (result != ~0)
+		return result;
+
+	result = MMCSD_MODE_RAW;
+	if (!IS_SD(mmc) && IS_ENABLED(CONFIG_SUPPORT_EMMC_BOOT)) {
+		if (sunxi_valid_emmc_boot(mmc))
+			result = MMCSD_MODE_EMMCBOOT;
+		else
+			mmc_switch_part(mmc, 0);
+	}
+
+	debug("%s(): %s part\n", __func__,
+	      result == MMCSD_MODE_RAW ? "user" : "boot");
+
+	return result;
+}
+
 void board_init_f(ulong dummy)
 {
 	spl_init();
-- 
2.17.5


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RESEND PATCH v2 3/3] sunxi: defconfig: enable eMMC boot partition support
  2021-07-12 10:06 [RESEND PATCH v2 0/3] sunxi: Improve automatic eMMC boot partition support Andre Przywara
  2021-07-12 10:06 ` [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument Andre Przywara
  2021-07-12 10:06 ` [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection Andre Przywara
@ 2021-07-12 10:06 ` Andre Przywara
  2 siblings, 0 replies; 7+ messages in thread
From: Andre Przywara @ 2021-07-12 10:06 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Sunil Mohan Adapa,
	linux-sunxi, u-boot

Now that the SPL can safely detect whether it was loaded from an eMMC
boot partition or the normal user data partition, let's enable this
feature on some boards that feature eMMC storage.

That covers the boards where I could test this on, and allows the same
build to be written to an SD card, eMMC user partition, eMMC boot
partition, or into SPI NOR flash.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---

(resent to also include forgotten U-Boot list)

 configs/bananapi_m64_defconfig             | 1 +
 configs/emlid_neutis_n5_devboard_defconfig | 1 +
 configs/pine64-lts_defconfig               | 1 +
 configs/pine_h64_defconfig                 | 1 +
 4 files changed, 4 insertions(+)

diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig
index 292044d7b8b..0c0117e3c14 100644
--- a/configs/bananapi_m64_defconfig
+++ b/configs/bananapi_m64_defconfig
@@ -6,6 +6,7 @@ CONFIG_MACH_SUN50I=y
 CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_SUPPORT_EMMC_BOOT=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/emlid_neutis_n5_devboard_defconfig b/configs/emlid_neutis_n5_devboard_defconfig
index e2d3b1397e2..586f0f031aa 100644
--- a/configs/emlid_neutis_n5_devboard_defconfig
+++ b/configs/emlid_neutis_n5_devboard_defconfig
@@ -7,4 +7,5 @@ CONFIG_DRAM_CLK=408
 CONFIG_DRAM_ZQ=3881977
 # CONFIG_DRAM_ODT_EN is not set
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_SUPPORT_EMMC_BOOT=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig
index 6209e68e2d1..b3727009d73 100644
--- a/configs/pine64-lts_defconfig
+++ b/configs/pine64-lts_defconfig
@@ -8,6 +8,7 @@ CONFIG_DRAM_CLK=552
 CONFIG_DRAM_ZQ=3881949
 CONFIG_MMC0_CD_PIN=""
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SUN8I_EMAC=y
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 4e621db0c03..75f49fc81d1 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -7,6 +7,7 @@ CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MACPWR="PC16"
 CONFIG_MMC0_CD_PIN="PF6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_USB3_VBUS_PIN="PL5"
 CONFIG_SPL_SPI_SUNXI=y
 # CONFIG_PSCI_RESET is not set
-- 
2.17.5


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection
  2021-07-12 10:06 ` [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection Andre Przywara
@ 2021-07-12 10:57   ` Jaehoon Chung
  2021-07-12 11:53     ` Andre Przywara
  0 siblings, 1 reply; 7+ messages in thread
From: Jaehoon Chung @ 2021-07-12 10:57 UTC (permalink / raw)
  To: Andre Przywara, Jagan Teki
  Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Sunil Mohan Adapa,
	linux-sunxi, u-boot

Hi Andre,

On 7/12/21 7:06 PM, Andre Przywara wrote:
> When the Allwinner BROM loads the SPL from an eMMC boot partition, it
> sets the boot source byte to the same value as when booting from the
> user data partition. This prevents us from determining the boot source
> to load U-Boot proper from the proper partition for sure.
> 
> The generic SPL MMC code already looks at the enabled boot partition
> number, to load U-Boot proper from the same partition, but this fails
> if there is nothing bootable in this partition, as the BROM then
> silently falls back to the user data partition, which the SPL misses.
> 
> To learn about the actual boot source anyway, we repeat the algorithm
> the BROM used to select the boot partition in the first place:
> - Test EXT_CSD[179] to check if an eMMC boot partition is enabled.
> - Test EXT_CSD[177] to check for valid MMC interface settings.
> - Check if BOOT_ACK is enabled.
> - Check the beginning of the first sector for a valid eGON signature.
> - Load the whole SPL.
> - Recalculate the checksum to verify the SPL is valid.
> 
> If one of those steps fails, we bail out and continue loading from the
> user data partition. Otherwise we load from the selected boot partition.
> 
> Since the boot source is needed twice in the boot process, we cache the
> result of this test to avoid doing this costly test multiple times.
> 
> This allows the very same image file to be put onto an SD card, into the
> eMMC user data partition or into the eMMC boot partition, and safely
> loads the whole of U-Boot from there.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> 
> (resent to also include forgotten U-Boot list)
> 
>  arch/arm/mach-sunxi/board.c | 80 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 80 insertions(+)
> 
> diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
> index e979e426dd1..2552c34733b 100644
> --- a/arch/arm/mach-sunxi/board.c
> +++ b/arch/arm/mach-sunxi/board.c
> @@ -334,6 +334,86 @@ u32 spl_boot_device(void)
>  	return sunxi_get_boot_device();
>  }
>  
> +/*
> + * When booting from an eMMC boot partition, the SPL puts the same boot
> + * source code into SRAM A1 as when loading the SPL from the normal
> + * eMMC user data partition: 0x2. So to know where we have been loaded
> + * from, we repeat the BROM algorithm here: checking for a valid eGON boot
> + * image at offset 0 of a (potentially) selected boot partition.
> + * If any of the conditions is not met, it must have been the eMMC user
> + * data partition.
> + */
> +static bool sunxi_valid_emmc_boot(struct mmc *mmc)
> +{
> +	struct blk_desc *bd = mmc_get_blk_desc(mmc);
> +	uint32_t *buffer = (void *)(uintptr_t)CONFIG_SYS_TEXT_BASE;
> +	int bootpart = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
> +	uint32_t spl_size, emmc_checksum, chksum = 0;
> +	ulong count;
> +
> +	/* The BROM requires BOOT_ACK to be enabled. */
> +	if (!EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config))
> +		return false;
> +
> +	/*
> +	 * The BOOT_BUS_CONDITION register must be 4-bit SDR, with (0x09)
> +	 * or without (0x01) high speed timings.
> +	 */
> +	if ((mmc->ext_csd[EXT_CSD_BOOT_BUS_WIDTH] & 0x1b) != 0x01 &&
> +	    (mmc->ext_csd[EXT_CSD_BOOT_BUS_WIDTH] & 0x1b) != 0x09)
> +		return false;
> +
> +	/* Partition 0 is the user data partition, bootpart must be 1 or 2. */
> +	if (bootpart != 1 && bootpart != 2)
> +		return false;
> +
> +	mmc_switch_part(mmc, bootpart);

It can be failed to switch to bootpart. Doesn't need to control error?

Best Regards,
Jaehoon Chung

> +
> +	/* Read the first block to do some sanity checks on the eGON header. */
> +	count = blk_dread(bd, 0, 1, buffer);
> +	if (count != 1 || !is_boot0_magic(buffer + 1))
> +		return false;
> +
> +	/* Read the rest of the SPL now we know it's halfway sane. */
> +	spl_size = buffer[4];
> +	count = blk_dread(bd, 1, DIV_ROUND_UP(spl_size, bd->blksz) - 1,
> +			  buffer + bd->blksz / 4);
> +
> +	/* Save the checksum and replace it with the "stamp value". */
> +	emmc_checksum = buffer[3];
> +	buffer[3] = 0x5f0a6c39;
> +
> +	/* The checksum is a simple ignore-carry addition of all words. */
> +	for (count = 0; count < spl_size / 4; count++)
> +		chksum += buffer[count];
> +
> +	debug("eMMC boot part SPL checksum: stored: 0x%08x, computed: 0x%08x\n",
> +	       emmc_checksum, chksum);
> +
> +	return emmc_checksum == chksum;
> +}
> +
> +u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
> +{
> +	static u32 result = ~0;
> +
> +	if (result != ~0)
> +		return result;
> +
> +	result = MMCSD_MODE_RAW;
> +	if (!IS_SD(mmc) && IS_ENABLED(CONFIG_SUPPORT_EMMC_BOOT)) {
> +		if (sunxi_valid_emmc_boot(mmc))
> +			result = MMCSD_MODE_EMMCBOOT;
> +		else
> +			mmc_switch_part(mmc, 0);
> +	}
> +
> +	debug("%s(): %s part\n", __func__,
> +	      result == MMCSD_MODE_RAW ? "user" : "boot");
> +
> +	return result;
> +}
> +
>  void board_init_f(ulong dummy)
>  {
>  	spl_init();
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection
  2021-07-12 10:57   ` Jaehoon Chung
@ 2021-07-12 11:53     ` Andre Przywara
  0 siblings, 0 replies; 7+ messages in thread
From: Andre Przywara @ 2021-07-12 11:53 UTC (permalink / raw)
  To: Jaehoon Chung
  Cc: Jagan Teki, Samuel Holland, Jernej Skrabec, Icenowy Zheng,
	Sunil Mohan Adapa, linux-sunxi, u-boot

On Mon, 12 Jul 2021 19:57:04 +0900
Jaehoon Chung <jh80.chung@samsung.com> wrote:

> Hi Andre,
> 
> On 7/12/21 7:06 PM, Andre Przywara wrote:
> > When the Allwinner BROM loads the SPL from an eMMC boot partition, it
> > sets the boot source byte to the same value as when booting from the
> > user data partition. This prevents us from determining the boot source
> > to load U-Boot proper from the proper partition for sure.
> > 
> > The generic SPL MMC code already looks at the enabled boot partition
> > number, to load U-Boot proper from the same partition, but this fails
> > if there is nothing bootable in this partition, as the BROM then
> > silently falls back to the user data partition, which the SPL misses.
> > 
> > To learn about the actual boot source anyway, we repeat the algorithm
> > the BROM used to select the boot partition in the first place:
> > - Test EXT_CSD[179] to check if an eMMC boot partition is enabled.
> > - Test EXT_CSD[177] to check for valid MMC interface settings.
> > - Check if BOOT_ACK is enabled.
> > - Check the beginning of the first sector for a valid eGON signature.
> > - Load the whole SPL.
> > - Recalculate the checksum to verify the SPL is valid.
> > 
> > If one of those steps fails, we bail out and continue loading from the
> > user data partition. Otherwise we load from the selected boot partition.
> > 
> > Since the boot source is needed twice in the boot process, we cache the
> > result of this test to avoid doing this costly test multiple times.
> > 
> > This allows the very same image file to be put onto an SD card, into the
> > eMMC user data partition or into the eMMC boot partition, and safely
> > loads the whole of U-Boot from there.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > 
> > (resent to also include forgotten U-Boot list)
> > 
> >  arch/arm/mach-sunxi/board.c | 80 +++++++++++++++++++++++++++++++++++++
> >  1 file changed, 80 insertions(+)
> > 
> > diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
> > index e979e426dd1..2552c34733b 100644
> > --- a/arch/arm/mach-sunxi/board.c
> > +++ b/arch/arm/mach-sunxi/board.c
> > @@ -334,6 +334,86 @@ u32 spl_boot_device(void)
> >  	return sunxi_get_boot_device();
> >  }
> >  
> > +/*
> > + * When booting from an eMMC boot partition, the SPL puts the same boot
> > + * source code into SRAM A1 as when loading the SPL from the normal
> > + * eMMC user data partition: 0x2. So to know where we have been loaded
> > + * from, we repeat the BROM algorithm here: checking for a valid eGON boot
> > + * image at offset 0 of a (potentially) selected boot partition.
> > + * If any of the conditions is not met, it must have been the eMMC user
> > + * data partition.
> > + */
> > +static bool sunxi_valid_emmc_boot(struct mmc *mmc)
> > +{
> > +	struct blk_desc *bd = mmc_get_blk_desc(mmc);
> > +	uint32_t *buffer = (void *)(uintptr_t)CONFIG_SYS_TEXT_BASE;
> > +	int bootpart = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
> > +	uint32_t spl_size, emmc_checksum, chksum = 0;
> > +	ulong count;
> > +
> > +	/* The BROM requires BOOT_ACK to be enabled. */
> > +	if (!EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config))
> > +		return false;
> > +
> > +	/*
> > +	 * The BOOT_BUS_CONDITION register must be 4-bit SDR, with (0x09)
> > +	 * or without (0x01) high speed timings.
> > +	 */
> > +	if ((mmc->ext_csd[EXT_CSD_BOOT_BUS_WIDTH] & 0x1b) != 0x01 &&
> > +	    (mmc->ext_csd[EXT_CSD_BOOT_BUS_WIDTH] & 0x1b) != 0x09)
> > +		return false;
> > +
> > +	/* Partition 0 is the user data partition, bootpart must be 1 or 2. */
> > +	if (bootpart != 1 && bootpart != 2)
> > +		return false;
> > +
> > +	mmc_switch_part(mmc, bootpart);  
> 
> It can be failed to switch to bootpart. Doesn't need to control error?

Yeah, good point, we should check this. If we can't switch to the boot
partition, that hopefully means the BROM couldn't do either. In any case
we can't continue booting from there, so we can as well return false
here.

Cheers,
Andre

> Best Regards,
> Jaehoon Chung
> 
> > +
> > +	/* Read the first block to do some sanity checks on the eGON header. */
> > +	count = blk_dread(bd, 0, 1, buffer);
> > +	if (count != 1 || !is_boot0_magic(buffer + 1))
> > +		return false;
> > +
> > +	/* Read the rest of the SPL now we know it's halfway sane. */
> > +	spl_size = buffer[4];
> > +	count = blk_dread(bd, 1, DIV_ROUND_UP(spl_size, bd->blksz) - 1,
> > +			  buffer + bd->blksz / 4);
> > +
> > +	/* Save the checksum and replace it with the "stamp value". */
> > +	emmc_checksum = buffer[3];
> > +	buffer[3] = 0x5f0a6c39;
> > +
> > +	/* The checksum is a simple ignore-carry addition of all words. */
> > +	for (count = 0; count < spl_size / 4; count++)
> > +		chksum += buffer[count];
> > +
> > +	debug("eMMC boot part SPL checksum: stored: 0x%08x, computed: 0x%08x\n",
> > +	       emmc_checksum, chksum);
> > +
> > +	return emmc_checksum == chksum;
> > +}
> > +
> > +u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
> > +{
> > +	static u32 result = ~0;
> > +
> > +	if (result != ~0)
> > +		return result;
> > +
> > +	result = MMCSD_MODE_RAW;
> > +	if (!IS_SD(mmc) && IS_ENABLED(CONFIG_SUPPORT_EMMC_BOOT)) {
> > +		if (sunxi_valid_emmc_boot(mmc))
> > +			result = MMCSD_MODE_EMMCBOOT;
> > +		else
> > +			mmc_switch_part(mmc, 0);
> > +	}
> > +
> > +	debug("%s(): %s part\n", __func__,
> > +	      result == MMCSD_MODE_RAW ? "user" : "boot");
> > +
> > +	return result;
> > +}
> > +
> >  void board_init_f(ulong dummy)
> >  {
> >  	spl_init();
> >   
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument
  2021-07-12 10:06 ` [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument Andre Przywara
@ 2021-07-20 18:32   ` Simon Glass
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Glass @ 2021-07-20 18:32 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Jagan Teki, Samuel Holland, Jernej Skrabec, Icenowy Zheng,
	Sunil Mohan Adapa, linux-sunxi, U-Boot Mailing List,
	Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Lokesh Vutla, Philipp Tomsich, Kever Yang, Marek Vasut,
	Simon Goldschmidt, Ley Foon Tan, Patrick Delaunay,
	Patrice Chotard

Hi Andre,

On Mon, 12 Jul 2021 at 04:07, Andre Przywara <andre.przywara@arm.com> wrote:
>
> Platforms can overwrite the weak definition of spl_mmc_boot_mode() to
> determine where to load U-Boot proper from.
> For most of them this is a trivial decision based on Kconfig variables,
> but it might be desirable the probe the actual device to answer this
> question.
>
> Pass the pointer to the mmc struct to that function, so implementations
> can make use of that.
>
> Compile-tested for all users changed.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Stefano Babic <sbabic@denx.de>
> Reviewed-by: Ley Foon Tan <ley.foon.tan@inte.com> (for SoCFPGA)
> Acked-by: Lokesh Vutla <lokeshvutla@ti.com> (for OMAP and K3)
> ---
> (resent to also include forgotten U-Boot list)
>
>  arch/arm/mach-imx/spl.c                | 2 +-
>  arch/arm/mach-k3/am6_init.c            | 2 +-
>  arch/arm/mach-k3/j721e_init.c          | 2 +-
>  arch/arm/mach-omap2/boot-common.c      | 2 +-
>  arch/arm/mach-rockchip/spl.c           | 2 +-
>  arch/arm/mach-socfpga/spl_a10.c        | 2 +-
>  arch/arm/mach-socfpga/spl_gen5.c       | 2 +-
>  arch/arm/mach-stm32mp/spl.c            | 2 +-
>  arch/arm/mach-uniphier/mmc-boot-mode.c | 5 +----
>  common/spl/spl_mmc.c                   | 4 ++--
>  include/spl.h                          | 3 ++-
>  11 files changed, 13 insertions(+), 15 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

But I think this should come from a sysinfo driver.

Regards,
Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-12 10:06 [RESEND PATCH v2 0/3] sunxi: Improve automatic eMMC boot partition support Andre Przywara
2021-07-12 10:06 ` [RESEND PATCH v2 1/3] spl: mmc: extend spl_mmc_boot_mode() to take mmc argument Andre Przywara
2021-07-20 18:32   ` Simon Glass
2021-07-12 10:06 ` [RESEND PATCH v2 2/3] sunxi: eMMC: Improve automatic boot source detection Andre Przywara
2021-07-12 10:57   ` Jaehoon Chung
2021-07-12 11:53     ` Andre Przywara
2021-07-12 10:06 ` [RESEND PATCH v2 3/3] sunxi: defconfig: enable eMMC boot partition support Andre Przywara

ARM Sunxi Platform Development

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-sunxi/0 linux-sunxi/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-sunxi linux-sunxi/ https://lore.kernel.org/linux-sunxi \
		linux-sunxi@lists.linux.dev
	public-inbox-index linux-sunxi

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/dev.linux.lists.linux-sunxi


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git