#! /sbin/sh

# @(#) $Revision: 1.4.98.4 $
#set -x

# We want classic behavior:
unset UNIX95

##########################################################################
# Name:  mk_ramfs
#
# Description:  This script is used to build the RAM filesystem for
#               machines which are booting from a remote kernel server.
#
##########################################################################

##########################################################################
# echo2, echo messages to a file
#
# Prepend "${myname}:  " to our echo output
#
echo2()
{
	echo "${myname}:  $*"
}

##########################################################################
# Usage message
#
myname="${0##*/}"
usage="Usage: $myname -r <ram-root> -R <system-root> -c <cpp-path> -8"

##########################################################################
# Set option argument defaults
#
RAMROOT="/usr/conf/ramroot"	# default ram commands root
SYSROOT="/"			# default system root
RAMFS="/usr/conf/vmunix.fs"	# default install target
CPP=/usr/ccs/lbin/cpp		# default cpp path
ARCHTYPE=700			# default client architecture

##########################################################################
# Parse the arguments
#

while getopts r:R:c:8 option
do
	case $option in
	*r)	#
    		# RAMROOT defaults to "/usr/conf/ramroot"
    		#
       		RAMROOT=$OPTARG
		;;
	*R)	#
    		# SYSROOT defaults to "/"  (standalone install case)
    		# or might be "/export/shared_roots/OS_700"
		# (alternate root install case)
    		#
       		SYSROOT=$OPTARG
    		RAMFS="${SYSROOT}/usr/conf/vmunix.fs"	# install target
		;;
	*c)     #
		# CPP defaults to /usr/ccs/lbin/cpp
	 	# Set a new CPP path.
		CPP=$OPTARG
		;;
	*8)	#
    		# ARCHTYPE defaults to "700"
    		#
		ARCHTYPE=800
		echo "Note: Building s800 style RAM FS"
		;;
	*)	echo "${usage}"
		exit 1
		;;
	esac
done

##########################################################################
# Set some useful variables
#
CPPFLAGS=""
BLKSIZE=4096			# for mkfs
FRAGSIZE=1024			# for mkfs
RAMSIZE=0			# dynamically determined *real* RAMSIZE

###########################################################################
# Error check the arguments
#
if [ ! -d "${RAMROOT}" ]; then
	echo2 "Exiting, no <ram-root> directory: ${RAMROOT}"
	echo "${usage}"
	exit 1
fi
if [ ! -d "${SYSROOT}" ]; then
	echo2 "Exiting, no <system-root> directory: ${SYSROOT}"
	echo "${usage}"
	exit 1
fi
if [ "${SYSROOT}" = "/" ]; then
	#
	# Strip off the 'trailing' slash, since we'll
	# supply it ourselves below.  This is only to
	# keep the proto file from having "//sbin/sh".
	#
	SYSROOT=""
fi
ramfs_targetdir="${RAMFS%/*}"		# Get "dirname" of RAMFS
if [ -d ${ramfs_targetdir} ]; then
	touch ${RAMFS}.n				# mkfs requirement
else
	echo2 "Exiting, no install target directory: ${RAMFS}"
	echo "${usage}"
	exit 1
fi

###########################################################################
# Verify the existance of the necessary files, these will be the source
# files used by the mkfs proto file below.  "mkfs" seems to quietly
# create zero length files if the source does not exist, so we need to
# make sure that they DO exist before we run "mkfs".
#
for file in \
	${RAMROOT}/sbin/kernel_rc 	\
	${RAMROOT}/sbin/get_bootp_info  \
	${SYSROOT}/sbin/link            \
	${SYSROOT}/sbin/mount           \
	${SYSROOT}/sbin/fs/nfs/mount    \
	${SYSROOT}/sbin/sh              \
	${RAMROOT}/sbin/swapon          \
	${RAMROOT}/sbin/ifconfig        \
	${RAMROOT}/sbin/route           \
	${RAMROOT}/usr/sbin/tftp
do
	if [ ! -f "${file}" ]; then
		echo2 "Missing required file: $file"
		echo2 "Leaving ${RAMFS} unchanged, and exiting..."
		rm -f ${RAMFS}.n
		exit 1
	else
		FILESIZE=`du $file | awk '{print $1}'`
		RAMSIZE="`expr $RAMSIZE + $FILESIZE`"
	fi
done


###########################################################################
# Adjust the RAMSIZE value
#
RAMSIZE="`expr ${RAMSIZE} / 2`"	     #convert from 512 -> 1k units
PAD="`expr ${RAMSIZE} / 20`"         #default PAD is 5%
if [ ${PAD} -le 200 ]; then
	PAD=200         #minimum PAD is 200 (sometimes 5% isn't enough)
fi
RAMSIZE="`expr ${RAMSIZE} + ${PAD}`"  #mkfs will choke if we don't PAD size


###########################################################################
# Hack up a quick ${RAMROOT}/etc/services file
#
if [ ! -d ${RAMROOT}/etc ]; then
	mkdir ${RAMROOT}/etc
fi
echo "tftp          69/udp                 # Trivial File Transfer Protocol" \
	> ${RAMROOT}/etc/services

