#!/bin/sh
# $Progeny: mkinitrd,v 1.99 2002/04/22 21:31:13 branden Exp $
#
# Make an initrd filesystem hierarchy in path_to_root for a specified kernel.

# XXX: Remove temporary files if interrupted.

set -e
set -x

usage () {
    cat >&2 << EOF
Usage: $0 [ --system | --installer ] kernel_version path_to_root [module ...]
  --installer  create a "Stage 0 PGI Installer" initrd
  --system     create a normal system initrd
EOF
    :;
}

# process arguments
if [ $# -lt 2 ]; then
    usage
    exit 1
fi

initrdtype=installer

while :; do
    case "$1" in
    --*)
        initrdtype=$(echo "$1" | sed 's/--//')
        ;;
    [0-9]*)
        version=$1
        ;;
    *)
        break
        ;;
    esac
    shift
done

root=$1
shift
modules=$*

case "$ARCH" in
i386|ia64)
    kernel_path=/boot/vmlinuz-$version
    ;;
powerpc)
    kernel_path=/boot/vmlinux-$version
    ;;
esac

if [ ! -f $kernel_path ]; then
    echo "$0: Could not open $kernel_path" >&2
    exit 1
fi

if [ ! -f /boot/System.map-$version ]; then
    echo "$0: Could not open /boot/System.map-$version" >&2
    exit 1
fi

rm -rf $root/lost+found

# create dirs
mkdir -m 755 $root/bin
mkdir -m 755 $root/dev
mkdir -m 755 $root/etc
mkdir -m 755 $root/etc/apt
mkdir -m 755 $root/etc/init.d
mkdir -m 755 $root/etc/network
mkdir -m 755 $root/etc/pcmcia
mkdir -m 755 $root/lib
mkdir -m 755 $root/live
mkdir -m 755 $root/mnt
mkdir -m 755 $root/proc
mkdir -m 755 $root/sbin
mkdir -m 755 $root/share
mkdir -m 755 $root/share/discover
mkdir -m 755 $root/share/installer
mkdir -m 755 $root/target
mkdir -m 755 $root/tmp
ln -s . $root/usr
mkdir -m 755 $root/var
mkdir -m 755 $root/var/log
mkdir -m 755 $root/var/run
mkdir -m 755 $root/var/lib
mkdir -m 755 $root/var/lib/xkb
mkdir -m 755 $root/var/tmp

# device files
( cd $root/dev && /sbin/MAKEDEV agpgart std console pty busmice input fd0 fd1 hda hdb hdc hdd hde hdf hdg hdh sda sdb sdc sdd scd0 scd1 tty0 tty1 tty2 tty3 tty4 tty5 tty6 ttyS0 ttyS1 )

# special reboot program
install -m 755 $TDIR/initrd-reboot $root/sbin/initrd-reboot

# essential tools for both initrds
install -m 755 /sbin/discover $root/sbin/discover
install -m 755 /sbin/modprobe $root/sbin/modprobe
install -m 755 /bin/ash $root/bin/sh
install -m 755 $TDIR/busybox.initrd $root/bin/busybox
for link in $(cat $TDIR/busybox.initrd.links); do
   ln -sf /bin/busybox $root/$link
done

# Copy in limited discover databases to save space.  Use kernel 2.4 databases
# preferentially, if they exist.
for discoverdb in pci pcmcia usb; do
    basekern=$(echo $KERNEL_VERSION | cut -d. -f1-2)
    if [ -f /usr/share/discover/${discoverdb}-$basekern.list ]; then
        discoverfn=$discoverdb-$basekern.lst
    else
        discoverfn=$discoverdb.lst
    fi
    cat /usr/share/discover/$discoverfn | \
        awk 'BEGIN { FS = "\t"; CURRENTVENDOR = ""; LASTVENDOR = "Nonexistent Vendor" }; /^[^\t]/ { CURRENTVENDOR = $0 }; /^\t/ && $3 ~ /(scsi|ether|cdrom)/ { if (CURRENTVENDOR != LASTVENDOR) print CURRENTVENDOR; print $0; LASTVENDOR = CURRENTVENDOR }' \
        > $root/share/discover/$discoverfn
done

if [ "$initrdtype" = "installer" ]; then
    # installer initrd
    install -m 755 stage0.sh $root/sbin/stage0.sh
    install -m 755 /sbin/pivot_root $root/sbin

    for etcfile in rescue.txt; do
        if [ -e $ETC_DIR/$etcfile ]; then
            cp $ETC_DIR/$etcfile $root/etc
        fi
    done

    touch $root/etc/ld.so.conf

    touch $root/etc/fstab
    touch $root/etc/mtab

    cat > $root/etc/host.conf <<EOF
