From: Heiko Schocher <hs@nabladev.com>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Fabio Estevam <festevam@gmail.com>,
Peng Fan <peng.fan@oss.nxp.com>,
Adrian Freihofer <adrian.freihofer@siemens.com>,
Peng Fan <peng.fan@nxp.com>, Heiko Schocher <hs@nabladev.com>,
Alexander Sverdlin <alexander.sverdlin@siemens.com>,
Tom Rini <trini@konsulko.com>,
Walter Schweizer <walter.schweizer@siemens.com>
Subject: [PATCH v2 10/11] siemens: capricorn: rework bootcmd environment variables
Date: Sat, 14 Feb 2026 05:57:02 +0100 [thread overview]
Message-ID: <20260214045703.28051-11-hs@nabladev.com> (raw)
In-Reply-To: <20260214045703.28051-1-hs@nabladev.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
Rework the boot state machine to a significantly simpler and more
robust implementation. The basic idea is to revert to the previous
partition whenever an issue is detected during the boot process.
- Broken SPL
If one of the two SPLs does not boot, the ROM code of the i.MX8 SoC
automatically starts the second SPL from the second boot partition.
For example, if the system's active partition is A but the SPL from
partition A is broken, the ROM code automatically uses the SPL/u-boot
from partition B.
Proceeding with this boot procedure would lead to booting the kernel/
rootfs from partition A, which could potentially successfully boot
the system and allow the user to apply the firmware update with the
broken SPL again. This would lead to a non-bootable system because
the second update would overwrite the last working bootloader.
To prevent such situations, zigzag boots are detected and the system
reverts to the previous partition rather than booting the kernel/rootfs
from the currently active partition. Detecting zigzag boots is done
via the new fallback variable.
To make this state machine even more consistent, the partitionset_active
variable is no longer used to determine the active partition during
boot. Instead, the active partition is always read from the eMMC
partconf registers.
For backward compatibility, the partitionset_active variable is still
updated whenever a partition switch occurs. However, u-boot no longer
relies on this variable, as it could potentially be out of sync with
the actual partition state, leading to situations where the ROM code
of the i.MX8 SoC would be out of sync with u-boot.
- Broken kernel, initramfs or rootfs
If the upgrade_available variable is set, u-boot counts the number of
consecutive boots via the bootcount variable. If the bootcount exceeds
the bootlimit variable, u-boot starts the altbootcmd instead of the
bootcmd. Previously, this logic was bypassed by assigning the regular
bootcmd to altbootcmd. Now, the altbootcmd is used to revert to the
previous partition when the bootlimit is exceeded.
The netdev variable is changed to eth0 by default. This is what the FEC
driver uses on Capricorn boards. For devices with switches and DSA
subsystems in use, the netdev should be set accordingly by additional
logic in the environment or u-boot code. This is not part of this commit.
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Heiko Schocher <hs@nabladev.com>
---
Ignore checkpatch warning:
board/siemens/capricorn/capricorn_default.env:4: warning: line length of 118 exceeds 100 columns
board/siemens/capricorn/capricorn_default.env:37: warning: line length of 130 exceeds 100 columns
board/siemens/capricorn/capricorn_default.env:40: warning: line length of 321 exceeds 100 columns
Changes in v2:
Added Acked-by from Peng, fixed typo in commit message
Added small fixes in Environment from Adrian: It fixes a serious bug which
Adrian detect. It occurs when a broken firmware is applied as a downgrade.
The old bootloader ended up in an endless reboot boot loop. With this fix
also the old bootloader is able to reject the update and recover. Also
slightly reworked bootcmd.
board/siemens/capricorn/capricorn_default.env | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/board/siemens/capricorn/capricorn_default.env b/board/siemens/capricorn/capricorn_default.env
index cf5bd09a4da..64bab7d10bb 100644
--- a/board/siemens/capricorn/capricorn_default.env
+++ b/board/siemens/capricorn/capricorn_default.env
@@ -1,17 +1,17 @@
-altbootcmd=run bootcmd
+terminate_upgrade=bootcount reset; setenv upgrade_available 0
+altbootcmd=run terminate_upgrade; run toggle_partition
baudrate=115200
bootcmd=run flash_self;reset;
bootdelay=3
bootdir=targetdir/rootfs/boot
bootlimit=3
-check_upgrade=if test ${upgrade_available} -eq 1; then echo upgrade_available is set; if test ${bootcount} -gt ${bootlimit}; then setenv upgrade_available 0;echo toggle partition;run toggle_partition;fi;fi;
cntr_addr=0x88000000
cntr_file=os_cntr_signed.bin
console=ttyLP2
dtb_name_default=default
ethprime=eth1
fdt_addr=0x83000000
-flash_self=run mmc_boot
+flash_self=if test -n "$fallback"; then echo "fallback: $fallback"; run terminate_upgrade; run toggle_partition; else run mmc_boot; fi
flash_self_test=setenv testargs test loglevel=3 systemd.unit=test.target; run mmc_boot
hostname=capricorn
initrd_addr=0x83100000
@@ -19,13 +19,13 @@ initrd_high=0xffffffffffffffff
ip_method=none
kernel_name=Image
loadaddr=0x80400000
-mmc_boot=run set_bootargs;run check_upgrade; run set_partition;run set_bootargs_mmc;run mmc_load_bootfiles
+mmc_boot=run set_bootargs; run set_partition;run set_bootargs_mmc;run mmc_load_bootfiles
mmc_boot_fit=ext4load mmc 0:${mmc_part_nr} 0x88000000 boot/fitImage;if test -n ${A};then setenv bootargs ${bootargs} rootfs_sig=${sig_a};fi;if test -n ${B};then setenv bootargs ${bootargs} rootfs_sig=${sig_b};fi;bootm 0x88000000#conf-${dtb_name}.dtb;bootm 0x88000000
mmc_boot_image=ext4load mmc 0:${mmc_part_nr} ${fdt_addr} boot/${dtb_name}.dtb;if test $? -eq 1;then ext4load mmc 0:${mmc_part_nr} ${fdt_addr} boot/${dtb_name_default}.dtb;fi; ext4load mmc 0:${mmc_part_nr} ${loadaddr} boot/${kernel_name}; booti ${loadaddr} - ${fdt_addr}
mmc_load_bootfiles=echo -n Loading from eMMC ...; if test -e mmc 0:${mmc_part_nr} boot/fitImage; then echo fit; setenv fdt_high; setenv initrd_high; run mmc_boot_fit; else echo image; run mmc_boot_image; fi
net_nfs=wdt dev scu-wdt; wdt stop; echo Booting from network ...; run set_bootargs_net; tftpboot ${loadaddr} ${bootdir}/${kernel_name}; printenv bootargs; if test ${kernel_name} = fitImage; then setenv fdt_high; setenv initrd_high; bootm ${loadaddr}#conf-${dtb_name}.dtb; else tftpboot ${fdt_addr} ${serverip}:${bootdir}/${dtb_name}.dtb; if test $? -eq 1; then echo Loading default.dtb!; tftpboot ${fdt_addr} ${serverip}:${bootdir}/${dtb_name_default}.dtb; fi; booti ${loadaddr} - ${fdt_addr}; fi
net_unfs=setenv nfsopts vers=3,udp,rsize=4096,wsize=4096,nolock,port=3049,mountport=3048 rw; run net_nfs
-netdev=lan0
+netdev=eth0
nfsopts=vers=3,udp,rsize=4096,wsize=4096,nolock rw
partitionset_active=A
rootfs_name=/dev/mmcblk0
@@ -34,9 +34,9 @@ script_file=u-boot-commands.img
set_bootargs_mmc=setenv bootargs ${bootargs} root=${mmc_active_vol} ro rootdelay=1 rootwait rootfstype=ext4 ip=${ip_method}
set_bootargs_net=run set_bootargs; if test ${kernel_name} = fitImage; then setenv loadaddr 0x88000000; fi; setenv bootargs ${bootargs} root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off
set_bootargs=setenv bootargs console=${console},${baudrate} target_env=${target_env} ${testargs} ${optargs}
-set_partition=setenv ${partitionset_active} true;if test -n ${A}; then setenv mmc_part_nr 1;fi;if test -n ${B}; then setenv mmc_part_nr 2;fi;setenv mmc_active_vol ${rootfs_name}p${mmc_part_nr}
+set_partition=mmc partconf 0 v_mmc_part_nr; setenv mmc_part_nr $v_mmc_part_nr; setenv mmc_active_vol ${rootfs_name}p$v_mmc_part_nr
tftp_run_script=tftpboot ${kernel_loadaddr} ${serverip}:${script_file};if test $? -eq 0;then source ${kernel_loadaddr};fi
-toggle_partition=setenv ${partitionset_active} true; if test -n ${A}; then setenv partitionset_active B; mmc partconf 0 1 2 0; env delete A; fi; if test -n ${B}; then setenv partitionset_active A; mmc partconf 0 1 1 0; env delete B; fi;saveenv; reset
+toggle_partition=mmc partconf 0 v_mmc_part_nr; if test $v_mmc_part_nr -eq 1; then mmc partconf 0 1 2 0; setenv partitionset_active B; elif test $v_mmc_part_nr -eq 2; then mmc partconf 0 1 1 0; setenv partitionset_active A; else echo error mmc_part_nr $v_mmc_part_nr; fi; saveenv; reset
upgrade_available=0
emmc_dev=0
sd_dev=1
--
2.20.1
next prev parent reply other threads:[~2026-02-14 4:58 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-14 4:56 [PATCH v2 00/11] imx8qxp: siemens: small board updates Heiko Schocher
2026-02-14 4:56 ` [PATCH v2 01/11] arm: dts: capricorn: pinctrl_usdhc1 cleanup Heiko Schocher
2026-02-14 4:56 ` [PATCH v2 02/11] siemens: capricorn: set max-frequency for usdhc1 Heiko Schocher
2026-02-14 4:56 ` [PATCH v2 03/11] arm: dts: capricorn: remove pinctrl_usdhc2 Heiko Schocher
2026-02-14 4:56 ` [PATCH v2 04/11] arm: dts: capricorn: move fec2 config Heiko Schocher
2026-02-14 4:56 ` [PATCH v2 05/11] imx8qxp_capricorn config: add wget command Heiko Schocher
2026-02-16 10:15 ` Marek Vasut
2026-02-16 10:53 ` Heiko Schocher
2026-02-16 11:19 ` Marek Vasut
2026-02-16 11:54 ` Fabio Estevam
2026-02-14 4:56 ` [PATCH v2 06/11] capricorn: config: add bootcounter command Heiko Schocher
2026-02-14 4:56 ` [PATCH v2 07/11] siemens: capricorn: add logic to U-Boot to avoid zig-zag boot Heiko Schocher
2026-02-14 4:57 ` [PATCH v2 08/11] siemens: capricorn: always detect emmc device Heiko Schocher
2026-02-14 4:57 ` [PATCH v2 09/11] siemens: capricorn: fix fallback bootm call for fitImage Heiko Schocher
2026-02-14 4:57 ` Heiko Schocher [this message]
2026-02-14 4:57 ` [PATCH v2 11/11] siemens: capricorn: protect environment Heiko Schocher
2026-02-16 7:33 ` [PATCH v2 00/11] imx8qxp: siemens: small board updates Max Merchel
2026-02-16 7:49 ` Heiko Schocher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260214045703.28051-11-hs@nabladev.com \
--to=hs@nabladev.com \
--cc=adrian.freihofer@siemens.com \
--cc=alexander.sverdlin@siemens.com \
--cc=festevam@gmail.com \
--cc=peng.fan@nxp.com \
--cc=peng.fan@oss.nxp.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=walter.schweizer@siemens.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox