[openwrt/openwrt] bcm4908: support "rootfs_data" on U-Boot devices

LEDE Commits lede-commits at lists.infradead.org
Fri Mar 4 07:15:15 PST 2022


rmilecki pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/93259e8ca261c7965618fe11c2d385638da5cfa6

commit 93259e8ca261c7965618fe11c2d385638da5cfa6
Author: Rafał Miłecki <rafal at milecki.pl>
AuthorDate: Fri Mar 4 16:03:26 2022 +0100

    bcm4908: support "rootfs_data" on U-Boot devices
    
    1. Create "rootfs_data" dynamicaly
    
    U-Boot firmware images can contain only 2 UBI volumes: bootfs (container
    with U-Boot + kernel + DTBs) and rootfs (e.g. squashfs). There is no way
    to include "rootfs_data" UBI volume or make firmware file tell U-Boot to
    create one.
    
    For that reason "rootfs_data" needs to be created dynamically. Use
    preinit script to handle that. Fire it right before "mount_root" one.
    
    2. Relate "rootfs_data" to flashed firmware
    
    As already explained flashing new firmware with U-Boot will do nothing
    to the "rootfs_data". It could result in new firmware reusing old
    "rootfs_data" overlay UBI volume and its file. Users expect a clean
    state after flashing firmware (even if flashing the same one).
    
    Solve that by reading flash counter of running firmware and storing it
    in "rootfs_data" UBI volume. Every mismatch will result in wiping old
    data.
    
    Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
---
 .../bcm4908/base-files/lib/functions/bcm4908.sh    | 73 ++++++++++++++++++++++
 .../base-files/lib/preinit/75_rootfs_prepare       | 35 +++++++++++
 .../bcm4908/base-files/lib/upgrade/platform.sh     | 27 ++++----
 3 files changed, 122 insertions(+), 13 deletions(-)

diff --git a/target/linux/bcm4908/base-files/lib/functions/bcm4908.sh b/target/linux/bcm4908/base-files/lib/functions/bcm4908.sh
new file mode 100644
index 0000000000..aea31e794b
--- /dev/null
+++ b/target/linux/bcm4908/base-files/lib/functions/bcm4908.sh
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
+
+FS_STATE_READY=2
+
+# $(1): file to read from
+# $(2): offset in bytes
+get_hex_u32_le() {
+	dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -e '1/4 "%02x"'
+}
+
+# Setup /tmp/env.config to provide "metadata" UBI volume access
+#
+# It can be used with "fw_printenv -c /tmp/env.config"
+bcm4908_pkgtb_setup_env_config() {
+	local size=$((0x$(get_hex_u32_le /dev/ubi0_1 4)))
+
+	dd if=/dev/ubi0_1 of=/tmp/env.head count=8 iflag=count_bytes
+	dd if=/dev/ubi0_1 of=/tmp/env.body skip=8 iflag=skip_bytes
+	printf "%s\t0x%x\t0x%x\t0x%x" "/tmp/env.body" 0x0 $size $size > /tmp/env.config
+}
+
+bcm4908_committed_image_seq() {
+	bcm4908_pkgtb_setup_env_config
+
+	commited="$(fw_printenv -n -c /tmp/env.config COMMITTED)"
+	[ -n "$commited" ] && {
+		seq=$(fw_printenv -n -c /tmp/env.config SEQ | cut -d ',' -f $commited)
+		[ -n "$seq" ] && {
+			echo $seq
+			return
+		}
+	}
+
+	echo "Failed to read COMMITED and SEQ from metadata1" >&2
+}
+
+# Make sure "rootfs_data" UBI volume matches currently flashed image
+#
+# On mismatch "rootfs_data" will be wiped and assigned
+#
+# $1: UBI volume of "rootfs_data" (e.g. ubi0_123)
+bcm4908_verify_rootfs_data() {
+	local ubivol="$1"
+	local dir=/tmp/rootfs_data
+	local seq="$(bcm4908_committed_image_seq)"
+
+	[ -z "$seq" ] && return
+
+	mkdir $dir
+	if ! mount -t ubifs /dev/$ubivol $dir; then
+		echo "Failed to mount $ubivol UBI volume" >&2
+		rmdir $dir
+		return
+	fi
+
+	# Wipe rootfs_data if it doesn't belong to us
+	[ "$(readlink $dir/.openwrt-image-seq)" != "$seq" ] && {
+		echo "Removing \"rootfs_data\" content"
+		rm -rf $dir/..?* $dir/.[!.]* $dir/*
+	}
+
+	# If rootfs_data is clean (or was just wiped) claim it
+	[ -z "$(ls -A $dir)" ] && {
+		echo "Assigning \"rootfs_data\" to the current firmware"
+		# Claim this "rootfs_data"
+		ln -s $seq $dir/.openwrt-image-seq
+		# Mark it ready to avoid "mount_root" wiping it again
+		ln -s $FS_STATE_READY $dir/.fs_state
+	}
+
+	umount $dir
+	rmdir $dir
+}
diff --git a/target/linux/bcm4908/base-files/lib/preinit/75_rootfs_prepare b/target/linux/bcm4908/base-files/lib/preinit/75_rootfs_prepare
new file mode 100644
index 0000000000..07fa21814e
--- /dev/null
+++ b/target/linux/bcm4908/base-files/lib/preinit/75_rootfs_prepare
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
+
+. /lib/functions/bcm4908.sh
+
+rootfs_create() {
+	local blocks
+
+	blocks=$(cat /sys/class/ubi/ubi0/avail_eraseblocks)
+	[ -z "$blocks" ] && {
+		echo "Failed to read amount of available erase blocks" >&2
+		return
+	}
+
+	# Use 80% of remaining flash size for "rootfs_data"
+	ubimkvol /dev/ubi0 -n 20 -N rootfs_data --lebs $((blocks / 100 * 80))
+	mknod -m 0600 /dev/ubi0_20 c 252 21
+
+	bcm4908_verify_rootfs_data ubi0_20
+}
+
+rootfs_prepare() {
+	# Do nothing on CFE devices
+	ubinfo /dev/ubi0 -N metadata1 > /dev/null 2>&1 || exit 0
+
+	# Find UBI volume device (e.g. ubi0_123)
+	local ubivol="$(grep rootfs_data /sys/devices/virtual/ubi/ubi*/ubi*/name | sed -n 's/.*\(ubi\d*_\d*\).*/\1/p')"
+	if [ -n "$ubivol" ]; then
+		bcm4908_verify_rootfs_data $ubivol
+	else
+		echo "Creating \"rootfs_data\" UBI volume"
+		rootfs_create
+	fi
+}
+
+boot_hook_add preinit_main rootfs_prepare
diff --git a/target/linux/bcm4908/base-files/lib/upgrade/platform.sh b/target/linux/bcm4908/base-files/lib/upgrade/platform.sh
index 1b94801fb0..0974331801 100644
--- a/target/linux/bcm4908/base-files/lib/upgrade/platform.sh
+++ b/target/linux/bcm4908/base-files/lib/upgrade/platform.sh
@@ -1,6 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
 
-RAMFS_COPY_BIN="bcm4908img expr grep fdtget fw_printenv fw_setenv tr"
+. /lib/functions/bcm4908.sh
+
+RAMFS_COPY_BIN="bcm4908img expr grep ln fdtget fw_printenv fw_setenv readlink tr"
 
 PART_NAME=firmware
 
@@ -134,17 +136,7 @@ platform_pkgtb_get_image() {
 	}
 }
 
-platform_pkgtb_setup_env_config() {
-	local size=$((0x$(get_hex_u32_le /dev/ubi0_1 4)))
-
-	dd if=/dev/ubi0_1 of=/tmp/env.head count=8 iflag=count_bytes
-	dd if=/dev/ubi0_1 of=/tmp/env.body skip=8 iflag=skip_bytes
-	printf "%s\t0x%x\t0x%x\t0x%x" "/tmp/env.body" 0x0 $size $size > /tmp/env.config
-}
-
 platform_pkgtb_get_upgrade_index() {
-	platform_pkgtb_setup_env_config
-
 	case "$(fw_printenv -l /tmp -n -c /tmp/env.config COMMITTED)" in
 		1) echo 2;;
 		2) echo 1;;
@@ -160,8 +152,6 @@ platform_pkgtb_commit() {
 	local seq2
 	local tmp
 
-	platform_pkgtb_setup_env_config
-
 	# Read current values
 	for valid in $(fw_printenv -l /tmp -n -c /tmp/env.config VALID | tr ',' ' '); do
 		case "$valid" in
@@ -272,11 +262,20 @@ platform_check_image() {
 # upgrade
 #
 
+platform_pkgtb_clean_rootfs_data() {
+	local ubidev=$(nand_find_ubi $CI_UBIPART)
+	local ubivol="$(nand_find_volume $ubidev rootfs_data)"
+
+	bcm4908_verify_rootfs_data "$ubivol"
+}
+
 platform_do_upgrade_pkgtb() {
 	local cmd="${2:-cat}"
 	local size
 	local idx bootfs_id rootfs_id
 
+	bcm4908_pkgtb_setup_env_config
+
 	idx=$(platform_pkgtb_get_upgrade_index)
 	case "$idx" in
 		1) bootfs_id=3; rootfs_id=4;;
@@ -295,6 +294,8 @@ platform_do_upgrade_pkgtb() {
 
 	platform_pkgtb_commit $idx
 
+	CI_UBIPART="image"
+	platform_pkgtb_clean_rootfs_data
 	nand_do_upgrade_success
 }
 




More information about the lede-commits mailing list