gemini: override IB-4220-B partitions for firmware

To optimize the flash usage and to make firmware upgrades
simpler, catenate the three firmware partitions "Kern",
"Ramdisk" and "Application" into one, and use all of this
for the combined MTD-splitted kernel+rootfs.

This works fine as long as the kernel is placed in the
beginning of this firmware partition and we leave the
RedBoot partition as is, so the boot loader still can load
the kernel from the first two RedBoot partitions.

Using the RedBoot partitions "as is" can be considered
harmful, because when you flash to a RedBoot partition the
file size is used for downsizing of the partition and make
firmware upgrades fail if they are larger than the RedBoot
partition size after flashing, despite there is actually
flash there. So overriding with fixed partitions is just
generally a good idea.

Link: https://github.com/openwrt/openwrt/pull/21820
Signed-off-by: Linus Walleij <linusw@kernel.org>
This commit is contained in:
Linus Walleij 2026-01-26 08:21:29 +01:00
parent 5ac8f14ccb
commit 387752dc76
4 changed files with 187 additions and 24 deletions

View file

@ -56,8 +56,8 @@ gemini_check_redboot_parts() {
fi
}
gemini_do_platform_upgrade() {
echo "Extract the three firmware parts"
gemini_do_redboot_upgrade() {
echo "Extract the three firmware parts from tarfile"
echo 3 > /proc/sys/vm/drop_caches
echo "COMMENCING UPGRADE. BE PATIENT, THIS IS NOT FAST!"
KFSZ=$(tar xfz "$1" zImage -O | wc -c)
@ -74,16 +74,45 @@ gemini_do_platform_upgrade() {
[ $? -ne 0 ] && exit 1
}
# This converts the old RedBoot partitioning to the new shared
# "firmware" partition.
gemini_do_flat_redboot_upgrade() {
ESZ=131072
KSZ=$(($ESZ * $2))
RSZ=$(($ESZ * $3))
KRSZ=$(($KSZ + $RSZ))
ASZ=$(($ESZ * $4))
echo "Partition sizes: Kern ${KSZ}, Ramdisk ${RSZ}, Application ${ASZ}"
echo "Extract Kern from flat image ${1}"
echo "Write Kern from flat image ${1}"
dd if="$1" bs=1 count=${KSZ} | mtd write - Kern
echo "Write rd.gz from flat image ${1}"
dd if="$1" bs=1 skip=${KSZ} count=${RSZ} | mtd write - Ramdisk
echo "Write hddapp.tgz from flat image ${1}"
dd if="$1" bs=1 skip=${KRSZ} count=${ASZ} | mtd write - Application
}
# Check if we have the new partition scheme, else do it the old
# way.
gemini_do_combined_upgrade() {
NAME=`cat ${MTDSYSFS}/mtd1/name`
if test "x${NAME}" == "xfirmware" ; then
PART_NAME=firmware
default_do_upgrade "$1"
else
gemini_check_redboot_parts "$1" $2 $3 $4
gemini_do_flat_redboot_upgrade "$1" $2 $3 $4
fi
}
platform_check_image() {
local board=$(board_name)
case "$board" in
dlink,dir-685)
return 0
;;
raidsonic,ib-4220-b|\
dlink,dir-685|\
itian,sq201|\
storlink,gemini324)
storlink,gemini324|\
raidsonic,ib-4220-b)
return 0
;;
esac
@ -100,14 +129,13 @@ platform_do_upgrade() {
PART_NAME=firmware
default_do_upgrade "$1"
;;
raidsonic,ib-4220-b)
gemini_do_combined_upgrade "$1" 24 48 48
;;
itian,sq201|\
storlink,gemini324)
gemini_check_redboot_parts "$1" 16 48 48
gemini_do_platform_upgrade "$1"
;;
raidsonic,ib-4220-b)
gemini_check_redboot_parts "$1" 24 48 48
gemini_do_platform_upgrade "$1"
gemini_do_redboot_upgrade "$1"
;;
esac
}

View file

@ -277,6 +277,7 @@ CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_GEMINI=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_OPENWRT_PROLOG=y
CONFIG_MTD_SPLIT_WRGG_FW=y
CONFIG_NAMESPACES=y
CONFIG_NEED_DMA_MAP_STATE=y

