275 lines
5.1 KiB
Bash
275 lines
5.1 KiB
Bash
|
|
#!/bin/sh
|
||
|
|
|
||
|
|
echo update: "$@"
|
||
|
|
|
||
|
|
echoerr() {
|
||
|
|
echo 1>&2 "ERROR: $*"
|
||
|
|
}
|
||
|
|
|
||
|
|
cd /
|
||
|
|
if ! test -r /proc/mounts || ! test -f /proc/mounts
|
||
|
|
then
|
||
|
|
mkdir -p /proc
|
||
|
|
mount -t proc proc proc
|
||
|
|
fi
|
||
|
|
if ! test -d /sys/class
|
||
|
|
then
|
||
|
|
mkdir -p /sys
|
||
|
|
mount -t sysfs sys sys
|
||
|
|
fi
|
||
|
|
if ! test -c /dev/null
|
||
|
|
then
|
||
|
|
mkdir -p /dev
|
||
|
|
mount -t devtmpfs dev dev
|
||
|
|
fi
|
||
|
|
|
||
|
|
# mtd number N with mtd name Name can be mounted via mtdN, or mtd:Name
|
||
|
|
# (with a mtd aware fs) or by /dev/mtdblockN (with a mtd or block fs).
|
||
|
|
mtdismounted() {
|
||
|
|
m=${1##mtd}
|
||
|
|
if grep -s "mtdblock$m " /proc/mounts || grep -s "mtd$m " /proc/mounts
|
||
|
|
then
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
n=$(cat "/sys/class/mtd/mtd$m/name")
|
||
|
|
if test -n "$n" && grep -s "mtd:$n " /proc/mounts
|
||
|
|
then
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
|
||
|
|
# Detect child partitions when the whole flash is to be updated.
|
||
|
|
# Ignore mtdNro and mtdblockN names in the class subsystem directory.
|
||
|
|
childmtds() {
|
||
|
|
for m in "/sys/class/mtd/$1/mtd"*
|
||
|
|
do
|
||
|
|
m=${m##*/}
|
||
|
|
if test "${m%ro}" = "${m#mtdblock}"
|
||
|
|
then
|
||
|
|
echo "$m"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
}
|
||
|
|
|
||
|
|
toobig() {
|
||
|
|
if test "$(stat -L -c "%s" "$1")" -gt "$(cat "/sys/class/mtd/$2/size")"
|
||
|
|
then
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
|
||
|
|
findmtd() {
|
||
|
|
m=$(grep -xl "$1" /sys/class/mtd/*/name)
|
||
|
|
m=${m%/name}
|
||
|
|
m=${m##*/}
|
||
|
|
echo "$m"
|
||
|
|
}
|
||
|
|
|
||
|
|
blkid_fs_type() {
|
||
|
|
# Emulate util-linux's `blkid -s TYPE -o value $1`
|
||
|
|
# Example busybox blkid output:
|
||
|
|
# # blkid /dev/mtdblock5
|
||
|
|
# /dev/mtdblock5: TYPE="squashfs"
|
||
|
|
# Process output to extract TYPE value "squashfs".
|
||
|
|
blkid "$1" | sed -e 's/^.*TYPE="//' -e 's/".*$//'
|
||
|
|
}
|
||
|
|
|
||
|
|
probe_fs_type() {
|
||
|
|
fst=$(blkid_fs_type "$1")
|
||
|
|
echo "${fst:=jffs2}"
|
||
|
|
}
|
||
|
|
|
||
|
|
rwfs=$(findmtd rwfs)
|
||
|
|
|
||
|
|
rwdev=/dev/mtdblock${rwfs#mtd}
|
||
|
|
rwopts=rw
|
||
|
|
rorwopts=ro${rwopts#rw}
|
||
|
|
|
||
|
|
rwdir=/run/initramfs/rw
|
||
|
|
upper=$rwdir/cow
|
||
|
|
save=/run/save/${upper##*/}
|
||
|
|
|
||
|
|
mounted=
|
||
|
|
doflash=y
|
||
|
|
doclean=
|
||
|
|
dosave=y
|
||
|
|
dorestore=y
|
||
|
|
toram=
|
||
|
|
checksize=y
|
||
|
|
checkmount=y
|
||
|
|
|
||
|
|
whitelist=/run/initramfs/whitelist
|
||
|
|
image=/run/initramfs/image-
|
||
|
|
imglist=
|
||
|
|
|
||
|
|
while test "$1" != "${1#-}"
|
||
|
|
do
|
||
|
|
case "$1" in
|
||
|
|
--help)
|
||
|
|
cat <<HERE
|
||
|
|
Usage: $0 [options] -- Write images in /run/initramfs to flash (/dev/mtd*)
|
||
|
|
--help Show this message
|
||
|
|
--no-flash Don't attempt to write images to flash
|
||
|
|
--ignore-size Don't compare image size to mtd device size
|
||
|
|
--ignore-mount Don't check if destination is mounted
|
||
|
|
--save-files Copy whitelisted files to save directory in RAM
|
||
|
|
--no-save-files Don't copy whitelisted files to save directory
|
||
|
|
--copy-files Copy files from save directory to rwfs mountpoint
|
||
|
|
--restore-files Restore files from save directory to rwfs layer
|
||
|
|
--no-restore-files Don't restore saved files from ram to rwfs layer
|
||
|
|
--clean-saved-files Delete saved whitelisted files from RAM
|
||
|
|
--no-clean-saved-files Retain saved whitelisted files in RAM
|
||
|
|
HERE
|
||
|
|
|
||
|
|
exit 0 ;;
|
||
|
|
|
||
|
|
--no-clean-saved-files)
|
||
|
|
doclean=
|
||
|
|
shift ;;
|
||
|
|
--clean-saved-files)
|
||
|
|
doclean=y
|
||
|
|
shift ;;
|
||
|
|
--no-save-files)
|
||
|
|
dosave=
|
||
|
|
shift ;;
|
||
|
|
--save-files)
|
||
|
|
dosave=y
|
||
|
|
shift ;;
|
||
|
|
--no-restore-files)
|
||
|
|
dorestore=
|
||
|
|
shift ;;
|
||
|
|
--restore-files)
|
||
|
|
dorestore=y
|
||
|
|
shift ;;
|
||
|
|
--no-flash)
|
||
|
|
doflash=
|
||
|
|
shift ;;
|
||
|
|
--ignore-size)
|
||
|
|
checksize=
|
||
|
|
shift ;;
|
||
|
|
--ignore-mount)
|
||
|
|
checkmount=
|
||
|
|
doflash=
|
||
|
|
shift ;;
|
||
|
|
--copy-files)
|
||
|
|
toram=y
|
||
|
|
shift ;;
|
||
|
|
*)
|
||
|
|
echoerr "Unknown option $1. Try $0 --help."
|
||
|
|
exit 1 ;;
|
||
|
|
esac
|
||
|
|
done
|
||
|
|
|
||
|
|
if test "$dosave" = "y"
|
||
|
|
then
|
||
|
|
if test ! -d $upper -a -n "$rwfs"
|
||
|
|
then
|
||
|
|
mkdir -p $rwdir
|
||
|
|
mount "$rwdev" $rwdir -t "$(probe_fs_type "$rwdev")" -o "$rorwopts"
|
||
|
|
mounted=$rwdir
|
||
|
|
fi
|
||
|
|
|
||
|
|
while read -r f
|
||
|
|
do
|
||
|
|
# Entries shall start with /, no trailing /.. or embedded /../
|
||
|
|
if test "/${f#/}" != "$f" -o "${f%/..}" != "${f#*/../}"
|
||
|
|
then
|
||
|
|
echo 1>&2 "WARNING: Skipping bad whitelist entry $f."
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
if ! test -e "$upper/$f"
|
||
|
|
then
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
d="$save/$f"
|
||
|
|
while test "${d%/}" != "${d%/.}"
|
||
|
|
do
|
||
|
|
d="${d%/.}"
|
||
|
|
d="${d%/}"
|
||
|
|
done
|
||
|
|
mkdir -p "${d%/*}"
|
||
|
|
cp -rp "$upper/$f" "${d%/*}/"
|
||
|
|
done < $whitelist
|
||
|
|
|
||
|
|
if test -n "$mounted"
|
||
|
|
then
|
||
|
|
umount $mounted
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
imglist=$(echo $image*)
|
||
|
|
if test "$imglist" = "$image*" -a ! -e "$imglist"
|
||
|
|
then
|
||
|
|
# shell didn't expand the wildcard, so no files exist
|
||
|
|
echo "No images found to update."
|
||
|
|
imglist=
|
||
|
|
fi
|
||
|
|
|
||
|
|
for f in $imglist
|
||
|
|
do
|
||
|
|
m=$(findmtd "${f#"$image"}")
|
||
|
|
if test -z "$m"
|
||
|
|
then
|
||
|
|
echoerr "Unable to find mtd partition for ${f##*/}."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
if test -n "$checksize" && toobig "$f" "$m"
|
||
|
|
then
|
||
|
|
echoerr "Image ${f##*/} too big for $m."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
for s in $m $(childmtds "$m")
|
||
|
|
do
|
||
|
|
if test -n "$checkmount" && mtdismounted "$s"
|
||
|
|
then
|
||
|
|
echoerr "Device $s is mounted, ${f##*/} is busy."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
done
|
||
|
|
|
||
|
|
if test -n "$doflash"
|
||
|
|
then
|
||
|
|
for f in $imglist
|
||
|
|
do
|
||
|
|
if test ! -s "$f"
|
||
|
|
then
|
||
|
|
echo "Skipping empty update of ${f#"$image"}."
|
||
|
|
rm "$f"
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
m=$(findmtd "${f#"$image"}")
|
||
|
|
echo "Updating ${f#"$image"}..."
|
||
|
|
flashcp -v "$f" "/dev/$m" && rm "$f"
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
if test -d "$save" -a "$toram" = "y"
|
||
|
|
then
|
||
|
|
mkdir -p $upper
|
||
|
|
cp -rp "$save/." "$upper/"
|
||
|
|
fi
|
||
|
|
|
||
|
|
if test -d "$save" -a "$dorestore" = "y"
|
||
|
|
then
|
||
|
|
odir=$rwdir
|
||
|
|
rwdir=/run/rw
|
||
|
|
upper=$rwdir${upper#"$odir"}
|
||
|
|
|
||
|
|
mkdir -p $rwdir
|
||
|
|
mount "$rwdev" $rwdir -t "$(probe_fs_type "$rwdev")" -o $rwopts
|
||
|
|
mkdir -p "$upper"
|
||
|
|
cp -rp "$save/." "$upper/"
|
||
|
|
umount $rwdir
|
||
|
|
rmdir $rwdir
|
||
|
|
fi
|
||
|
|
|
||
|
|
if test "$doclean" = "y"
|
||
|
|
then
|
||
|
|
rm -rf "$save"
|
||
|
|
fi
|
||
|
|
|
||
|
|
exit
|