Mercurial > hg > aboriginal
changeset 551:0b270ad76c8e
Shell script to create linksys firmware images. (Not tested yet.)
author | Rob Landley <rob@landley.net> |
---|---|
date | Fri, 26 Dec 2008 19:06:23 -0600 |
parents | 64779e0f6c28 |
children | a0a26ea9299d |
files | sources/toys/trximg.sh |
diffstat | 1 files changed, 148 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/toys/trximg.sh Fri Dec 26 19:06:23 2008 -0600 @@ -0,0 +1,148 @@ +#!/bin/bash + +# Create a TRX image from up to three source files (kernel, initramfs, rootfs), +# and output it to stdout. (This is the format you flash linksys routers with.) + +# The TRX format is a simple (28 byte) header followed by the concatenation of +# the files with each file zero padded to a multiple of 4 bytes, and then the +# file as a whole padded up to 4k. Padding is done with zero bytes. + +# The tricky part is calculating the lengths and CRC for the header before +# outputting the header, without screwing up the ability to pipe the output +# somewhere. + +if [ ! -f "$1" ] || + ( [ ! -z "$2" ] && [ ! -f "$2" ] ) || + ( [ ! -z "$3" ] && [ ! -f "$3" ] ) +then + echo "Usage: trximg.sh file1 [file2 [file3]]" >&2 + exit 1 +fi + +# Output $1 bytes of decimal number $2 as little endian binary data + +function leout() +{ + X=0 + DATA=$2 + + # Loop through bytes, smallest first + + while [ $X -lt $1 ] + do + # Grab next byte + + BYTE=$[$DATA%256] + DATA=$[$DATA/256] + + # Convert to octal (because that's what echo needs) + + OCTAL="" + for i in 1 2 3 + do + OCTAL=$[$BYTE%8]"$OCTAL" + BYTE=$[$BYTE/8] + done + + # Emit byte and loop + + echo -ne "\0$OCTAL" + + X=$[$X+1] + BYTE=$x + done +} + +# Print number of bytes required to round $2 up to a multiple of $1 + +function padlen() +{ + echo $[($1-($2%$1))%$1] +} + +# Print number $2 rounded up to $1 + +function roundlen() +{ + echo $[$2+$(padlen $1 $2)] +} + +# Return length of file $1 in bytes + +function filelen() +{ + wc -c "$1" | awk '{print $1}' +} + +# Output $1 zero bytes + +function zpad() +{ + [ $1 -ne 0 ] && dd if=/dev/zero bs=$1 count=1 2>/dev/null +} + +# Output file $2, followed by enough zero bytes to pad length up to $1 bytes + +function zpad_file() +{ + [ -z "$2" ] && return + cat $2 + zpad $(padlen $1 $(filelen "$2")) +} + +# Output header. (Optionally just the part included in the CRC32). + +function emit_header +{ + if [ -z "$1" ] + then + echo -n "HDR0" # File ID magic + leout 4 $LENGTH # Length of file (including this header) + leout 4 $CRC32 # crc32 of all file data after this crc field + fi + + leout 2 0 # flags + leout 2 1 # version + leout 4 28 # Start of first file + leout 4 $OFFSET2 # Start of second file + leout 4 $OFFSET3 # Start of third file +} + +# Calculate file offsets for the three arguments + +TOTAL=$[28+$(roundlen 4 $(filelen "$1"))] +if [ -z "$2" ] +then + OFFSET2=0 +else + OFFSET2=$TOTAL + TOTAL=$[$TOTAL+$(roundlen 4 $(filelen "$2"))] +fi +if [ -z "$3" ] +then + OFFSET3=0 +else + OFFSET3=$TOTAL + TOTAL=$[$TOTAL+$(roundlen 4 $(filelen "$3"))] +fi +LENGTH=$(roundlen 4096 $TOTAL) + +# Calculate the CRC value for the header + +CRC32=$( + ( + emit_header skip + zpad_file 4 "$1" + zpad_file 4 "$2" + zpad_file 4 "$2" + zpad $(padlen 4096 $TOTAL) + ) | cksum +) + +# Output the image to stdout + +emit_header +zpad_file 4 "$1" +zpad_file 4 "$2" +zpad_file 4 "$3" +zpad $(padlen 4096 $TOTAL)