All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] am335x: add support for loading u-boot from multiple offsets
@ 2026-01-22 13:17 Rasmus Villemoes
  2026-01-22 13:49 ` Rasmus Villemoes
  2026-01-22 16:21 ` Tom Rini
  0 siblings, 2 replies; 3+ messages in thread
From: Rasmus Villemoes @ 2026-01-22 13:17 UTC (permalink / raw)
  To: u-boot; +Cc: Tom Rini, Rasmus Villemoes

The am335x knows nothing about eMMC boot partitions, so in order to
implement an update procedure of the bootloader which is robust
against power failure or other interruptions, one must make use of the
fact that ROM code on the am335x looks for a valid first stage
bootloader at several different offsets. Updating that can then be
implemented by (assume we put MLO at offsets 128K and 256K):

(1) At least one of the two slots must contain a valid header, since
we successfully booted. Pick the other one.

(2) Overwrite the first sector of the slot chosen in step (a) with all
zeroes.

(3) Write everything but the first sector to the chosen slot.

(4) Write the first sector (containing the magic signature that the
boot ROM uses to identify a valid image) to the chosen slot.

(5) Repeat steps (2)-(4) for the other slot.

It's not possible to simply write the whole MLO in one go, especially
not when updating the 128K slot, because an interruption after the
first sector is written would make the ROM code believe the image is
valid.

But this only caters for SPL itself; regardless of where SPL was
loaded from, it would go on to load U-Boot proper from
SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR. So in order to update the whole
bootloader, we need to teach SPL to use a
different offset for U-Boot proper depending on where SPL itself was
loaded from (*). With that, the update procedure is just amended by a step

(3a) Write U-Boot proper to the offset corresponding to the SPL slot
being updated.

We can know (*) because the ROM code sets a new bit in a certain
"trace vector" before each successive attempt.

Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
---
 arch/arm/mach-omap2/Kconfig       | 37 +++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/boot-common.c | 31 ++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index c07dd68e6ce..1e989ac48ac 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -156,6 +156,43 @@ config SYS_DEFAULT_LPDDR2_TIMINGS
 
 endchoice
 
+config SPL_AM33XX_MMCSD_MULTIPLE
+	bool "Support multiple locations of next boot phase"
+	depends on AM33XX
+	depends on SPL_SYS_MMCSD_RAW_MODE
+	depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+	help
+	  The boot ROM on the am33xx looks for the first stage
+	  bootloader at several hard-coded offsets in the mmc device
+	  (0, 128K, 256K, 384K) and uses the first location which has
+	  a valid header. This can be used to implement failsafe
+	  update of that first stage (SPL). But in order for the
+	  update of the whole bootloader to be failsafe, SPL must load
+	  U-Boot proper from a location dependent on where SPL itself
+	  was loaded from. This option allows you to specify four
+	  different offsets corresponding to the different places
+	  where SPL could have been loaded from.
+
+if SPL_AM33XX_MMCSD_MULTIPLE
+
+config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_0K
+	hex "Address on the MMC to load U-Boot from when SPL was loaded from offset 0K"
+	default SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
+
+config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_128K
+	hex "Address on the MMC to load U-Boot from when SPL was loaded from offset 128K"
+	default SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
+
+config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_256K
+	hex "Address on the MMC to load U-Boot from when SPL was loaded from offset 256K"
+	default SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
+
+config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_384K
+	hex "Address on the MMC to load U-Boot from when SPL was loaded from offset 384K"
+	default SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
+
+endif
+
 source "arch/arm/mach-omap2/omap3/Kconfig"
 
 source "arch/arm/mach-omap2/omap5/Kconfig"
diff --git a/arch/arm/mach-omap2/boot-common.c b/arch/arm/mach-omap2/boot-common.c
index 95b44c8b1e5..88fa59feaf1 100644
--- a/arch/arm/mach-omap2/boot-common.c
+++ b/arch/arm/mach-omap2/boot-common.c
@@ -318,3 +318,34 @@ static void tee_image_process(ulong tee_image, size_t tee_size)
 }
 U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_TEE, tee_image_process);
 #endif
+
+#ifdef CONFIG_SPL_AM33XX_MMCSD_MULTIPLE
+
+#define AM335X_TRACE_VECTOR2 0x4030CE44
+
+unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect)
+{
+	u32 bits = *(u32 *)AM335X_TRACE_VECTOR2;
+
+	bits &= 0xf000;
+
+	/*
+	 * The ROM code sets the "trial bit 3", bit 15, first, when
+	 * attempting offset 0, then "trial bit 2", bit 14, when
+	 * attempting offset 128K, and so on. If the tracing vector
+	 * has completely unexpected contents, fall back to the
+	 * raw_sect we were given.
+	 */
+	switch (bits) {
+	case 0x8000: raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_0K;   break;
+	case 0xc000: raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_128K; break;
+	case 0xe000: raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_256K; break;
+	case 0xf000: raw_sect = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_384K; break;
+	default:
+		printf("Warning: Unexpected trial bits 0x%04x in trace vector 2, falling back to 0x%lx\n",
+		       bits, raw_sect);
+	}
+
+	return raw_sect;
+}
+#endif
-- 
2.52.0


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

