#!/bin/sh -e

# Shellscript version of the kind-of hard to find cmplzma program, used to
# compress kernels for certain CFE bootloaders. Originally found somewhere
# else, but pretty much rewritten completely to actually make it work for
# my router. Give it an vmlinux file and it'll do all the objdumping and
# compressing for you.
#
# Needs lzma to do the actual compression. Use apt-get install or whatever
# your distro comes with to get it.
#
# Use at your own risk, etc. Doesn't generate exactly the same files like
# the original tool and they're a few hundred bytes bigger, but meh.
#
# Wilmer van der Gaast. <wilmer@gaast.net>

# I guess there's no need to use the native binutils so you may just leave
# $TC empty.
TARGET=mips-linux-uclibc
TC=/usr/$TARGET/bin/$TARGET-

[ "$#" = 2 ] || {
	echo "Usage: $0 vmlinux lzfile" >&2
	exit 1
}
infile="$1"
outfile="$2"

# The bootloader only needs the binary part of the ELF file. Get this.
binfile=$(mktemp /tmp/vmlinux.bin.XXXXXX)
trap "rm $binfile" EXIT
${TC}objcopy -O binary $infile $binfile

# LZMA compression.
lztemp=$(mktemp /tmp/vmlinux.lzma.XXXXXX)
trap "rm $binfile $lztemp" EXIT
lzma -c9 $binfile > $lztemp

# Get the entry point from the original ELF file.
entry=$(${TC}objdump -f $infile | grep '^start address ' | sed -e 's/.*0x//')
if [ -z "$entry" ]; then
	echo "Couldn't find entry point." >&2
	exit 1
fi

let size=$(wc -c < $lztemp)-8

{
	# CFE headers: Three 32-byte network order integers:
	# Load offset, code entry point, compressed size.
	perl -e "print pack('NNN', 0x80010000, 0x$entry, $size)"

	# Leave out bytes 5..12, looks like CFE isn't interested in
	# decompressed size. Odd, since that means the compressed
	# image isn't properly terminated in any way.
	head -c +5 $lztemp
	tail -c +14 $lztemp
} > "$outfile"