View file

@ -89,14 +89,23 @@ endef
# 0x000000320000-0x000000920000 : "Ramdisk" - second part of the kernel and
# some padding goes here
# 0x000000920000-0x000000f20000 : "Application" - rootfs goes here
define CreateStorlinkProlog
# 512 bytes copy routine
dd if=$(KDIR)/copy-kernel-$(2).bin of=$(1)
# Add OpenWrt prolog header (used by partition splitter)
echo "OPENWRT-PROLOG-512" >> $(1)
stat -c %s ${IMAGE_KERNEL} >> $(1)
$(call Image/pad-to,$(1),512)
endef
define CreateStorlinkTarfile
mkdir -p $@.tmp
# "Application" partition is the rootfs
mv $@ $@.tmp/hddapp.tgz
# 512 bytes copy routine
dd if=$(KDIR)/copy-kernel-$(2).bin of=$@.tmp/zImage
$(call Image/pad-to,$@.tmp/zImage,512)
$(STAGING_DIR_HOST)/bin/padjffs2 $(IMAGE_ROOTFS) -c 128 >>$@.tmp/hddapp.tgz
$(call CreateStorlinkProlog,$@.tmp/zImage,$(2))
# Copy first part of the kernel into zImage
dd if=$(IMAGE_KERNEL) of=$@.tmp/zImage bs=1 seek=512 count=$(3)
$(call Image/pad-to,$@.tmp/zImage,128k)
@ -114,14 +123,60 @@ define CreateStorlinkTarfile
exit 0
endef
define CreateStorlinkFactoryfile
mkdir -p $@.tmp
$(call CreateStorlinkProlog,$@.tmp/zImage,$(2))
# Copy first part of the kernel into zImage
dd if=$(IMAGE_KERNEL) of=$@.tmp/zImage bs=1 seek=512 count=$(3)
$(call Image/pad-to,$@.tmp/zImage,128k)
# Put the rest of the kernel into the "ramdisk"
dd if=$(IMAGE_KERNEL) of=$@-ramdisk bs=1 skip=$(3) conv=sync
$(call Image/pad-to,$@-ramdisk,128k)
# Append the root filesystem right after this
dd if=$(IMAGE_ROOTFS) >> $@-ramdisk
$(STAGING_DIR_HOST)/bin/padjffs2 $(IMAGE_ROOTFS) -c 128 >> $@-ramdisk
# Now rd.gz is too big so split off rd.gz and the tail into "hddapp.gz"
dd if=$@-ramdisk of=$@.tmp/rd.gz bs=1 count=6144k conv=sync
dd if=$@-ramdisk of=$@.tmp/hddapp.tgz bs=1 skip=6144k count=6144k conv=sync
rm -f $@-ramdisk
# Taglabel
cp ./ImageInfo-$(1) $@.tmp/ImageInfo
sed -i -e "s/DATESTR/`date +%Y%m%d $(if $(SOURCE_DATE_EPOCH),--date "@$(SOURCE_DATE_EPOCH)")`/g" $@.tmp/ImageInfo
(cd $@.tmp; tar --sort=name --owner=0 --group=0 --numeric-owner -czf $@ * \
$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)"))
rm -rf $@.tmp
exit 0
endef
define CreateStorlinkSysupgradefile
$(call CreateStorlinkProlog,$@,$(2))
# Catenate the kernel
dd if=$(IMAGE_KERNEL) >> $@
$(call Image/pad-to,$@,128k)
# Append the root filesystem right after this
dd if=$(IMAGE_ROOTFS) >> $@
$(STAGING_DIR_HOST)/bin/padjffs2 $(IMAGE_ROOTFS) -c 128 >> $@
endef
# 2048k "Kern" partition
define Build/storlink-default-image
define Build/storlink-2048k-default-image
$(call CreateStorlinkTarfile,$(1),2048k,2096640)
endef
define Build/storlink-2048k-sysupgrade-image
$(call CreateStorlinkSysupgradefile,$(1),2048k)
endef
# 3072k "Kern" partition
define Build/raidsonic-ib-4220-b-image
$(call CreateStorlinkTarfile,$(1),3072k,3145216)
define Build/storlink-3072k-factory-image
$(call CreateStorlinkFactoryfile,$(1),3072k,3145216)
endef
define Build/storlink-3072k-sysupgrade-image
$(call CreateStorlinkSysupgradefile,$(1),3072k)
endef
# WBD-111 and WBD-222:
@ -203,9 +258,9 @@ define Device/storlink-reference
# Ramdisk 6144k remaining zImage
# Application 6144k
IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 128k | \
storlink-default-image $(1)
storlink-2048k-default-image $(1)
IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to 128k | \
storlink-default-image $(1) | append-metadata
storlink-2048k-default-image $(1) | append-metadata
DEVICE_PACKAGES := $(GEMINI_NAS_PACKAGES)
endef
@ -227,10 +282,9 @@ define Device/raidsonic_ib-4220-b
# Kern 3072k - 512 | = 3145216
# Ramdisk 6144k | = 9216k
# Application 6144k | = 15360k
IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 128k | \
raidsonic-ib-4220-b-image $(1)
IMAGE/sysupgrade.bin := append-rootfs | pad-rootfs | pad-to 128k | \
raidsonic-ib-4220-b-image $(1) | append-metadata
IMAGE/factory.bin := storlink-3072k-factory-image $(1)
IMAGE/sysupgrade.bin := storlink-3072k-sysupgrade-image $(1) |\
append-metadata
endef
TARGET_DEVICES += raidsonic_ib-4220-b

