airoha: an7581: add uboot chainloader

Due to issues surrounding the implementation of the vendor BMT/BBT
on Airoha, upstream ATF + uboot has switched to UBI flash partitions.

However, some devices shipped on this platform are bootloader locked,
and thus it is impossible to replace ATF + uboot.

During testing for the Gemtek W1700K (#17869), sysupgrades from Linux
(which is unaware of the underlying BMT/BBT) would occasionally write
data into blocks which were remapped by the vendor uboot when it was
read on the following reboot, causing a soft brick.

An acceptable workaround [1],[2] was discussed where an intermediate
uboot would be written by the vendor uboot (which is aware of Airoha
BMT/BBT). This chainloader would then ignore the regions of flash
used by the vendor uboot, and store all relevant data inside of UBI.

UBI would then be used to handle bad block management. As the vendor
ATF + uboot do not read or interact with the UBI region, we would avoid
unwanted remaps from BMT/BBT.

This commit introduces support for building such a chainloader, by
packaging u-boot and DTS into a FIT image; to be flashed like a kernel.

Configuration for the Gemtek W1700K is provided as an example of how the
chainloader is used.

[1] https://github.com/openwrt/openwrt/pull/17869#discussion_r2836066746
[2] https://github.com/openwrt/openwrt/pull/17869#discussion_r2838395671

Signed-off-by: Kenneth Kasilag <kenneth@kasilag.me>
[ move FIP_COMPRESS to Build/Compile, wrap some long lines ]
Link: https://github.com/openwrt/openwrt/pull/22151
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
Kenneth Kasilag 2026-02-21 21:49:46 +00:00 committed by Christian Marangi
parent 97035a5e7f
commit 442e67d31f
No known key found for this signature in database
GPG key ID: AC001D09ADBFEAD7
3 changed files with 363 additions and 4 deletions

View file

@ -46,10 +46,19 @@ define U-Boot/an7583_rfb
BL31_IMAGE:=an7583-bl31.bin
endef
define U-Boot/an7581_gemtek_w1700k
NAME:=Gemtek W1700K (UBI)
UBOOT_CONFIG:=an7581_w1700k
BUILD_DEVICES:=gemtek_w1700k-ubi
BUILD_SUBTARGET:=an7581
UBOOT_IMAGE:=u-boot.bin
endef
UBOOT_TARGETS := \
en7523_rfb \
an7581_rfb \
an7583_rfb
an7583_rfb \
an7581_gemtek_w1700k
UBOOT_CUSTOMIZE_CONFIG := \
--disable TOOLS_KWBIMAGE \
@ -65,9 +74,6 @@ define Build/fip-image-bl2
endef
define Build/fip-image
$(if $(LZMA_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
$(PKG_BUILD_DIR)/u-boot.bin \
$(PKG_BUILD_DIR)/u-boot.bin.lzma)
$(if $(LZMA_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
files/$(BL31_IMAGE) \
$(PKG_BUILD_DIR)/bl31.bin.lzma)
@ -84,6 +90,9 @@ endef
define Build/Compile
$(call Build/Compile/U-Boot)
$(if $(LZMA_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
$(PKG_BUILD_DIR)/u-boot.bin \
$(PKG_BUILD_DIR)/u-boot.bin.lzma)
ifeq ($(UBOOT_IMAGE),u-boot.fip)
$(call Build/fip-image-bl2)
$(call Build/fip-image)
@ -99,6 +108,11 @@ define Build/InstallDev
ifeq ($(UBOOT_IMAGE),u-boot.fip)
$(INSTALL_DATA) $(PKG_BUILD_DIR)/bl2.fip $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl2.fip
$(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.fip $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl31-u-boot.fip
else
$(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.bin$(if $(LZMA_COMPRESS),.lzma) \
$(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.bin$(if $(LZMA_COMPRESS),.lzma)
$(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.dtb \
$(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.dtb
endif
endef

View file

@ -0,0 +1,318 @@
From d6402eadaa56494b382e389d739b9f80d6883788 Mon Sep 17 00:00:00 2001
From: Kenneth Kasilag <kenneth@kasilag.me>
Date: Sat, 21 Feb 2026 21:49:46 +0000
Subject: [PATCH] an7581: add uboot chainloader for w1700k
Due to issues surrounding the implementation of the vendor BMT/BBT
on Airoha, upstream ATF + uboot has switched to UBI flash partitions.
However, some devices shipped on this platform are bootloader locked,
and thus it is impossible to replace ATF + uboot.
During testing for the Gemtek W1700K (#17869), sysupgrades from Linux
(which is unaware of the underlying BMT/BBT) would occasionally write
data into blocks which were remapped by the vendor uboot when it was
read on the following reboot, causing a soft brick.
An acceptable workaround [1],[2] was discussed where an intermediate
uboot would be written by the vendor uboot (which is aware of Airoha
BMT/BBT). This chainloader would then ignore the regions of flash
used by the vendor uboot, and store all relevant data inside of UBI.
UBI would then be used to handle bad block management. As the vendor
ATF + uboot do not read or interact with the UBI region, we would avoid
unwanted remaps from BMT/BBT.
This commit introduces support for building such a chainloader, by
packaging u-boot and DTS into a FIT image; to be flashed like a kernel.
Configuration for the Gemtek W1700K is provided as an example of how the
chainloader is used.
[1] https://github.com/openwrt/openwrt/pull/17869#discussion_r2836066746
[2] https://github.com/openwrt/openwrt/pull/17869#discussion_r2838395671
Signed-off-by: Kenneth Kasilag <kenneth@kasilag.me>
---
configs/an7581_w1700k_defconfig | 107 ++++++++++
defenvs/an7581_w1700k_env | 21 ++
dts/upstream/src/arm64/airoha/an7581-w1700k-ubi.dts | 87 +++++
3 files changed, 215 insertions(+), 0 deletions(-)
create mode 100644 configs/an7581_w1700k_defconfig
create mode 100644 defenvs/an7581_w1700k_env
create mode 100644 dts/upstream/src/arm64/airoha/an7581-w1700k-ubi.dts
--- /dev/null
+++ b/configs/an7581_w1700k_defconfig
@@ -0,0 +1,107 @@
+CONFIG_ARM=y
+CONFIG_ARCH_AIROHA=y
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_MENU_SHOW=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_TARGET_AN7581=y
+CONFIG_TEXT_BASE=0x81E00000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x4000
+CONFIG_ENV_OFFSET=0x7c000
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="airoha/an7581-w1700k-ubi"
+CONFIG_SYS_LOAD_ADDR=0x81800000
+CONFIG_BUILD_TARGET="u-boot.bin"
+# CONFIG_EFI_LOADER is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=30
+CONFIG_DEFAULT_FDT_FILE="an7581-w1700k-ubi"
+CONFIG_SYS_PBSIZE=1049
+CONFIG_SYS_CONSOLE_IS_IN_ENV=y
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="U-Boot> "
+CONFIG_SYS_MAXARGS=8
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_BOOTMENU=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_CMD_BIND=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SF_TEST=y
+CONFIG_CMD_SPI=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_CMD_LOG=y
+CONFIG_OF_UPSTREAM=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+# CONFIG_ENV_IS_IN_MTD is not set
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SYS_RX_ETH_BUFFER=8
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+CONFIG_DMA=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_MTK=y
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_AIROHA_ETH=y
+CONFIG_DM_MDIO=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_MDIO=y
+CONFIG_PHY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_RAM=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_AIROHA_SNFI_SPI=y
+CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBI_RENAME is not set
+CONFIG_CMD_UBIFS=y
+CONFIG_ENV_IS_IN_UBI=y
+CONFIG_ENV_REDUNDANT=y
+CONFIG_ENV_UBI_PART="ubi"
+CONFIG_ENV_UBI_VOLUME="ubootenv"
+CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2"
+CONFIG_ENV_UBI_VID_OFFSET=0
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_MODULE=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+CONFIG_UBI_BLOCK=y
+# CONFIG_UBIFS_SILENCE_MSG is not set
+# CONFIG_UBIFS_SILENCE_DEBUG_DUMP is not set
+CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y
+CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/an7581_w1700k_env"
+CONFIG_SHA512=y
--- /dev/null
+++ b/defenvs/an7581_w1700k_env
@@ -0,0 +1,27 @@
+loadaddr=0x81800000
+initaddr=0x89000000
+ipaddr=192.168.1.1
+serverip=192.168.1.10
+bootfile=openwrt-airoha-an7581-gemtek_w1700k-ubi-initramfs-recovery.itb
+installfile=openwrt-airoha-an7581-gemtek_w1700k-ubi-initramfs-installer.itb
+bootled_pwr=status:red
+bootled_rec=status:blue
+boot_ubi=ubi part ubi && run boot_production ; run boot_recovery
+boot_production=led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off
+boot_recovery=led $bootled_rec on ; run ubi_read_recovery ; bootm $initaddr#$bootconf ; led $bootled_rec off
+boot_tftp=tftpboot $initaddr $bootfile && bootm $initaddr#$bootconf
+boot_installer=tftpboot $initaddr $installfile && bootm $initaddr#$bootconf
+bootconf=config-1
+bootcmd=boot_ubi
+bootdelay=3
+bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60
+bootmenu_default=0
+bootmenu_delay=3
+bootmenu_title= 34m( ( ( mOpenWrt34m ) ) )
+bootmenu_0=Run default boot command.=run boot_production
+bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return
+bootmenu_2=Boot recovery system from flash.=run boot_recovery ; run bootmenu_confirm_return
+bootmenu_3=Boot installer via TFTP.=run boot_installer ; run bootmenu_confirm_return
+bootmenu_4=Reboot.=reset
+ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr
+ubi_read_recovery=ubi check recovery && ubi read $initaddr recovery
--- /dev/null
+++ b/dts/upstream/src/arm64/airoha/an7581-w1700k-ubi.dts
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+/* Bootloader installs ATF here */
+/memreserve/ 0x80000000 0x200000;
+
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "en7581.dtsi"
+
+/ {
+ model = "Gemtek W1700K (UBI)";
+ compatible = "gemtek,w1700k-ubi", "airoha,an7581", "airoha,en7581";
+
+ aliases {
+ serial0 = &uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ linux,usable-memory-range = <0x0 0x80200000 0x0 0x7fe00000>;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x2 0x00000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ key-restart {
+ label = "reset";
+ gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ led_status_green {
+ label = "status:green";
+ gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led_status_blue {
+ label = "status:blue";
+ gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led_status_red {
+ label = "status:red";
+ gpios = <&en7581_pinctrl 29 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+
+ led_status_white {
+ label = "status:white";
+ gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ };
+};
+
+&snfi {
+ status = "okay";
+};
+
+&spi_nand {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ vendor@0 {
+ label = "vendor";
+ reg = <0x00000000 0x00600000>;
+ read-only;
+ };
+
+ chainloader@600000 {
+ label = "chainloader";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+
+ ubi@700000 {
+ label = "ubi";
+ reg = <0x00700000 0x1f700000>;
+ };
+
+ /* reserved for bad block table */
+ reserved_bmt@1fe00000 {
+ label = "reserved_bmt";
+ reg = <0x1fe00000 0x00200000>;
+ read-only;
+ };
+ };
+};
+
+&en7581_pinctrl {
+ gpio-ranges = <&en7581_pinctrl 0 13 47>;
+
+ pcie0_rst_pins: pcie0-rst-pins {
+ conf {
+ pins = "pcie_reset0";
+ drive-open-drain = <1>;
+ };
+ };
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_rst_pins>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&eth {
+ status = "okay";
+};
+
+&gdm1 {
+ status = "okay";
+};

View file

@ -12,6 +12,33 @@ define Build/an7581-bl31-uboot
cat $(STAGING_DIR_IMAGE)/an7581_$1-bl31-u-boot.fip >> $@
endef
define Build/an7581-chainloader
$(INSTALL_DIR) $(KDIR)/chainload-fit-$(notdir $@)
@if [ -f "$(STAGING_DIR_IMAGE)/an7581_$1-u-boot.bin.lzma" ]; then \
KERNEL="$(STAGING_DIR_IMAGE)/an7581_$1-u-boot.bin.lzma"; \
COMP="lzma"; \
else \
KERNEL="$(STAGING_DIR_IMAGE)/an7581_$1-u-boot.bin"; \
COMP="none"; \
fi; \
$(TOPDIR)/scripts/mkits.sh \
-D $(DEVICE_NAME) \
-o $(KDIR)/chainload-fit-$(notdir $@)/u-boot.its \
-k $$KERNEL \
-C $$COMP \
-a 0x80200000 -e 0x80200000 \
-c conf-uboot \
-A arm64 -v u-boot \
-d $(STAGING_DIR_IMAGE)/an7581_$1-u-boot.dtb \
-s 0x82000000
PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) \
$(STAGING_DIR_HOST)/bin/mkimage \
-D "-i $(KDIR)/chainload-fit-$(notdir $@)" \
-f $(KDIR)/chainload-fit-$(notdir $@)/u-boot.its \
$(STAGING_DIR_IMAGE)/an7581_$1-chainload-u-boot.itb
cat $(STAGING_DIR_IMAGE)/an7581_$1-chainload-u-boot.itb >> $@
endef
define Device/FitImageLzma
KERNEL_SUFFIX := -uImage.itb
KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb