[openwrt/openwrt] qualcommax: ipq50xx: functions for bootconfig partition

LEDE Commits lede-commits at lists.infradead.org
Wed Dec 24 01:42:46 PST 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/d02de1d35a37cdcb3890aef5cbddee598ff16a7d

commit d02de1d35a37cdcb3890aef5cbddee598ff16a7d
Author: George Moussalem <george.moussalem at outlook.com>
AuthorDate: Wed Dec 3 23:22:09 2025 +0400

    qualcommax: ipq50xx: functions for bootconfig partition
    
    The BOOTCONFIG partition is used by Qualcomm's boot chain to store
    metadata about the device's startup configuration. It contains info such
    as versioning, configuration flags, primary boot partition, and more.
    
    Newer devices with dual boot partitions not only store the active boot
    partition in a U-boot variable but also in partition info in the
    BOOTCONFIG partition. As such, add library functions to set and toggle
    the active boot partition.
    
    Signed-off-by: George Moussalem <george.moussalem at outlook.com>
    Link: https://github.com/openwrt/openwrt/pull/21038
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 .../ipq50xx/base-files/lib/functions/bootconfig.sh | 177 +++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/target/linux/qualcommax/ipq50xx/base-files/lib/functions/bootconfig.sh b/target/linux/qualcommax/ipq50xx/base-files/lib/functions/bootconfig.sh
new file mode 100644
index 0000000000..3632c6a25e
--- /dev/null
+++ b/target/linux/qualcommax/ipq50xx/base-files/lib/functions/bootconfig.sh
@@ -0,0 +1,177 @@
+. /lib/functions.sh
+
+PART_SIZE=20
+NAME_SIZE=16
+MAX_NUM_PARTS=16
+
+MAGIC_START_HEX="a0 a1 a2 a3"
+MAGIC_START_TRY_HEX="a1 a1 a2 a3"
+MAGIC_END_HEX="b0 b1 b2 b3"
+
+validate_bootconfig_magic() {
+	local file=$1
+	magic_start=$(hexdump -v -n 4 -e '4/1 "%02x "' "$file")
+	magic_end=$(hexdump -v -s 332 -n 4 -e '4/1 "%02x "' "$file")
+	
+	if [ "$magic_start" != "$MAGIC_START_HEX" ] && \
+	   [ "$magic_start" != "$MAGIC_START_TRY_HEX" ]; then
+		echo "Not a valid bootconfig file, start magic does not match" >&2
+		return 1
+	fi
+
+	if [ "$magic_end" != "$MAGIC_END_HEX" ]; then
+		echo "Not a valid bootconfig file, end magic does not match" >&2
+		return 1
+	fi
+	return 0
+}
+
+get_bootconfig_numparts() {
+	local file=$1
+	numpartshex=$(hexdump -v -s 8 -n 4 -e '4/1 "%02x "' "$file")
+	numparts=$(( 0x$(echo $numpartshex | awk '{print $4$3$2$1}') ))
+	echo ${numparts}
+}
+
+get_bootconfig_partidx() {
+	local file=$1
+	local partname=$2
+	local numparts=$(get_bootconfig_numparts "$file")
+
+	if [ -z "$numparts" ]; then
+		echo "Could not get number of partitions" >&2
+		return
+	fi
+
+	if [ $numparts -gt $MAX_NUM_PARTS ]; then
+		numparts=$MAX_NUM_PARTS
+	fi
+
+	for i in $(seq 0 $((numparts -1))); do
+		nameoffset=$((12 + i * $PART_SIZE))
+		nameraw=$(dd if="$file" bs=1 skip="$nameoffset" count=12 2>/dev/null)
+		name=${nameraw//S'\x00'/}
+		if [ "$partname" = "$name" ]; then
+			echo $i
+		fi
+	done
+}
+
+get_bootconfig_primaryboot() {
+	local file=$1
+	local partname=$2
+
+	local partidx=$(get_bootconfig_partidx "$file" "$partname")
+	if ! echo "$partidx" | grep -Eq '^[0-9]+$'; then
+		echo "Could not get partition index for $partname in $file" >&2
+		return
+	fi
+
+	if [ "$partidx" -ge 0 ] && [ "$partidx" -lt $MAX_NUM_PARTS ]; then
+		offset=$((12 + $partidx * $PART_SIZE + $NAME_SIZE))
+		primaryboothex=$(hexdump -v -s "$offset" -n 4 -e '4/1 "%02x "' $file)
+		primaryboot=$(( 0x$(echo $primaryboothex | awk '{print $4$3$2$1}') ))
+		echo $primaryboot
+	fi
+}
+
+_set_bootconfig_primaryboot() {
+	local file=$1
+	local partname=$2
+	local primaryboot=$3
+	local primaryboothex
+	local partidx
+	local primarybootoffset
+
+	partidx=$(get_bootconfig_partidx "$file" "$partname")
+	if ! echo "$partidx" | grep -Eq '^[0-9]+$'; then
+		echo "Could not get partition index for $2" >&2
+		return 1
+	fi
+	primarybootoffset=$((12 + $partidx * $PART_SIZE + $NAME_SIZE))
+
+	case "$primaryboot" in
+		0)
+			printf "\x00\x00\x00\x00" | dd of="$file" seek="$primarybootoffset" bs=1 count=4 conv=notrunc 2>/dev/null
+			;;
+		1)
+			printf "\x01\x00\x00\x00" | dd of="$file" seek="$primarybootoffset" bs=1 count=4 conv=notrunc 2>/dev/null
+			;;
+		*)
+			echo "invalid argument: primaryboot must be 0 or 1" >&2
+			return 1
+			;;
+	esac
+}
+
+set_bootconfig_primaryboot() {
+	local file=$1
+	local partname=$2
+	local primaryboot=$3
+
+	[ -z "$file" ] || [ -z "$partname" ] || [ -z "$primaryboot" ] && {
+		echo "usage: $0 <file> <partition name> <0|1>"
+		return 1
+	}
+
+	[ ! -e "$file" ] && {
+		echo "file $file not found" >&2
+		return 1
+	}
+
+	[ ! -w $file ] && {
+		echo "file $file not writable" >&2
+		return 1
+	}
+
+	validate_bootconfig_magic "$file"
+	[ $? -ne 0 ] && return 1
+
+	_set_bootconfig_primaryboot $file $partname $primaryboot
+	[ $? -ne 0 ] && return 1
+
+	return 0
+}
+
+toggle_bootconfig_primaryboot() {
+	local file=$1
+	local partname=$2
+	local primaryboot
+	
+	[ -z "$file" ] || [ -z "$partname" ] && {
+		echo "usage: $0 <file> <partition name>"
+		return 1
+	}
+
+	[ ! -e "$file" ] && {
+		echo "file $file not found" >&2
+		return 1
+	}
+
+	[ ! -w $file ] && {
+		echo "file $file not writable" >&2
+		return 1
+	}
+
+	validate_bootconfig_magic "$file"
+	[ $? -ne 0 ] && return 1
+	
+	primaryboot=$(get_bootconfig_primaryboot "$1" "$2")
+
+	case "$primaryboot" in
+		0)
+			_set_bootconfig_primaryboot "$1" "$2" 1
+			;;
+		1)
+			_set_bootconfig_primaryboot "$1" "$2" 0
+			;;
+		*)
+			echo "invalid value: primaryboot must be 0 or 1" >&2
+			return 1
+			;;
+	esac
+
+	[ $? -ne 0 ] && return 1
+
+	return 0
+}




More information about the lede-commits mailing list