OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #!/bin/sh |
2 | # Copyright (C) 2014 OpenWrt.org |
||
3 | # |
||
4 | |||
5 | . /lib/functions.sh |
||
6 | |||
7 | # 'kernel' partition on NAND contains the kernel |
||
8 | CI_KERNPART="${CI_KERNPART:-kernel}" |
||
9 | |||
10 | # 'ubi' partition on NAND contains UBI |
||
11 | CI_UBIPART="${CI_UBIPART:-ubi}" |
||
12 | |||
13 | ubi_mknod() { |
||
14 | local dir="$1" |
||
15 | local dev="/dev/$(basename $dir)" |
||
16 | |||
17 | [ -e "$dev" ] && return 0 |
||
18 | |||
19 | local devid="$(cat $dir/dev)" |
||
20 | local major="${devid%%:*}" |
||
21 | local minor="${devid##*:}" |
||
22 | mknod "$dev" c $major $minor |
||
23 | } |
||
24 | |||
25 | nand_find_volume() { |
||
26 | local ubidevdir ubivoldir |
||
27 | ubidevdir="/sys/devices/virtual/ubi/$1" |
||
28 | [ ! -d "$ubidevdir" ] && return 1 |
||
29 | for ubivoldir in $ubidevdir/${1}_*; do |
||
30 | [ ! -d "$ubivoldir" ] && continue |
||
31 | if [ "$( cat $ubivoldir/name )" = "$2" ]; then |
||
32 | basename $ubivoldir |
||
33 | ubi_mknod "$ubivoldir" |
||
34 | return 0 |
||
35 | fi |
||
36 | done |
||
37 | } |
||
38 | |||
39 | nand_find_ubi() { |
||
40 | local ubidevdir ubidev mtdnum |
||
41 | mtdnum="$( find_mtd_index $1 )" |
||
42 | [ ! "$mtdnum" ] && return 1 |
||
43 | for ubidevdir in /sys/devices/virtual/ubi/ubi*; do |
||
44 | [ ! -d "$ubidevdir" ] && continue |
||
45 | cmtdnum="$( cat $ubidevdir/mtd_num )" |
||
46 | [ ! "$mtdnum" ] && continue |
||
47 | if [ "$mtdnum" = "$cmtdnum" ]; then |
||
48 | ubidev=$( basename $ubidevdir ) |
||
49 | ubi_mknod "$ubidevdir" |
||
50 | echo $ubidev |
||
51 | return 0 |
||
52 | fi |
||
53 | done |
||
54 | } |
||
55 | |||
56 | nand_get_magic_long() { |
||
57 | dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' |
||
58 | } |
||
59 | |||
60 | get_magic_long_tar() { |
||
61 | ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null |
||
62 | } |
||
63 | |||
64 | identify_magic() { |
||
65 | local magic=$1 |
||
66 | case "$magic" in |
||
67 | "55424923") |
||
68 | echo "ubi" |
||
69 | ;; |
||
70 | "31181006") |
||
71 | echo "ubifs" |
||
72 | ;; |
||
73 | "68737173") |
||
74 | echo "squashfs" |
||
75 | ;; |
||
76 | "d00dfeed") |
||
77 | echo "fit" |
||
78 | ;; |
||
79 | "4349"*) |
||
80 | echo "combined" |
||
81 | ;; |
||
82 | *) |
||
83 | echo "unknown $magic" |
||
84 | ;; |
||
85 | esac |
||
86 | } |
||
87 | |||
88 | |||
89 | identify() { |
||
90 | identify_magic $(nand_get_magic_long "$1" "${2:-0}") |
||
91 | } |
||
92 | |||
93 | identify_tar() { |
||
94 | identify_magic $(get_magic_long_tar "$1" "$2") |
||
95 | } |
||
96 | |||
97 | nand_restore_config() { |
||
98 | sync |
||
99 | local ubidev=$( nand_find_ubi $CI_UBIPART ) |
||
100 | local ubivol="$( nand_find_volume $ubidev rootfs_data )" |
||
101 | [ ! "$ubivol" ] && |
||
3 | office | 102 | ubivol="$( nand_find_volume $ubidev rootfs )" |
1 | office | 103 | mkdir /tmp/new_root |
104 | if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then |
||
105 | echo "mounting ubifs $ubivol failed" |
||
106 | rmdir /tmp/new_root |
||
107 | return 1 |
||
108 | fi |
||
109 | mv "$1" "/tmp/new_root/sysupgrade.tgz" |
||
110 | umount /tmp/new_root |
||
111 | sync |
||
112 | rmdir /tmp/new_root |
||
113 | } |
||
114 | |||
115 | nand_upgrade_prepare_ubi() { |
||
116 | local rootfs_length="$1" |
||
117 | local rootfs_type="$2" |
||
118 | local has_kernel="${3:-0}" |
||
119 | local has_env="${4:-0}" |
||
120 | |||
121 | local mtdnum="$( find_mtd_index "$CI_UBIPART" )" |
||
122 | if [ ! "$mtdnum" ]; then |
||
123 | echo "cannot find ubi mtd partition $CI_UBIPART" |
||
124 | return 1 |
||
125 | fi |
||
126 | |||
127 | local ubidev="$( nand_find_ubi "$CI_UBIPART" )" |
||
128 | if [ ! "$ubidev" ]; then |
||
129 | ubiattach -m "$mtdnum" |
||
130 | sync |
||
131 | ubidev="$( nand_find_ubi "$CI_UBIPART" )" |
||
132 | fi |
||
133 | |||
134 | if [ ! "$ubidev" ]; then |
||
135 | ubiformat /dev/mtd$mtdnum -y |
||
136 | ubiattach -m "$mtdnum" |
||
137 | sync |
||
138 | ubidev="$( nand_find_ubi "$CI_UBIPART" )" |
||
139 | [ "$has_env" -gt 0 ] && { |
||
140 | ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB |
||
141 | ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB |
||
142 | } |
||
143 | fi |
||
144 | |||
145 | local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )" |
||
3 | office | 146 | local root_ubivol="$( nand_find_volume $ubidev rootfs )" |
1 | office | 147 | local data_ubivol="$( nand_find_volume $ubidev rootfs_data )" |
148 | |||
149 | # remove ubiblock device of rootfs |
||
150 | local root_ubiblk="ubiblock${root_ubivol:3}" |
||
151 | if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then |
||
152 | echo "removing $root_ubiblk" |
||
153 | if ! ubiblock -r /dev/$root_ubivol; then |
||
154 | echo "cannot remove $root_ubiblk" |
||
155 | return 1; |
||
156 | fi |
||
157 | fi |
||
158 | |||
159 | # kill volumes |
||
160 | [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true |
||
3 | office | 161 | [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs || true |
1 | office | 162 | [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true |
163 | |||
164 | # update kernel |
||
165 | if [ "$has_kernel" = "1" ]; then |
||
166 | if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then |
||
167 | echo "cannot create kernel volume" |
||
168 | return 1; |
||
169 | fi |
||
170 | fi |
||
171 | |||
172 | # update rootfs |
||
173 | local root_size_param |
||
174 | if [ "$rootfs_type" = "ubifs" ]; then |
||
175 | root_size_param="-m" |
||
176 | else |
||
177 | root_size_param="-s $rootfs_length" |
||
178 | fi |
||
3 | office | 179 | if ! ubimkvol /dev/$ubidev -N rootfs $root_size_param; then |
1 | office | 180 | echo "cannot create rootfs volume" |
181 | return 1; |
||
182 | fi |
||
183 | |||
184 | # create rootfs_data for non-ubifs rootfs |
||
185 | if [ "$rootfs_type" != "ubifs" ]; then |
||
186 | if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then |
||
187 | echo "cannot initialize rootfs_data volume" |
||
188 | return 1 |
||
189 | fi |
||
190 | fi |
||
191 | sync |
||
192 | return 0 |
||
193 | } |
||
194 | |||
195 | nand_do_upgrade_success() { |
||
196 | local conf_tar="/tmp/sysupgrade.tgz" |
||
197 | |||
198 | sync |
||
199 | [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" |
||
200 | echo "sysupgrade successful" |
||
201 | umount -a |
||
202 | reboot -f |
||
203 | } |
||
204 | |||
205 | # Flash the UBI image to MTD partition |
||
206 | nand_upgrade_ubinized() { |
||
207 | local ubi_file="$1" |
||
208 | local mtdnum="$(find_mtd_index "$CI_UBIPART")" |
||
209 | |||
210 | [ ! "$mtdnum" ] && { |
||
211 | CI_UBIPART="rootfs" |
||
212 | mtdnum="$(find_mtd_index "$CI_UBIPART")" |
||
213 | } |
||
214 | |||
215 | if [ ! "$mtdnum" ]; then |
||
216 | echo "cannot find mtd device $CI_UBIPART" |
||
217 | umount -a |
||
218 | reboot -f |
||
219 | fi |
||
220 | |||
221 | local mtddev="/dev/mtd${mtdnum}" |
||
222 | ubidetach -p "${mtddev}" || true |
||
223 | sync |
||
224 | ubiformat "${mtddev}" -y -f "${ubi_file}" |
||
225 | ubiattach -p "${mtddev}" |
||
226 | nand_do_upgrade_success |
||
227 | } |
||
228 | |||
229 | # Write the UBIFS image to UBI volume |
||
230 | nand_upgrade_ubifs() { |
||
231 | local rootfs_length=`(cat $1 | wc -c) 2> /dev/null` |
||
232 | |||
233 | nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0" |
||
234 | |||
235 | local ubidev="$( nand_find_ubi "$CI_UBIPART" )" |
||
3 | office | 236 | local root_ubivol="$(nand_find_volume $ubidev rootfs)" |
1 | office | 237 | ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 |
238 | |||
239 | nand_do_upgrade_success |
||
240 | } |
||
241 | |||
242 | nand_upgrade_tar() { |
||
243 | local tar_file="$1" |
||
244 | local kernel_mtd="$(find_mtd_index $CI_KERNPART)" |
||
245 | |||
246 | local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') |
||
247 | board_dir=${board_dir%/} |
||
248 | |||
249 | local kernel_length=`(tar xf $tar_file ${board_dir}/kernel -O | wc -c) 2> /dev/null` |
||
250 | local rootfs_length=`(tar xf $tar_file ${board_dir}/root -O | wc -c) 2> /dev/null` |
||
251 | |||
252 | local rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)" |
||
253 | |||
254 | local has_kernel=1 |
||
255 | local has_env=0 |
||
256 | |||
257 | [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && { |
||
258 | tar xf $tar_file ${board_dir}/kernel -O | mtd write - $CI_KERNPART |
||
259 | } |
||
260 | [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0 |
||
261 | |||
262 | nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env" |
||
263 | |||
264 | local ubidev="$( nand_find_ubi "$CI_UBIPART" )" |
||
265 | [ "$has_kernel" = "1" ] && { |
||
266 | local kern_ubivol="$(nand_find_volume $ubidev $CI_KERNPART)" |
||
267 | tar xf $tar_file ${board_dir}/kernel -O | \ |
||
268 | ubiupdatevol /dev/$kern_ubivol -s $kernel_length - |
||
269 | } |
||
270 | |||
3 | office | 271 | local root_ubivol="$(nand_find_volume $ubidev rootfs)" |
1 | office | 272 | tar xf $tar_file ${board_dir}/root -O | \ |
273 | ubiupdatevol /dev/$root_ubivol -s $rootfs_length - |
||
274 | |||
275 | nand_do_upgrade_success |
||
276 | } |
||
277 | |||
278 | # Recognize type of passed file and start the upgrade process |
||
279 | nand_do_upgrade() { |
||
280 | if [ -n "$IS_PRE_UPGRADE" ]; then |
||
281 | # Previously, nand_do_upgrade was called from the platform_pre_upgrade |
||
282 | # hook; this piece of code handles scripts that haven't been |
||
283 | # updated. All scripts should gradually move to call nand_do_upgrade |
||
284 | # from platform_do_upgrade instead. |
||
285 | export do_upgrade="nand_do_upgrade '$1'" |
||
286 | return |
||
287 | fi |
||
288 | |||
289 | local file_type=$(identify $1) |
||
290 | |||
291 | if type 'platform_nand_pre_upgrade' >/dev/null 2>/dev/null; then |
||
292 | platform_nand_pre_upgrade "$1" |
||
293 | fi |
||
294 | |||
295 | [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs" |
||
296 | |||
297 | case "$file_type" in |
||
298 | "ubi") nand_upgrade_ubinized $1;; |
||
299 | "ubifs") nand_upgrade_ubifs $1;; |
||
300 | *) nand_upgrade_tar $1;; |
||
301 | esac |
||
302 | } |
||
303 | |||
304 | # Check if passed file is a valid one for NAND sysupgrade. Currently it accepts |
||
305 | # 3 types of files: |
||
306 | # 1) UBI - should contain an ubinized image, header is checked for the proper |
||
307 | # MAGIC |
||
308 | # 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume, |
||
309 | # header is checked for the proper MAGIC |
||
310 | # 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty |
||
311 | # "CONTROL" file (at this point its content isn't verified) |
||
312 | # |
||
313 | # You usually want to call this function in platform_check_image. |
||
314 | # |
||
315 | # $(1): board name, used in case of passing TAR file |
||
316 | # $(2): file to be checked |
||
317 | nand_do_platform_check() { |
||
318 | local board_name="$1" |
||
319 | local tar_file="$2" |
||
320 | local control_length=`(tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null` |
||
321 | local file_type="$(identify $2)" |
||
322 | |||
323 | [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && { |
||
324 | echo "Invalid sysupgrade file." |
||
325 | return 1 |
||
326 | } |
||
327 | |||
328 | return 0 |
||
329 | } |