x86: generalize partition discovery for sysupgrade

Backport a few patches to allow sysupgrades on mmcblk and similar block
devices.
This commit is contained in:
Matthias Schiffer 2016-12-20 01:19:32 +01:00
parent 689de50c27
commit 1f08074438
No known key found for this signature in database
GPG Key ID: 16EF3F64CB201D9C
4 changed files with 413 additions and 0 deletions

View File

@ -0,0 +1,135 @@
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Tue, 9 Feb 2016 12:33:17 +0000
Subject: x86: preserve partition table on sysupgrade
With this patch sysupgrade will write directly to the partitions
instead of to the main disk. The UUID is copied from the image
to the MBR as well. This prevents the mbr from being completely
overwritten and losing the partition table. The -p option has
been added to maintain the original behavior and overwite the
entire disk with the new image. Tests have been added to ensure
that the image partitions match up with the active partitions.
Signed-off-by: Rob Mosher <nyt-openwrt@countercultured.net>
Backport of OpenWrt r48682
diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh
index 761b4c17957e2cf63b88025520b6fba59c890255..dc865544f65c16399dcced55b8b09c671b31b5d1 100644
--- a/package/base-files/files/lib/upgrade/common.sh
+++ b/package/base-files/files/lib/upgrade/common.sh
@@ -67,6 +67,7 @@ run_ramfs() { # <command> [...]
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
diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade
index ef83c4b00f1a88ae5d68fc70adf51a6af3dc109c..759c841e131a415c8009995c372cce1f55fb78a0 100755
--- a/package/base-files/files/sbin/sysupgrade
+++ b/package/base-files/files/sbin/sysupgrade
@@ -10,6 +10,7 @@ export INTERACTIVE=0
export VERBOSE=1
export SAVE_CONFIG=1
export SAVE_OVERLAY=0
+export SAVE_PARTITIONS=1
export DELAY=
export CONF_IMAGE=
export CONF_BACKUP_LIST=0
@@ -29,6 +30,7 @@ while [ -n "$1" ]; do
-q) export VERBOSE="$(($VERBOSE - 1))";;
-n) export SAVE_CONFIG=0;;
-c) export SAVE_OVERLAY=1;;
+ -p) export SAVE_PARTITIONS=0;;
-b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
-r|--restore-backup) export CONF_RESTORE="$2" NEED_IMAGE=1; shift;;
-l|--list-backup) export CONF_BACKUP_LIST=1; break;;
@@ -62,6 +64,7 @@ upgrade-option:
-i interactive mode
-c attempt to preserve all changed files in /etc/
-n do not save configuration over reflash
+ -p do not attempt to restore the partition table after flash.
-T | --test
Verify image and config .tar.gz but do not actually flash.
-F | --force
diff --git a/target/linux/x86/Makefile b/target/linux/x86/Makefile
index ba733c02480b248aa95331da2bcd8fee3e25f812..29a232296a02b253344927a61eecb40503473d59 100644
--- a/target/linux/x86/Makefile
+++ b/target/linux/x86/Makefile
@@ -13,6 +13,8 @@ FEATURES:=squashfs ext4 vdi vmdk pcmcia targz
SUBTARGETS=generic xen_domu ep80579 geode kvm_guest rdc 64
MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+DEFAULT_PACKAGES += partx-utils
+
KERNEL_PATCHVER:=3.18
KERNELNAME:=bzImage
diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh
index adc119c897ed840aef17c2041a48244d0922564e..c21f1a7e5feba553110f138c14977daaa472da70 100644
--- a/target/linux/x86/base-files/lib/upgrade/platform.sh
+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh
@@ -55,12 +55,59 @@ platform_copy_config() {
fi
}
+get_partitions() { # <device> <filename>
+ local disk="$1"
+ local filename="$2"
+
+ if [ -b "$disk" -o -f "$disk" ]; then
+ echo "Reading partition table from $filename..."
+ partx -r "$disk" -gbo NR,START,SECTORS > "/tmp/partx.$filename"
+ fi
+}
+
platform_do_upgrade() {
platform_export_bootpart
+ disk="${BOOTPART%[0-9]}"
- if [ -b "${BOOTPART%[0-9]}" ]; then
+ if [ -b "$disk" ]; then
sync
- get_image "$@" | dd of="${BOOTPART%[0-9]}" bs=4096 conv=fsync
+ if [ "$SAVE_PARTITIONS" = "1" ]; then
+ get_partitions "$disk" bootdisk
+
+
+ #get block size
+ sectors="$(partx -r $disk -gbo SECTORS --nr 1:1)"
+ size="$(partx -r $disk -gbo SIZE --nr 1:1)"
+ ibs="$(($size / $sectors))"
+
+ #extract the boot sector from the image
+ get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b
+
+ get_partitions /tmp/image.bs image
+
+ #compare tables
+ diff="$(grep -F -x -v -f /tmp/partx.bootdisk /tmp/partx.image)"
+ if [ -n "$diff" ]; then
+ echo "Partition layout is changed. Full image will be written."
+ ask_bool 0 "Abort" && exit
+
+ get_image "$@" | dd of="$disk" bs=4096 conv=fsync
+ return 0
+ fi
+
+ #iterate over each partition from the image and write it to the boot disk
+ while read part start size; do
+ echo "Writing image to $disk$part..."
+ get_image "$@" | dd of="$disk$part" ibs="$ibs" obs=1M skip="$start" count="$size" conv=fsync
+ done < /tmp/partx.image
+
+ #copy partition uuid
+ echo "Writing new UUID to $disk$part..."
+ get_image "$@" | dd of="$disk" bs=1 skip=440 count=4 seek=440 conv=fsync
+ else
+ get_image "$@" | dd of="$disk" bs=4096 conv=fsync
+ fi
+
sleep 1
fi
}

