bcm4908: sysupgrade: refactor handling different firmware formats

This results in setting format specific data (format info, extract
commands) in a single function. It should help maintaining sysupgrade
code.

This change has been tested on Asus GT-AC5300 and Netgear R8000P.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
Rafał Miłecki 2021-11-29 10:25:30 +01:00
parent 80041dea70
commit 30b168b9b8
1 changed files with 77 additions and 33 deletions

View File

@ -4,6 +4,10 @@ RAMFS_COPY_BIN="bcm4908img expr"
PART_NAME=firmware PART_NAME=firmware
BCM4908_FW_FORMAT=
BCM4908_FW_BOARD_ID=
BCM4908_FW_INT_IMG_FORMAT=
# $(1): file to read from # $(1): file to read from
# $(2): offset in bytes # $(2): offset in bytes
# $(3): length in bytes # $(3): length in bytes
@ -34,7 +38,12 @@ platform_identify() {
magic=$(get_hex_u32_be "$1" 0) magic=$(get_hex_u32_be "$1" 0)
case "$magic" in case "$magic" in
2a23245e) 2a23245e)
echo "chk" local header_len=$((0x$(get_hex_u32_be "$1" 4)))
local board_id_len=$(($header_len - 40))
BCM4908_FW_FORMAT="chk"
BCM4908_FW_BOARD_ID=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"')
BCM4908_FW_INT_IMG_FORMAT="bcm4908img"
return return
;; ;;
esac esac
@ -44,12 +53,22 @@ platform_identify() {
magic=$(get_content "$1" $((size - 20 - 64 + 8)) 12) magic=$(get_content "$1" $((size - 20 - 64 + 8)) 12)
case "$magic" in case "$magic" in
GT-AC5300) GT-AC5300)
echo "asus" local size=$(wc -c "$1" | cut -d ' ' -f 1)
BCM4908_FW_FORMAT="asus"
BCM4908_FW_BOARD_ID=$(get_content "$1" $((size - 20 - 64 + 8)) 12)
BCM4908_FW_INT_IMG_FORMAT="bcm4908img"
return return
;; ;;
esac esac
echo "unknown" # Detecting native format is a bit complex (it may start with CFE or
# JFFS2) so just use bcm4908img instead of bash hacks.
# Make it the last attempt as bcm4908img detects also vendor formats.
bcm4908img info -i "$1" > /dev/null && {
BCM4908_FW_FORMAT="bcm4908img"
return
}
} }
platform_check_image() { platform_check_image() {
@ -58,43 +77,51 @@ platform_check_image() {
local expected_image=$(platform_expected_image) local expected_image=$(platform_expected_image)
local error=0 local error=0
bcm4908img info -i "$1" > /dev/null || { platform_identify "$1"
echo "Failed to validate BCM4908 image" >&2 [ -z "$BCM4908_FW_FORMAT" ] && {
echo "Invalid image type. Please use firmware specific for this device."
notify_firmware_broken notify_firmware_broken
return 1 return 1
} }
echo "Found $BCM4908_FW_FORMAT firmware for device ${BCM4908_FW_BOARD_ID:----}"
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" || { local expected_image="$(platform_expected_image)"
# OpenWrt images have 1-openwrt dummy file in the bootfs. [ -n "$expected_image" -a -n "$BCM4908_FW_BOARD_ID" -a "$BCM4908_FW_FORMAT $BCM4908_FW_BOARD_ID" != "$expected_image" ] && {
# Don't allow backup if it's missing echo "Firmware doesn't match device ($expected_image)"
notify_firmware_no_backup error=1
} }
case "$(platform_identify "$1")" in case "$BCM4908_FW_FORMAT" in
asus) "bcm4908img")
local size=$(wc -c "$1" | cut -d ' ' -f 1) bcm4908img info -i "$1" > /dev/null || {
local productid=$(get_content "$1" $((size - 20 - 64 + 8)) 12) echo "Failed to validate BCM4908 image" >&2
notify_firmware_broken
[ -n "$expected_image" -a "asus $productid" != "$expected_image" ] && { return 1
echo "Firmware productid mismatch ($productid)" >&2
error=1
} }
;;
chk)
local header_len=$((0x$(get_hex_u32_be "$1" 4)))
local board_id_len=$(($header_len - 40))
local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"')
[ -n "$expected_image" -a "chk $board_id" != "$expected_image" ] && { bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" || {
echo "Firmware board_id mismatch ($board_id)" >&2 # OpenWrt images have 1-openwrt dummy file in the bootfs.
error=1 # Don't allow backup if it's missing
notify_firmware_no_backup
} }
;; ;;
*) *)
echo "Invalid image type. Please use firmware specific for this device." >&2 case "$BCM4908_FW_INT_IMG_FORMAT" in
notify_firmware_broken "bcm4908img")
error=1 bcm4908img info -i "$1" > /dev/null || {
;; echo "Failed to validate BCM4908 image" >&2
notify_firmware_broken
return 1
}
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" || {
# OpenWrt images have 1-openwrt dummy file in the bootfs.
# Don't allow backup if it's missing
notify_firmware_no_backup
}
;;
esac
;;
esac esac
return $error return $error
@ -189,10 +216,27 @@ platform_do_upgrade_ubi() {
} }
platform_do_upgrade() { platform_do_upgrade() {
# Try NAND aware UBI upgrade for OpenWrt images platform_identify "$1"
# Below call will exit on success
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" && platform_do_upgrade_ubi "$1"
# Try NAND aware UBI upgrade for OpenWrt images
case "$BCM4908_FW_FORMAT" in
"bcm4908img")
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" && platform_do_upgrade_ubi "$1"
;;
*)
case "$BCM4908_FW_INT_IMG_FORMAT" in
"bcm4908img")
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" && platform_do_upgrade_ubi "$1"
;;
*)
echo "NAND aware sysupgrade is unsupported for $BCM4908_FW_FORMAT format"
;;
esac
;;
esac
# Above calls exit on success.
# If we got here it isn't OpenWrt image or something went wrong.
echo "Writing whole image to NAND flash. All erase counters will be lost." echo "Writing whole image to NAND flash. All erase counters will be lost."
# Find cferam name for new firmware # Find cferam name for new firmware