View file

@ -0,0 +1,80 @@
From 1b5c6be7b6dc6c096e1fd55ce10809d350e3afab Mon Sep 17 00:00:00 2001
From: Linus Walleij <linusw@kernel.org>
Date: Mon, 26 Jan 2026 08:09:04 +0100
Subject: [PATCH] gemini: augment DTS with botched partitions
We override the RedBoot FIS partition table with a custom one
using fixed-partitions.
Mostly this is a 1-to-1 copy, but the three partitions called
"Kern", "Ramdisk" and "Application" are combined into one
called "firmware" which is optimal for OpenWrt.
The RedBoot bootloader still sees the three partitions and will
load the first two into memory to boot the system, which
is fine: the kernel will still be there.
To avoid confusing the MTD partition splitter we also need to
remove any command line root partition arguments.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
arch/arm/boot/dts/gemini/gemini-nas4220b.dts | 39 ++++++++++++++++++--
1 file changed, 35 insertions(+), 4 deletions(-)
--- a/arch/arm/boot/dts/gemini/gemini-nas4220b.dts
+++ b/arch/arm/boot/dts/gemini/gemini-nas4220b.dts
@@ -20,7 +20,7 @@
};
chosen {
- bootargs = "console=ttyS0,19200n8 root=/dev/mtdblock3 rw rootfstype=squashfs,jffs2 rootwait";
+ bootargs = "console=ttyS0,19200n8";
stdout-path = &uart0;
};
@@ -82,10 +82,41 @@
/* 16MB of flash */
reg = <0x30000000 0x01000000>;
+ /*
+ * Override the RedBoot partition table with fixed partitions
+ * in order to create a coherent "firmware" partition so that
+ * we can have optimal flash usage with OpenWrt in a big
+ * MTD-splitted "firmware" partition.
+ */
partitions {
- compatible = "redboot-fis";
- /* Eraseblock at 0xfe0000 */
- fis-index-block = <0x7f>;
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "BOOT";
+ reg = <0x00000000 0x00020000>;
+ read-only;
+ };
+ partition@1 {
+ compatible = "openwrt,executable-prolog";
+ label = "firmware";
+ reg = <0x00020000 0x00f00000>;
+ };
+ partition@2 {
+ label = "VCTL";
+ reg = <0x00f20000 0x00020000>;
+ read-only;
+ };
+ partition@3 {
+ label = "CurConf";
+ reg = <0x00f40000 0x000a0000>;
+ read-only;
+ };
+ partition@4 {
+ label = "FIS directory";
+ reg = <0x00fe0000 0x00020000>;
+ read-only;
+ };
};
};