From f6c527b9a5acdcead5d23a0ebe4aa03443b0d304 Mon Sep 17 00:00:00 2001 From: Jan Schneider Date: Thu, 31 May 2018 13:28:31 +0200 Subject: [PATCH] Enable firmware update with userfs on usb storage --- addon/firmware_update_script | 150 +++++++++++++++++++---------------- addon/lib/rmupdate.tcl | 81 +++++++++++++++---- 2 files changed, 147 insertions(+), 84 deletions(-) diff --git a/addon/firmware_update_script b/addon/firmware_update_script index db57c7c..5ed90ae 100644 --- a/addon/firmware_update_script +++ b/addon/firmware_update_script @@ -3,14 +3,8 @@ DISK="/dev/mmcblk0" BOOT_SIZE=268435456 ROOT_SIZE=1073741824 - - -echo "Deleting update_script.
" 1>&2 -mount -o remount,rw /userfs -rm -f "$0" -mount -o remount,ro /userfs - -echo "Checking for rootfs2 on $DISK.
" 1>&2 +REPARTITION=0 +RELABEL=0 function start_sshd() { echo "Starting ssh daemon.
" 1>&2 @@ -20,68 +14,86 @@ function start_sshd() { /etc/init.d/S50sshd start } -if blkid ${DISK}p3 | grep 'LABEL="rootfs2"' 1>/dev/null 2>/dev/null; then - echo "Rootfs2 found.
" 1>&2 +function repartition() { + echo "Checking for rootfs2 on $DISK.
" 1>&2 - start_sshd - - cp /bootfs/VERSION /tmp/bootfs.VERSION - umount /bootfs - umount /rootfs - - echo "Current partition table:
" 1>&2 - parted $DISK unit B print | sed ':a;N;$!ba;s#\n#
#g' 1>&2 - - boot_start=$(parted $DISK unit B print | grep '^ 1' | sed -n 's/ [1-4] *\([0-9]*\)B *\([0-9]*\)B.*/\1/p') - user_start=$(parted $DISK unit B print | grep '^ 4' | sed -n 's/ [1-4] *\([0-9]*\)B *\([0-9]*\)B.*/\1/p') - user_end=$(parted $DISK unit B print | grep '^ 4' | sed -n 's/ [1-4] *\([0-9]*\)B *\([0-9]*\)B.*/\2/p') - - boot_end=$(($boot_start+$BOOT_SIZE-1)) - root_start=$(($boot_end+1)) - root_end=$(($root_start+$ROOT_SIZE-1)) - - boot_start_s=$((${boot_start}/512)) - boot_size_s=$(((${boot_end}-${boot_start}+1)/512)) - root_start_s=$((${root_start}/512)) - root_size_s=$(((${root_end}-${root_start}+1)/512)) - user_start_s=$((${user_start}/512)) - user_size_s=$(((${user_end}-${user_start}+1)/512)) - - echo "Calculated new partition layout:
" 1>&2 - echo " bootfs: $boot_start ($boot_start_s) - $boot_end - $boot_size_s
" 1>&2 - echo " rootfs: $root_start ($root_start_s) - $root_end - $root_size_s
" 1>&2 - echo " userfs: $user_start ($user_start_s) - $user_end - $user_size_s
" 1>&2 - - echo "Writing new partition table to disk.
" 1>&2 - # parted will refuse to write partition table because partitions are mounted - #parted --script $DISK \ - # mklabel msdos \ - # mkpart primary fat32 ${boot_start}B ${boot_end}B \ - # set 1 boot on \ - # mkpart primary ext4 ${root_start}B ${root_end}B \ - # mkpart primary ext4 ${user_start}B ${user_end}B - - { - echo "$boot_start_s,$boot_size_s,0x0C,*" - echo "$root_start_s,$root_size_s,0x83" - echo "$user_start_s,$user_size_s,0x83" - ,0 - } | sfdisk --no-reread --force --wipe=always --label=dos $DISK 2>&1 | sed ':a;N;$!ba;s#\n#
#g' 1>&2 - - # Use dd to write label id - printf "\xde\xed\xbe\xef" | dd of=$DISK bs=1 count=4 seek=440 - - #echo "New partition table:
" 1>&2 - #parted $DISK unit B print | sed ':a;N;$!ba;s#\n#
#g' 1>&2 - - partprobe - - # RaspberryMatic will check for label rootfs and VERSION file - mkfs.ext4 -L rootfs ${DISK}p2 - mount ${DISK}p2 /rootfs - cp /tmp/bootfs.VERSION /rootfs/VERSION - umount /rootfs -fi + if blkid ${DISK}p3 | grep 'LABEL="rootfs2"' 1>/dev/null 2>/dev/null; then + echo "Rootfs2 found.
" 1>&2 + + cp /bootfs/VERSION /tmp/bootfs.VERSION + umount /bootfs + umount /rootfs + + echo "Current partition table:
" 1>&2 + parted $DISK unit B print | sed ':a;N;$!ba;s#\n#
#g' 1>&2 + + boot_start=$(parted $DISK unit B print | grep '^ 1' | sed -n 's/ [1-4] *\([0-9]*\)B *\([0-9]*\)B.*/\1/p') + user_start=$(parted $DISK unit B print | grep '^ 4' | sed -n 's/ [1-4] *\([0-9]*\)B *\([0-9]*\)B.*/\1/p') + user_end=$(parted $DISK unit B print | grep '^ 4' | sed -n 's/ [1-4] *\([0-9]*\)B *\([0-9]*\)B.*/\2/p') + + boot_end=$(($boot_start+$BOOT_SIZE-1)) + root_start=$(($boot_end+1)) + root_end=$(($root_start+$ROOT_SIZE-1)) + + boot_start_s=$((${boot_start}/512)) + boot_size_s=$(((${boot_end}-${boot_start}+1)/512)) + root_start_s=$((${root_start}/512)) + root_size_s=$(((${root_end}-${root_start}+1)/512)) + user_start_s=$((${user_start}/512)) + user_size_s=$(((${user_end}-${user_start}+1)/512)) + + echo "Calculated new partition layout:
" 1>&2 + echo " bootfs: $boot_start ($boot_start_s) - $boot_end - $boot_size_s
" 1>&2 + echo " rootfs: $root_start ($root_start_s) - $root_end - $root_size_s
" 1>&2 + echo " userfs: $user_start ($user_start_s) - $user_end - $user_size_s
" 1>&2 + + echo "Writing new partition table to disk.
" 1>&2 + # parted will refuse to write partition table because partitions are mounted + #parted --script $DISK \ + # mklabel msdos \ + # mkpart primary fat32 ${boot_start}B ${boot_end}B \ + # set 1 boot on \ + # mkpart primary ext4 ${root_start}B ${root_end}B \ + # mkpart primary ext4 ${user_start}B ${user_end}B + + { + echo "$boot_start_s,$boot_size_s,0x0C,*" + echo "$root_start_s,$root_size_s,0x83" + echo "$user_start_s,$user_size_s,0x83" + ,0 + } | sfdisk --no-reread --force --wipe=always --label=dos $DISK 2>&1 | sed ':a;N;$!ba;s#\n#
#g' 1>&2 + + # Use dd to write label id + printf "\xef\xbe\xed\xde" | dd of=$DISK bs=1 count=4 seek=440 + + #echo "New partition table:
" 1>&2 + #parted $DISK unit B print | sed ':a;N;$!ba;s#\n#
#g' 1>&2 + + partprobe + + # RaspberryMatic will check for label rootfs and VERSION file + mkfs.ext4 -L rootfs ${DISK}p2 + mount ${DISK}p2 /rootfs + cp /tmp/bootfs.VERSION /rootfs/VERSION + umount /rootfs + fi +} + +function relabel() { + user=$(readlink -f /dev/disk/by-label/userfs) + user0=$(readlink -f /dev/disk/by-label/0userfs) + tune2fs -L 0userfs $user + tune2fs -L userfs $user0 +} + +echo "Deleting update_script.
" 1>&2 +mount -o remount,rw /userfs +rm -f "$0" +mount -o remount,ro /userfs + +start_sshd +[ "$RELABEL" = "1" ] && relabel +[ "$REPARTITION" = "1" ] && repartition echo "Running fwinstall.sh (again).
" 1>&2 rm -f /tmp/.runningFirmwareUpdate diff --git a/addon/lib/rmupdate.tcl b/addon/lib/rmupdate.tcl index 35e8160..acd19fc 100644 --- a/addon/lib/rmupdate.tcl +++ b/addon/lib/rmupdate.tcl @@ -469,7 +469,7 @@ proc ::rmupdate::update_cmdline {cmdline root} { close $fd } -proc ::rmupdate::update_boot_scr {boot_scr root} { +proc ::rmupdate::update_boot_scr {boot_scr rootfs userfs} { set boot_script "/tmp/boot.script" catch { exec /bin/dd if=$boot_scr of=$boot_script bs=72 skip=1 } @@ -478,8 +478,8 @@ proc ::rmupdate::update_boot_scr {boot_scr root} { set data [read $fd] close $fd - regsub -all "setenv rootfs \[0-9\]" $data "setenv rootfs ${root}" data - regsub -all "setenv userfs \[0-9\]" $data "setenv userfs 4" data + regsub -all "setenv rootfs \[0-9\]" $data "setenv rootfs ${rootfs}" data + regsub -all "setenv userfs \[0-9\]" $data "setenv userfs ${userfs}" data set fd [open $boot_script w] puts -nonewline $fd $data @@ -749,7 +749,7 @@ proc ::rmupdate::update_filesystems {image {dryrun 0}} { } set part_uuid [get_part_uuid $sys_dev $new_root_partition_number] if {[file exists "${mnt_s}/boot.scr"]} { - update_boot_scr "${mnt_s}/boot.scr" $new_root_partition_number + update_boot_scr "${mnt_s}/boot.scr" $new_root_partition_number 4 } elseif {[file exists "${mnt_s}/extlinux/extlinux.conf"]} { update_cmdline "${mnt_s}/extlinux/extlinux.conf" "PARTUUID=${part_uuid}" } elseif {[file exists "${mnt_s}/cmdline.txt"]} { @@ -842,7 +842,7 @@ proc ::rmupdate::move_userfs_to_device {target_device {sync_data 0} {repartition } set target_partition_device [get_partition_device $target_device $partition_number] } - + if {$sync_data == 1} { catch { exec /bin/umount $target_partition_device } set exitcode [catch { exec /sbin/mkfs.ext4 -F -L userfs $target_partition_device } output] @@ -863,7 +863,7 @@ proc ::rmupdate::move_userfs_to_device {target_device {sync_data 0} {repartition error $output } } - + catch { exec /sbin/tune2fs -L 0userfs $source_partition_device } catch { exec /sbin/tune2fs -L userfs $target_partition_device } } @@ -1301,27 +1301,78 @@ proc ::rmupdate::install_firmware {{download_url ""} {version ""} {lang ""} {reb if {$use_recovery} { # Use recovery system firmware update feature write_install_log "Using recovery system to update firmware." - set tmp_dir "/usr/local/tmp" - catch { file mkdir $tmp_dir } - catch { file delete "${tmp_dir}/new_firmware.img" } - catch { file delete /usr/local/.firmwareUpdate } + set usr_local "/usr/local" + + # Test if userfs is on the same device as bootfs + set boot_dev "" + set user_dev "" + set user_part "" + set user0_part "" + set use_user0 0 + foreach d [split [exec /sbin/blkid] "\n"] { + if {[regexp {^(/dev.*)(\d):.*LABEL="([^"]+)"} $d match dev pnum lab]} { + if {$lab == "bootfs"} { + set boot_dev $dev + } elseif {$lab == "userfs"} { + set user_dev $dev + set user_part "${dev}${pnum}" + } elseif {$lab == "0userfs"} { + set user0_part "${dev}${pnum}" + } + } + } if {!$dryrun} { + if {$boot_dev != "" && $user_dev != "" && $boot_dev != $user_dev} { + if {$user0_part == ""} { + error "userfs0 not found" + } + set usr_local "/tmp/mnt_user0" + set use_user0 1 + if {[file exists $usr_local]} { + catch {exec /bin/umount "${usr_local}"} + } else { + file mkdir $usr_local + } + catch {exec /bin/mount $user0_part "${usr_local}"} + } + set tmp_dir "${usr_local}/tmp" + catch { file mkdir $tmp_dir } + catch { file delete "${tmp_dir}/new_firmware.img" } + catch { file delete "${usr_local}/.firmwareUpdate" } if {$version == "" || $keep_download == 0} { file rename -force $firmware_image "${tmp_dir}/new_firmware.img" } else { file copy -force $firmware_image "${tmp_dir}/new_firmware.img" } - catch { exec ln -sf $tmp_dir /usr/local/.firmwareUpdate } - set fd [open "/usr/local/.recoveryMode" "w"] + catch { exec ln -sf "/usr/local/tmp" "${usr_local}/.firmwareUpdate" } + + set fd [open "${usr_local}/.recoveryMode" "w"] close $fd + + file copy -force "${addon_dir}/firmware_update_script" "${tmp_dir}/update_script" + file attributes "${tmp_dir}/update_script" -permissions 0755 if { [get_filesystem_label $sys_dev 3] == "rootfs2" } { - file copy -force "${addon_dir}/update_script_repartition" "${tmp_dir}/update_script" - file attributes "${tmp_dir}/update_script" -permissions 0755 + exec /bin/sed -i s/REPARTITION=0/REPARTITION=1/ "${tmp_dir}/update_script" # Ensure correct partition number for userfs exec /bin/mount -o remount,rw "/boot" - update_boot_scr "/boot/boot.scr" 2 + update_boot_scr "/boot/boot.scr" 2 4 exec /bin/mount -o remount,ro "/boot" } + + #exec /bin/mount -o remount,rw "/boot" + #set fd [open "/boot/recoveryfs-sshpwd" "w"] + #puts -nonewline $fd "rmupdate" + #close $fd + #exec /bin/mount -o remount,ro "/boot" + + if {$use_user0} { + exec /bin/sed -i s/RELABEL=0/RELABEL=1/ "${tmp_dir}/update_script" + exec /bin/umount "${usr_local}" + file delete $usr_local + catch { exec /sbin/tune2fs -L 0userfs $user_part } + catch { exec /sbin/tune2fs -L userfs $user0_part } + } + set reboot 1 } } else {