Repository navigation
3. Boot Chain
ROM -> TF-A BL2 (fsbl1/fsbl2) -> FIP -> OP-TEE (BL32) -> U-Boot (BL33) -> Linux
TF-A produces the following artifacts:
-
*.stm32: raw BL2, written tofsbl1andfsbl2. -
fip.bin: FIP containing BL32 and BL33, written tofip-activeandfip-factory.
The boot chain provides A/B recovery for both the firmware (the FIP) and the root filesystem without relying on PSA Firmware Update (FWU) metadata. This keeps every component on its upstream release, since the upstream FWU path would require out-of-tree patches to TF-A and U-Boot. For the reasoning behind this choice, refer to the Differences page.
The mechanism has three parts:
- BL2 normally loads the FIP from
fip-active. When that load fails, BL2 walks forward in 128 KB steps across the FIP window and falls back to thefip-factorycopy. The factory copy is normally immutable, so a corrupt or interrupted firmware update still leaves a bootable image. RAUC managesfip-activeas a raw bootloader slot. - U-Boot iterates a boot order of slot A, then slot B, then the factory root filesystem. Each A/B slot carries a retry counter that is decremented before an attempt and reset by
rauc-mark-goodafter a healthy boot. If the factory root filesystem also fails, U-Boot runsstm32prog usb 0, so the board enumerates as a USB DFU target for recovery without any change to the BOOT pins. - Because there is no FWU metadata to report which firmware slot booted, the running U-Boot version is stamped from
git describeat build time and recorded both in the U-Boot environment and in/etc/firmware/expected-bl33-versionon the root filesystem. At boot,report-boot-state.servicecompares the two and writes a verdict to/run/boot-state, where a companion application can detect that the device fell back to factory firmware and offer a repair.
Root filesystem slots mount read-only, with /tmp and /run on tmpfs. For persistent data, overlayfs is used for /etc and /var, with the upper dir on the overlay UBI volume (/mnt/overlay).
The overlay persists across reboots and RAUC installs, and is shared by the A, B, and factory slots. A full DFU reflash wipes it.
A file modified in the overlay always shadows that path in the rootfs, including changes from later updates. Prefer drop-in directories or separate files for runtime-edited config.
U-Boot derives a stable 128-bit systemd machine ID from the fixed prefix deadba7d + 96-bit die UID (OTP words 13-15).
try_boot passes it as systemd.machine_id= on the kernel command line, to ensure the ID is stable across A/B/factory slots and reflashes. If the OTP read fails, the argument is omitted and systemd generates a random ID.
On the read-only rootfs, systemd bind-mounts the ID over /etc/machine-id. machine-id-overlay.service copies it into the /etc overlay upper dir and unmounts it before etc.mount, so it stays visible once the overlay is mounted.
All DTS files live in board/myd-yf135/dts/ and are passed to each firmware component via BR2_*_CUSTOM_DTS_PATH (Linux: external.mk hook, see below). Nothing is patched into upstream source.
| File | Used by |
|---|---|
stm32mp135d-myd-yf135.dts |
Linux, U-Boot |
stm32mp135d-myd-yf135-u-boot.dtsi |
U-Boot additions |
stm32mp135d-myd-yf135-tf-a.dts / .dtsi
|
TF-A BL2 |
stm32mp135d-myd-yf135-tf-a-fw-config.dts |
BL32/BL33 load addresses |
stm32mp135d-myd-yf135-optee.dts |
OP-TEE secure peripherals |
Due to a recent refactoring of the kernel ST device tree sources, a special build step is needed to inject DTS files into the build via external.mk. This may be fixed in a future Buildroot release.
Superprojects can extend all five DTs (including Linux and U-Boot), see Parent device tree.
The upstream qspi_bk1_pins_a definition has wrong IO2 and IO3 pins for this board:
| Signal | Upstream | MYD-YF135 |
|---|---|---|
QSPI_BK1_IO2 |
PD11 (AF9) | PD7 (AF11) |
QSPI_BK1_IO3 |
PH7 (AF13) | PD13 (AF9) |
This is fixed via qspi_bk1_pins_b defined in the board DTS.
Upstream TF-A BL2 reads the SPI-NAND geometry from OTP word 9. SOMs ship with this word blank (0x00000000), so it must be burned once before the first boot from SPI-NAND. The vendor BSP never reads this word (see Differences).
For the Micron MT29F2G01ABAGDWB on this SOM, the value is 0x80424000. Bit breakdown (from plat/st/stm32mp1/stm32mp1_def.h):
| Bits | Field | Value | Meaning |
|---|---|---|---|
| 31 | NAND_PARAM_STORED_IN_OTP | 1 | Parameters from OTP |
| 30-29 | page_size | 00 | 2 KB pages |
| 28-27 | block_size | 00 | 64 pages/block (128 KB) |
| 26-19 | block_nb | 0x08 | 2048 blocks (8 x 256) |
| 18 | width | 0 | 8-bit bus |
| 17-15 | ECC | 100 | On-die ECC |
| 14 | nb_planes | 1 | 2 planes |
Burn it from the U-Boot console:
STM32MP> fuse sense 0 9
STM32MP> fuse prog 0 9 0x80424000
STM32MP> fuse sense 0 9
The first fuse sense should show 00000000 and the last should show 80424000. If the word is not blank, stop. OTP bits are one-way: fuse prog can set bits but never clear them, so continue only if the value already burned is a subset of 0x80424000.
TF-A's spi_nand_read_from_cache() selects the plane from the nb_planes field. If the plane count is wrong, BL2 reads pages out of order. Boot can appear to work until a load spans a plane boundary, and then the data comes back corrupt.