#!/bin/sh

# mkinitrd
#
# Written by Erik Troan <ewt@redhat.com>
#
# Contributors:
#	Elliot Lee <sopwith@cuc.edu>
#	Miguel de Icaza <miguel@nuclecu.unam.mx>

PATH=/sbin:$PATH
export PATH

VERSION=1.3

target=""
kernel=""
force=""
verbose=""
MODULES=""

usage () {
    echo "usage: $0 [--version] [-v] [-f] [--ifneeded] [--preload <module>]" >&2
    echo "       [--needs-scsi-modules] [--with <module>] <initrd-image> <kernel>" >&2
    echo "       (ex: $0 /boot/initrd 2.0.3)" >&2
    exit 1
}

findmodule() {
    if [ -n "$1" ]; then
	fmPath="$1"/"$2".o
    else
	fmPath=`(cd /lib/modules/$kernel; echo */$2.o)`
    fi

    if [ ! -f /lib/modules/$kernel/$fmPath ]; then
	echo "No module $2 found for kernel $kernel" >&2
	exit 1
    fi

    MODULES="$MODULES $fmPath"
}

while [ $# -gt 0 ]; do
    case $1 in
	--with*)
	    if echo $1 | grep '=' >/dev/null ; then
	    	modname=`echo $1 | sed 's/^--with=//'`
	    else
		modname=$2
		shift
	    fi		    

	    basicmodules="$basicmodules $modname"
	    ;;

	--version)
	    echo "mkinitrd: version $VERSION"
	    exit 0
	    ;;

	-v)
	    verbose=-v
	    ;;

	--ifneeded)
	    ifneeded=1
	    ;;

	-f)
	    force=1
	    ;;
	--preload)
	    if echo $1 | grep '=' >/dev/null ; then
	    	modname=`echo $1 | sed 's/^--with=//'`
	    else
		modname=$2
		shift
	    fi		    
	    PREMODS="$PREMODS $modname"
	    ;;
	--needs-scsi-modules)
	    PRESCSIMODS="scsi_mod sd_mod"
	    ;;
	*)
	    if [ -z "$target" ]; then
		target=$1
	    elif [ -z "$kernel" ]; then
		kernel=$1
	    else
		usage
	    fi
	    ;;
    esac

    shift
done

if [ -z "$target" -o -z "$kernel" ]; then
    usage
fi

if [ -z "$force" -a -f $target ]; then
    echo "$target already exists." >&2
    exit 1
fi

if [ ! -d /lib/modules/$kernel ]; then
    echo "/lib/modules/$kernel is not a directory." >&2
    exit 1
fi

for n in $PREMODS; do
	findmodule "" $n
done
for n in $PRESCSIMODS; do
	findmodule scsi $n
done

if [ -f /etc/conf.modules ]; then
    scsimodules=`grep scsi_hostadapter /etc/conf.modules | grep -v '^[ 	]*#' | sort -u | awk '{ print $3 }'`
    for n in $scsimodules; do
	findmodule scsi $n
    done
fi

for n in $basicmodules; do 
    findmodule "" $n
done

if [ -n "$ifneeded" -a -z "$MODULES" ]; then
    if [ -n "$verbose" ]; then
	echo "No modules are needed -- not building initrd image."
    fi
    exit 0
fi

if [ -n "$verbose" ]; then
    echo "Using modules: $MODULES"
fi

IMAGE=/tmp/initrd.img-$$
MNTPOINT=/tmp/initrd.mnt-$$
RCFILE=$MNTPOINT/linuxrc

if [ -f $IMAGE ]; then
    echo "$IMAGE already exists. Remove it and try again" >&2
    exit 1
fi

dd if=/dev/zero of=$IMAGE bs=1k count=1500 2> /dev/null

# We have to "echo y |" so that it doesn't complain about $IMAGE not
# being a block device
echo y | mke2fs $IMAGE 1500 >/dev/null 2>/dev/null

if [ -n "$verbose" ]; then
    echo "Using loopback device $LODEV"
fi

mkdir -p $MNTPOINT
mount -t ext2 -o loop $IMAGE $MNTPOINT || {
	echo "Can't get a loopback device"
	exit 1
}

mkdir -p $MNTPOINT/lib
mkdir -p $MNTPOINT/bin
mkdir -p $MNTPOINT/etc
mkdir -p $MNTPOINT/dev
# We don't need this directory, so let's save space
rm -rf $MNTPOINT/lost+found

# Hard links aren't handled right, so we just copy the main files
# ignoring symlinks and it works.
cp $verbose -f /lib/libc.so.? $MNTPOINT/lib
cp $verbose -f /lib/ld-linux.so.? /lib/ld.so.? $MNTPOINT/lib 2>/dev/null
strip $MNTPOINT/lib/ld*.so*
# Copy misc utilities needed
cp $verbose -af /etc/ld.so.cache $MNTPOINT/etc
cp $verbose -af /bin/ash $MNTPOINT/bin/sh
cp $verbose -af /sbin/insmod $MNTPOINT/bin/insmod
strip $MNTPOINT/bin/*

for MODULE in $MODULES; do
	cp $verbose -a /lib/modules/$kernel/$MODULE $MNTPOINT/lib
done

for n in console null ram systty tty[1234]; do
    cp -a /dev/$n $MNTPOINT/dev
done

echo "#!/bin/sh" > $RCFILE
echo "" >> $RCFILE

for MODULE in $MODULES; do
	module=`echo $MODULE | sed "s|.*/||" | sed "s/.o$//"`

	options=`grep $module /etc/conf.modules | grep "^options" | sed "s/.*$module *//"`

	if [ -n "$verbose" ]; then
	    echo "Loading module $module with options $options"
	fi
	echo "echo \"Loading $module module\"" >> $RCFILE
	echo "insmod /lib/$module.o $options" >> $RCFILE
done

chmod +x $RCFILE

umount $MNTPOINT

gzip -9 < $IMAGE > $target
rm -rf $MNTPOINT $IMAGE

