1012701014
Generalize the partition discovery in sysupgrade in order to fix sysupgrade and config backup/recovery on MMC block devices which use a different naming scheme compared to mtdblock or sd* devices. The change also adds the find applet to the ramdisk utilities so that upgrade code can rely on it. The commit is based on the initial submission by Russell Senior at http://patchwork.ozlabs.org/patch/625440/ . Signed-off-by: Russell Senior <russell@personaltelco.net> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
250 lines
5.9 KiB
Bash
250 lines
5.9 KiB
Bash
#!/bin/sh
|
|
|
|
RAM_ROOT=/tmp/root
|
|
|
|
[ -x /usr/bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
|
|
libs() { ldd $* 2>/dev/null | sed -r 's/(.* => )?(.*) .*/\2/'; }
|
|
|
|
install_file() { # <file> [ <file> ... ]
|
|
for file in "$@"; do
|
|
dest="$RAM_ROOT/$file"
|
|
[ -f $file -a ! -f $dest ] && {
|
|
dir="$(dirname $dest)"
|
|
mkdir -p "$dir"
|
|
cp $file $dest
|
|
}
|
|
done
|
|
}
|
|
|
|
install_bin() { # <file> [ <symlink> ... ]
|
|
src=$1
|
|
files=$1
|
|
[ -x "$src" ] && files="$src $(libs $src)"
|
|
install_file $files
|
|
shift
|
|
for link in "$@"; do {
|
|
dest="$RAM_ROOT/$link"
|
|
dir="$(dirname $dest)"
|
|
mkdir -p "$dir"
|
|
[ -f "$dest" ] || ln -s $src $dest
|
|
}; done
|
|
}
|
|
|
|
supivot() { # <new_root> <old_root>
|
|
/bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1
|
|
mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \
|
|
/bin/mount -o noatime,move /proc $1/proc && \
|
|
pivot_root $1 $1$2 || {
|
|
/bin/umount -l $1 $1
|
|
return 1
|
|
}
|
|
|
|
/bin/mount -o noatime,move $2/sys /sys
|
|
/bin/mount -o noatime,move $2/dev /dev
|
|
/bin/mount -o noatime,move $2/tmp /tmp
|
|
/bin/mount -o noatime,move $2/overlay /overlay 2>&-
|
|
return 0
|
|
}
|
|
|
|
run_ramfs() { # <command> [...]
|
|
install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \
|
|
/sbin/pivot_root /sbin/reboot /bin/sync /bin/dd /bin/grep \
|
|
/bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" /bin/dd \
|
|
/bin/vi /bin/ls /bin/cat /usr/bin/awk /usr/bin/hexdump \
|
|
/bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc \
|
|
/bin/cut /usr/bin/printf /bin/sync /bin/mkdir /bin/rmdir \
|
|
/bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find
|
|
|
|
install_bin /bin/uclient-fetch /bin/wget
|
|
install_bin /sbin/mtd
|
|
install_bin /sbin/mount_root
|
|
install_bin /sbin/snapshot
|
|
install_bin /sbin/snapshot_tool
|
|
install_bin /usr/sbin/ubiupdatevol
|
|
install_bin /usr/sbin/ubiattach
|
|
install_bin /usr/sbin/ubiblock
|
|
install_bin /usr/sbin/ubiformat
|
|
install_bin /usr/sbin/ubidetach
|
|
install_bin /usr/sbin/ubirsvol
|
|
install_bin /usr/sbin/ubirmvol
|
|
install_bin /usr/sbin/ubimkvol
|
|
install_bin /usr/sbin/partx
|
|
for file in $RAMFS_COPY_BIN; do
|
|
install_bin ${file//:/ }
|
|
done
|
|
install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA
|
|
|
|
[ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64
|
|
|
|
supivot $RAM_ROOT /mnt || {
|
|
echo "Failed to switch over to ramfs. Please reboot."
|
|
exit 1
|
|
}
|
|
|
|
/bin/mount -o remount,ro /mnt
|
|
/bin/umount -l /mnt
|
|
|
|
grep /overlay /proc/mounts > /dev/null && {
|
|
/bin/mount -o noatime,remount,ro /overlay
|
|
/bin/umount -l /overlay
|
|
}
|
|
|
|
# spawn a new shell from ramdisk to reduce the probability of cache issues
|
|
exec /bin/busybox ash -c "$*"
|
|
}
|
|
|
|
kill_remaining() { # [ <signal> ]
|
|
local sig="${1:-TERM}"
|
|
echo -n "Sending $sig to remaining processes ... "
|
|
|
|
local my_pid=$$
|
|
local my_ppid=$(cut -d' ' -f4 /proc/$my_pid/stat)
|
|
local my_ppisupgraded=
|
|
grep -q upgraded /proc/$my_ppid/cmdline >/dev/null && {
|
|
local my_ppisupgraded=1
|
|
}
|
|
|
|
local stat
|
|
for stat in /proc/[0-9]*/stat; do
|
|
[ -f "$stat" ] || continue
|
|
|
|
local pid name state ppid rest
|
|
read pid name state ppid rest < $stat
|
|
name="${name#(}"; name="${name%)}"
|
|
|
|
local cmdline
|
|
read cmdline < /proc/$pid/cmdline
|
|
|
|
# Skip kernel threads
|
|
[ -n "$cmdline" ] || continue
|
|
|
|
if [ $$ -eq 1 ] || [ $my_ppid -eq 1 ] && [ -n "$my_ppisupgraded" ]; then
|
|
# Running as init process, kill everything except me
|
|
if [ $pid -ne $$ ] && [ $pid -ne $my_ppid ]; then
|
|
echo -n "$name "
|
|
kill -$sig $pid 2>/dev/null
|
|
fi
|
|
else
|
|
case "$name" in
|
|
# Skip essential services
|
|
*procd*|*ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*|*nas*) : ;;
|
|
|
|
# Killable process
|
|
*)
|
|
if [ $pid -ne $$ ] && [ $ppid -ne $$ ]; then
|
|
echo -n "$name "
|
|
kill -$sig $pid 2>/dev/null
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
done
|
|
echo ""
|
|
}
|
|
|
|
run_hooks() {
|
|
local arg="$1"; shift
|
|
for func in "$@"; do
|
|
eval "$func $arg"
|
|
done
|
|
}
|
|
|
|
ask_bool() {
|
|
local default="$1"; shift;
|
|
local answer="$default"
|
|
|
|
[ "$INTERACTIVE" -eq 1 ] && {
|
|
case "$default" in
|
|
0) echo -n "$* (y/N): ";;
|
|
*) echo -n "$* (Y/n): ";;
|
|
esac
|
|
read answer
|
|
case "$answer" in
|
|
y*) answer=1;;
|
|
n*) answer=0;;
|
|
*) answer="$default";;
|
|
esac
|
|
}
|
|
[ "$answer" -gt 0 ]
|
|
}
|
|
|
|
v() {
|
|
[ "$VERBOSE" -ge 1 ] && echo "$@"
|
|
}
|
|
|
|
rootfs_type() {
|
|
/bin/mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }'
|
|
}
|
|
|
|
get_image() { # <source> [ <command> ]
|
|
local from="$1"
|
|
local conc="$2"
|
|
local cmd
|
|
|
|
case "$from" in
|
|
http://*|ftp://*) cmd="wget -O- -q";;
|
|
*) cmd="cat";;
|
|
esac
|
|
if [ -z "$conc" ]; then
|
|
local magic="$(eval $cmd \"$from\" 2>/dev/null | dd bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
|
|
case "$magic" in
|
|
1f8b) conc="zcat";;
|
|
425a) conc="bzcat";;
|
|
esac
|
|
fi
|
|
|
|
eval "$cmd \"$from\" 2>/dev/null ${conc:+| $conc}"
|
|
}
|
|
|
|
get_magic_word() {
|
|
(get_image "$@" | dd bs=2 count=1 | hexdump -v -n 2 -e '1/1 "%02x"') 2>/dev/null
|
|
}
|
|
|
|
get_magic_long() {
|
|
(get_image "$@" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2>/dev/null
|
|
}
|
|
|
|
jffs2_copy_config() {
|
|
if grep rootfs_data /proc/mtd >/dev/null; then
|
|
# squashfs+jffs2
|
|
mtd -e rootfs_data jffs2write "$CONF_TAR" rootfs_data
|
|
else
|
|
# jffs2
|
|
mtd jffs2write "$CONF_TAR" rootfs
|
|
fi
|
|
}
|
|
|
|
# Flash firmware to MTD partition
|
|
#
|
|
# $(1): path to image
|
|
# $(2): (optional) pipe command to extract firmware, e.g. dd bs=n skip=m
|
|
default_do_upgrade() {
|
|
sync
|
|
if [ "$SAVE_CONFIG" -eq 1 ]; then
|
|
get_image "$1" "$2" | mtd $MTD_CONFIG_ARGS -j "$CONF_TAR" write - "${PART_NAME:-image}"
|
|
else
|
|
get_image "$1" "$2" | mtd write - "${PART_NAME:-image}"
|
|
fi
|
|
}
|
|
|
|
do_upgrade() {
|
|
v "Performing system upgrade..."
|
|
if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
|
|
platform_do_upgrade "$ARGV"
|
|
else
|
|
default_do_upgrade "$ARGV"
|
|
fi
|
|
|
|
if [ "$SAVE_CONFIG" -eq 1 ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then
|
|
platform_copy_config
|
|
fi
|
|
|
|
v "Upgrade completed"
|
|
[ -n "$DELAY" ] && sleep "$DELAY"
|
|
ask_bool 1 "Reboot" && {
|
|
v "Rebooting system..."
|
|
reboot -f
|
|
sleep 5
|
|
echo b 2>/dev/null >/proc/sysrq-trigger
|
|
}
|
|
}
|