summaryrefslogtreecommitdiff
path: root/packages/openslug-init/openslug-init-0.10/reflash
diff options
context:
space:
mode:
Diffstat (limited to 'packages/openslug-init/openslug-init-0.10/reflash')
-rw-r--r--packages/openslug-init/openslug-init-0.10/reflash560
1 files changed, 339 insertions, 221 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