###########################################################################
# Based on the architecture this RAM FS will be used with, we create
# a file named "700" or "800" in the RAM FS.  Contents of this file isn't
# important -- just its existence.  We need this so kernel_rc can query the
# type at boot time, before we have the real root mounted.
#
# Create an empty file as the source for the console log and the
# architecture type files.
#
> ${RAMROOT}/etc/empty


###########################################################################
# Build up cpp flags
#
CPPFLAGS="${CPPFLAGS} -DX_RAMROOT=${RAMROOT}"
CPPFLAGS="${CPPFLAGS} -DX_SYSROOT=${SYSROOT}"
CPPFLAGS="${CPPFLAGS} -DX_RAMSIZE=${RAMSIZE}"
CPPFLAGS="${CPPFLAGS} -DX_ARCHTYPE=${ARCHTYPE}"

###########################################################################
# Create the 'mkfs' proto file.
#
# What follows is a normal prototype file, stuffed in a "here" document.
# Cpp will replace "X_SYSROOT", "X_RAMROOT", etc, with the real path to
# the <system-root>, <ram-root>, etc, respectively.
#
# We pass it through cpp so we can add #ifdefs, do substitutes, add
# comments, etc.  See CPPFLAGS above.
#
PROTO=/tmp/proto.$$

${CPP} ${CPPFLAGS} <<'end-of-proto' | sed 's/#.*$//' > ${PROTO}
""
X_RAMSIZE
d--555 bin  bin
conslog ---644 bin bin X_RAMROOT/etc/empty
dev	d--555 bin  bin
        console		c--622 root other  0 0x000000
        config		c--600 root root  69 0x000000
        kepd		c--600 root root 227 0x000000
        kmem		c--600 root root   3 0x000001
	null            c--666 bin  bin    3 0x000002
	$
etc	d--555 bin  bin
	services  	---555 bin  bin	   X_RAMROOT/etc/services
	hosts	  	l--555 bin  bin	   /newroot/etc/hosts
	X_ARCHTYPE  	L--555 bin  bin	   /conslog
	$
sbin	d--555 bin  bin
	get_bootp_info	---555 bin  bin    X_RAMROOT/sbin/get_bootp_info
	hostname	L--555 bin  bin    /sbin/get_bootp_info
	link	     	---555 bin  bin    X_SYSROOT/sbin/link
	vminfo		L--555 bin  bin    /sbin/get_bootp_info
	mount     	---555 bin  bin    X_SYSROOT/sbin/mount
	pre_init_rc     ---544 bin  bin    X_RAMROOT/sbin/kernel_rc
	rename	     	L--555 bin  bin    /sbin/link
	swapon 		---555 bin  bin    X_RAMROOT/sbin/swapon
	uname		L--555 bin  bin    /sbin/get_bootp_info
	sh	  	---555 bin  bin	   X_SYSROOT/sbin/sh
	unlink	     	L--555 bin  bin    /sbin/link
	ifconfig  	---555 bin  bin    X_RAMROOT/sbin/ifconfig
	route     	---555 bin  bin    X_RAMROOT/sbin/route
	tftp 		---555 bin  bin    X_RAMROOT/usr/sbin/tftp
	fs	d--555 bin  bin
		nfs	d--555 bin  bin
			mount	---555 bin  bin	X_SYSROOT/sbin/fs/nfs/mount
			$
		$
	$
tmp	d--777 bin  bin
	$
newroot	d--555 root root
	$
$
end-of-proto

###########################################################################
# prepare the mkfs output file
#
MKO="${RAMROOT}/mkfs.out"
if [ -f "${MKO}" ]; then
	rm -f ${MKO}.bk
	mv ${MKO} ${MKO}.bk
	echo2 "Moved old mkfs log to ${MKO}.bk"
fi

###########################################################################
# Build the RAM filesystem, based on the proto file we created (${PROTO}).
#
mkfs -L -F hfs -d ${RAMFS}.n ${PROTO} 176 10 ${BLKSIZE} ${FRAGSIZE} \
	2 0 8 32768 > ${MKO} 2>&1

###########################################################################
# Check return value from mkfs command
#
if [ $? -ne 0 ] ; then

    #######################################################################
    # mkfs failed, print mkfs error output, exit 1
    #
    echo2 "RAM filesystem build failed"
    echo2 "Error Output (of mkfs) follows:"
    cat ${MKO}
    echo2 "End of Error Output (of mkfs)"
    echo2 "Leaving ${RAMFS} unchanged, and exiting..."
    rm -f ${MKO} ${PROTO} ${RAMFS}.n
    exit 1
else
    #######################################################################
    # mkfs succeeded, backup original vmunix.fs, install the new, exit 0.
    #
    echo2 "RAM filesystem build succeeded"
    if [ -f "${RAMFS}" ]; then
	rm -f ${RAMFS}.bk
	mv ${RAMFS} ${RAMFS}.bk
	echo2 "Moved:  ${RAMFS}"
	echo2 "To:     ${RAMFS}.bk"
    fi
    if [ -f "${RAMFS}.n" ]; then
	echo2 "Installing new ${RAMFS}"
	mv ${RAMFS}.n ${RAMFS}
    else  # should not be reached
	echo2 "Strange... mkfs succeeded, but cannot find ${RAMFS}.n"
	echo2 "Unable to install new ${RAMFS}, exiting..."
        exit 1
    fi
    rm -f ${MKO} ${PROTO}
    exit 0
fi
