#! /bin/sh -

# $FreeBSD: stable/3/release/picobsd/build/stage1 61123 2000-05-31 12:49:10Z luigi $
#
# stage1 -- this script fills the mfs for the picobsd kernel

. ../Version

set -e	# abort in case of untested errors

MFS_NAME=fs.PICOBSD
MFS_MOUNTPOINT=/mnt
# fail errno errcode
# This function is used to trap errors and print msgs
#
fail() {
    errno=$1
    errcode=$2
    echo "--> Error $errno code $errcode"
    case $errcode in
    no_vnconfig)
	echo "Error while doing vnconfig of ${MFS_NAME} on /dev/rvn0..."
	echo "   Most probably your running kernel doesn't have the vn(4) device."
	;;
    disklabel)
	echo "Error while labeling ${MFS_NAME} size ${MFS_SIZE}"
	;;
    no_mount)
	echo "Error while mounting ${MFS_NAME} (/dev/vn0c) on ${MFS_MOUNTPOINT}"
	;;
    mtree)
	echo "Error while making hierarchy in ${MFS_MOUNTPOINT}"
	;;
    makedevs)
	echo "Error while making devices in ${MFS_MOUNTPOINT}"
	;;
    crunch)
	echo "Error while building ../${TYPE}/crunch1..."
	;;
    vnconfig2)
	echo "Error while doing vnconfig of floppy.img on /dev/rvn0..."
	;;
    disklabel)
	echo "Error while doing disklabel on of floppy.img size $FLOPPY_SIZE"
	;;
    kernel_compress)
	echo "Error while copying compressed kernel to disk"
	;;
    mfs_compress)
	echo "Error while copying compressed mfs image to disk"
	;;
    missing_kernel)
	echo "-> ERROR: you must build PICOBSD${suffix} kernel first"
	;;
    esac
    echo "-> Aborting $0"
    exit 10
}

rm -f kernel.gz ${MFS_NAME}	# cleanup...

create_mfs() {
    echo "-> Preparing MFS filesystem..."
    umount /dev/vn0 2> /dev/null || true
    umount ${MFS_MOUNTPOINT} 2> /dev/null || true
    vnconfig -u /dev/rvn0 2> /dev/null || true

    dd of=${MFS_NAME} if=/dev/zero count=${MFS_SIZE} bs=1k 2> /dev/null

    awk 'BEGIN {printf "%c%c", 85, 170}' | \
	dd of=${MFS_NAME} obs=1 seek=510 conv=notrunc  2> /dev/null

    vnconfig -s labels -c /dev/rvn0 ${MFS_NAME} 2>/dev/null || \
	fail $? no_vnconfig

    dd if=/boot/boot1 of=${MFS_NAME} conv=notrunc 2> /dev/null

    # This command does weird things on 2.2.x systems.
    # For small image sizes, use std disktypes
    if [ ${MFS_SIZE} -lt 1024 ] ; then
	disklabel -rw /dev/rvn0 fd${MFS_SIZE} || fail $? disklabel
    else
	disklabel -rw vn0 auto || fail $? disklabel
    fi

    newfs -i ${MFS_INODES} -m 0 -p 0 -o space /dev/rvn0c
    mount /dev/vn0c ${MFS_MOUNTPOINT} || fail $? no_mount

    pwd=`pwd`
}

