base-files: upgrade: make get_partitions() endian agnostic
[openwrt/openwrt.git] / package / base-files / files / lib / upgrade / common.sh
index ba9de99dc90d1991c134c121dba79ee975b4c87b..3ddd1e74657e0f9893533f917cb56ed0c2e3196c 100644 (file)
@@ -2,8 +2,8 @@
 
 RAM_ROOT=/tmp/root
 
-ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
-libs() { ldd $* | awk '{print $3}'; }
+[ -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
@@ -21,9 +21,6 @@ install_bin() { # <file> [ <symlink> ... ]
        files=$1
        [ -x "$src" ] && files="$src $(libs $src)"
        install_file $files
-       [ -e /lib/ld.so.1 ] && {
-               install_file /lib/ld.so.1
-       }
        shift
        for link in "$@"; do {
                dest="$RAM_ROOT/$link"
@@ -51,15 +48,16 @@ supivot() { # <new_root> <old_root>
 
 run_ramfs() { # <command> [...]
        install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount        \
-               /sbin/pivot_root /usr/bin/wget /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  \
+               /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
+               /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \
+               /bin/mknod
 
+       install_bin /bin/uclient-fetch /bin/wget
        install_bin /sbin/mtd
-       install_bin /sbin/ubi
        install_bin /sbin/mount_root
        install_bin /sbin/snapshot
        install_bin /sbin/snapshot_tool
@@ -71,6 +69,9 @@ run_ramfs() { # <command> [...]
        install_bin /usr/sbin/ubirsvol
        install_bin /usr/sbin/ubirmvol
        install_bin /usr/sbin/ubimkvol
+       install_bin /usr/sbin/partx
+       install_bin /usr/sbin/losetup
+       install_bin /usr/sbin/mkfs.ext4
        for file in $RAMFS_COPY_BIN; do
                install_bin ${file//:/ }
        done
@@ -129,7 +130,7 @@ kill_remaining() { # [ <signal> ]
                else 
                        case "$name" in
                                # Skip essential services
-                               *procd*|*ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*|*nas*) : ;;
+                               *procd*|*ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*|*nas*|*relayd*) : ;;
 
                                # Killable process
                                *)
@@ -188,14 +189,14 @@ get_image() { # <source> [ <command> ]
                *) 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"')"
+               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}"
+       eval "$cmd \"$from\" 2>/dev/null ${conc:+| $conc}"
 }
 
 get_magic_word() {
@@ -206,6 +207,104 @@ get_magic_long() {
        (get_image "$@" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2>/dev/null
 }
 
+export_bootdevice() {
+       local cmdline uuid disk uevent
+       local MAJOR MINOR DEVNAME DEVTYPE
+
+       if read cmdline < /proc/cmdline; then
+               case "$cmdline" in
+                       *block2mtd=*)
+                               disk="${cmdline##*block2mtd=}"
+                               disk="${disk%%,*}"
+                       ;;
+                       *root=*)
+                               disk="${cmdline##*root=}"
+                               disk="${disk%% *}"
+                       ;;
+               esac
+
+               case "$disk" in
+                       PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-02)
+                               uuid="${disk#PARTUUID=}"
+                               uuid="${uuid%-02}"
+                               for disk in $(find /dev -type b); do
+                                       set -- $(dd if=$disk bs=1 skip=440 count=4 2>/dev/null | hexdump -v -e '4/1 "%02x "')
+                                       if [ "$4$3$2$1" = "$uuid" ]; then
+                                               uevent="/sys/class/block/${disk##*/}/uevent"
+                                               break
+                                       fi
+                               done
+                       ;;
+                       /dev/*)
+                               uevent="/sys/class/block/${disk##*/}/uevent"
+                       ;;
+               esac
+
+               if [ -e "$uevent" ]; then
+                       . "$uevent"
+
+                       export BOOTDEV_MAJOR=$MAJOR
+                       export BOOTDEV_MINOR=$MINOR
+                       return 0
+               fi
+       fi
+
+       return 1
+}
+
+export_partdevice() {
+       local var="$1" offset="$2"
+       local uevent MAJOR MINOR DEVNAME DEVTYPE
+
+       for uevent in /sys/class/block/*/uevent; do
+               . "$uevent"
+               if [ $BOOTDEV_MAJOR = $MAJOR -a $(($BOOTDEV_MINOR + $offset)) = $MINOR -a -b "/dev/$DEVNAME" ]; then
+                       export "$var=$DEVNAME"
+                       return 0
+               fi
+       done
+
+       return 1
+}
+
+hex_le32_to_cpu() {
+       [ "$(echo 01 | hexdump -v -n 2 -e '/2 "%x"')" == "3031" ] && {
+               echo "${1:0:2}${1:8:2}${1:6:2}${1:4:2}${1:2:2}"
+               return
+       }
+       echo "$@"
+}
+
+get_partitions() { # <device> <filename>
+       local disk="$1"
+       local filename="$2"
+
+       if [ -b "$disk" -o -f "$disk" ]; then
+               v "Reading partition table from $filename..."
+
+               local magic=$(dd if="$disk" bs=2 count=1 skip=255 2>/dev/null)
+               if [ "$magic" != $'\x55\xAA' ]; then
+                       v "Invalid partition table on $disk"
+                       exit
+               fi
+
+               rm -f "/tmp/partmap.$filename"
+
+               local part
+               for part in 1 2 3 4; do
+                       set -- $(hexdump -v -n 12 -s "$((0x1B2 + $part * 16))" -e '3/4 "0x%08X "' "$disk")
+
+                       local type="$(( $(hex_le32_to_cpu $1) % 256))"
+                       local lba="$(( $(hex_le32_to_cpu $2) ))"
+                       local num="$(( $(hex_le32_to_cpu $3) ))"
+
+                       [ $type -gt 0 ] || continue
+
+                       printf "%2d %5d %7d\n" $part $lba $num >> "/tmp/partmap.$filename"
+               done
+       fi
+}
+
 jffs2_copy_config() {
        if grep rootfs_data /proc/mtd >/dev/null; then
                # squashfs+jffs2
@@ -216,12 +315,16 @@ jffs2_copy_config() {
        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" | mtd $MTD_CONFIG_ARGS -j "$CONF_TAR" write - "${PART_NAME:-image}"
+               get_image "$1" "$2" | mtd $MTD_CONFIG_ARGS -j "$CONF_TAR" write - "${PART_NAME:-image}"
        else
-               get_image "$1" | mtd write - "${PART_NAME:-image}"
+               get_image "$1" "$2" | mtd write - "${PART_NAME:-image}"
        fi
 }
 
@@ -241,6 +344,7 @@ do_upgrade() {
        [ -n "$DELAY" ] && sleep "$DELAY"
        ask_bool 1 "Reboot" && {
                v "Rebooting system..."
+               umount -a
                reboot -f
                sleep 5
                echo b 2>/dev/null >/proc/sysrq-trigger