]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
airoha: an7581: add uboot chainloader
authorKenneth Kasilag <kenneth@kasilag.me>
Sat, 21 Feb 2026 21:49:46 +0000 (21:49 +0000)
committerChristian Marangi <ansuelsmth@gmail.com>
Thu, 5 Mar 2026 10:17:46 +0000 (11:17 +0100)
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>
package/boot/uboot-airoha/Makefile
package/boot/uboot-airoha/patches/999-airoha-add-gemtek-w1700k.patch [new file with mode: 0644]
target/linux/airoha/image/an7581.mk

index 4fedd972e42c4540e9a5555f5a96f5ec09db3bbe..1230e879da2664c80dfac369f6a725d5150c3b4a 100644 (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
 
diff --git a/package/boot/uboot-airoha/patches/999-airoha-add-gemtek-w1700k.patch b/package/boot/uboot-airoha/patches/999-airoha-add-gemtek-w1700k.patch
new file mode 100644 (file)
index 0000000..c346499
--- /dev/null
@@ -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";
++};
index 497c7acacfd2ef4c0bedd3b639cb5d1042f88155..35bfd09a5053f92fff5a059bbc7d97f16e380c76 100644 (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