populate_mfs() {
    echo "-> Populating MFS tree..."
    cd ../${TYPE}
    make -f Makefile.mfs DESTDIR=${MFS_MOUNTPOINT} >/dev/null || \
	fail $? mtree
    if [ X"${NO_DEVFS}" != X"" ] ; then
	make -f Makefile.mfs DESTDIR=${MFS_MOUNTPOINT} devnodes \
		>/dev/null || fail $? makedevs
    fi

    MFS_RC=mfs_tree/etc/rc
    if [ ! -f ${MFS_RC} ] ; then # no private version. use generic mfs.rc
	MFS_RC=${BUILDDIR}/../${MFS_RC}
    fi
    if [ "${INIT}" = "oinit" ] ; then
	cat ${MFS_RC} | sed -e "s/@VER@/${VER}/g" > ${MFS_MOUNTPOINT}/etc/oinit.rc
    else
	cat ${MFS_RC} | sed -e "s/@VER@/${VER}/g" > ${MFS_MOUNTPOINT}/etc/rc
	if [ -f mfs_tree/etc/login.conf ] ; then
	    cp mfs_tree/etc/login.conf ${MFS_MOUNTPOINT}/etc/login.conf
	else
	    cp ${BUILDDIR}/../mfs_tree/etc/login.conf \
			${MFS_MOUNTPOINT}/etc/login.conf
	fi
    fi

    if [ "${TYPE}" = "dial" ] ; then
	for i in login dialup; do
	    cp lang/${i}.${LANGUAGE} ${MFS_MOUNTPOINT}/stand/${i}
	done
	ln -s /stand/reboot ${MFS_MOUNTPOINT}/stand/shutdown
	(cd ../help;\
	rm -rf tmp_hlp;\
	mkdir tmp_hlp;\
	for i in `ls *.hlp.${LANGUAGE}`; do \
		cp $i tmp_hlp/`basename $i .hlp.${LANGUAGE}`;\
	done;\
	cd tmp_hlp;\
	ar -cru help.a *;\
	cp help.a ${MFS_MOUNTPOINT}/help.a)
    fi

    echo "-> Making and installing crunch1..."
    cd crunch1
    make -f ../../build/Makefile.crunch "SRC=${SRC}" && \
	make -f ../../build/Makefile.crunch install 2>&1 >/dev/null || \
	fail $? crunch

    cd ${pwd}
    if [ -f ${MFS_MOUNTPOINT}/stand/sshd ] ; then
	echo "creating host key for sshd"
	ssh-keygen1 -f ${MFS_MOUNTPOINT}/etc/ssh_host_key -N "" -C "root@picobsd"
    fi
    cp -Rp ../mfs_tree/stand/update ${MFS_MOUNTPOINT}/stand/update

    (echo "-> Fixing permissions"; cd ${MFS_MOUNTPOINT}; chown -R root *)
    df -ik ${MFS_MOUNTPOINT}
    umount ${MFS_MOUNTPOINT}
    fsck -p /dev/rvn0c
    vnconfig -u /dev/rvn0
}

# stage2

do_kernel() {
    echo "-> Preparing kernel..."
    (cd ../${TYPE}; make -f ${BUILDDIR}/Makefile.conf )
    cp -p ${SRC}/sys/compile/PICOBSD${suffix}/kernel kernel || \
	fail $? missing_kernel
    strip kernel
    strip --remove-section=.note --remove-section=.comment kernel
    gzip -9 -v -n kernel
}

