bcm4908: fix calculation of new cferam index
[openwrt/staging/thess.git] / target / linux / bcm4908 / base-files / lib / upgrade / platform.sh
1 # SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
2
3 RAMFS_COPY_BIN="bcm4908img expr"
4
5 PART_NAME=firmware
6
7 # $(1): file to read from
8 # $(2): offset in bytes
9 # $(3): length in bytes
10 get_content() {
11 dd if="$1" skip=$2 bs=1 count=$3 2>/dev/null
12 }
13
14 # $(1): file to read from
15 # $(2): offset in bytes
16 get_hex_u32_be() {
17 dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%02x"'
18 }
19
20 platform_expected_image() {
21 local machine=$(board_name)
22
23 case "$machine" in
24 asus,gt-ac5300) echo "asus GT-AC5300";;
25 netgear,r8000p) echo "chk U12H359T00_NETGEAR";;
26 tplink,archer-c2300-v1) echo "";;
27 esac
28 }
29
30 platform_identify() {
31 local magic
32 local size
33
34 magic=$(get_hex_u32_be "$1" 0)
35 case "$magic" in
36 2a23245e)
37 echo "chk"
38 return
39 ;;
40 esac
41
42 size=$(wc -c "$1" | cut -d ' ' -f 1)
43
44 magic=$(get_content "$1" $((size - 20 - 64 + 8)) 12)
45 case "$magic" in
46 GT-AC5300)
47 echo "asus"
48 return
49 ;;
50 esac
51
52 echo "unknown"
53 }
54
55 platform_check_image() {
56 [ "$#" -gt 1 ] && return 1
57
58 local expected_image=$(platform_expected_image)
59 local error=0
60
61 bcm4908img info -i "$1" > /dev/null || {
62 echo "Failed to validate BCM4908 image" >&2
63 notify_firmware_broken
64 return 1
65 }
66
67 bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" || {
68 # OpenWrt images have 1-openwrt dummy file in the bootfs.
69 # Don't allow backup if it's missing
70 notify_firmware_no_backup
71 }
72
73 case "$(platform_identify "$1")" in
74 asus)
75 local size=$(wc -c "$1" | cut -d ' ' -f 1)
76 local productid=$(get_content "$1" $((size - 20 - 64 + 8)) 12)
77
78 [ -n "$expected_image" -a "asus $productid" != "$expected_image" ] && {
79 echo "Firmware productid mismatch ($productid)" >&2
80 error=1
81 }
82 ;;
83 chk)
84 local header_len=$((0x$(get_hex_u32_be "$1" 4)))
85 local board_id_len=$(($header_len - 40))
86 local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"')
87
88 [ -n "$expected_image" -a "chk $board_id" != "$expected_image" ] && {
89 echo "Firmware board_id mismatch ($board_id)" >&2
90 error=1
91 }
92 ;;
93 *)
94 echo "Invalid image type. Please use firmware specific for this device." >&2
95 notify_firmware_broken
96 error=1
97 ;;
98 esac
99
100 return $error
101 }
102
103 # $1: cferam index increment value
104 platform_calc_new_cferam() {
105 local inc="$1"
106 local dir="/tmp/sysupgrade-bcm4908"
107
108 local mtd=$(find_mtd_part bootfs)
109 [ -z "$mtd" ] && {
110 echo "Failed to find bootfs partition" >&2
111 return
112 }
113
114 rm -fR $dir
115 mkdir -p $dir
116 mount -t jffs2 -o ro $mtd $dir || {
117 echo "Failed to mount bootfs partition $mtd" >&2
118 rm -fr $dir
119 return
120 }
121
122 local idx=$(ls $dir/cferam.??? | sed -n 's/.*cferam\.\(\d\d\d\)/\1/p')
123 [ -z "$idx" ] && {
124 echo "Failed to find cferam current index" >&2
125 rm -fr $dir
126 return
127 }
128
129 umount $dir
130 rm -fr $dir
131
132 idx=$(($(expr $idx + $inc) % 1000))
133
134 echo $(printf "cferam.%03d" $idx)
135 }
136
137 platform_do_upgrade_ubi() {
138 local dir="/tmp/sysupgrade-bcm4908"
139 local inc=1
140
141 # Verify new bootfs size
142 local mtd_bootfs_size=$(grep "\"bootfs\"" /proc/mtd | sed "s/mtd[0-9]*:[ \t]*\([^ \t]*\).*/\1/")
143 [ -z "$mtd_bootfs_size" ] && {
144 echo "Unable to find \"bootfs\" partition size"
145 return
146 }
147 mtd_bootfs_size=$((0x$mtd_bootfs_size))
148 local img_bootfs_size=$(bcm4908img extract -i "$1" -t bootfs | wc -c)
149 [ $img_bootfs_size -gt $mtd_bootfs_size ] && {
150 echo "New bootfs doesn't fit MTD partition."
151 return
152 }
153
154 # Find cferam name for new firmware
155 # For UBI we always flash "firmware" so don't increase cferam index if
156 # there is "fallback". That could result in cferam.999 & cferam.001
157 [ -n "$(find_mtd_index backup)" -o -n "$(find_mtd_index fallback)" ] && inc=0
158 local cferam=$(platform_calc_new_cferam $inc)
159 [ -z "$cferam" ] && exit 1
160
161 # Prepare new firmware
162 bcm4908img bootfs -i "$1" mv cferam.000 $cferam || {
163 echo "Failed to rename cferam.000 to $cferam" >&2
164 exit 1
165 }
166
167 # Extract rootfs for further flashing
168 rm -fr $dir
169 mkdir -p $dir
170 bcm4908img extract -i "$1" -t rootfs > $dir/root || {
171 echo "Failed to extract rootfs" >&2
172 rm -fr $dir
173 exit 1
174 }
175
176 # Flash bootfs MTD partition with new one
177 mtd erase bootfs || {
178 echo "Failed to erase bootfs" >&2
179 rm -fr $dir
180 exit 1
181 }
182 bcm4908img extract -i "$1" -t bootfs | mtd write - bootfs || {
183 echo "Failed to flash bootfs" >&2
184 rm -fr $dir
185 exit 1
186 }
187
188 nand_do_upgrade $dir/root
189 }
190
191 platform_do_upgrade() {
192 # Try NAND aware UBI upgrade for OpenWrt images
193 # Below call will exit on success
194 bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" && platform_do_upgrade_ubi "$1"
195
196 echo "Writing whole image to NAND flash. All erase counters will be lost."
197
198 # Find cferam name for new firmware
199 local cferam=$(platform_calc_new_cferam 1)
200 [ -z "$cferam" ] && exit 1
201
202 # Prepare new firmware
203 bcm4908img bootfs -i "$1" mv cferam.000 $cferam || {
204 echo "Failed to rename cferam.000 to $cferam" >&2
205 exit 1
206 }
207
208 # Jush flash firmware partition as is
209 [ -n "$(find_mtd_index backup)" ] && PART_NAME=backup
210 [ -n "$(find_mtd_index fallback)" ] && PART_NAME=fallback
211 mtd erase $PART_NAME
212 default_do_upgrade "$1" "bcm4908img extract -t firmware"
213 }