| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
if test -z "$KSH_VERSION$BASH_VERSION"; then |
|---|
| 8 |
echo >&2 Sorry, at the moment, a Korn shell or GNU bash is required. |
|---|
| 9 |
exit 255 |
|---|
| 10 |
fi |
|---|
| 11 |
|
|---|
| 12 |
[[ -n $BASH_VERSION ]] && shopt -s extglob |
|---|
| 13 |
[[ -n $KSH_VERSION ]] && alias which='whence -p' |
|---|
| 14 |
|
|---|
| 15 |
me=${0 |
|---|
| 16 |
wd=$(pwd) |
|---|
| 17 |
|
|---|
| 18 |
if ! which stat >/dev/null 2>&1; then |
|---|
| 19 |
getsize() { |
|---|
| 20 |
|
|---|
| 21 |
echo 0 |
|---|
| 22 |
} |
|---|
| 23 |
elif stat --help >/dev/null 2>&1; then |
|---|
| 24 |
getsize() { |
|---|
| 25 |
|
|---|
| 26 |
stat -c '%s' "$@" 2>/dev/null |
|---|
| 27 |
} |
|---|
| 28 |
else |
|---|
| 29 |
getsize() { |
|---|
| 30 |
|
|---|
| 31 |
stat -f '%z' "$@" 2>/dev/null |
|---|
| 32 |
} |
|---|
| 33 |
fi |
|---|
| 34 |
|
|---|
| 35 |
die() { |
|---|
| 36 |
printf >&2 '%s: %s\n' "$me" "$*" |
|---|
| 37 |
exit 1 |
|---|
| 38 |
} |
|---|
| 39 |
|
|---|
| 40 |
usage() { |
|---|
| 41 |
cat >&2 <<-EOF |
|---|
| 42 |
Syntax: $me [-nx] [-c tftp] [-D dir | -F | -f fwcf.bin] [-t type] file [ip] |
|---|
| 43 |
Valid types are: |
|---|
| 44 |
wl500g wl500gd wl500gp wl500gx linksys |
|---|
| 45 |
Meta-types (no support for -f or -F): |
|---|
| 46 |
wl500gx = wl500gd or wl500gp |
|---|
| 47 |
linksys = all linksys models |
|---|
| 48 |
Use -x to flash oversized images. |
|---|
| 49 |
EOF |
|---|
| 50 |
exit 1 |
|---|
| 51 |
} |
|---|
| 52 |
|
|---|
| 53 |
imgtype=auto |
|---|
| 54 |
flashtype=auto |
|---|
| 55 |
typeset -i dopad=0 |
|---|
| 56 |
typeset -i padsize=0 |
|---|
| 57 |
paddir= |
|---|
| 58 |
padfile= |
|---|
| 59 |
tftp=tftp |
|---|
| 60 |
typeset -i nflag=0 |
|---|
| 61 |
typeset -i sflag=0 |
|---|
| 62 |
typeset -i xflag=0 |
|---|
| 63 |
|
|---|
| 64 |
while getopts ":c:D:Ff:nst:x" ch; do |
|---|
| 65 |
case $ch in |
|---|
| 66 |
(c) tftp=$OPTARG |
|---|
| 67 |
;; |
|---|
| 68 |
(D) dopad=1 |
|---|
| 69 |
paddir=$OPTARG |
|---|
| 70 |
padfile= |
|---|
| 71 |
;; |
|---|
| 72 |
(F) dopad=1 |
|---|
| 73 |
paddir= |
|---|
| 74 |
padfile= |
|---|
| 75 |
;; |
|---|
| 76 |
(f) dopad=1 |
|---|
| 77 |
paddir= |
|---|
| 78 |
padfile=$OPTARG |
|---|
| 79 |
[[ -s $padfile ]] || die "Invalid pad file '$padfile'" |
|---|
| 80 |
;; |
|---|
| 81 |
(n) nflag=1 |
|---|
| 82 |
;; |
|---|
| 83 |
(s) sflag=1 |
|---|
| 84 |
;; |
|---|
| 85 |
(t) imgtype=$OPTARG |
|---|
| 86 |
;; |
|---|
| 87 |
(x) xflag=1 |
|---|
| 88 |
;; |
|---|
| 89 |
(:) echo >&2 "$me: Error: missing argument to -$OPTARG" |
|---|
| 90 |
usage |
|---|
| 91 |
;; |
|---|
| 92 |
(*) echo >&2 "$me: Error: invalid option -$OPTARG" |
|---|
| 93 |
usage |
|---|
| 94 |
;; |
|---|
| 95 |
esac |
|---|
| 96 |
done |
|---|
| 97 |
shift $((OPTIND - 1)) |
|---|
| 98 |
|
|---|
| 99 |
[[ $ |
|---|
| 100 |
imgfile=$1 |
|---|
| 101 |
[[ $imgfile = *@( )* ]] && die Spaces in filenames are not supported |
|---|
| 102 |
[[ -s $imgfile ]] || die "Image file '$imgfile' non-existent or 0 bytes" |
|---|
| 103 |
if (( nflag )); then |
|---|
| 104 |
ofile=${2:-flash.out} |
|---|
| 105 |
else |
|---|
| 106 |
ip=${2:-192.168.1.1} |
|---|
| 107 |
[[ $ip = +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]] || \ |
|---|
| 108 |
die "Invalid IPv4 address '$ip'" |
|---|
| 109 |
fi |
|---|
| 110 |
|
|---|
| 111 |
[[ $imgtype = auto ]] && case ${imgfile%.[bt][ir][nx]} in |
|---|
| 112 |
*-asus-wl500g-premium-*) |
|---|
| 113 |
imgtype=wl500gp ;; |
|---|
| 114 |
*-asus-wl500g-deluxe-*) |
|---|
| 115 |
imgtype=wl500gd ;; |
|---|
| 116 |
*-asus-wl500g-*) |
|---|
| 117 |
imgtype=wl500g ;; |
|---|
| 118 |
*-linksys-*) |
|---|
| 119 |
imgtype=linksys ;; |
|---|
| 120 |
*) |
|---|
| 121 |
die "Cannot determine model from filename '$imgfile', use -t option" ;; |
|---|
| 122 |
esac |
|---|
| 123 |
|
|---|
| 124 |
case $imgtype in |
|---|
| 125 |
wl500g) |
|---|
| 126 |
flashtype=wl500g ;; |
|---|
| 127 |
wl500gd|wl500gp|wl500gx) |
|---|
| 128 |
flashtype=wl500gx ;; |
|---|
| 129 |
linksys) |
|---|
| 130 |
flashtype=linksys ;; |
|---|
| 131 |
*) |
|---|
| 132 |
die "Unknown model '$imgtype'" ;; |
|---|
| 133 |
esac |
|---|
| 134 |
|
|---|
| 135 |
case $imgtype in |
|---|
| 136 |
wl500g|wl500gd) |
|---|
| 137 |
padsize=3735552 ;; |
|---|
| 138 |
wl500gp) |
|---|
| 139 |
padsize=7929856 ;; |
|---|
| 140 |
*) |
|---|
| 141 |
padsize=0 ;; |
|---|
| 142 |
esac |
|---|
| 143 |
|
|---|
| 144 |
typeset -i imgsize="$(getsize "$imgfile")" 2>&- |
|---|
| 145 |
|
|---|
| 146 |
(( xflag )) && imgsize=0 |
|---|
| 147 |
(( (imgsize > 65536) && (padsize > 0) && (imgsize > padsize) )) && \ |
|---|
| 148 |
die "Image '$imgfile' too large ($imgsize bytes, max. $padsize bytes)" |
|---|
| 149 |
|
|---|
| 150 |
if (( dopad )); then |
|---|
| 151 |
(( padsize )) || die "Cannot use -F or -f with a $imgtype yet" |
|---|
| 152 |
TF=$(mktemp /tmp/fwflash.XXXXXXXXXX) || die Cannot mktemp |
|---|
| 153 |
TI=$(mktemp /tmp/fwflash.XXXXXXXXXX) || { rm $TF; die Cannot mktemp; } |
|---|
| 154 |
trap 'cd "$wd"; rm -f $TF $TI; exit 0' 0 |
|---|
| 155 |
trap 'cd "$wd"; rm -f $TF $TI; exit 1' 1 2 3 5 13 15 |
|---|
| 156 |
randsrc=/dev/arandom |
|---|
| 157 |
[[ -e $randsrc ]] || randsrc=/dev/urandom |
|---|
| 158 |
[[ -e $randsrc ]] || randsrc=/dev/random |
|---|
| 159 |
[[ -e $randsrc ]] || die Cannot find an entropy source |
|---|
| 160 |
dd if=$randsrc of=$TF bs=131072 count=1 2>&- |
|---|
| 161 |
if [[ -n $padfile ]]; then |
|---|
| 162 |
id= |
|---|
| 163 |
eval $(dd if="$padfile" bs=7 count=1 2>&- | \ |
|---|
| 164 |
hexdump -e '"id=" 4/1 "%02X" " n=" 3/1 "%02X" "\n"') |
|---|
| 165 |
if [[ $id = 46574346 ]]; then |
|---|
| 166 |
sz=$(printf 'ibase=16\n%s\n' $(echo -n $n | \ |
|---|
| 167 |
sed 's/\(..\)\(..\)\(..\)/\3\2\1/') | bc) |
|---|
| 168 |
dd if="$padfile" bs=$sz count=1 |
|---|
| 169 |
else |
|---|
| 170 |
cat "$padfile" |
|---|
| 171 |
fi | dd of=$TF conv=notrunc 2>&- |
|---|
| 172 |
typeset -i fwcfsize="$(getsize $TF)" 2>&- |
|---|
| 173 |
(( fwcfsize > 131072 )) && die "FWCF filesystem '$padfile' too" \ |
|---|
| 174 |
"large ($fwcfsize bytes, max. 131072 bytes)" |
|---|
| 175 |
echo "TRX file constructed from root='$imgfile' and fwcf='$padfile'" |
|---|
| 176 |
elif [[ -n $paddir ]]; then |
|---|
| 177 |
|
|---|
| 178 |
p=fwcf.helper |
|---|
| 179 |
$p -l 2>&1 | fgrep lzo1x1 >/dev/null || \ |
|---|
| 180 |
for dir in . .. ../.. ../../.. ../../../.. *wrt* *WRT*; do |
|---|
| 181 |
p=$dir/lbin/fwcf.helper |
|---|
| 182 |
[[ -e $dir/. ]] || continue |
|---|
| 183 |
[[ -x $p ]] || continue |
|---|
| 184 |
$p -l 2>&1 | fgrep lzo1x1 >/dev/null && break |
|---|
| 185 |
p= |
|---|
| 186 |
done |
|---|
| 187 |
[[ $p = fwcf.helper || -x $p ]] || die Cannot find fwcf.helper |
|---|
| 188 |
|
|---|
| 189 |
$p -M "$paddir" >$TI || die Error creating fwcf filesystem image |
|---|
| 190 |
dd if=$TI of=$TF conv=notrunc 2>&- |
|---|
| 191 |
echo "TRX file constructed from '$imgfile' and FWCF from '$paddir'" |
|---|
| 192 |
else |
|---|
| 193 |
printf 'FWCF\x18\x00\x00\x01\x01\x00\x00\x10\x12\x00\x11\x00\x00\x00\x00\x00\x74\x01\x7C\x18' | \ |
|---|
| 194 |
dd of=$TF conv=notrunc 2>&- |
|---|
| 195 |
echo "TRX file constructed from '$imgfile' and empty fwcf filesystem" |
|---|
| 196 |
fi |
|---|
| 197 |
dd if=/dev/zero of=$TI bs=$padsize count=1 2>&- |
|---|
| 198 |
dd if="$imgfile" of=$TI conv=notrunc 2>&- |
|---|
| 199 |
if (( sflag )); then |
|---|
| 200 |
[[ -n $padfile || -n $paddir ]] && die Cannot use -s without -F |
|---|
| 201 |
printf '!' >>$TI |
|---|
| 202 |
else |
|---|
| 203 |
cat $TF >>$TI |
|---|
| 204 |
fi |
|---|
| 205 |
imgfile=$TI |
|---|
| 206 |
else |
|---|
| 207 |
echo "Using TRX file from '$imgfile'" |
|---|
| 208 |
fi |
|---|
| 209 |
|
|---|
| 210 |
if (( nflag )); then |
|---|
| 211 |
cat "$imgfile" >"$ofile" |
|---|
| 212 |
echo "Output file '$ofile' written." |
|---|
| 213 |
exit 0 |
|---|
| 214 |
fi |
|---|
| 215 |
|
|---|
| 216 |
x=$tftp |
|---|
| 217 |
[[ -x $tftp ]] || tftp=$(which $tftp 2>&-) |
|---|
| 218 |
[[ -x $tftp ]] || die "TFTP client '${x:-tftp}' not found" |
|---|
| 219 |
|
|---|
| 220 |
echo ATTENTION: Do not turn off the power on your device $ip now! |
|---|
| 221 |
sleep 3 |
|---|
| 222 |
|
|---|
| 223 |
imgdir=${imgfile%/*} |
|---|
| 224 |
[[ $imgdir = $imgfile ]] && imgdir=. |
|---|
| 225 |
imgfile=${imgfile |
|---|
| 226 |
cd "$imgdir" |
|---|
| 227 |
typeset -i rv=1 |
|---|
| 228 |
text2='This device will reboot itself automatically.' |
|---|
| 229 |
case $flashtype in |
|---|
| 230 |
wl500g) |
|---|
| 231 |
echo Confirming IP address setting... |
|---|
| 232 |
printf 'get ASUSSPACELINK\x01\x01\xA8\xC0 /dev/null\nquit\n' | $tftp $ip |
|---|
| 233 |
echo Flashing image... |
|---|
| 234 |
printf 'binary\nput %s ASUSSPACELINK\nquit\n' "$imgfile" | $tftp $ip |
|---|
| 235 |
rv=$? |
|---|
| 236 |
text1='Please wait until the LEDs stop flashing.' |
|---|
| 237 |
;; |
|---|
| 238 |
wl500gx) |
|---|
| 239 |
echo Flashing image... |
|---|
| 240 |
printf 'rexmt 1\ntrace\nbinary\nput %s\nquit\n' "$imgfile" | $tftp $ip |
|---|
| 241 |
rv=$? |
|---|
| 242 |
text1='Please wait 5-6 minutes and then remove the power plug.' |
|---|
| 243 |
text2='This device does not reboot automatically after flashing.' |
|---|
| 244 |
;; |
|---|
| 245 |
linksys) |
|---|
| 246 |
echo Flashing image... |
|---|
| 247 |
printf 'rexmt 1\ntrace\nbinary\nput %s\nquit\n' "$imgfile" | $tftp $ip |
|---|
| 248 |
rv=$? |
|---|
| 249 |
text1='Please wait 3-5 minutes.' |
|---|
| 250 |
;; |
|---|
| 251 |
esac |
|---|
| 252 |
cd "$wd" |
|---|
| 253 |
if (( rv )); then |
|---|
| 254 |
echo tftp returned with error code $rv. |
|---|
| 255 |
echo The device may not have been flashed correctly. |
|---|
| 256 |
exit 1 |
|---|
| 257 |
fi |
|---|
| 258 |
cat <<-EOF |
|---|
| 259 |
$text1 |
|---|
| 260 |
$text2 |
|---|
| 261 |
|
|---|
| 262 |
After flashing is finished and the device has rebooted, it will need |
|---|
| 263 |
to restart once if the filesystem type is squashfs with jffs2 overlay. |
|---|
| 264 |
The power LED will flash quickly as long as startup is in progress. |
|---|
| 265 |
|
|---|
| 266 |
Once it has finished flashing, you should be able to access the device |
|---|
| 267 |
via ssh to the "admin" user, for example: ssh -l admin $ip |
|---|
| 268 |
|
|---|
| 269 |
If you didn't change the password in menuconfig, it's "FreeWRT" (case |
|---|
| 270 |
sensitive and without the quotation marks). Give the device a while to |
|---|
| 271 |
generate the SSH keys for dropbear first. |
|---|
| 272 |
|
|---|
| 273 |
After device initialisation and key generation has finished, it is |
|---|
| 274 |
highly recommended to log in and issue the command "fwcf commit" so that |
|---|
| 275 |
the SSH host keys will be stored in the configuration filesystem and |
|---|
| 276 |
do not have to be regenerated each time the device starts. |
|---|
| 277 |
|
|---|
| 278 |
EOF |
|---|
| 279 |
exit 0 |
|---|