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>

SVN-Revision: 48682
lede-17.01
Jo-Philipp Wich 2016-02-09 12:33:17 +00:00
parent 6b73b7a8ec
commit 4aeeead303
4 changed files with 55 additions and 2 deletions

View File

@ -68,6 +68,7 @@ run_ramfs() { # <command> [...]
install_bin /usr/sbin/ubirsvol install_bin /usr/sbin/ubirsvol
install_bin /usr/sbin/ubirmvol install_bin /usr/sbin/ubirmvol
install_bin /usr/sbin/ubimkvol install_bin /usr/sbin/ubimkvol
install_bin /usr/sbin/partx
for file in $RAMFS_COPY_BIN; do for file in $RAMFS_COPY_BIN; do
install_bin ${file//:/ } install_bin ${file//:/ }
done done

View File

@ -10,6 +10,7 @@ export INTERACTIVE=0
export VERBOSE=1 export VERBOSE=1
export SAVE_CONFIG=1 export SAVE_CONFIG=1
export SAVE_OVERLAY=0 export SAVE_OVERLAY=0
export SAVE_PARTITIONS=1
export DELAY= export DELAY=
export CONF_IMAGE= export CONF_IMAGE=
export CONF_BACKUP_LIST=0 export CONF_BACKUP_LIST=0
@ -29,6 +30,7 @@ while [ -n "$1" ]; do
-q) export VERBOSE="$(($VERBOSE - 1))";; -q) export VERBOSE="$(($VERBOSE - 1))";;
-n) export SAVE_CONFIG=0;; -n) export SAVE_CONFIG=0;;
-c) export SAVE_OVERLAY=1;; -c) export SAVE_OVERLAY=1;;
-p) export SAVE_PARTITIONS=0;;
-b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;; -b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
-r|--restore-backup) export CONF_RESTORE="$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;; -l|--list-backup) export CONF_BACKUP_LIST=1; break;;
@ -62,6 +64,7 @@ upgrade-option:
-i interactive mode -i interactive mode
-c attempt to preserve all changed files in /etc/ -c attempt to preserve all changed files in /etc/
-n do not save configuration over reflash -n do not save configuration over reflash
-p do not attempt to restore the partition table after flash.
-T | --test -T | --test
Verify image and config .tar.gz but do not actually flash. Verify image and config .tar.gz but do not actually flash.
-F | --force -F | --force

View File

@ -13,6 +13,8 @@ FEATURES:=squashfs ext4 vdi vmdk pcmcia targz
SUBTARGETS=generic xen_domu ep80579 geode kvm_guest 64 SUBTARGETS=generic xen_domu ep80579 geode kvm_guest 64
MAINTAINER:=Felix Fietkau <nbd@openwrt.org> MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
DEFAULT_PACKAGES += partx-utils
KERNEL_PATCHVER:=4.4 KERNEL_PATCHVER:=4.4
KERNELNAME:=bzImage KERNELNAME:=bzImage

View File

@ -55,12 +55,59 @@ platform_copy_config() {
fi 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_do_upgrade() {
platform_export_bootpart platform_export_bootpart
disk="${BOOTPART%[0-9]}"
if [ -b "${BOOTPART%[0-9]}" ]; then if [ -b "$disk" ]; then
sync 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 sleep 1
fi fi
} }