U-Boot persistent environment + Linux-controlled boot state ("EFI variables") #7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal: control boot behavior from inside Linux — choose the next boot target (normal / fastboot / recovery), change the default bootmenu entry and timeout, and persist U-Boot settings — the moral equivalent of EFI variables. Bonus tier: talk to sboot as well.
1. Persistent U-Boot env on a partition
gts6l.env); nothing persists.CONFIG_ENV_IS_IN_BLK(UFS/SCSI) pointing at a dedicated partition — candidates from the existing GPT: a spare likedqmdbg/dpo/pad, or shrink/repurpose deliberately (do NOT touch efs/sec_efs/modemst/persist — modem calibration lives there). Redundant env (CONFIG_SYS_REDUNDAND_ENVIRONMENT) for power-cut safety.env savewrites the partition.2. Linux side: libubootenv
fw_printenv/fw_setenvwith/etc/fw_env.configpointing at the same partition/offset — instant "EFI variables" UX from Linux. Package it in gts6l-alarm with the config.3. Boot-state protocol
bootcmdconsults abootmodevariable before the normal flow:once_fastboot,once_recovery,once_sd, etc. — one-shot semantics (U-Boot clears it after acting) so a bad target can't wedge the boot loop.gts6l-reboot fastboot=fw_setenv bootmode once_fastboot && reboot. Optional systemd integration later.bootdelay/menu timeout become plain env vars — settable from Linux.4. sboot communication (stretch)
sec_debug/restart handlers for the exact addresses/values). Mainline has the plumbing (syscon-reboot-mode,qcom,ponreboot modes) — wiring the right magic values would makereboot downloadwork from Linux and possibly let sboot skip straight to where we want.parampartition flags) — Samsung traditionally keeps boot flags there.Interaction with existing infra: the CRC-verified sdboot flow and bootmenu_16 mirror stay; they just start reading their knobs (default target, timeout, image path) from the persistent env. Also relates to #2 (vol-up navigation) — together they make U-Boot fully drivable both physically and remotely.
2026-08-21 recon: the planned
CONFIG_ENV_IS_IN_BLKroute doesn't exist in our U-BootStorage survey done on-device; the issue's part 1 needs revising before any of it gets built.
Blocker for the UFS-partition plan
Our tree is U-Boot 2025.04-rc5, and
env/Kconfigoffers only:EEPROM, FAT, EXT4, FLASH, MMC, NAND, NVRAM, ONENAND, REMOTE, SPI_FLASH, UBI.There is no
ENV_IS_IN_BLKand noENV_IS_IN_SCSI— so "point the env at a UFS partition" means writing an env backend for SCSI/blk, not setting a Kconfig symbol. That's a real (upstreamable) mini-project, not a config change.Partition survey (UFS), for whenever that route is taken
Empty (all-zero) 512 KiB candidates, both on stock-purpose partitions:
keystore→ sda11, 512 K, all zerouefivarstore→ sdd28, 512 K, all zero (semantically perfect, but it's XBL's own variable store — repurposing it is the riskiest option here)Not empty, i.e. in use — leave alone:
dqmdbg(sda15, 16 M),steady(sda14, 4 M),bota(sda12, 40 M),logfs(sdd19, 8 M),debug(sda8, 10 M),omr(sda29, 20 M). (Confirmed the untouchables are untouched: no proposal goes nearefs/sec_efs/modemst*/persist.)SD layout
mmcblk0p1= 1 GiB vfatGTS6LBOOT,mmcblk0p2= 58.5 GiB ext4gts6l-root, 0 B unpartitioned. So a rawENV_IS_IN_MMCoffset has nowhere clean to live — it would have to squat inside p1's sectors the waygtslogsquats at 64 MiB. Fine for an expendable log, a landmine for persistent state (FAT can hand those sectors to a file).Recommendation:
ENV_IS_IN_FATonmmc 0:1, fileuboot.envI'd lean here for the first cut:
boot-gts6l.imgfrom that exact partition insdboot— proven path, no new storage stack at env-load time.gts6l.env, which is precisely the fallback semantics part 1 wants.fw_env.configaccepts a plain file path, sofw_setenvworks against the mounted file (needs verifying that libubootenv is packaged for ALARM aarch64 — not yet checked, the tablet has no NAT route up this session).Trade-off to accept, stated plainly: the env then lives on the SD card, so no card = default env. Given the whole boot chain already depends on the SD, I think that's the right price for not touching stock partitions. If you'd rather have it independent of the SD, that's option (d) — write the SCSI env backend and put it in
keystore; more work, more upside, and it's the version worth upstreaming.Nothing has been built or flashed for this yet — flagging the decision first since it changes what gets implemented.
2026-08-21: parts 1 and 2 working — environment lives on UFS, editable from Linux
Part 1 — persistent env on a UFS partition: DONE
The issue's premise needed correcting first: U-Boot 2025.04-rc5 has no
ENV_IS_IN_BLKand noENV_IS_IN_SCSI.env/Kconfigoffers only EEPROM/FAT/EXT4/FLASH/MMC/NAND/NVRAM/ONENAND/REMOTE/SPI_FLASH/UBI.ENV_IS_IN_MMCcannot reach a SCSI device and the filesystem backends need a filesystem to already exist, so this needed a new backend rather than a Kconfig line.Written as
env/scsi.c— U-Boot commita2742d0640eonkit/u-boot-gts6l, branchgts6l/uboot:ENV_IS_IN_SCSImust also be added to theENV_IS_DEFAULTexpression inenv/Kconfig, or a board selecting only this backend is still treated as having no persistent env and theenv savesubcommand is silently compiled out (cmd/nvedit.cgates it on!ENV_IS_DEFAULT). That cost a build/flash cycle to find.Configured for
keystore(sda11, 512 KiB, verified all-zero — Android keymaster storage, untouched by a Linux userspace). No partition table change, so the sboot/PIT risk that rules out repartitioning does not apply here. Nothing goes nearefs/sec_efs/modemst*/persist.Verified on hardware:
env save→Saving Environment to SCSI... done0x52f3c3df== computed — a structurally valid environment, 103 variables.bootmenu_defaultwritten to UFS is honoured on the next boot (built-in default is 16, so the persisted value being used proves the read path).Part 2 — Linux-side control: WORKING (via our own tool, not libubootenv yet)
tools/gts6l-env.py—dump/get/set/unsetagainst the raw partition. The format is just CRC32 + NUL-separatedkey=value, so libubootenv isn't required to get the "EFI variables" UX. It refuses to write if the existing env has a bad CRC, and verifies the readback after writing.Demonstrated end-to-end: flipped
bootmenu_default17 → 16 from Linux, read it back CRC-valid off the device.Two practical notes:
ddout, edit,ddback). For on-device use it needs either python packaged, a C rewrite, or the reallibubootenv+/etc/fw_env.config— which is the remaining packaging work for this part.dd ... bs=4096 oflag=direct(abs=1024direct write is rejected withInvalid argument), andENV_SIZEis exactly0x1f000= 126976 bytes = 31 × 4096.Still open
/etc/fw_env.configon the rootfs, in gts6l-alarm.bootmodeone-shot protocol (once_fastboot/once_recovery) and agts6l-reboothelper. This is the high-value remainder — it removes most of the physical button-holding.2026-08-21: part 3 complete, part 4 (recovery/download) WORKING via PMIC PON
Part 4 — reboot to recovery/download from Linux: DONE (recovery verified on hardware)
The restart-reason values come from ABL's
BootChecker(PMIC PON register):recovery = 0x01,bootloader = 0x02,download = 0x15. Mainline already has the whole mechanism —qcom-pon.cwritesPON_SOFT_RB_SPARE, andpm8150.dtsihaspon@800(qcom,pm8998-pon). So this was a DT-only change, no driver.Kernel commit
e681e6386e09adds to&pon:Verified on the device:
reboot(RESTART2, "recovery")from Linux → the device landed in TWRP, routed by sboot reading the PON register before U-Boot loads — no env one-shot, no button combo.recovery=0x01/bootloader=0x02also match the generic Qualcomm values (pmk8350.dtsi), so they're not even Samsung-specific.download=0x15is from the same BootChecker table and high-confidence, but not yet fire-tested (it sends the device to Odin, which needs a person to exit) — will confirm when convenient.The full picture, and how targets are split
gts6l-reboot <target>now routes by mechanism:reboot-modehelper →reboot(RESTART2, ...)), handled by sboot before U-Boot.reboot bootloader/0x02would hit ABL's own fastboot, not ours, so it's not used.bootmodeone-shot (parts already done), handled by U-Boot.So between the two mechanisms, every useful boot target is now selectable from a running Linux with a single command. The button combo and the panel-menu are no longer required for anything.
Status
env/scsi.c, keystore)gts6l-env)bootmodeone-shot protocol +gts6l-reboot(fastboot/console/menu/sd)gts6l-env/gts6l-reboot/reboot-mode+ libubootenv into gts6l-alarm; fire-testdownload.This issue is essentially done — the "EFI variables" goal is met and then some.