do_floppy() {
    # On entry we are in /usr/src/release/build.

    echo "==> Preparing ${FLOPPY_SIZE}kB floppy filesystem..."

    dd of=picobsd.bin if=/dev/zero count=${FLOPPY_SIZE} bs=1k

    awk 'BEGIN {printf "%c%c", 85, 170}' | \
                dd of=picobsd.bin obs=1 seek=510 conv=notrunc  2> /dev/null

    vnconfig -c /dev/rvn0 picobsd.bin || fail $? vnconfig2

    dd if=/boot/boot1 of=picobsd.bin conv=notrunc 2> /dev/null

    # XXX todo: use a type matching floppy size.
    disklabel -Brw -b /boot/boot1 -s /boot/boot2 /dev/rvn0 fd1440 || \
	fail $?  disklabel

    newfs -i ${FLOPPY_INODES} -m 0 -p 0 -o space /dev/rvn0c

    mount /dev/vn0c ${MFS_MOUNTPOINT}

    echo "==> Populating floppy filesystem..."

    # Configuration files are first copied to a local tree, then
    # compressed, then transferred back to the floppy.
    rm -rf floppy.tree || true
    mkdir floppy.tree

    excl=${BUILDDIR}/../${TYPE}/floppy.tree.exclude
    if [ -f ${excl} ] ; then
	excl="--exclude-from ${excl}"
	echo "Exclude following files from ${excl}:\n==="
	cat ${excl}
	echo "==="
    else
	excl=""
    fi
    (cd ${BUILDDIR}/../floppy.tree ; tar -cf - ${excl} . ) | \
		(cd floppy.tree ; tar xvf - )

    if [ -d ${BUILDDIR}/../${TYPE}/floppy.tree ] ; then
	echo "-> update with private files:"
	(cd ${BUILDDIR}/../${TYPE}/floppy.tree ; tar cf - . ) | \
		(cd floppy.tree ; tar xvf - )
    fi
    if [ -d ${BUILDDIR}/../${TYPE}/floppy.tree.${SITE} ] ; then
	echo "-> update with site-specific (${SITE}) files:"
	(cd ${BUILDDIR}/../${TYPE}/floppy.tree.${SITE} ; tar cf - . ) | \
		(cd floppy.tree ; tar xvf - )
    fi
    rm -f floppy.tree/etc/mfs\.*  # mfs.rc, mfs.login.conf
    files="motd"
    echo "-> Copying language dependent files: ${files} -> ${MFS_MOUNTPOINT}/etc ..."
    for i in ${files} ; do
	cat ${BUILDDIR}/../${TYPE}/lang/${i}.${LANGUAGE} | \
		sed -e "s/@VER@/${VER}/g" > floppy.tree/etc/${i}
    done

    # XXX check this! i am unsure how it is necessary.
    if [ "${TYPE}" = "dial" ] ; then
	cp -p floppy.tree/etc/master.passwd .
	pwd_mkdb -d . master.passwd
	mv spwd.db floppy.tree/etc/
	rm pwd.db master.passwd
    fi
    # gzip returns an error if it fails to compress some file
    gzip -9 floppy.tree/etc/* || true

    # Now, first copy large files, then small ones.
    cp -p kernel.gz ${MFS_MOUNTPOINT}/kernel.gz || fail $? kernel_compress

    gzip -9cv ${MFS_NAME} > ${MFS_MOUNTPOINT}/${MFS_NAME}.gz || \
		fail $? mfs_compress

    if [ ! -d ${MFS_MOUNTPOINT}/boot ] ; then
	mkdir -p ${MFS_MOUNTPOINT}/boot
    fi
    #
    # make small loader
    #(cd /usr/src/sys/boot/i386/loader ; make clean ;
    # cd /usr/src/sys/boot/i386 ; make -DNOFORTH )
    if [ -f /usr/src/sys/boot/i386/loader/loader ]; then
	theloader=/usr/src/sys/boot/i386/loader/loader
    else
	theloader=/boot/loader
    fi
    kgzip -o loader $theloader
    cp -p loader ${MFS_MOUNTPOINT}/boot/loader

    #
    # now transfer the floppy tree
    cp -Rp floppy.tree/* ${MFS_MOUNTPOINT}
    echo "q" > ${MFS_MOUNTPOINT}/boot/kernel.conf
    cat <<__EOF > ${MFS_MOUNTPOINT}/boot/loader.rc
load kernel
load -t userconfig_script /boot/kernel.conf
load -t mfs_root ${MFS_NAME}
__EOF
    (echo "-> Fixing permissions"; cd ${MFS_MOUNTPOINT}; chown -R root *)

    df -ik ${MFS_MOUNTPOINT} > .build.reply
    umount ${MFS_MOUNTPOINT}
    vnconfig -u /dev/rvn0
    # rm kernel.gz ${MFS_NAME}
}

do_kernel
create_mfs
populate_mfs
do_floppy