View File

@ -0,0 +1,74 @@
From: Jo-Philipp Wich <jo@mein.io>
Date: Wed, 30 Mar 2016 03:10:51 +0200
Subject: x86: make sysupgrade work without partx
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Backport of LEDE 9f422eba7c1a297a96a03b1cce05fa3cb9d71a4a
diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh
index c21f1a7e5feba553110f138c14977daaa472da70..f12deebf6484df6f3f69e453ad67688a76d57972 100644
--- a/target/linux/x86/base-files/lib/upgrade/platform.sh
+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh
@@ -61,7 +61,27 @@ get_partitions() { # <device> <filename>
if [ -b "$disk" -o -f "$disk" ]; then
echo "Reading partition table from $filename..."
- partx -r "$disk" -gbo NR,START,SECTORS > "/tmp/partx.$filename"
+
+ local magic="$(hexdump -v -n 2 -s 0x1FE -e '1/2 "0x%04X"' "$disk")"
+ if [ "$magic" != 0xAA55 ]; then
+ echo "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="$(($1 % 256))"
+ local lba="$(($2))"
+ local num="$(($3))"
+
+ [ $type -gt 0 ] || continue
+
+ printf "%2d %5d %7d\n" $part $lba $num >> "/tmp/partmap.$filename"
+ done
fi
}
@@ -76,9 +96,11 @@ platform_do_upgrade() {
#get block size
- sectors="$(partx -r $disk -gbo SECTORS --nr 1:1)"
- size="$(partx -r $disk -gbo SIZE --nr 1:1)"
- ibs="$(($size / $sectors))"
+ if [ -f "/sys/block/${disk##*/}/queue/physical_block_size" ]; then
+ ibs="$(cat "/sys/block/${disk##*/}/queue/physical_block_size")"
+ else
+ ibs=512
+ fi
#extract the boot sector from the image
get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b
@@ -86,7 +108,7 @@ platform_do_upgrade() {
get_partitions /tmp/image.bs image
#compare tables
- diff="$(grep -F -x -v -f /tmp/partx.bootdisk /tmp/partx.image)"
+ diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
if [ -n "$diff" ]; then
echo "Partition layout is changed. Full image will be written."
ask_bool 0 "Abort" && exit
@@ -99,7 +121,7 @@ platform_do_upgrade() {
while read part start size; do
echo "Writing image to $disk$part..."
get_image "$@" | dd of="$disk$part" ibs="$ibs" obs=1M skip="$start" count="$size" conv=fsync
- done < /tmp/partx.image
+ done < /tmp/partmap.image
#copy partition uuid
echo "Writing new UUID to $disk$part..."

View File

@ -0,0 +1,22 @@
From: Jo-Philipp Wich <jo@mein.io>
Date: Wed, 30 Mar 2016 03:19:23 +0200
Subject: x86: search PARTUUID in any block device
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Backport of LEDE 924fb794bde41eca8289c6cf10322bf6683b4a80
diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh
index f12deebf6484df6f3f69e453ad67688a76d57972..29eac77dfb0ae52f241696f3f62dce7d16106b20 100644
--- a/target/linux/x86/base-files/lib/upgrade/platform.sh
+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh
@@ -17,7 +17,8 @@ platform_export_bootpart() {
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 /dev/[hsv]d[a-z] /dev/xvd[a-z]; do
+ for disk in /dev/*; do
+ [ -b "$disk" ] || continue
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
export BOOTPART="${disk}1"

View File

@ -0,0 +1,182 @@
From: Jo-Philipp Wich <jo@mein.io>
Date: Tue, 24 May 2016 12:07:02 +0200
Subject: x86: generalize partition discovery for sysupgrade
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>
Backport of LEDE 1012701014bd944197031a3c0023527861b521b4
diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh
index dc865544f65c16399dcced55b8b09c671b31b5d1..14684959dd46d04b1c4b72213dbe06943ae64686 100644
--- a/package/base-files/files/lib/upgrade/common.sh
+++ b/package/base-files/files/lib/upgrade/common.sh
@@ -53,7 +53,7 @@ run_ramfs() { # <command> [...]
/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
install_bin /sbin/mtd
install_bin /sbin/mount_root
diff --git a/target/linux/x86/base-files/lib/preinit/79_move_config b/target/linux/x86/base-files/lib/preinit/79_move_config
index 1d4873d78b480cb3f11e04e6246559417b431a8a..5ac81cb90d1c15782a9c4f271720cfa66d6d03a9 100644
--- a/target/linux/x86/base-files/lib/preinit/79_move_config
+++ b/target/linux/x86/base-files/lib/preinit/79_move_config
@@ -2,10 +2,12 @@
# Copyright (C) 2012-2015 OpenWrt.org
move_config() {
+ local partdev
+
. /lib/upgrade/platform.sh
- if platform_export_bootpart; then
- mount -t ext4 -o rw,noatime "$BOOTPART" /mnt
+ if platform_export_bootdevice && platform_export_partdevice partdev 1; then
+ mount -t ext4 -o rw,noatime "/dev/$partdev" /mnt
mv -f /mnt/sysupgrade.tgz /
umount /mnt
fi
diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh
index 29eac77dfb0ae52f241696f3f62dce7d16106b20..c8bc3f7f608fc82ee3afc049b64af3a740fd2c37 100644
--- a/target/linux/x86/base-files/lib/upgrade/platform.sh
+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh
@@ -1,5 +1,21 @@
-platform_export_bootpart() {
- local cmdline uuid disk
+platform_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
+}
+
+platform_export_bootdevice() {
+ local cmdline uuid disk uevent
+ local MAJOR MINOR DEVNAME DEVTYPE
if read cmdline < /proc/cmdline; then
case "$cmdline" in
@@ -17,20 +33,27 @@ platform_export_bootpart() {
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 /dev/*; do
- [ -b "$disk" ] || continue
+ 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
- export BOOTPART="${disk}1"
- return 0
+ uevent="/sys/class/block/${disk##*/}/uevent"
+ break
fi
done
;;
/dev/*)
- export BOOTPART="${disk%[0-9]}1"
- return 0
+ 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
@@ -49,8 +72,10 @@ platform_check_image() {
}
platform_copy_config() {
- if [ -b "$BOOTPART" ]; then
- mount -t ext4 -o rw,noatime "$BOOTPART" /mnt
+ local partdev
+
+ if platform_export_partdevice partdev 1; then
+ mount -t ext4 -o rw,noatime "/dev/$partdev" /mnt
cp -af "$CONF_TAR" /mnt/
umount /mnt
fi
@@ -87,18 +112,16 @@ get_partitions() { # <device> <filename>
}
platform_do_upgrade() {
- platform_export_bootpart
- disk="${BOOTPART%[0-9]}"
+ local diskdev partdev ibs diff
- if [ -b "$disk" ]; then
+ if platform_export_bootdevice && platform_export_partdevice diskdev 0; then
sync
if [ "$SAVE_PARTITIONS" = "1" ]; then
- get_partitions "$disk" bootdisk
-
+ get_partitions "/dev/$diskdev" bootdisk
#get block size
- if [ -f "/sys/block/${disk##*/}/queue/physical_block_size" ]; then
- ibs="$(cat "/sys/block/${disk##*/}/queue/physical_block_size")"
+ if [ -f "/sys/block/$diskdev/queue/physical_block_size" ]; then
+ ibs="$(cat "/sys/block/$diskdev/queue/physical_block_size")"
else
ibs=512
fi
@@ -114,21 +137,25 @@ platform_do_upgrade() {
echo "Partition layout is changed. Full image will be written."
ask_bool 0 "Abort" && exit
- get_image "$@" | dd of="$disk" bs=4096 conv=fsync
+ get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync
return 0
fi
#iterate over each partition from the image and write it to the boot disk
while read part start size; do
- echo "Writing image to $disk$part..."
- get_image "$@" | dd of="$disk$part" ibs="$ibs" obs=1M skip="$start" count="$size" conv=fsync
+ if platform_export_partdevice partdev $part; then
+ echo "Writing image to /dev/$partdev..."
+ get_image "$@" | dd of="/dev/$partdev" ibs="$ibs" obs=1M skip="$start" count="$size" conv=fsync
+ else
+ echo "Unable to find partition $part device, skipped."
+ fi
done < /tmp/partmap.image
#copy partition uuid
- echo "Writing new UUID to $disk$part..."
- get_image "$@" | dd of="$disk" bs=1 skip=440 count=4 seek=440 conv=fsync
+ echo "Writing new UUID to /dev/$diskdev..."
+ get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
else
- get_image "$@" | dd of="$disk" bs=4096 conv=fsync
+ get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync
fi
sleep 1