#! /bin/sh
#
# copyright - PKG.fr - 2008
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA

echo
echo "kernel extract v0.1"
echo

if [ ! -s "$1" ]; then
	echo "You must provide the extracted MTD file as first argument"
	exit 1
fi

MTD="$1"
BIN="$2"

# Update BIN to default if not set
: ${BIN:=uImage.bin}

function get_int () {
	Hex="0x"
	let i=0 offset=$1
	while (( i < 4 ))
	do
		Chr=$( dd if="$MTD" bs=1 count=1 skip=$((offset+i)) 2>/dev/null )
		Chr=$( printf '%d' "'$Chr" )
		#echo $Chr 1>&2
		(( Chr < 0 )) && let Chr+=256
		Hex="$Hex$( printf '%02lX' $Chr )"
		#echo $Hex 1>&2
		let i++
	done
	echo "$Hex"
}

function get_str () {
	Str=""
	let Ascii=1 offset=$1
	while (( Ascii > 0 ))
	do
		Chr=$( dd if="$MTD" bs=1 count=1 skip=$((offset)) 2>/dev/null )
		Ascii=$( printf '%d' "'$Chr" )
		(( Ascii > 31 && Ascii < 127 )) && Str="$Str$Chr"
		(( ++offset >= 0x40 )) && break
	done
	echo "$Str"
}

# uImage.bin header used by u-boot
MAGIC=$(get_int 0)
HCRC=$(get_int 4)
TIME=$(get_int 8)
SIZE=$(get_int 12)
ADDR=$(get_int 16)
ADDS=$(get_int 20)
DCRC=$(get_int 24)
ARCH=$(get_int 28)
VERS=$(get_str 32)

printf "Magic=%s HCRC=%d Timestamp=%d DCRC=%d Arch=%s\n\n" $MAGIC $HCRC $TIME $DCRC $ARCH
printf "Kernel size = %d\nKernel should be loaded at %s address, entry point is %s\n" $SIZE $ADDR $ADDS
echo "Linux version: $VERS"
echo

if [ "$MAGIC" != "0x27051956" ]; then
	echo "Error: Found wrong magic value at offset 0" 1>&2
	exit 4
fi

TEST=$(get_int $(($INT1+0x40)) )
(( TEST )) && echo "Warning: bytes after the kernel are not null"

if (( SIZE > 4096000 )); then
	echo "The kernel size seems too high, can't process"
	exit 2
fi

# Keeping header to get uImage.bin
let SIZE+=64

# Copy kernel with dd using 4 bytes block size to have minimum performance
dd if=$MTD of=$BIN bs=4 count=$((SIZE/4))

echo
CTRL=$( wc -c "$BIN" | cut -d ' ' -f 1 )
if [ "$CTRL" -eq "$((SIZE+64))" ]; then
	echo "Kernel extracted to '$BIN'"
	echo
else
	echo "Kernel extraction failed ($CTRL!=$((SIZE)))"
	echo
	exit 3
fi
