Document how one can use the CONFIG_SPL_AM33XX_MMCSD_MULTIPLE option to implement a scheme for failsafe updating of the whole bootloader on the am335x.
Signed-off-by: Rasmus Villemoes <[email protected]> --- doc/board/ti/am335x_evm.rst | 80 +++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/doc/board/ti/am335x_evm.rst b/doc/board/ti/am335x_evm.rst index b14ba41917e..904881b4146 100644 --- a/doc/board/ti/am335x_evm.rst +++ b/doc/board/ti/am335x_evm.rst @@ -481,3 +481,83 @@ bind with it: misc 0 [ + ] ti-musb-wrapper | |-- usb@47400000 usb 0 [ ] ti-musb-peripheral | | |-- usb@47401000 usb 0 [ ] ti-musb-host | | `-- usb@47401800 + +Failsafe bootloader update +-------------------------- + +As indicated above, the ROM code on the AM335x supports loading SPL +from one of several different locations. It looks at offsets 0, +128KiB, 256KiB and 384KiB (sectors 0, 0x100, 0x200, 0x300) for a +sector containing a valid "TOC structure" (see the reference manual +for details). + +This can be used to implement a scheme for updating SPL which is +robust against power failure or other interruptions: Suppose we store +copies of SPL (wrapped in the "MLO" image, which is what includes that +TOC structure) at offsets 128KiB and 256KiB, and let us refer to those +two locations as slot 1 and slot 2. + +The whole procedure maintains the invariant that at any time, at +least one of the slots contains a complete and valid MLO image. In +order to update SPL: + +(1) Determine a slot X containing a valid image (by having a proper + TOC structure in the first sector). Designate the other + slot Y. Since the TOC is always the same 512 bytes (see section + 26.1.11 in the reference manual), checking for a valid image can + be done using something like + +.. code-block:: bash + + if cmp -s -n 512 MLO /path/to/SPL-1 ; then + X=1 + Y=2 + elif cmp -s -n 512 MLO /path/to/SPL-2 ; then + X=2 + Y=1 + else + # invariant broken, fatal error, refuse update... + fi + +(2) Ensure Y will be deemed invalid by the ROM code by writing all + zeroes to the first sector of Y, for example using + +.. code-block:: bash + + dd if=/dev/zero of=/path/to/SPL-Y bs=512 count=1 conv=fsync + +(3) Write everything but the first sector of the MLO image to slot Y: + +.. code-block:: bash + + dd if=MLO of=/path/to/SPL-Y bs=512 skip=1 seek=1 conv=fsync + +(4) Write the TOC structure to slot Y: + +.. code-block:: bash + + dd if=MLO of=/path/to/SPL-Y bs=512 count=1 conv=fsync + +(5) Repeat steps (2)--(4) for slot X. + +Now, this procedure only accounts for safely updating SPL. If U-Boot +proper is only stored in a single location, there is no way to update +that which is safe against powercut during the update. However, by +selecting the configuration option CONFIG_SPL_AM33XX_MMCSD_MULTIPLE, +you can tell SPL to load U-Boot proper from a location which depends on +where SPL itself was loaded from. Hence, one can for example put +copies of u-boot.img at offsets 512KiB and 1536KiB, and set + +:: + + CONFIG_SPL_AM33XX_MMCSD_MULTIPLE=y + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_128K=0x400 + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR_256K=0xc00 + +and amend the step (3) above by + + Write U-Boot proper to the location corresponding to slot Y: + +.. code-block:: bash + + dd if=u-boot.img of=/path/to/U-BOOT-Y bs=512 conv=fsync -- 2.52.0

