#!/bin/sh
#
# NAME
#
#	makecard - prepare SD card with Linux or Logic Loader boot
#
# SYNOPSIS
#
#	makecard block-dev LogicLoader-dir Linux-dir
#
# DESCRIPTION
#
#	Formats a SD card and installs Linux or Logic Loader boot
#	files suitable for upgrading the Logic Loader version
#
#	The first argument is the base block device where the SD
#	card can be accessed (for example, /dev/sdf)  Note that
#	partition device names are created by appending the partition
#	number to the base block device (for example, /dev/sdf1)
#
#	The second and third arguments are the names of the directories
#	where the Logic Loader and Linux files are kept.  For each
#	of these, if the field is not blank, the directory will be
#	accessed to initialize the card.
#

# Receives a stream of filtered output from mount and uses the first
# column of each line as device names to be unmounted
umount_from_stdin() {

    while true
    do
	read MOUNTDEV REST

	if [ -z "$MOUNTDEV" ]
	then
	   exit 0
	else
	   umount $MOUNTDEV
	fi
    done

    return 0
}

# Unmounts all partitions with device names  like the first parameter
umount_all() {

    mount | grep $1 | umount_from_stdin
    return 0
}

# Gets the size of the of the media at the named block device ($1)
# and echos it to stdout
get_size() {

    fdisk -l $1 2>/dev/null | \
	grep Disk | \
	( read V1 V2 V3 V4 V5 VREST; echo $V5 )

    return 0
}

# Copies a file ($2) from the source directory ($1) to the destination
# directory ($3), optionally using a different name ($4) in the destination
# directory if the parameter is not blank
copy_file() {

    if [ ! -f $1/$2 ]
    then
	echo "File $2 not found in $1"
	exit 1
    else
	echo "-- $2"

	if [ -z "$4" ]
	then
	    cp $1/$2 $3
	else
	    cp $1/$2 $3/$4
	fi
    fi

    return 0
}

# Calls mkfs.vfat to initialize the media at the named partition ($1)
# in FAT32 format with a given name ($2)
setup_fat32() {

    if [ ! -b $1 ]
    then
	sleep 1
    fi

    if [ -b $1 ]
    then
    	mkfs.vfat -F 32 -n $2 $1
    else
	echo "Missing filesystem node for $1"
	exit 1
    fi

    return 0
}

# Calls mkfs.ext3 to initialize the media at the named partition ($1)
# in EXT3 format with a given name ($2); the partition is marked as not
# needing to be checked
setup_ext3() {

    if [ ! -b $1 ]
    then
	sleep 1
    fi

    if [ -b $1 ]
    then
	mkfs.ext3 -L $2 $1
	tune2fs -c 0 $1
    else
	echo "Missing filesystem node for $1"
	exit 1
    fi

    return 0
}

# Gets the name of the kernel image in the given directory ($1)
get_uimage_name() {

    cd $1
    find . -mindepth 1 -type f -print | grep uImage | ( read X ; echo $X )
    return 0
}

# === Start of script ===

DEV="$1"
LLDIR="$2"
LINUXDIR="$3"

if [ `whoami` != "root" ]
then
    echo "This script must be run as root (current user is `whoami`)"
    exit 1
fi

if [ -z "$DEV" ]
then
    echo "No device was specified"
    exit
fi

if [ ! -b $DEV ]
then
    echo "$DEV does not exist or is not a block device"
    exit 1
fi

if [ -z "$LLDIR" ]
then
    echo "LogicLoader directory not specified; no Logic Loader files will be created"
else
    if [ ! -d "$LLDIR" ]
    then
        echo "Provided LogicLoader directory ($LLDIR) was not found"
        exit 1
    fi
fi

if [ -z "$LINUXDIR" ]
then
    echo "Linux directory not specified; Linux partitions will not be initialized"
else
    if [ ! -d "$LINUXDIR" ]
    then
	echo "Provided Linux directory ($LINUXDIR) was not found"
	exit 1
    fi
fi

echo "Unmounting all volumes on $DEV"
umount_all $DEV

echo ""
echo "Initializing $DEV using /dev/zero"
dd if=/dev/zero of=$DEV bs=1024 count=1024

echo ""
echo -n "Calculating size of media on $DEV ... "
SIZE=`get_size $DEV`
echo "$SIZE bytes"

if [ -z "$SIZE" ]
then
    echo "No size was reported"
    exit 1
fi

if [ "$SIZE" -lt 4000000000 ]
then
    echo "The device is too small for use"
    exit 1
fi

echo -n "Calculating size of media on $DEV in cylinders ... "
CYLINDERS=`echo $SIZE/255/63/512 | bc`
echo $CYLINDERS

echo ""
echo "Configuring $DEV physical attributes"

{
    echo ,13,0x0C,*

    if [ "$SIZE" -gt 8000000000 ]
    then
        echo ,523,,-
    fi

    echo ,,,-
} | sfdisk -D -H 255 -S 63 -C $CYLINDERS $DEV

echo ""
echo "Writing FAT32 filesystem on ${DEV}1"
dd if=/dev/zero of=${DEV}1 bs=512 count=1
setup_fat32 ${DEV}1 BOOT

if [ ! -z "$LINUXDIR" ]
then
    echo ""
    echo "Writing EXT3 filesystem on ${DEV}2"
    setup_ext3 ${DEV}2 LINUX
fi

echo ""
echo "Mounting BOOT partition"

if [ ! -d /mnt ]
then
    mkdir /mnt
fi

if [ ! -d /mnt/BOOT ]
then
    mkdir /mnt/BOOT
fi

mount ${DEV}1 /mnt/BOOT

if [ ! -z "$LLDIR" ]
then
    echo ""
    echo "Loading LogicLoader files to BOOT partition"
    copy_file $LLDIR MLO /mnt/BOOT
    copy_file $LLDIR lboot.elf /mnt/BOOT
    copy_file $LLDIR 1016698_lolo_NAND.upd /mnt/BOOT
    copy_file $LLDIR 1016698_nolo_NAND.upd /mnt/BOOT
fi

if [ ! -z "$LINUXDIR" ]
then

    echo ""
    echo "Creating startup script on BOOT partition"
    {
   	echo "load elf /sd/u-boot"
        echo "exec -"
    } > /mnt/BOOT/script

    echo ""
    echo "Loading u-boot to BOOT partition"
    copy_file ${LINUXDIR}/bootloader u-boot /mnt/BOOT
    SRCIMG=`get_uimage_name $LINUXDIR`
    copy_file ${LINUXDIR} $SRCIMG /mnt/BOOT uImage

fi

echo ""
echo "Flushing writes to device"
sync

echo ""
echo "Unmounting BOOT partition"
umount ${DEV}1

if [ ! -z "$LINUXDIR" ]
then

     echo ""
     echo "Mounting LINUX partition"

     if [ ! -d /mnt/LINUX ]
     then
	mkdir /mnt/LINUX
     fi

     mount ${DEV}2 /mnt/LINUX

     echo ""
     echo "Writing root filesystem"
     THISDIR=`pwd`
     cd /mnt/LINUX
     tar xvzpf $LINUXDIR/rootfs.tar.gz
     cd "$THISDIR"

     echo ""
     echo "Flushing writes to device"
     sync

     echo ""
     echo "Unmounting LINUX partition"
     umount ${DEV}2
fi