order bind
multi off
EOF

    echo "127.0.0.1 localhost" > $root/etc/hosts

    echo "alias block-major-8 sd_mod" > $root/etc/modules.conf

    # OpenSSH *insists* on being able to use getpwent(), and debootstrap wants
    # getgrent().
    echo "root:x:0:0:root:/:/bin/sh" > $root/etc/passwd
    echo "root:x:0:root" > $root/etc/group

    cat > $root/etc/nsswitch.conf <<EOF
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
EOF

    # Store configuration information about this initrd.
    install -m 644 $PGI_DIR/pgi_version $root/etc
    install -m 644 $ETC_DIR/options $root/etc/pgi_options
    echo "$PGI_COMMAND_LINE" > $root/etc/pgi_cmdline
    echo "$VENDOR" > $root/etc/vendor
    echo "$PRODUCT" > $root/etc/product
    echo "$VERSION" > $root/etc/product_version
    echo "$BUILDER" > $root/etc/builder
    echo "$DEBVERSION" > $root/etc/debian_version
    echo "$ARCH" > $root/etc/arch
    echo "$KERNEL_VERSION" > $root/etc/kernel_version
    echo "$PGI_MIRROR" > $root/etc/mirror
    echo "$SUITE" > $root/etc/suite

    if [ -n "$PGI_HTTP_PROXY" ]; then
        echo "$PGI_HTTP_PROXY" > $root/etc/http_proxy
    fi

    if [ -n "$INSTALLER_ONLY" ]; then
        # If there are no packages on the installer disc, we MUST do a network
        # based install, so assume DHCP is to be used.
        echo true > $root/etc/auto_dhcp
    fi

    if [ -n "$EXPERIMENTAL" ]; then
        echo $EXPERIMENTAL > $root/etc/experimental
    fi

    # essential tools
    install -m 755 configure-network $root/sbin/configure-network
    install -m 755 /sbin/ifconfig $root/sbin/ifconfig
    install -m 755 /sbin/route $root/sbin/route
    install -m 755 /sbin/udhcpc $root/sbin/udhcpc
    if [ "$ARCH" = "ia64" -o "$ARCH" = "powerpc" ]; then
        install -m 755 /sbin/insmod $root/bin/insmod
    fi

    # PCMCIA support
    if [ -e /sbin/cardmgr ]; then
        install -m 755  /sbin/cardmgr $root/sbin/cardmgr
    fi

    if [ -e /etc/pcmcia/config ]; then
        gzip -9c /etc/pcmcia/config > $root/etc/pcmcia/config.gz
    fi

    if [ -e /etc/pcmcia/config.opts ]; then
        install -m 644 /etc/pcmcia/config.opts $root/etc/pcmcia/config.opts
    fi

    # Copy in the stupid nss modules and resolver library so we can resolve
    # hostnames.
    glibc_version=`ls /lib/libc-2.2.?.so | xargs basename | awk -F- '{print $2}' | sed 's/\.so//'`
    cp /lib/libnss_dns-$glibc_version.so $root/lib
    cp /lib/libnss_files-$glibc_version.so $root/lib
    cp /lib/libresolv-$glibc_version.so $root/lib
    ln -s libnss_dns-$glibc_version.so $root/lib/libnss_dns.so.2
    ln -s libnss_files-$glibc_version.so $root/lib/libnss_files.so.2
    ln -s libresolv-$glibc_version.so $root/lib/libresolv.so.2

else
    # system initrd
    install -m 755 linuxrc.system $root/linuxrc
fi

# Copy in reduced libraries as needed.
bash $RELEASE_tools/mklibs.bash -d $root/lib $root/bin/* $root/sbin/*
#python $RELEASE_tools/mklibs.py -d $root/lib $root/bin/* $root/sbin/*

install -m 755 ./envsh $root/bin/envsh

# create the modules.dep file
mkdir -m 755 -p $root/lib/modules/$version
install -m 644 $TDIR/modules.dep $root/lib/modules/$version

# Touch the modules.conf file to midnight, January 1st of the current year
# so that modprobe won't complain that modules.conf is newer TO STANDARD
# OUTPUT.  The malice and stupidity it must require to do that simply takes
# my breath away.
touch 01010000 $root/etc/modules.conf
touch $root/lib/modules/$version/modules.dep

# Copy in modules specified on command line, along with all modules
# they depend on.  We saved this step until last because we want to squeeze on
# as many modules as possible.

INITRD_ACTUAL_SIZE=$(du -ks $root | awk '{ print $1 }')

case "$ARCH" in
ia64|powerpc)
    modules_size=$(( ($INITRD_FS_SIZE - $INITRD_ACTUAL_SIZE) * 1024 ))
    ;;
i386)
    # XXX: If using SYSLINUX on i386, our initrd is extremely limited in size,
    # because we have to squeeze it into a 2.88 megabyte floppy image that is
    # shared with a kernel (and SYSLINUX guts of negligible size).

    # Assume that gzip -9 can get us down to 60% of our original size, on
    # average.  Experimentation on actual kernel modules reveals that gzip does
    # a little better than this.  With all the text files on the initrd, this
    # compression ratio should be better still.  With this assumption, a full
    # 8192kB filesystem would compress down to 4915kB.  We need to be at most
    # 2880kB, so our maximum allowed size is 4800kB, uncompressed.  (And that
    # doesn't count the kernel itself.)

    # Data point: for the Debian 2.4.18-386 kernel flavor, we ended up with a
    # 4052kB initrd, which gzipped to 1540kB, and was shared with a 643kB
    # kernel and syslinux's miscellany.  The resulting 2.88MB floppy image was
    # 78% full.  That is about as close a margin as I'm willing to cut given
    # that we can't know exactly kind of kernels people are going to build.

    modules_size=$(( (4800 - $INITRD_ACTUAL_SIZE) * 1024 ))

    # XXX: this is the old logic
    # if [ "$initrdtype" = "system" ]; then
    #     modules_size=$(( 2880 * 1024 ))
    # else
    #     # installer initrd has more stuff on it
    #     modules_size=$(( 1440 * 1024 ))
    # fi
    ;;
esac

(for module in $modules; do echo $module; done) | \
    python $RELEASE_tools/reducemodules.py $version $modules_size | \
    xargs tar -c | (cd $root && tar -x)

exit 0

# vim:ai:et:sts=4:sw=4:tw=0:
