1#!/bin/sh 2 3echo update: "$@" 4 5echoerr() { 6 echo 1>&2 "ERROR: $*" 7} 8 9cd / 10if ! test -r /proc/mounts || ! test -f /proc/mounts 11then 12 mkdir -p /proc 13 mount -t proc proc proc 14fi 15if ! test -d /sys/class 16then 17 mkdir -p /sys 18 mount -t sysfs sys sys 19fi 20if ! test -c /dev/null 21then 22 mkdir -p /dev 23 mount -t devtmpfs dev dev 24fi 25 26# mtd number N with mtd name Name can be mounted via mtdN, or mtd:Name 27# (with a mtd aware fs) or by /dev/mtdblockN (with a mtd or block fs). 28mtdismounted() { 29 m=${1##mtd} 30 if grep -s "mtdblock$m " /proc/mounts || grep -s "mtd$m " /proc/mounts 31 then 32 return 0 33 fi 34 n=$(cat "/sys/class/mtd/mtd$m/name") 35 if test -n "$n" && grep -s "mtd:$n " /proc/mounts 36 then 37 return 0 38 fi 39 return 1 40} 41 42# Detect child partitions when the whole flash is to be updated. 43# Ignore mtdNro and mtdblockN names in the class subsystem directory. 44childmtds() { 45 for m in "/sys/class/mtd/$1/mtd"* 46 do 47 m=${m##*/} 48 if test "${m%ro}" = "${m#mtdblock}" 49 then 50 echo "$m" 51 fi 52 done 53} 54 55toobig() { 56 if test "$(stat -L -c "%s" "$1")" -gt "$(cat "/sys/class/mtd/$2/size")" 57 then 58 return 0 59 fi 60 return 1 61} 62 63findmtd() { 64 m=$(grep -xl "$1" /sys/class/mtd/*/name) 65 m=${m%/name} 66 m=${m##*/} 67 echo "$m" 68} 69 70blkid_fs_type() { 71 # Emulate util-linux's `blkid -s TYPE -o value $1` 72 # Example busybox blkid output: 73 # # blkid /dev/mtdblock5 74 # /dev/mtdblock5: TYPE="squashfs" 75 # Process output to extract TYPE value "squashfs". 76 blkid "$1" | sed -e 's/^.*TYPE="//' -e 's/".*$//' 77} 78 79probe_fs_type() { 80 fst=$(blkid_fs_type "$1") 81 echo "${fst:=jffs2}" 82} 83 84rwfs=$(findmtd rwfs) 85 86rwdev=/dev/mtdblock${rwfs#mtd} 87rwopts=rw 88rorwopts=ro${rwopts#rw} 89 90rwdir=/run/initramfs/rw 91upper=$rwdir/cow 92save=/run/save/${upper##*/} 93 94mounted= 95doflash=y 96doclean= 97dosave=y 98dorestore=y 99toram= 100checksize=y 101checkmount=y 102 103whitelist=/run/initramfs/whitelist 104image=/run/initramfs/image- 105imglist= 106 107while test "$1" != "${1#-}" 108do 109 case "$1" in 110 --help) 111 cat <<HERE 112Usage: $0 [options] -- Write images in /run/initramfs to flash (/dev/mtd*) 113 --help Show this message 114 --no-flash Don't attempt to write images to flash 115 --ignore-size Don't compare image size to mtd device size 116 --ignore-mount Don't check if destination is mounted 117 --save-files Copy whitelisted files to save directory in RAM 118 --no-save-files Don't copy whitelisted files to save directory 119 --copy-files Copy files from save directory to rwfs mountpoint 120 --restore-files Restore files from save directory to rwfs layer 121 --no-restore-files Don't restore saved files from ram to rwfs layer 122 --clean-saved-files Delete saved whitelisted files from RAM 123 --no-clean-saved-files Retain saved whitelisted files in RAM 124HERE 125 126 exit 0 ;; 127 128 --no-clean-saved-files) 129 doclean= 130 shift ;; 131 --clean-saved-files) 132 doclean=y 133 shift ;; 134 --no-save-files) 135 dosave= 136 shift ;; 137 --save-files) 138 dosave=y 139 shift ;; 140 --no-restore-files) 141 dorestore= 142 shift ;; 143 --restore-files) 144 dorestore=y 145 shift ;; 146 --no-flash) 147 doflash= 148 shift ;; 149 --ignore-size) 150 checksize= 151 shift ;; 152 --ignore-mount) 153 checkmount= 154 doflash= 155 shift ;; 156 --copy-files) 157 toram=y 158 shift ;; 159 *) 160 echoerr "Unknown option $1. Try $0 --help." 161 exit 1 ;; 162 esac 163done 164 165if test "$dosave" = "y" 166then 167 if test ! -d $upper -a -n "$rwfs" 168 then 169 mkdir -p $rwdir 170 mount "$rwdev" $rwdir -t "$(probe_fs_type "$rwdev")" -o "$rorwopts" 171 mounted=$rwdir 172 fi 173 174 while read -r f 175 do 176 # Entries shall start with /, no trailing /.. or embedded /../ 177 if test "/${f#/}" != "$f" -o "${f%/..}" != "${f#*/../}" 178 then 179 echo 1>&2 "WARNING: Skipping bad whitelist entry $f." 180 continue 181 fi 182 if ! test -e "$upper/$f" 183 then 184 continue 185 fi 186 d="$save/$f" 187 while test "${d%/}" != "${d%/.}" 188 do 189 d="${d%/.}" 190 d="${d%/}" 191 done 192 mkdir -p "${d%/*}" 193 cp -rp "$upper/$f" "${d%/*}/" 194 done < $whitelist 195 196 if test -n "$mounted" 197 then 198 umount $mounted 199 fi 200fi 201 202imglist=$(echo $image*) 203if test "$imglist" = "$image*" -a ! -e "$imglist" 204then 205 # shell didn't expand the wildcard, so no files exist 206 echo "No images found to update." 207 imglist= 208fi 209 210for f in $imglist 211do 212 m=$(findmtd "${f#"$image"}") 213 if test -z "$m" 214 then 215 echoerr "Unable to find mtd partition for ${f##*/}." 216 exit 1 217 fi 218 if test -n "$checksize" && toobig "$f" "$m" 219 then 220 echoerr "Image ${f##*/} too big for $m." 221 exit 1 222 fi 223 for s in $m $(childmtds "$m") 224 do 225 if test -n "$checkmount" && mtdismounted "$s" 226 then 227 echoerr "Device $s is mounted, ${f##*/} is busy." 228 exit 1 229 fi 230 done 231done 232 233if test -n "$doflash" 234then 235 for f in $imglist 236 do 237 if test ! -s "$f" 238 then 239 echo "Skipping empty update of ${f#"$image"}." 240 rm "$f" 241 continue 242 fi 243 m=$(findmtd "${f#"$image"}") 244 echo "Updating ${f#"$image"}..." 245 flashcp -v "$f" "/dev/$m" && rm "$f" 246 done 247fi 248 249if test -d "$save" -a "$toram" = "y" 250then 251 mkdir -p $upper 252 cp -rp "$save/." "$upper/" 253fi 254 255if test -d "$save" -a "$dorestore" = "y" 256then 257 odir=$rwdir 258 rwdir=/run/rw 259 upper=$rwdir${upper#"$odir"} 260 261 mkdir -p $rwdir 262 mount "$rwdev" $rwdir -t "$(probe_fs_type "$rwdev")" -o $rwopts 263 mkdir -p "$upper" 264 cp -rp "$save/." "$upper/" 265 umount $rwdir 266 rmdir $rwdir 267fi 268 269if test "$doclean" = "y" 270then 271 rm -rf "$save" 272fi 273 274exit 275