blob: 90fc5190d10bd3130caecf4e9ab6ccba303f374a [file] [log] [blame]
developer0e0b0ce2022-07-20 14:30:33 +08001
2
3#. /lib/functions.sh
4
5# 'kernel' partition on NAND contains the kernel
6CI_KERNPART="${CI_KERNPART:-kernel}"
7
8# 'ubi' partition on NAND contains UBI
9CI_UBIPART="${CI_UBIPART:-ubi}"
10
11# 'rootfs' partition on NAND contains the rootfs
12CI_ROOTPART="${CI_ROOTPART:-rootfs}"
13
14find_mtd_index() {
15 local PART="$(grep "\"$1\"" /proc/mtd | awk -F: '{print $1}')"
16 local INDEX="${PART##mtd}"
17
18 echo ${INDEX}
19}
20
21ubi_mknod() {
22 local dir="$1"
23 local dev="/dev/$(basename $dir)"
24
25 [ -e "$dev" ] && return 0
26
27 local devid="$(cat $dir/dev)"
28 local major="${devid%%:*}"
29 local minor="${devid##*:}"
30 mknod "$dev" c $major $minor
31}
32
33nand_find_volume() {
34 local ubidevdir ubivoldir
35 ubidevdir="/sys/devices/virtual/ubi/$1"
36 [ ! -d "$ubidevdir" ] && return 1
37 for ubivoldir in $ubidevdir/${1}_*; do
38 [ ! -d "$ubivoldir" ] && continue
39 if [ "$( cat $ubivoldir/name )" = "$2" ]; then
40 basename $ubivoldir
41 ubi_mknod "$ubivoldir"
42 return 0
43 fi
44 done
45}
46
47nand_find_ubi() {
48 local ubidevdir ubidev mtdnum
49 mtdnum="$( find_mtd_index $1 )"
50 [ ! "$mtdnum" ] && return 1
51 for ubidevdir in /sys/devices/virtual/ubi/ubi*; do
52 [ ! -d "$ubidevdir" ] && continue
53 cmtdnum="$( cat $ubidevdir/mtd_num )"
54 [ ! "$mtdnum" ] && continue
55 if [ "$mtdnum" = "$cmtdnum" ]; then
56 ubidev=$( basename $ubidevdir )
57 ubi_mknod "$ubidevdir"
58 echo $ubidev
59 return 0
60 fi
61 done
62}
63
64nand_get_magic_long() {
65 dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
66}
67
68get_magic_long_tar() {
69 ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
70}
71
72identify_magic() {
73 local magic=$1
74 case "$magic" in
75 "55424923")
76 echo "ubi"
77 ;;
78 "31181006")
79 echo "ubifs"
80 ;;
81 "68737173")
82 echo "squashfs"
83 ;;
84 "d00dfeed")
85 echo "fit"
86 ;;
87 "4349"*)
88 echo "combined"
89 ;;
90 *)
91 echo "unknown $magic"
92 ;;
93 esac
94}
95
96
97identify() {
98 identify_magic $(nand_get_magic_long "$1" "${2:-0}")
99}
100
101identify_tar() {
102 identify_magic $(get_magic_long_tar "$1" "$2")
103}
104
105nand_restore_config() {
106 sync
107 local ubidev=$( nand_find_ubi $CI_UBIPART )
108 local ubivol="$( nand_find_volume $ubidev rootfs_data )"
109 [ ! "$ubivol" ] &&
110 ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
111 mkdir /tmp/new_root
112 if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then
113 echo "mounting ubifs $ubivol failed"
114 rmdir /tmp/new_root
115 return 1
116 fi
117 mv "$1" "/tmp/new_root/$BACKUP_FILE"
118 umount /tmp/new_root
119 sync
120 rmdir /tmp/new_root
121}
122
123nand_upgrade_prepare_ubi() {
124 local rootfs_length="$1"
125 local rootfs_type="$2"
126 local has_kernel="${3:-0}"
127 local has_env="${4:-0}"
128
129 local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
130 echo -e "mtdnum = $mtdnum"
131 if [ ! "$mtdnum" ]; then
132 echo "cannot find ubi mtd partition $CI_UBIPART"
133 return 1
134 fi
135
136 local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
137
138 echo -e "ubidev = $ubidev"
139 if [ ! "$ubidev" ]; then
140 ubiattach -m "$mtdnum"
141 sync
142 ubidev="$( nand_find_ubi "$CI_UBIPART" )"
143 fi
144
145 if [ ! "$ubidev" ]; then
146 ubiformat /dev/mtd$mtdnum -y
147 ubiattach -m "$mtdnum"
148 sync
149 ubidev="$( nand_find_ubi "$CI_UBIPART" )"
150 [ "$has_env" -gt 0 ] && {
151 ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB
152 ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB
153 }
154 fi
155
156 local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )"
157 local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
158 local data_ubivol="$( nand_find_volume $ubidev rootfs_data )"
159
160 echo -e "root_ubivol = $root_ubivol"
161 # remove ubiblock device of rootfs
162 local root_ubiblk="ubiblock${root_ubivol:3}"
163
164 echo -e "root_ubiblk = $root_ubiblk"
165
166 if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then
167 echo "removing $root_ubiblk"
168 if ! ubiblock -r /dev/$root_ubivol; then
169 echo "cannot remove $root_ubiblk"
170 return 1;
171 fi
172 fi
173
174 # kill volumes
175 [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true
176 [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true
177 [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true
178
179 # update kernel
180 if [ "$has_kernel" = "1" ]; then
181 if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then
182 echo "cannot create kernel volume"
183 return 1;
184 fi
185 fi
186
187 # update rootfs
188 echo -e "rootfs_type = $rootfs_type"
189
190 local root_size_param
191 if [ "$rootfs_type" = "ubifs" ]; then
192 root_size_param="-m"
193 else
194 root_size_param="-s $rootfs_length"
195 fi
196 if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $root_size_param; then
197 echo "cannot create rootfs volume"
198 return 1;
199 fi
200
201 # create rootfs_data for non-ubifs rootfs
202 if [ "$rootfs_type" != "ubifs" ]; then
203 if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then
204 echo "cannot initialize rootfs_data volume"
205 return 1
206 fi
207 fi
208 sync
209 return 0
210}
211
212nand_do_upgrade_success() {
213 local conf_tar="/tmp/sysupgrade.tgz"
214
215 sync
216 [ -f "$conf_tar" ] && nand_restore_config "$conf_tar"
217 echo "sysupgrade successful"
218 umount -a
219 reboot -f
220}
221
222# Flash the UBI image to MTD partition
223nand_upgrade_ubinized() {
224 local ubi_file="$1"
225 local mtdnum="$(find_mtd_index "$CI_UBIPART")"
226
227 [ ! "$mtdnum" ] && {
228 CI_UBIPART="rootfs"
229 mtdnum="$(find_mtd_index "$CI_UBIPART")"
230 }
231
232 if [ ! "$mtdnum" ]; then
233 echo "cannot find mtd device $CI_UBIPART"
234 umount -a
235 reboot -f
236 fi
237
238 local mtddev="/dev/mtd${mtdnum}"
239 ubidetach -p "${mtddev}" || true
240 sync
241 ubiformat "${mtddev}" -y -f "${ubi_file}"
242 ubiattach -p "${mtddev}"
243 nand_do_upgrade_success
244}
245
246# Write the UBIFS image to UBI volume
247nand_upgrade_ubifs() {
248 local rootfs_length=$( (cat $1 | wc -c) 2> /dev/null)
249
250 nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0"
251
252 local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
253 local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
254 ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1
255
256 nand_do_upgrade_success
257}
258
259nand_upgrade_tar() {
260 local tar_file="$1"
261 local kernel_mtd="$(find_mtd_index $CI_KERNPART)"
262
263 local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
264 board_dir=${board_dir%/}
265
266 local kernel_length=$( (tar xf $tar_file ${board_dir}/kernel -O | wc -c) 2> /dev/null)
267 local rootfs_length=$( (tar xf $tar_file ${board_dir}/root -O | wc -c) 2> /dev/null)
268
269 local rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)"
270
271 local has_kernel=1
272 local has_env=0
273
274 [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
275 tar xf $tar_file ${board_dir}/kernel -O | mtd write - $CI_KERNPART
276 }
277 [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0
278
279 nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env"
280
281 local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
282 [ "$has_kernel" = "1" ] && {
283 local kern_ubivol="$(nand_find_volume $ubidev $CI_KERNPART)"
284 tar xf $tar_file ${board_dir}/kernel -O | \
285 ubiupdatevol /dev/$kern_ubivol -s $kernel_length -
286 }
287
288 local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
289 tar xf $tar_file ${board_dir}/root -O | \
290 ubiupdatevol /dev/$root_ubivol -s $rootfs_length -
291
292 nand_do_upgrade_success
293}
294
295# Recognize type of passed file and start the upgrade process
296nand_do_upgrade() {
297 local file_type=$(identify $1)
298
299 [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs"
300
301 case "$file_type" in
302 "ubi") nand_upgrade_ubinized $1;;
303 "ubifs") nand_upgrade_ubifs $1;;
304 *) nand_upgrade_tar $1;;
305 esac
306}
307
308# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts
309# 3 types of files:
310# 1) UBI - should contain an ubinized image, header is checked for the proper
311# MAGIC
312# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume,
313# header is checked for the proper MAGIC
314# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty
315# "CONTROL" file (at this point its content isn't verified)
316#
317# You usually want to call this function in platform_check_image.
318#
319# $(1): board name, used in case of passing TAR file
320# $(2): file to be checked
321nand_do_platform_check() {
322 local board_name="$1"
323 local tar_file="$2"
324 local control_length=$( (tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null)
325 local file_type="$(identify $2)"
326
327 [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && {
328 echo "Invalid sysupgrade file."
329 return 1
330 }
331
332 return 0
333}
334
335dual_boot_upgrade_prepare_ubi() {
336 local kernel_vol_name="$1"
337 local rootfs_vol_name="$2"
338 local kernel_length="$3"
339 local rootfs_length="$4"
340 local reserve_rootfs_data="$5"
341
342 local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
343 if [ ! "$mtdnum" ]; then
344 echo "cannot find ubi mtd partition $CI_UBIPART"
345 return 1
346 fi
347
348 local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
349 if [ ! "$ubidev" ]; then
350 ubiattach -m "$mtdnum"
351 sync
352 ubidev="$( nand_find_ubi "$CI_UBIPART" )"
353 fi
354
355 if [ ! "$ubidev" ]; then
356 ubiformat /dev/mtd$mtdnum -y
357 ubiattach -m "$mtdnum"
358 sync
359 ubidev="$( nand_find_ubi "$CI_UBIPART" )"
360 ubimkvol /dev/$ubidev -n 0 -N u-boot-env -s 512KiB
361 fi
362
363 local rootfs_data_vol_name=$(cat /sys/module/boot_param/parameters/rootfs_data_part 2>/dev/null)
364
365 local kern_ubivol="$( nand_find_volume $ubidev $kernel_vol_name )"
366 local root_ubivol="$( nand_find_volume $ubidev $rootfs_vol_name )"
367 local data_ubivol="$( nand_find_volume $ubidev $rootfs_data_vol_name )"
368
369 # remove ubiblock device of rootfs
370 local root_ubiblk="ubiblock${root_ubivol:3}"
371 if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then
372 echo "removing $root_ubiblk"
373 if ! ubiblock -r /dev/$root_ubivol; then
374 echo "cannot remove $root_ubiblk"
375 return 1;
376 fi
377 fi
378
379 # kill volumes
380 [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $kernel_vol_name || true
381 [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N $rootfs_vol_name || true
382
383 # update kernel
384 if ! ubimkvol /dev/$ubidev -N $kernel_vol_name -s $kernel_length; then
385 echo "cannot create kernel volume"
386 return 1;
387 fi
388
389 # update rootfs
390 if ! ubimkvol /dev/$ubidev -N $rootfs_vol_name -s $rootfs_length; then
391 echo "cannot create rootfs volume"
392 return 1;
393 fi
394
395 if [ x"${reserve_rootfs_data}" = xY ]; then
396 # Do not touch rootfs_data
397 sync
398 return 0
399 fi
400
401 # 'format' rootfs_data volume
402 [ "$data_ubivol" ] && {
403 local rootfs_data_length=$(cat /sys/class/ubi/$data_ubivol/data_bytes)
404
405 # kill rootfs_data volume
406 ubirmvol /dev/$ubidev -N $rootfs_data_vol_name || true
407
408 # update rootfs_data
409 if ! ubimkvol /dev/$ubidev -N $rootfs_data_vol_name -s $rootfs_data_length; then
410 echo "cannot create $rootfs_data_vol_name volume"
411 fi
412 }
413
414 sync
415 return 0
416}
417
418ubi_dual_boot_upgrade_tar() {
419 local tar_file="$1"
420 local board_dir=$(tar tf ${tar_file} | grep -m 1 '^sysupgrade-.*/$')
421 local reserve_rootfs_data=$(cat /sys/module/boot_param/parameters/reserve_rootfs_data 2>/dev/null)
422 board_dir=${board_dir%/}
423
424 kernel_vol_name=$(cat /sys/module/boot_param/parameters/upgrade_kernel_part 2>/dev/null)
425 [ -z "${kernel_vol_name}" -o $? -ne 0 ] && return 1
426
427 rootfs_vol_name=$(cat /sys/module/boot_param/parameters/upgrade_rootfs_part 2>/dev/null)
428 [ -z "${rootfs_vol_name}" -o $? -ne 0 ] && return 1
429
430 local kernel_length=$( (tar xf ${tar_file} ${board_dir}/kernel -O | wc -c) 2> /dev/null)
431 local rootfs_length=$( (tar xf ${tar_file} ${board_dir}/root -O | wc -c) 2> /dev/null)
432
433 dual_boot_upgrade_prepare_ubi "${kernel_vol_name}" "${rootfs_vol_name}" \
434 "${kernel_length}" "${rootfs_length}" \
435 "${reserve_rootfs_data}"
436
437 local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
438
439 [ "${kernel_length}" != 0 ] && {
440 local kern_ubivol="$(nand_find_volume $ubidev ${kernel_vol_name})"
441 tar xf ${tar_file} ${board_dir}/kernel -O | \
442 ubiupdatevol /dev/${kern_ubivol} -s ${kernel_length} -
443 }
444
445 [ "${rootfs_length}" != 0 ] && {
446 local root_ubivol="$(nand_find_volume $ubidev ${rootfs_vol_name})"
447 tar xf ${tar_file} ${board_dir}/root -O | \
448 ubiupdatevol /dev/${root_ubivol} -s ${rootfs_length} -
449 }
450
451 upgrade_image_slot=$(cat /sys/module/boot_param/parameters/upgrade_image_slot 2>/dev/null)
452 [ -n "${upgrade_image_slot}" ] && {
453 v "Set new boot image slot to ${upgrade_image_slot}"
454 # Force the creation of fw_printenv.lock
455 mkdir -p /var/lock
456 touch /var/lock/fw_printenv.lock
457 fw_setenv "dual_boot.current_slot" "${upgrade_image_slot}"
458 fw_setenv "dual_boot.slot_${upgrade_image_slot}_invalid" "0"
459 }
460
461 if [ x"${reserve_rootfs_data}" != xY ]; then
462 # do normal upgrade flow
463 nand_do_upgrade_success
464 fi
465
466 # Do not touch rootfs_data
467 sync
468
469 echo "sysupgrade successful"
470 #umount -a
471 #reboot -f
472}
473
474ubi_do_upgrade() {
475 local dual_boot=$(cat /sys/module/boot_param/parameters/dual_boot 2>/dev/null)
476 local file_type=$(identify $1)
477
478 if [ -b /dev/dm-0 ]; then
479 v "Detach all device mapper devices"
480 dmsetup remove_all
481 fi
482
483 if [ x"${dual_boot}" != xY ]; then
484 nand_do_upgrade "$1"
485 return
486 fi
487
488 case "$file_type" in
489 "ubi") v "Unsupported firmware type: ubinized";;
490 "ubifs") v "Unsupported firmware type: ubifs";;
491 *) ubi_dual_boot_upgrade_tar $1;;
492 esac
493}