05d9214377fd293a19b8adb86d6c9e8e58968340
[openwrt/openwrt.git] / package / base-files / files / lib / upgrade / stage2
1 #!/bin/sh
2
3 . /lib/functions.sh
4 . /lib/functions/system.sh
5
6 export IMAGE="$1"
7 COMMAND="$2"
8
9 export ARGV="$IMAGE"
10 export ARGC=1
11
12 export SAVE_CONFIG=1
13 export SAVE_PARTITIONS=1
14
15 export INTERACTIVE=0
16 export VERBOSE=1
17 export CONFFILES=/tmp/sysupgrade.conffiles
18 export CONF_TAR=/tmp/sysupgrade.tgz
19
20 RAMFS_COPY_BIN= # extra programs for temporary ramfs root
21 RAMFS_COPY_DATA= # extra data files
22
23
24 [ -f "$CONF_TAR" ] || export SAVE_CONFIG=0
25 [ -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap ] && export SAVE_PARTITIONS=0
26
27 include /lib/upgrade
28
29
30 supivot() { # <new_root> <old_root>
31 /bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1
32 mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \
33 /bin/mount -o noatime,move /proc $1/proc && \
34 pivot_root $1 $1$2 || {
35 /bin/umount -l $1 $1
36 return 1
37 }
38
39 /bin/mount -o noatime,move $2/sys /sys
40 /bin/mount -o noatime,move $2/dev /dev
41 /bin/mount -o noatime,move $2/tmp /tmp
42 /bin/mount -o noatime,move $2/overlay /overlay 2>&-
43 return 0
44 }
45
46 switch_to_ramfs() {
47 for binary in \
48 /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \
49 pivot_root mount_root reboot sync kill sleep \
50 md5sum hexdump cat zcat bzcat dd tar \
51 ls basename find cp mv rm mkdir rmdir mknod touch chmod \
52 '[' printf wc grep awk sed cut \
53 mtd partx losetup mkfs.ext4 \
54 ubiupdatevol ubiattach ubiblock ubiformat \
55 ubidetach ubirsvol ubirmvol ubimkvol \
56 snapshot snapshot_tool \
57 $RAMFS_COPY_BIN
58 do
59 local file="$(which "$binary" 2>/dev/null)"
60 [ -n "$file" ] && install_bin "$file"
61 done
62 install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA
63
64 [ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64
65
66 supivot $RAM_ROOT /mnt || {
67 echo "Failed to switch over to ramfs. Please reboot."
68 exit 1
69 }
70
71 /bin/mount -o remount,ro /mnt
72 /bin/umount -l /mnt
73
74 grep /overlay /proc/mounts > /dev/null && {
75 /bin/mount -o noatime,remount,ro /overlay
76 /bin/umount -l /overlay
77 }
78 }
79
80 kill_remaining() { # [ <signal> [ <loop> ] ]
81 local loop_limit=10
82
83 local sig="${1:-TERM}"
84 local loop="${2:-0}"
85 local run=true
86 local stat
87 local proc_ppid=$(cut -d' ' -f4 /proc/$$/stat)
88
89 echo -n "Sending $sig to remaining processes ... "
90
91 while $run; do
92 run=false
93 for stat in /proc/[0-9]*/stat; do
94 [ -f "$stat" ] || continue
95
96 local pid name state ppid rest
97 read pid name state ppid rest < $stat
98 name="${name#(}"; name="${name%)}"
99
100 # Skip PID1, our parent, ourself and our children
101 [ $pid -ne 1 -a $pid -ne $proc_ppid -a $pid -ne $$ -a $ppid -ne $$ ] || continue
102
103 local cmdline
104 read cmdline < /proc/$pid/cmdline
105
106 # Skip kernel threads
107 [ -n "$cmdline" ] || continue
108
109 echo -n "$name "
110 kill -$sig $pid 2>/dev/null
111
112 [ $loop -eq 1 ] && run=true
113 done
114
115 let loop_limit--
116 [ $loop_limit -eq 0 ] && {
117 echo
118 echo "Failed to kill all processes."
119 exit 1
120 }
121 done
122 echo
123 }
124
125 indicate_upgrade
126
127 killall -9 telnetd
128 killall -9 dropbear
129 killall -9 ash
130
131 kill_remaining TERM
132 sleep 3
133 kill_remaining KILL 1
134
135 sleep 1
136
137
138 if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
139 platform_pre_upgrade "$IMAGE"
140 fi
141
142 if [ -n "$(rootfs_type)" ]; then
143 echo "Switching to ramdisk..."
144 switch_to_ramfs
145 fi
146
147 # Exec new shell from ramfs
148 exec /bin/busybox ash -c "$COMMAND"