* Re: [PATCH] am335x: add support for loading u-boot from multiple offsets
  2026-01-22 13:17 [PATCH] am335x: add support for loading u-boot from multiple offsets Rasmus Villemoes
@ 2026-01-22 13:49 ` Rasmus Villemoes
  2026-01-22 16:21 ` Tom Rini
  1 sibling, 0 replies; 3+ messages in thread
From: Rasmus Villemoes @ 2026-01-22 13:49 UTC (permalink / raw)
  To: u-boot; +Cc: Tom Rini

On Thu, Jan 22 2026, Rasmus Villemoes <ravi@prevas.dk> wrote:

> The am335x knows nothing about eMMC boot partitions, so in order to
> implement an update procedure of the bootloader which is robust
> against power failure or other interruptions, one must make use of the
> fact that ROM code on the am335x looks for a valid first stage
> bootloader at several different offsets.

Additional info I had written under the --- separator, but for some
reason didn't make it into the mail:

I finally got around to follow up on https://lore.kernel.org/u-boot/871prgzuui.fsf@prevas.dk/ .

I'm not at all sure about the naming of the config option(s), they can of course be changed.

The order the trial bits gets set is somewhat odd, but is clearly what
happens, and somebody else trying to reverse engineer the ROM code has
observed the same thing: See the TracingVectors.ods in
https://github.com/sjgallagher2/am335xbootrom .

Rasmus

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

* Re: [PATCH] am335x: add support for loading u-boot from multiple offsets
  2026-01-22 13:17 [PATCH] am335x: add support for loading u-boot from multiple offsets Rasmus Villemoes
  2026-01-22 13:49 ` Rasmus Villemoes
@ 2026-01-22 16:21 ` Tom Rini
  1 sibling, 0 replies; 3+ messages in thread
From: Tom Rini @ 2026-01-22 16:21 UTC (permalink / raw)
  To: Rasmus Villemoes; +Cc: u-boot

[-- Attachment #1: Type: text/plain, Size: 2167 bytes --]

On Thu, Jan 22, 2026 at 02:17:28PM +0100, Rasmus Villemoes wrote:

> The am335x knows nothing about eMMC boot partitions, so in order to
> implement an update procedure of the bootloader which is robust
> against power failure or other interruptions, one must make use of the
> fact that ROM code on the am335x looks for a valid first stage
> bootloader at several different offsets. Updating that can then be
> implemented by (assume we put MLO at offsets 128K and 256K):
> 
> (1) At least one of the two slots must contain a valid header, since
> we successfully booted. Pick the other one.
> 
> (2) Overwrite the first sector of the slot chosen in step (a) with all
> zeroes.
> 
> (3) Write everything but the first sector to the chosen slot.
> 
> (4) Write the first sector (containing the magic signature that the
> boot ROM uses to identify a valid image) to the chosen slot.
> 
> (5) Repeat steps (2)-(4) for the other slot.
> 
> It's not possible to simply write the whole MLO in one go, especially
> not when updating the 128K slot, because an interruption after the
> first sector is written would make the ROM code believe the image is
> valid.
> 
> But this only caters for SPL itself; regardless of where SPL was
> loaded from, it would go on to load U-Boot proper from
> SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR. So in order to update the whole
> bootloader, we need to teach SPL to use a
> different offset for U-Boot proper depending on where SPL itself was
> loaded from (*). With that, the update procedure is just amended by a step
> 
> (3a) Write U-Boot proper to the offset corresponding to the SPL slot
> being updated.
> 
> We can know (*) because the ROM code sets a new bit in a certain
> "trace vector" before each successive attempt.
> 
> Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
> ---
>  arch/arm/mach-omap2/Kconfig       | 37 +++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/boot-common.c | 31 ++++++++++++++++++++++++++
>  2 files changed, 68 insertions(+)

Very interesting. I think the only thing really missing is that this
needs to be covered under doc/ as well.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

end of thread, other threads:[~2026-01-22 16:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-22 13:17 [PATCH] am335x: add support for loading u-boot from multiple offsets Rasmus Villemoes
2026-01-22 13:49 ` Rasmus Villemoes
2026-01-22 16:21 ` Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.