procd: update to latest git HEAD
[openwrt/svn-archive/archive.git] / package / system / procd / files / nand.sh
1 #!/bin/sh
2 # Copyright (C) 2014 OpenWrt.org
3 #
4
5 . /lib/functions.sh
6
7 # combined-image uses 64k blocks
8 CI_BLKSZ=65536
9 # 'data' partition on NAND contains UBI
10 CI_UBIPART="ubi"
11
12 nand_find_volume() {
13 local ubidevdir ubivoldir
14 ubidevdir="/sys/devices/virtual/ubi/$1"
15 [ ! -d "$ubidevdir" ] && return 1
16 for ubivoldir in $ubidevdir/${1}_*; do
17 [ ! -d "$ubivoldir" ] && continue
18 if [ "$( cat $ubivoldir/name )" = "$2" ]; then
19 basename $ubivoldir
20 return 0
21 fi
22 done
23 }
24
25 nand_find_ubi() {
26 local ubidevdir ubidev mtdnum
27 mtdnum="$( find_mtd_index $1 )"
28 [ ! "$mtdnum" ] && return 1
29 for ubidevdir in /sys/devices/virtual/ubi/ubi*; do
30 [ ! -d "$ubidevdir" ] && continue
31 cmtdnum="$( cat $ubidevdir/mtd_num )"
32 [ ! "$mtdnum" ] && continue
33 if [ "$mtdnum" = "$cmtdnum" ]; then
34 ubidev=$( basename $ubidevdir )
35 echo $ubidev
36 return 0
37 fi
38 done
39 }
40
41 nand_restore_config() {
42 sync
43 local ubidev=$( nand_find_ubi $CI_UBIPART )
44 local ubivol="$( nand_find_volume $ubidev rootfs_data )"
45 [ ! "$ubivol" ] &&
46 ubivol="$( nand_find_volume $ubidev rootfs )"
47 mkdir /tmp/new_root
48 if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then
49 echo "mounting ubifs $ubivol failed"
50 rmdir /tmp/new_root
51 return 1
52 fi
53 mv "$1" "/tmp/new_root/sysupgrade.tgz"
54 umount /tmp/new_root
55 sync
56 rmdir /tmp/new_root
57 }
58
59 nand_upgrade_ubinized() {
60 local upgrade_image="$1"
61 local conf_tar="$2"
62 local save_config="$3"
63 local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
64 if [ ! "$mtdnum" ]; then
65 echo "cannot find mtd device $CI_UBIPART"
66 return 1;
67 fi
68 local mtddev="/dev/mtd${mtdnum}"
69 ubidetach -p "${mtddev}" || true
70 sync
71 ubiformat "${mtddev}" -y -f "$upgrade_image"
72 ubiattach -p "${mtddev}"
73 sync
74 if [ -f "$conf_tar" -a "$save_config" -eq 1 ]; then
75 nand_restore_config "$conf_tar"
76 fi
77 return 0;
78 }
79
80 # get the first 4 bytes (magic) of a given file starting at offset in hex format
81 get_magic_long_at() {
82 dd if="$2" skip=$1 bs=$CI_BLKSZ count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
83 }
84
85 identify() {
86 local block;
87 local magic=$( get_magic_long_at ${2:-0} "$1" )
88 case "$magic" in
89 "55424923")
90 echo "ubi"
91 ;;
92 "31181006")
93 echo "ubifs"
94 ;;
95 "68737173")
96 echo "squashfs"
97 ;;
98 "d00dfeed")
99 echo "fit"
100 ;;
101 "4349"*)
102 echo "combined"
103 ;;
104 *)
105 echo "unknown $magic"
106 ;;
107 esac
108 }
109
110 nand_upgrade_combined_ubi() {
111 local kernel_image="$1"
112 local kernel_length=0
113 local rootfs_image="$2"
114 local rootfs_length=`ls -la $rootfs_image | awk '{ print $5}')`
115 local conf_tar="$3"
116 local has_env="${4:-0}"
117
118 local root_fs="$( identify "$rootfs_image" )"
119 local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
120 local has_kernel=0
121
122 [ -z "$kernel_image" ] || {
123 has_kernel=1
124 kernel_length=`ls -la $kernel_image | awk '{ print $5}')`
125 echo "kernel length $kernel_length"
126 }
127 [ "$has_kernel" = 0 ] || echo "kernel is inside ubi"
128 echo "rootfs type $root_fs, length $rootfs_length"
129
130 if [ ! "$mtdnum" ]; then
131 echo "cannot find ubi mtd partition $CI_UBIPART"
132 return 1
133 fi
134 local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
135 if [ ! "$ubidev" ]; then
136 ubiattach -m "$mtdnum"
137 sync
138 ubidev="$( nand_find_ubi "$CI_UBIPART" )"
139 fi
140 if [ ! "$ubidev" ]; then
141 ubiformat /dev/mtd$mtdnum -y
142 ubiattach -m "$mtdnum"
143 sync
144 ubidev="$( nand_find_ubi "$CI_UBIPART" )"
145 [ -z "$has_env" ] || {
146 ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB
147 ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB
148 }
149 fi
150 local kern_ubivol="$( nand_find_volume $ubidev kernel )"
151 local root_ubivol="$( nand_find_volume $ubidev rootfs )"
152 local data_ubivol="$( nand_find_volume $ubidev rootfs_data )"
153
154 # remove ubiblock device of rootfs
155 local root_ubiblk="ubiblock${root_ubivol:3}"
156 if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then
157 echo "removing $root_ubiblk"
158 if ! ubiblock -r /dev/$root_ubivol; then
159 echo "cannot remove $root_ubiblk"
160 return 1;
161 fi
162 fi
163
164 # kill volumes
165 if [ "$kern_ubivol" ]; then
166 ubirmvol /dev/$ubidev -N kernel || true
167 fi
168 if [ "$root_ubivol" ]; then
169 ubirmvol /dev/$ubidev -N rootfs || true
170 fi
171 if [ "$data_ubivol" ]; then
172 ubirmvol /dev/$ubidev -N rootfs_data || true
173 fi
174
175 # update kernel
176 if [ "$has_kernel" = "1" ]; then
177 if ! ubimkvol /dev/$ubidev -N kernel -s $kernel_length; then
178 echo "cannot create kernel volume"
179 return 1;
180 fi
181 fi
182
183 # update rootfs
184 local root_size_param
185 if [ "$root_fs" = "ubifs" ]; then
186 root_size_param="-m"
187 else
188 root_size_param="-s $rootfs_length"
189 fi
190 if ! ubimkvol /dev/$ubidev -N rootfs $root_size_param; then
191 echo "cannot create rootfs volume"
192 return 1;
193 fi
194
195 # create rootfs_data for non-ubifs rootfs
196 if [ "$root_fs" != "ubifs" ]; then
197 if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then
198 echo "cannot initialize rootfs_data volume"
199 return 1
200 fi
201 fi
202 sync
203
204 if [ "$has_kernel" = "1" ]; then
205 local kern_ubivol="$( nand_find_volume $ubidev kernel )"
206 ubiupdatevol /dev/$kern_ubivol -s $kernel_length $kernel_image
207 fi
208
209 local root_ubivol="$( nand_find_volume $ubidev rootfs )"
210 ubiupdatevol /dev/$root_ubivol -s $rootfs_length $rootfs_image
211 if [ -f "$conf_tar" ]; then
212 nand_restore_config "$conf_tar"
213 fi
214 echo "sysupgrade successfull"
215 return 0
216 }
217
218 nand_do_upgrade_stage1() {
219 local board_name="$1"
220 local tar_file="$2"
221 local kernel_file=""
222 local kernel_file=""
223
224 tar xzf $tar_file -C /tmp/
225 [ -f "/tmp/sysupgrade-$board_name/CONTROL" ] || {
226 echo "failed to find /tmp/sysupgrade-$board_name/CONTROL"
227 return 1
228 }
229
230 kernel_file=/tmp/sysupgrade-$board_name/kernel
231 [ -f "$kernel_file" ] || {
232 echo "$kernel_file is missing"
233 return 1
234 }
235
236 rootfs_file=/tmp/sysupgrade-$board_name/root
237 [ -f "$rootfs_file" ] || {
238 echo "$rootfs_file is missing"
239 return 1
240 }
241
242 echo -n /tmp/sysupgrade-$board_name > /tmp/sysupgrade-nand-folder
243 cp /sbin/upgraded /tmp/
244
245 return 0
246 }
247
248 nand_do_upgrade_stage2() {
249 rootfs_file=$1/root
250 kernel_file=$1/kernel
251 config_file=$1/config
252
253 [ -f $config_file ] || config_file=""
254
255 . $1/CONTROL
256
257 [ "$UBI_KERNEL" = "1" ] || {
258 mtd write $kernel_file kernel
259 kernel_file=""
260 }
261 nand_upgrade_combined_ubi "$kernel_file" "$rootfs_file" "$conf_tar" "$UBI_ENV"
262 reboot -f
263 }
264
265 nand_do_upgrade() {
266 [ $1 = "nand" ] && {
267 [ -d "$2" ] && {
268 touch /tmp/sysupgrade
269
270 killall -9 telnetd
271 killall -9 dropbear
272 killall -9 ash
273
274 kill_remaining TERM
275 sleep 3
276 kill_remaining KILL
277
278 sleep 1
279
280 if [ -n "$(rootfs_type)" ]; then
281 v "Switching to ramdisk..."
282 run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2"
283 else
284 nand_do_upgrade_stage2 $2
285 fi
286 return 0
287 }
288 echo "Nand upgrade failed"
289 exit 1
290 }
291 }
292
293 nand_upgrade_stage1() {
294 [ -f /tmp/sysupgrade-nand-folder ] && {
295 folder="$(cat /tmp/sysupgrade-nand-folder)"
296 [ "$SAVE_CONFIG" = 1 -a -f "$CONF_TAR" ] &&
297 cp $CONF_TAR $folder/config
298
299 ubus call system nandupgrade "{\"folder\": \"$folder\" }"
300 exit 0
301 }
302 }
303 append sysupgrade_pre_upgrade nand_upgrade_stage1