diff options
author | John Bowler <jbowler@nslu2-linux.org> | 2005-07-05 00:21:47 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2005-07-05 00:21:47 +0000 |
commit | b84e7ee4183590765bb0da041ca21bd2a15587e6 (patch) | |
tree | d4c6fd2e7594e4613b99cd8c0429574ea3b2f4d9 | |
parent | 904879ece7a2d48913c08f5b8c617dc676a0c0ba (diff) |
Allow kernel and root partition to be updated in the flash alone, i.e.
just the kernel or just the root partition. Add support for progress
indicator (requires new rev of devio).
-rw-r--r-- | packages/openslug-init/openslug-init-0.10/reflash | 560 | ||||
-rw-r--r-- | packages/openslug-init/openslug-init_0.10.bb | 2 |
2 files changed, 340 insertions, 222 deletions
diff --git a/packages/openslug-init/openslug-init-0.10/reflash b/packages/openslug-init/openslug-init-0.10/reflash index dc6ef0bbd8..504e78f694 100644 --- a/packages/openslug-init/openslug-init-0.10/reflash +++ b/packages/openslug-init/openslug-init-0.10/reflash @@ -11,52 +11,13 @@ # /etc/default/functions contains useful utility functions . /etc/default/functions # -# CHECKING THE ENVIRONMENT -# ------------------------ -# basic setup. This could be parameterised to use different partitions! -ffspart=Flashdisk -kpart=Kernel -# -ffsdev="$(mtblockdev $ffspart)" -test -n "$ffsdev" -a -b "$ffsdev" || { - echo "reflash: $ffspart($ffsdev): cannot find $ffspart mtd partition." >&2 - echo " check /proc/mtd, either the partition does not exist or there is no" >&2 - echo " corresponding block device." >&2 - exit 1 -} -ffssize="$(devio "<<$ffsdev" 'pr$')" -# -kdev="$(mtblockdev $kpart)" -test -n "$kdev" -a -b "$kdev" || { - echo "reflash: $kpart($kdev): cannot find $kpart mtd partition." >&2 - echo " check /proc/mtd, either the partition does not exist or there is no" >&2 - echo " corresponding block device." >&2 - exit 1 -} -ksize="$(devio "<<$kdev" 'pr$')" -# -# find the device number of the flash partition then make sure it isn't -# mounted anywhere. -ffsno="$(devio "<<$ffsdev" prd)" -test -n "$ffsno" -a "$ffsno" -ge 0 || { - echo "reflash: $ffsdev: device number $ffsno is not valid, cannot continue." >&2 - exit 1 -} -# -# Make sure that Flashdisk isn't mounted on / -if test "$(devio "<</etc/init.d/sysconfsetup" prd)" -eq "$ffsno" -then - echo "reflash: $ffsdev is mounted on /, use turnup ram to reflash" >&2 - exit 1 -fi -# # CHECKING FOR INPUT (ARGUMENTS ETC) # ---------------------------------- # -# find the kernel and the new flash file system, they default to /boot/zImage -# and /boot/rootfs.jffs2, an image file can be used to specify both images. -ffsfile=/boot/rootfs.jffs2 -kfile=/boot/zImage +# find the kernel and the new flash file system, an image file can +# be used to specify both images. +ffsfile= +kfile= imgfile= while test $# -gt 0 do @@ -67,15 +28,13 @@ do exit 1 } kfile="$1" - imgfile= shift;; - -j) shift + -[jr]) shift test $# -gt 0 || { echo "reflash: -j: give the file containing the root jffs2 image" >&2 exit 1 } ffsfile="$1" - imgfile= shift;; -i) shift test $# -gt 0 || { @@ -84,20 +43,31 @@ do } imgfile="$1" shift;; - *) echo "reflash: usage: $0 [-k kernel -j rootfs] | -i image" >&2 - echo " -k [$kfile]: the new compressed kernel image ('zImage')" >&2 - echo " -j [$ffsfile]: the new root file system (jffs2)" >&2 - echo " -i image: a complete flash image (gives both kernel and jffs2)" >&2 + *) echo "reflash: usage: $0 [-k kernel] [-j rootfs] [-i image]" >&2 + echo " -k file: the new compressed kernel image ('zImage')" >&2 + echo " -j file: the new root file system (jffs2)" >&2 + echo " -i file: a complete flash image (gives both kernel and jffs2)" >&2 echo " The current jffs2 will be umounted if mounted." >&2 exit 1;; esac done # +# Sanity check on the arguments +if test -n "$imgfile" -a -n "$ffsfile" -a -n "$kfile" +then + echo "reflash: -k,-j,-i: specify at most two files" >&2 + echo " -i has both a kernel and rootfs, the kernel from -k and" >&2 + echo " the rootfs from -j override the one in the image (if given)" >&2 + exit 1 +elif test -z "$imgfile" -a -z "$ffsfile" -a -z "$kfile" +then + echo "reflash: -k,-j,-i: specify at least one file to flash" >&2 + exit 1 +fi +# # Perform basic checks on the input (must exist, size must be ok). if test -n "$imgfile" then - kfile= - ffsfile= if test -r "$imgfile" then # read the partition table and from this find the offset @@ -120,6 +90,7 @@ then done <<EOI $(devio "<<$imgfile" ' <= $ 0x20000 - + L= 0x1000 $( 1 # 0xff byte in name[0] ends the partition table $? @ 255 = @@ -133,219 +104,366 @@ $(devio "<<$imgfile" ' cp 16 pn <= f240+ - $) 1') + L= L256- + $) L255>') EOI # check the result - test -n "$imgksize" -a "$imgksize" -gt 0 -a "$imgksize" -le "$ksize" || { - echo "reflash: $imgfile: bad kernel size ($imgksize, max $ksize)" >&2 + test "$imgksize" -gt 0 -a "$imgkoffset" -ge 0 || { + echo "reflash: $imgfile: failed to find Kernel partition in image" >&2 + exit 1 + } + # the kernel is after a 16 byte header which holds the + # values length,0,0,0 Get the true size. + ktmp="$(devio "<<$imgfile" "L=$imgksize" "O=$imgkoffset" ' + $( OL+$>! + <= O + A= b + $( AL>! + pr A + $) 0 + $) 0')" + test "$ktmp" -gt 0 || { + echo "reflash: $imgfile($imgkoffset,$imgksize): invalid kernel offset/size" >&2 exit 1 } - test -n "$imgffssize" -a "$imgffssize" -gt 0 -a "$imgffssize" -le "$ffssize" || { - echo "reflash: $imgfile: bad flashdisk size ($imgffssize, max $ffssize)" >&2 + # update the size and offset to these values (the offset is 16+ because + # of the header). + imgksize="$ktmp" + imgkoffset="$(devio "O=$imgkoffset" 'pr O16+')" + # just test the size for the rootfs + test "$imgffssize" -gt 0 -a "$imgffsoffset" -ge 0 || { + echo "reflash: $imgfile: failed to find Flashdisk" >&2 exit 1 } else echo "reflash: $imgfile: image file not found" >&2 exit 1 fi -else - if test -r "$kfile" +fi +if test -n "$kfile" +then + if test ! -r "$kfile" then - # check the size - s="$(devio "<<$kfile" 'pr$')" - test -n "$s" -a "$s" -gt 0 -a "$s" -le "$ksize" || { - echo "reflash: $kfile: bad size ($s, max $ksize)" >&2 - exit 1 - } - else echo "reflash: $kfile: kernel file not found" >&2 exit 1 fi - if test -r "$ffsfile" + # the file values override anything from the image. + imgksize="$(devio "<<$kfile" 'pr$')" + imgkoffset=0 +else + kfile="$imgfile" +fi +if test -n "$ffsfile" +then + if test ! -r "$ffsfile" then - s="$(devio "<<$ffsfile" 'pr$')" - test -n "$s" -a "$s" -gt 0 -a "$s" -le "$ffssize" || { - echo "reflash: $ffsfile: bad size ($s, max $ffssize)" >&2 - exit 1 - } - else echo "reflash: $ffsfile: root file system image file not found" >&2 exit 1 fi + # values override those from the image + imgffssize="$(devio "<<$ffsfile" 'pr$')" + imgffsoffset=0 +else + ffsfile="$imgfile" +fi +# +# INPUTS OK, CHECKING THE ENVIRONMENT +# ----------------------------------- +# basic setup. This could be parameterised to use different partitions! +kpart=Kernel +ffspart=Flashdisk +# +kdev= +ksize=0 +if test -n "$kfile" +then + # we have a new kernel + kdev="$(mtblockdev $kpart)" + test -n "$kdev" -a -b "$kdev" || { + echo "reflash: $kpart($kdev): cannot find $kpart mtd partition." >&2 + echo " check /proc/mtd, either the partition does not exist or there is no" >&2 + echo " corresponding block device." >&2 + exit 1 + } + ksize="$(devio "<<$kdev" 'pr$')" + # + # check the input file size + test -n "$imgksize" -a "$imgksize" -gt 0 -a "$imgksize" -le "$ksize" || { + echo "reflash: $kfile: bad Kernel size ($s, max $ksize)" >&2 + exit 1 + } fi # -# INPUTS OK, UMOUNT ANY EXISTING MOUNT OF THE FLASHDISK -# ---------------------------------------------------- -echo "reflash: umounting any existing mount of $ffsdev" >&2 +ffsdev= +ffssize=0 +if test -n "$ffsfile" +then + ffsdev="$(mtblockdev $ffspart)" + test -n "$ffsdev" -a -b "$ffsdev" || { + echo "reflash: $ffspart($ffsdev): cannot find $ffspart mtd partition." >&2 + echo " check /proc/mtd, either the partition does not exist or there is no" >&2 + echo " corresponding block device." >&2 + exit 1 + } + ffssize="$(devio "<<$ffsdev" 'pr$')" + # + # check the input file size + test -n "$imgffssize" -a "$imgffssize" -gt 0 -a "$imgffssize" -le "$ffssize" || { + echo "reflash: $ffsfile: bad Flashdisk size ($s, max $ffssize)" >&2 + exit 1 + } +fi # -# check each mount point, do this last first because otherwise nested -# mounts of ffsdev cannot be umounted. -ffs_umount() { - local device mp type options stuff +# find the device number of the flash partition then make sure it isn't +# mounted anywhere. +if test -n "$ffsdev" +then + ffsno="$(devio "<<$ffsdev" prd)" + test -n "$ffsno" -a "$ffsno" -ge 0 || { + echo "reflash: $ffsdev: device number $ffsno is not valid, cannot continue." >&2 + exit 1 + } + # + # Make sure that Flashdisk isn't mounted on / + if test "$(devio "<</etc/init.d/sysconfsetup" prd)" -eq "$ffsno" + then + echo "reflash: $ffsdev is mounted on /, use turnup ram to reflash" >&2 + exit 1 + fi +fi +# +# INPUTS OK, ENVIRONMENT OK, UMOUNT ANY EXISTING MOUNT OF THE FLASHDISK +# --------------------------------------------------------------------- +# This is only required if the device is going to be used +if test -n "$ffsdev" +then + echo "reflash: umounting any existing mount of $ffsdev" >&2 + # + # check each mount point, do this last first because otherwise nested + # mounts of ffsdev cannot be umounted. + ffs_umount() { + local device mp type options stuff - read device mp type options stuff - test -z "$device" && return 0 + read device mp type options stuff + test -z "$device" && return 0 - # handle following entries first - ffs_umount || return 1 + # handle following entries first + ffs_umount || return 1 - # handle this entry - case "$type" in - jffs2) test "$(devio "<<$mp/etc/init.d/sysconfsetup" prd)" -ne "$ffsno" || - umount "$mp" || { - echo "reflash: $mp: unable to umount $ffsdev" >&2 - return 1 - };; - esac + # handle this entry + case "$type" in + jffs2) test "$(devio "<<$mp/etc/init.d/sysconfsetup" prd)" -ne "$ffsno" || + umount "$mp" || { + echo "reflash: $mp: unable to umount $ffsdev" >&2 + return 1 + };; + esac - return 0 -} -# -ffs_umount </proc/mounts || { - echo "reflash: umount $ffsdev from all mount points then re-run reflash" >&2 - exit 1 -} + return 0 + } + # + ffs_umount </proc/mounts || { + echo "reflash: umount $ffsdev from all mount points then re-run reflash" >&2 + exit 1 + } + # + # Everything is umounted, now remount on a temporary directory. + ffsdir="/tmp/flashdisk.$$" + mkdir "$ffsdir" || { + echo "reflash: $ffsdir: failed to create temporary directory" >&2 + exit 1 + } + # + mountflash "$ffsdir" -o ro || { + rmdir "$ffsdir" + exit 1 + } + # + # this is a utility function to make the cleanup easier + errorexit() { + umount "$ffsdir" && rmdir "$ffsdir" || + echo "reflash: $ffsdir: temporary directory cleanup failed" >&2 + exit 1 + } + # + test -r "$ffsdir/etc/default/conffiles" || { + echo "reflash: [/initrd]/etc/default/conffiles: file not found" >&2 + errorexit + } +else + errorexit() { + exit 1 + } +fi # -# Everything is umounted, now remount on a temporary directory. -ffsdir="/tmp/flashdisk.$$" -mkdir "$ffsdir" || { - echo "reflash: $ffsdir: failed to create temporary directory" >&2 - exit 1 -} +# PRESERVE EXISTING CONFIGURATION +# ------------------------------- +# Only required if the flash partition will be written +if test -n "$ffsdev" +then + echo "reflash: preserving existing configuration file" >&2 + # + # This step produces /tmp/preserve.$$ and /tmp/cpio.$$, the former is + # a list of the preserved configuration files together with the processing + # option, the latter is a directory tree of the preserved files (a directory + # tree makes the restore step easier.) + saved=/tmp/cpio.$$ + list=/tmp/preserve.$$ + mkdir "$saved" || { + echo "reflash: $saved: could not create save directory" >&2 + errorexit + } + # + ( cd "$ffsdir" + find etc/*.conf $(sed 's!^/!!' usr/lib/ipkg/info/*.conffiles) ! -type d -newer etc/.configured -print | + sed 's/^/diff /' + exec sed 's/#.*$//;/^[ ]*$/d' etc/default/conffiles + ) | sed 's!^/*!!' | awk '{ op=$1; $1=""; file[$0]=op } + END{ for (f in file) if (file[f] != "ignore") print file[f] f }' | + while read op file + do + if test -e "$ffsdir/$file" + then + echo "$op $file" >&3 + echo "$file" + fi + done 3>"$list" | (cd "$ffsdir"; exec cpio -p -d -m -u "$saved") || { + echo "reflash: $saved: copy of saved configuration files failed" >&2 + rm -rf "$saved" + rm "$list" + errorexit + } + # + # If this umount fails do not try to continue... + umount "$ffsdir" || { + echo "reflash: $ffsdir: temporary mount point umount failed" >&2 + echo " No changes have been made." >&2 + rm -rf "$saved" + rm "$list" + exit 1 + } +fi # -mountflash "$ffsdir" -o ro || { - rmdir "$ffsdir" - exit 1 +# FLASH THE NEW IMAGES +# -------------------- +echo "reflash: about to flash new image" >&2 +# +# There are four possibilities here - kernel only, flashdisk only, then +# kernel&flashdisk in either one or two different files. The code used +# to attempt to do everything in one step, but this complicates it, +# so two steps are used (as required). A failure between the two +# steps is a problem, but then so is a failure in a partial write. +# Write the flashdisk first because this is larger (most likely to +# fail). +# Temporarily check for devio progress indicator capability this way... +if devio -p '' 2>/dev/null +then + progress=-p +else + progress= +fi +do_kernel() { + devio $progress "$@" "<<$kfile" ">>$kdev" ' + # kernel is at imgkoffset[imgksize] + ' "<= $imgkoffset" "L=$imgksize" ' + # kernel write length,0,0,0 header, then fill + wb L,4 + fb 12,0 + cp L + # fill with 255 + fb #t-,255' } # -# this is a utility function to make the cleanup easier -errorexit() { - umount "$ffsdir" && rmdir "$ffsdir" || - echo "reflash: $ffsdir: temporary directory cleanup failed" >&2 - exit 1 +do_ffs() { + devio $progress "$@" "<<$ffsfile" ">>$ffsdev" ' + # rootfs is at imgffsoffset[imgffssize] + ' "<= $imgffsoffset" "cp $imgffssize" ' + # fill with 255 + fb #t-,255' } # -test -r "$ffsdir/etc/default/conffiles" || { - echo "reflash: [/initrd]/etc/default/conffiles: file not found" >&2 - errorexit +# check_status $? type file(offset,size) device +# check the devio status code (given in $1) +check_status() { + case "$1" in + 0) echo " done" >&2;; + 1) echo " failed" >&2 + echo "reflash: $3: flash $2 failed, no changes have been made to $4" >&2 + if test "$2" = rootfs + then + rm -rf "$saved" + rm "$list" + exit 1 + else + echo "reflash: $2: continuing with rootfs changes" >&2 + echo " NOTE: the old kernel is still in $4!" >&2 + fi;; + 3) echo " failed" >&2 + echo "reflash: $3: WARNING: partial flash of $2 to $4 the system is unbootable" >&2 + echo " Reflash from RedBoot or correct the problem here." >&2 + if test "$2" = rootfs + then + exit 3 + else + echo "reflash: $2: continuing with rootfs changes" >&2 + echo " NOTE: the kernel in $4 must be reflashed!" >&2 + fi;; + *) echo " failed" >&2 + echo "reflash($1): $3: internal error flashing $2 to $4" >&2 + exit $1;; + esac } # -# PRESERVE EXISTING CONFIGURATION -# ------------------------------- -echo "reflash: preserving existing configuration file" >&2 +if test -n "$ffsdev" +then + echo -n "reflash: writing rootfs to $ffsdev " >&2 + do_ffs + check_status $? rootfs "$ffsfile($imgffsoffset,$imgffssize)" "$ffsdev" +fi # -# This step produces /tmp/preserve.$$ and /tmp/cpio.$$, the former is -# a list of the preserved configuration files together with the processing -# option, the latter is a directory tree of the preserved files (a directory -# tree makes the restore step easier.) -saved=/tmp/cpio.$$ -list=/tmp/preserve.$$ -mkdir "$saved" || { - echo "reflash: $saved: could not create save directory" >&2 - errorexit -} +if test -n "$kdev" +then + echo -n "reflash: writing kernel to $kdev " >&2 + do_kernel + check_status $? kernel "$kfile($imgkoffset,$imgksize)" "$kdev" +fi # -( cd "$ffsdir" - find etc/*.conf $(sed 's!^/!!' usr/lib/ipkg/info/*.conffiles) ! -type d -newer etc/.configured -print | - sed 's/^/diff /' - exec sed 's/#.*$//;/^[ ]*$/d' etc/default/conffiles -) | sed 's!^/*!!' | awk '{ op=$1; $1=""; file[$0]=op } - END{ for (f in file) if (file[f] != "ignore") print file[f] f }' | -while read op file -do - if test -e "$ffsdir/$file" +# verify - this just produces a warning +if test -n "$ffsdev" +then + echo -n "reflash: verifying new flash image " >&2 + if do_ffs -v then - echo "$op $file" >&3 - echo "$file" + echo " done" >&2 + else + echo " failed" >&2 + echo "reflash: WARNING: rootfs flash image verification failed" >&2 + echo " The system is probably unbootable." >&2 + echo " System configuration files will be restored but this may fail" >&2 + echo " Starting a shell for user recovery (exit to continue)" >&2 + PS1='badflash$ ' sh -i <>/dev/tty >&0 2>&0 fi -done 3>"$list" | (cd "$ffsdir"; exec cpio -p -d -m -u "$saved") || { - echo "reflash: $saved: copy of saved configuration files failed" >&2 - rm -rf "$saved" - rm "$list" - errorexit -} -# -# If this umount fails do not try to continue... -umount "$ffsdir" || { - echo "reflash: $ffsdir: temporary mount point umount failed" >&2 - echo " No changes have been made." >&2 - rm -rf "$saved" - rm "$list" - exit 1 -} -# -# FLASH THE NEW IMAGES -# -------------------- -echo "reflash: about to flash new images" >&2 +fi # -# If the images are in separate files do this in two steps, kernel then -# rootfs (this seems like it might be safer if the first fails). For an -# image file use one step but still write the kernel first. -do_devio() { - if test -r "$imgfile" - then - # image file case - copy the whole of the image partition, - # which already includes headers (etc). - devio "$@" "<<$imgfile" ">>$ffsdev" ">>$kdev" ' - # kernel is at imgkoffset[imgksize] - ' "<= $imgkoffset" "cp $imgksize" ' - fb #t-,255 - ' "<>$kdev" ">>$ffsdev" ' - # rootfs is at imgffsoffset[imgffssize] - ' "<= $imgffsoffset" "cp $imgffssize" ' - fb #t-,255' - elif test -r "$kfile" -a -r "$ffsfile" +if test -n "$kdev" +then + echo -n "reflash: verifying new kernel image " >&2 + if do_kernel -v then - # use separate files, do this in one command to be sure - # that everything can be opened at the start - devio "$@" "<<$ffsfile" ">>$ffsdev" "<<$kfile" ">>$kdev" ' - # kernel write length+16,0,0,0 header, then fill - wb $16+,4 - fb 12,0 - cp $ - fb #t-,255 - ' "<>$kfile" "<>$kdev" "<<$ffsfile" ">>$ffsdev" ' - # rootfs, write the whole image, fill if necessary - cp $ - fb #t-,255' + echo " done" >&2 else - # oops, my checking was wrong... - echo "reflash: internal error: image files not found!" >&2 - echo " No changes have been made." >&2 - exit 2 + echo " failed" >&2 + echo "reflash: WARNING: kernel flash image verification failed" >&2 + echo " The system is probably unbootable." >&2 + echo " System configuration files will be restored in the rootfs." >&2 fi -} -# -echo "reflash: writing kernel to $kdev and rootfs to $ffsdev..." >&2 -do_devio -st=$? -case "$st" in -0) ;; -1) echo "reflash: flash of new images failed, no changes have been made" >&2 - rm -rf "$saved" - rm "$list" - exit 1;; -3) echo "reflash: WARNING: partial flash, the system is unbootable" >&2 - echo " Reflash from RedBoot or correct the problem here." >&2 - exit 3;; -*) echo "reflash($st): internal error" >&2 - exit $st;; -esac -echo " ... done" >&2 -# -# verify - this just produces a warning -echo "reflash: verifying new flash image..." >&2 -do_devio -v || { - echo "reflash: WARNING: flash image verification failed" >&2 - echo " The system is probably unbootable." >&2 - echo " System configuration files will be restored but this may fail" >&2 - echo " Starting a shell for user recovery (exit to continue)" >&2 - PS1='badflash$ ' sh -i <>/dev/tty >&0 2>&0 -} -echo " ... done" >&2 +fi # # RESTORE THE OLD CONFIGURATION # ----------------------------- +# If not write the rootfs none of the following is required - exit now. +test -n "$ffsdev" || exit 0 +# echo "reflash: restoring saved configuration files" >&2 # # the file /etc/.configured is the datestamp file used to ensure that diff --git a/packages/openslug-init/openslug-init_0.10.bb b/packages/openslug-init/openslug-init_0.10.bb index bf43759aa7..f0af1aa9fb 100644 --- a/packages/openslug-init/openslug-init_0.10.bb +++ b/packages/openslug-init/openslug-init_0.10.bb @@ -3,7 +3,7 @@ SECTION = "console/network" LICENSE = "GPL" DEPENDS = "base-files devio" RDEPENDS = "busybox devio" -PR = "r32" +PR = "r33" SRC_URI = "file://linuxrc \ file://boot/flash \ |