picobsd revision 85833
172770Sluigi#!/bin/sh -
272770Sluigi#
372770Sluigi# $FreeBSD: head/release/picobsd/build/picobsd 85833 2001-11-01 16:17:37Z luigi $
472770Sluigi#
572770Sluigi# The new PicoBSD build script. Invoked as
672770Sluigi#
772770Sluigi# picobsd [options] floppy_type site_name
872770Sluigi#
972770Sluigi# Where floppy_type is a directory where the picobsd config info
1072770Sluigi# is held, and ${floppy_type}/floppy.tree.${site_name} contains
1172770Sluigi# optional site-specific configuration.
1272770Sluigi#
1372770Sluigi# For Options, see the bottom of the file where the processing is
1478494Sluigi# done. The picobsd(8) manpage might be of some help, but code and docs
1578494Sluigi# tend to lose sync over time...
1672770Sluigi#
1772770Sluigi# This script depends on the following files:
1872770Sluigi#
1972770Sluigi# in ${PICO_TREE} :
2072770Sluigi#   Makefile.conf	Makefile used to build the kernel
2172770Sluigi#   config		shell variables, sourced here.
2272770Sluigi#   mfs.mtree		mtree config file
2372770Sluigi#
2472770Sluigi#   floppy.tree/	files which go on the floppy
2572770Sluigi#   mfs_tree/		files which go onto the mfs
2672770Sluigi#
2772770Sluigi# in ${MY_TREE} :
2872770Sluigi#   PICOBSD		kernel config file
2972770Sluigi#   config		shell variables, sourced here.
3072770Sluigi#   crunch.conf		crunchgen configuration
3172770Sluigi#   floppy.tree.exclude	files from floppy.tree/ which we do not need here.
3272770Sluigi#   floppy.tree/	local additions to the floppy.tree
3372770Sluigi#   floppy.tree.${site}/ same as above, site specific.
3472770Sluigi
3572770Sluigi#
3672770Sluigi#--- The main entry point is at the end.
3772770Sluigi#
3872770Sluigi
3984377Sluigi# There are two set of initialization. The first one (set_defaults)
4084377Sluigi# is done on entry to the script, and is used to set default values
4184377Sluigi# for all variables which do not depend on floppy type and source tree.
4284377Sluigi#
4384377Sluigi# The second set is done after command line parsing, e.g.
4484377Sluigi# to resolve dependencies on the source tree.
4584377Sluigi#
4684377Sluigi# Naming:
4784377Sluigi# + variables that control operation (e.g. verbosity) and are generally
4884377Sluigi#   set from the command line have o_ ("option") as a name prefix
4984377Sluigi#
5084377Sluigi# + variables which contain pathnames and values that should not change
5184377Sluigi#   have c_ ("constant") as a name prefix
5284377Sluigi#
5384377Sluigi# + variables exported to Makefiles and subshells are CAPITAL
5484377Sluigi#
5584377Sluigi# + variables local to the script are lowercase, possibly with
5684377Sluigi#   an l_ ("local") prefix
5772770Sluigi
5884377Sluigi# SRC points to your FreeBSD source tree.
5984377Sluigi# l_usrtree points to the /usr subdir for the source tree.
6084377Sluigi#     Normally /usr or ${SRC}/../usr
6184377Sluigi# l_objtree points to the obj tree. Normally ${l_usrtree}/obj-pico
6284377Sluigi# PICO_TREE is where standard picobsd stuff resides.
6384377Sluigi#     Normally ${SRC}/release/picobsd
6484377Sluigi# You can set SRC with --src <directory>
6584377Sluigi# It is not recommended to override the other variables.
6672770Sluigi
6784377Sluigi# MY_TREE (set later) is where this floppy type resides.
6884377Sluigi# BUILDDIR is the build directory
6972770Sluigi
7084377Sluigi# set some default values for variables.
7184377Sluigi# needs to be done as the first thing in the script.
7272770Sluigi
7384377Sluigi# log something on stdout if verbose.
7484377Sluigio_verbose=0	# this needs to be here!
7584377Sluigilog() {
7684377Sluigi    if [ ${o_verbose} -gt 0 ] ; then
7784377Sluigi	printf "\n*** %s\n" "$*"
7884377Sluigi	if [ ${o_verbose}  -gt 1 ] ; then
7984377Sluigi	    read -p "=== Press enter to continue" foo
8084377Sluigi	fi
8184377Sluigi    fi
8284377Sluigi}
8383723Sjoe
8484377Sluigiset_defaults() {
8584377Sluigi    # no way to use logging in this function, variable not set yet.
8672770Sluigi
8772770Sluigi    # EDITOR is the editor you use
8884377Sluigi    # fd_size  floppy size in KB (default to 1440). You can use 1480,
8972770Sluigi    #	1720, 2880, etc. but beware that only 1440 and 1480 will boot
9072770Sluigi    #	from 1.44M floppy drives (1480 will not work on vmware).
9172770Sluigi    EDITOR=${EDITOR:-vi}
9284377Sluigi    fd_size=${fd_size:-1440}
9372770Sluigi
9484377Sluigi    o_all_in_mfs="yes"		# put all files in mfs so you can boot and run
9584377Sluigi				# the image via diskless boot.
9684377Sluigi    o_clean=""			# do not clean
9784377Sluigi    o_interactive=""		# default is interactive
9884377Sluigi    o_verbose=0			# verbose level, 0 is silent
9984377Sluigi    o_tarv=""			# tar verbose flag, "" or "v"
10084377Sluigi    o_init_src=""		# non "" if we need to init libs and includes.
10184377Sluigi    o_makeopts=${MAKEOPTS:--s}	# make options, be silent by default
10284377Sluigi    o_no_devfs=yes		# we do not want devfs
10385833Sluigi    o_do_modules=""		# do not build modules
10472770Sluigi
10584377Sluigi    SRC="/usr/src"		# default location for sources
10684377Sluigi    c_startdir=`pwd`	# directory where we start
10784377Sluigi			# used to lookup config and create BUILDDIR
10884377Sluigi
10984377Sluigi    c_boot1=/boot/boot1	# boot blocks (in case you want custom ones)
11084377Sluigi    c_boot2=/boot/boot2
11184377Sluigi
11284377Sluigi    c_reply=${c_reply:-`mktemp "/tmp/reply.XXXXXXXXXX"`}
11384377Sluigi    			# file where User replies will be put
11484377Sluigi    c_mnt=`mktemp -d "/tmp/picobsd.XXXXXXXXXX"`
11584377Sluigi    			# mountpoint used to build memory filesystems
11684377Sluigi    c_fs=fs.PICOBSD	# filename used for the memory filesystem
11784377Sluigi    c_img=picobsd.bin	# filename used for the picobsd image
11884377Sluigi
11984377Sluigi    # select the right memory disk name
12084377Sluigi    case `uname -r` in
12184377Sluigi	5.*)
12284377Sluigi	    l_vn="md"
12384377Sluigi	    l_makedev="${SRC}/etc/MAKEDEV"
12484377Sluigi	    ;;
12584377Sluigi	*)
12684377Sluigi	    l_vn="vn"
12784377Sluigi	    l_makedev="/dev/MAKEDEV"
12884377Sluigi    esac
12972770Sluigi    # Find a suitable vnode
13084377Sluigi    l_vnum=`mount | awk "/${l_vn}/ { num++ } END { printf \"%d\", num }"`
13184377Sluigi    l_vndev=${l_vn}${l_vnum}
13272770Sluigi
13372770Sluigi    set -e
13472770Sluigi
13584377Sluigi    trap fail 2
13684377Sluigi    #trap fail 3
13784377Sluigi    #trap fail 6
13884377Sluigi    trap fail 15
13984377Sluigi    free_vnode			# cleanup old vnodes
14072770Sluigi}
14172770Sluigi
14284377Sluigicreate_includes_and_libraries() {
14384377Sluigi    log "create_includes_and_libraries() for ${SRC}"
14484377Sluigi    # Optionally creates include directory and libraries.
14584377Sluigi    mkdir -p ${l_usrtree}/include		# the include directory...
14684377Sluigi    mkdir -p ${l_usrtree}/share/misc	# a few things go here
14784377Sluigi    mkdir -p ${l_usrtree}/lib		# libraries
14884377Sluigi    mkdir -p ${l_usrtree}/sbin		# some binaries
14984377Sluigi    (cd ${SRC}; INCOWN=`id -un`  BINOWN=`id -un` DESTDIR=${SRC}/.. \
15084377Sluigi		make includes ) || fail $? includes
15184377Sluigi    # libraries already have the include path in the Makefile
15284377Sluigi    CFLAGS="-nostdinc" ; export CFLAGS
15384377Sluigi
15484377Sluigi    (cd ${SRC}
15584377Sluigi	# $e is the invocation of make with correct environment
15684377Sluigi	e="MAKEOBJDIRPREFIX=${l_objtree}/picobsd/libraries \
15784377Sluigi	    INCOWN=`id -un` BINOWN=`id -un` DESTDIR=${SRC}/.. \
15884377Sluigi	    make -DNOHTML -DNOINFO -DNOMAN -DNOSHARE -DNOFSCHG "
15984377Sluigi	# need to 'make obj' in a few places. This is very
16084377Sluigi	# version-specific... The following works for 5.0
16184377Sluigi	for i in lib secure/lib gnu/lib usr.sbin/pcvt/keycap \
16284377Sluigi		gnu/usr.bin/perl usr.bin/lex usr.sbin/config ; do
16384377Sluigi	    (cd ${i}; eval $e obj)
16484377Sluigi	done
16584377Sluigi	# now make the static libraries
16684377Sluigi	eval $e -DNOPROFILE -DNOPIC libraries
16784377Sluigi	(cd ${SRC}/usr.sbin/config
16884377Sluigi	eval $e		# build binary
16984377Sluigi	eval $e	install	# install it
17084377Sluigi	)
17184377Sluigi    ) || fail $? "libraries"
17284377Sluigi    log "Libraries done"
17372770Sluigi}
17472770Sluigi
17584377Sluigi# set_type <type> looks in user or system directories for the floppy type
17684377Sluigi# specified as first argument, and sets variables according to the config.
17784377Sluigi# file. Also sets MY_TREE and BUILDDIR and SITE
17872770Sluigi
17984377Sluigiset_type() {
18084377Sluigi    local a
18184377Sluigi
18284377Sluigi    log "set_type()"
18384377Sluigi    THETYPE=$1
18484377Sluigi    SITE=$2
18572770Sluigi    a=$1
18684377Sluigi    for i in ${c_startdir}/${a} ${PICO_TREE}/${a} ; do
18778494Sluigi	log "set_type: checking $i"
18872770Sluigi	if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ] ; then
18972770Sluigi	    set -- `cat $i/PICOBSD | \
19072770Sluigi	    awk '/^#PicoBSD/ {print $2, $3, $4, $5, $6}'`
19172770Sluigi	    if [ "$1" != "" ]; then
19284377Sluigi		MFS_SIZE=$1 ; init_name=$2
19384377Sluigi		mfs_inodes=$3 ; fd_inodes=$4
19472770Sluigi		name=`(cd $i ; pwd) `
19572770Sluigi		name=`basename $name`
19672770Sluigi		MY_TREE=$i
19784377Sluigi		BUILDDIR=${c_startdir}/build_dir-${name}
19884377Sluigi		log "Matching file $name in $i"
19972770Sluigi		return ;
20072770Sluigi	    fi
20172770Sluigi	fi
20272770Sluigi    done
20372770Sluigi    echo "Type $a NOT FOUND"
20472770Sluigi}
20572770Sluigi
20672770Sluigiclean_tree() {
20784377Sluigi    log "clean_tree()"
20872770Sluigi    if [ "${name}" = "" ] ; then
20984377Sluigi	echo "---> Wrong floppy type"
21072770Sluigi	exit 3
21172770Sluigi    fi
21272770Sluigi    rm -rf ${BUILDDIR}
21372770Sluigi}
21472770Sluigi
21583692Sluigi# free as much as possible from the vnode
21683692Sluigifree_vnode() {
21784377Sluigi    log "free_vnode() ${l_vndev} "
21884377Sluigi    umount ${c_mnt}    2> /dev/null || true
21984377Sluigi    umount /dev/${l_vndev}       2> /dev/null || true
22084377Sluigi    if [ "${l_vn}" = "vn" ] ; then
22184377Sluigi	vnconfig -u ${l_vndev} 2> /dev/null || true
22283692Sluigi    else
22384377Sluigi	mdconfig -d -u ${l_vnum} 2> /dev/null || true
22483692Sluigi    fi
22583692Sluigi}
22683692Sluigi
22772770Sluigi# prepare a message to be printed in the dialog menus.
22872770Sluigiset_msgs() {		# OK
22984377Sluigi    log "set_msgs()"
23084377Sluigi
23172770Sluigi    MSG1="Type: ${THETYPE} name $name"
23272770Sluigi
23372770Sluigi    MSG="PicoBSD build -- Current parameters:\n\n\t1.  ${MSG1}\n\
23472770Sluigi\t2.  MFS size: ${MFS_SIZE} kB\n\
23572770Sluigi\t3.  Site-info: ${SITE}\n\t4.  Full-path: ${MY_TREE}\n"
23672770Sluigi}
23772770Sluigi
23872770Sluigi
23972770Sluigi# Main build procedure.
24072770Sluigibuild_image() {
24184377Sluigi    log "build_image() <${name}>"
24284377Sluigi    [ "${name}" != "" ] || fail $? bad_type
24372770Sluigi    clear
24472770Sluigi    set_msgs
24584377Sluigi    printf "${MSG}---> We'll use the sources living in ${SRC}\n\n"
24672770Sluigi
24784377Sluigi    # read config variables from a global and then a type-specific file
24884377Sluigi    # basically STAND_LINKS and MY_DEVS, but can also override other
24984377Sluigi    # variables.
25084377Sluigi    # 
25184377Sluigi    . ${PICO_TREE}/build/config
25284377Sluigi    if [ -f ${MY_TREE}/config ] ; then
25384377Sluigi	. ${MY_TREE}/config
25484377Sluigi    fi
25584377Sluigi
25684377Sluigi    # location of the object directory
25784377Sluigi    PICO_OBJ=${l_objtree}/picobsd/${THETYPE}
25884377Sluigi    log "PICO_OBJ is ${PICO_OBJ}"
25984377Sluigi
26084377Sluigi    # create build directory and subtree
26184377Sluigi    mkdir -p ${BUILDDIR}/crunch
26284377Sluigi    # remove any old stuff
26384377Sluigi    rm -f ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
26484377Sluigi    # invoke commands to build a kernel
26572770Sluigi    do_kernel
26684377Sluigi    # fill a subdirectory with things that go into the floppy
26784377Sluigi    # (mostly /etc and similar stuff)
26884377Sluigi    populate_floppy_fs
26984377Sluigi    # populate it and produce a file with the MFS image
27084377Sluigi    populate_mfs_tree		# things which go into mfs
27184377Sluigi    # create, mount and fill a filesystem with floppy image
27272770Sluigi    fill_floppy_image # copies everything into the floppy
27372770Sluigi}
27472770Sluigi
27572770Sluigibuild_package() {
27684377Sluigi    local z msg
27784377Sluigi
27884377Sluigi    log "build_package()"
27972770Sluigi    touch build.status
28072770Sluigi    echo "##############################################" >>build.status
28172770Sluigi    echo "## `date` ">>build.status
28272770Sluigi    echo "##############################################" >>build.status
28376380Sluigi    for z in bridge dial router net isp ; do
28472770Sluigi	set_type ${z}
28572770Sluigi	echo "---------------------------------------------">>build.status
28672770Sluigi	echo "Building TYPE=${z}, SIZE=${MFS_SIZE}" >>build.status
28784377Sluigi	msg="(ok)"	# error message
28884377Sluigi	build_image || msg="** FAILED! **"
28984377Sluigi        echo "	${msg}">>build.status
29084377Sluigi	# where do i put things ?
29184377Sluigi	# clean_tree
29272770Sluigi    done
29372770Sluigi    exit 0
29472770Sluigi}
29572770Sluigi
29672770Sluigi# Set build parameters interactively
29772770Sluigi
29872770Sluigimain_dialog() {
29984377Sluigi  local ans i l
30084377Sluigi
30184377Sluigi  log "main_dialog()"
30272770Sluigi  while [ true ] ; do
30372770Sluigi    set_msgs
30484377Sluigi    rm ${c_reply}
30584377Sluigi    dialog --menu "PicoBSD build menu -- (29 sep 2001)" 19 70 12 \
30672770Sluigi	N "--> READY, build it <---" \
30772770Sluigi	T "${MSG1}" \
30872770Sluigi	K "edit Kernel config file" \
30972770Sluigi	E "Edit crunch.conf file" \
31072770Sluigi	S "MFS Size: ${MFS_SIZE}kB" \
31184377Sluigi	I "Init type: ${init_name}" \
31284377Sluigi	F "Floppy size: ${fd_size}kB" \
31384377Sluigi	M "MFS bytes per inode: ${mfs_inodes}" \
31484377Sluigi	U "UFS bytes per inode: ${fd_inodes}" \
31572770Sluigi	$ "Site-info: ${SITE}" \
31672770Sluigi	Q "Quit" \
31784377Sluigi	2> ${c_reply}
31884377Sluigi    ans=`cat ${c_reply}`
31984377Sluigi    rm ${c_reply}
32072770Sluigi    case ${ans} in
32172770Sluigi    T)
32272770Sluigi	l=""
32384377Sluigi	for i in ${c_startdir} ${c_startdir}/* ${PICO_TREE}/* ; do
32472770Sluigi	    if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ]; then
32572770Sluigi		l="$l `basename $i` `basename $i`"
32672770Sluigi	    fi
32772770Sluigi	done
32872770Sluigi	log $l
32984377Sluigi	(dialog --menu "Setup the type of configuration" 12 70 5 $l \
33084377Sluigi		2> ${c_reply} && set_type "`cat ${c_reply}`" ${SITE} ) || true
33172770Sluigi	;;
33272770Sluigi    I)
33384377Sluigi	(dialog --menu "Choose your init(8) program" \
33472770Sluigi	10 70 2 init "Standard init (requires getty)" \
33584377Sluigi	oinit "small init from TinyWare" 2> ${c_reply} \
33684377Sluigi		&& init_name=`cat ${c_reply}` ) || true
33772770Sluigi	;;
33872770Sluigi
33972770Sluigi    K) ${EDITOR} ${MY_TREE}/PICOBSD ;;
34072770Sluigi
34172770Sluigi    E) ${EDITOR} ${MY_TREE}/crunch.conf ;;
34272770Sluigi
34372770Sluigi    S)
34484377Sluigi	( dialog --title "MFS Size setup" --inputbox \
34572770Sluigi"MFS size depends on what you need to put on the MFS image. Typically \
34672770Sluigiranges between 820kB (for very small bridge/router images) to \
34772770Sluigias much as 2500kB kB for a densely packed image. \
34872770SluigiKeep in mind that this memory is \
34972770Sluigitotally lost to other programs. Usually you want to keep \
35084377Sluigithis as small as possible. " 10 70 2> ${c_reply} \
35184377Sluigi	&& MFS_SIZE=`cat ${c_reply}` ) || true
35272770Sluigi	;;
35372770Sluigi
35472770Sluigi    \$)
35584377Sluigi	(dialog --title "Site info setup" --inputbox \
35672770Sluigi	"Please enter the full path to the directory \
35772770Sluigi	containing site-specific setup. \
35872770Sluigi	This directory tree must contain files that replace \
35972770Sluigi	standard ones in floppy.tree/ and mfs.tree/ . " \
36084377Sluigi	10 70 2> ${c_reply} && SITE=`cat ${c_reply}` ) || true
36172770Sluigi	;;
36272770Sluigi
36372770Sluigi    F)
36484377Sluigi	(dialog --menu "Set floppy size" 15 70 4 \
36584377Sluigi	    1440 "1.44MB" 1720 "1.72MB" 2880 "2.88MB" 4096 "4MB" \
36684377Sluigi		 2> ${c_reply} && fd_size=`cat ${c_reply}` ) || true
36772770Sluigi	;;
36872770Sluigi
36972770Sluigi    M)
37084377Sluigi	(dialog --title "MFS bytes per inode:" --inputbox \
37172770Sluigi	"Enter MFS bytes per inode (typically 4096..65536). \
37272770Sluigi	A larger value means fewer inodes but more space on MFS" \
37384377Sluigi	10 70 2> ${c_reply} && mfs_inodes=`cat ${c_reply}` ) || true
37472770Sluigi	;;
37572770Sluigi
37672770Sluigi    U)
37784377Sluigi	(dialog --title "Floppy bytes per inode:" --inputbox \
37872770Sluigi	"Enter floppy bytes per inode (typically 3072..65536). \
37972770Sluigi	A larger value means fewer inodes but more space on the floppy." \
38084377Sluigi	10 70 2> ${c_reply} && fd_inodes=`cat ${c_reply}` ) || true
38172770Sluigi	;;
38272770Sluigi
38372770Sluigi    N) break 2
38472770Sluigi	;;
38572770Sluigi
38672770Sluigi    Q) exit 0 ;;
38772770Sluigi
38872770Sluigi    *) echo "Unknown option \"${ans}\". Try again."
38972770Sluigi	sleep 2
39072770Sluigi	clear
39172770Sluigi	;;
39272770Sluigi    esac
39372770Sluigi  done
39472770Sluigi}
39572770Sluigi
39672770Sluigi# Call the build procedure
39772770Sluigi# Install image
39872770Sluigido_install() {
39984377Sluigi    log "do_install()"
40084377Sluigi
40185833Sluigi    if [ "${o_interactive}" = "NO" ] ; then
40285833Sluigi	echo "+++ Build completed +++"
40385833Sluigi	cat .build.reply
40485833Sluigi	return
40585833Sluigi    fi
40682747Sluigi    dialog --title "Build ${THETYPE} completed" --inputbox \
40772770Sluigi"\nThe build process was completed successfuly.\n\
40872770Sluigi`cat .build.reply` \n\n\
40972770SluigiNow we are going to install the image on the floppy.\n\
41072770SluigiPlease insert a blank floppy in /dev/fd0.\\n
41172770SluigiWARNING: the contents of the floppy will be permanently erased!\n\
41272770Sluigi\n\
41372770SluigiYour options:\n\
41472770Sluigi	* ^C or [Cancel] to abort,\n\
41584377Sluigi	* Enter to install ${c_img},\n\
41684377Sluigi" 20 80 2> ${c_reply}
41772770Sluigi    if [ "$?" = "0" ]; then
41884377Sluigi	echo "Writing ${c_img}..."
41984377Sluigi	dd if=${BUILDDIR}/${c_img} of=/dev/fd0.${fd_size}
42072770Sluigi    else
42184377Sluigi	echo "Ok, the image is in ${c_img}"
42272770Sluigi    fi
42372770Sluigi    echo "Done."
42472770Sluigi}
42572770Sluigi
42672770Sluigi
42772770Sluigi#-------------------------------------------------------------------
42872770Sluigi
42984377Sluigi# invoke the Makefile to compile the kernel.
43072770Sluigido_kernel() {		# OK
43184377Sluigi    log "do_kernel() Preparing kernel \"$name\" in $MY_TREE"
43282917Sluigi    (cd $MY_TREE; export name SRC CONFIG BUILDDIR # used in this makefile ;
43385833Sluigi	if [ "${o_do_modules}" = "yes" ] ; then
43485833Sluigi		MODULES=""
43585833Sluigi		export MODULES
43685833Sluigi	fi
43782917Sluigi	make -v -f ${PICO_TREE}/build/Makefile.conf ) || \
43872770Sluigi	fail $? missing_kernel
43972770Sluigi}
44072770Sluigi
44184377Sluigi# Populate the variable part of the floppy filesystem. Must be done before
44284377Sluigi# the MFS because its content might need to be copied there as well.
44372770Sluigi#
44484377Sluigi# This involves fetching files from three subtrees, in this order:
44572770Sluigi#
44684377Sluigi#  1. a standard one, from which type-specific files are excluded;
44772770Sluigi#  2. a type-specific one;
44872770Sluigi#  3. a site-specific one.
44972770Sluigi#
45072770Sluigi# Files are first copied to a local tree and then compressed.
45172770Sluigi
45272770Sluigipopulate_floppy_fs() {		# OK
45383692Sluigi    local dst excl srcdir
45472770Sluigi
45584377Sluigi    log "populate_floppy_fs()"
45672770Sluigi    dst=${BUILDDIR}/floppy.tree
45784377Sluigi    log "pwd=`pwd` Populating floppy filesystem..."
45872770Sluigi
45983692Sluigi    # clean relics from old compilations.
46083692Sluigi    rm -rf ${dst} || true
46183692Sluigi    mkdir ${dst}
46272770Sluigi
46372770Sluigi    excl=${MY_TREE}/floppy.tree.exclude
46472770Sluigi    if [ -f ${excl} ] ; then
46572770Sluigi	excl="--exclude-from ${excl}"
46684377Sluigi	log "Files excluded from generic tree: `echo;cat ${excl}`"
46772770Sluigi    else
46872770Sluigi	excl=""
46972770Sluigi    fi
47072770Sluigi    (cd ${PICO_TREE}/floppy.tree ; tar -cf - --exclude CVS ${excl} . ) | \
47184377Sluigi		(cd ${dst} ; tar x${o_tarv}f - )
47284377Sluigi    log "Copied from generic floppy-tree `echo; ls -laR ${dst}`"
47372770Sluigi
47472770Sluigi    srcdir=${MY_TREE}/floppy.tree
47572770Sluigi    if [ -d ${srcdir} ] ; then
47684377Sluigi	log "update with type-specific files:"
47772770Sluigi	(cd ${srcdir} ; tar -cf - --exclude CVS . ) | \
47884377Sluigi	    (cd ${dst} ; tar x${o_tarv}f - )
47984377Sluigi	log "Copied from type floppy-tree `echo; ls -laR ${dst}`"
48072770Sluigi    else
48184377Sluigi	log "No type-specific floppy-tree"
48272770Sluigi    fi
48372770Sluigi    if [ -d ${srcdir}.${SITE} ] ; then
48484377Sluigi	log "Update with site-specific (${SITE}) files:"
48572770Sluigi	(cd ${srcdir}.${SITE} ; tar -cf - --exclude CVS . ) | \
48684377Sluigi	    (cd ${dst} ; tar x${o_tarv}f - )
48784377Sluigi	log "Copied from site floppy-tree `echo; ls -laR ${dst}`"
48872770Sluigi    else
48984377Sluigi	log "No site-specific floppy-tree"
49072770Sluigi    fi
49172770Sluigi    # gzip returns an error if it fails to compress some file
49284377Sluigi    (cd $dst ; gzip -9 etc/*
49384377Sluigi	    log "Compressed files in etc/ `echo; ls -l etc`"
49472770Sluigi    ) || true
49572770Sluigi}
49672770Sluigi
49772770Sluigicreate_mfs() {		# OK
49884377Sluigi    log "create_mfs() Preparing MFS filesystem..."
49972770Sluigi
50072770Sluigi    free_vnode
50172770Sluigi
50272770Sluigi    # zero-fill the MFS image
50384377Sluigi    init_fs_image ${BUILDDIR}/${c_fs} ${MFS_SIZE}
50472770Sluigi
50584377Sluigi    log "Labeling MFS image"
50672770Sluigi    # Disklabel "auto" behaves strangely for sizes < 1024K. Basically
50772770Sluigi    # it fails to install a label on the system. On the other hand,
50872770Sluigi    # if you provide a specific disk type, the boot code is not
50972770Sluigi    # installed so you have more space on the disk...
51072770Sluigi    # For small image sizes, use std disktypes
51172770Sluigi    if [ ${MFS_SIZE} -lt 1024 ] ; then
51284377Sluigi	disklabel -rw ${l_vndev} fd${MFS_SIZE} || fail $? mfs_disklabel
51372770Sluigi    else
51484377Sluigi	disklabel -rw ${l_vndev} auto || fail $? mfs_disklabel
51572770Sluigi    fi
51684377Sluigi    newfs -i ${mfs_inodes} -m 0 -p 0 -o space /dev/${l_vndev}c > /dev/null
51784377Sluigi    mount /dev/${l_vndev}c ${c_mnt} || fail $? no_mount
51884377Sluigi    log "`df /dev/${l_vndev}c`"
51972770Sluigi}
52072770Sluigi
52172770Sluigi# Populate the memory filesystem with binaries and non-variable
52272770Sluigi# configuration files.
52372770Sluigi# First do an mtree pass, then create directory links and device entries,
52472770Sluigi# then run crunchgen etc. to build the binary and create links.
52572770Sluigi# Then copy the specific/generic mfs_tree.
52672770Sluigi# Finally, if required, make a copy of the floppy.tree onto /fd
52772770Sluigi
52884377Sluigipopulate_mfs_tree() {
52984377Sluigi    local a dst
53072770Sluigi
53184377Sluigi    log "populate_mfs_tree()"
53284377Sluigi    early_mfs_mount=0
53384377Sluigi    if [ "${early_mfs_mount}" = "1" ] ; then
53484377Sluigi	create_mfs
53584377Sluigi        dst=${c_mnt}
53672770Sluigi    else
53784377Sluigi	dst=${BUILDDIR}/mfs.tree
53884377Sluigi	# clean relics from old compilations.
53984377Sluigi	rm -rf ${dst} || true
54084377Sluigi	mkdir ${dst}
54172770Sluigi    fi
54272770Sluigi
54384377Sluigi    log "pwd=`pwd`, Populating MFS tree..."
54484377Sluigi
54584377Sluigi    # use type-specific mfs.mtree, default to generic one.
54684377Sluigi    a=${MY_TREE}/mfs.mtree
54784377Sluigi    [ -f ${a} ] || a=${PICO_TREE}/build/mfs.mtree
54884377Sluigi    log "Running mtree using $a..."
54984377Sluigi    mtree -deU -f $a -p ${dst} > /dev/null || fail $? mtree
55084377Sluigi
55172770Sluigi    # XXX create links
55272770Sluigi    for i in ${STAND_LINKS}; do
55384377Sluigi	ln -s /stand ${dst}/$i
55472770Sluigi    done
55584377Sluigi    ln -s /dev/null ${dst}/var/run/log
55684377Sluigi    ln -s /etc/termcap ${dst}/usr/share/misc/termcap
55772770Sluigi
55872770Sluigi
55972770Sluigi    (
56072770Sluigi    cd ${BUILDDIR}/crunch
56184377Sluigi    log "Making and installing crunch1 from `pwd` src ${SRC}..."
56272770Sluigi    a=${BUILDDIR}/crunch1.conf
56378541Sluigi    ( export BUILDDIR SRC MY_TREE PICO_OBJ ;
56482917Sluigi	make -v -f ${PICO_TREE}/build/Makefile.conf ${BUILDDIR}/crunch.mk )
56584377Sluigi    log "Libs are ${LIBS} "
56683692Sluigi    export SRC LIBS CFLAGS # used by crunch.mk
56772770Sluigi    log "Now make -f crunch.mk"
56884377Sluigi    make ${o_makeopts} -f ${BUILDDIR}/crunch.mk
56972770Sluigi    strip --remove-section=.note --remove-section=.comment crunch1
57084377Sluigi    mv crunch1 ${dst}/stand/crunch
57184377Sluigi    chmod 555 ${dst}/stand/crunch
57284377Sluigi    log "Making links for binaries..."
57372770Sluigi    for i in `crunchgen -l $a` ; do
57484377Sluigi	ln ${dst}/stand/crunch ${dst}/stand/${i};
57572770Sluigi    done
57678541Sluigi    # rm $a # do not remove!
57772770Sluigi    ) || fail $? crunch
57872770Sluigi
57984377Sluigi    if [ -f ${dst}/stand/sshd ] ; then
58084377Sluigi	log "Creating host key for sshd"
58184627Sluigi	if [ -f ${dst}/etc/ssh_host_key ] ; then
58284627Sluigi	    log "Using existing host key"
58384627Sluigi	else
58484627Sluigi	    ssh-keygen -f ${dst}/etc/ssh_host_key -N "" -C "root@picobsd"
58584627Sluigi	fi
58672770Sluigi    fi
58772770Sluigi
58872770Sluigi    if [ -d ${MY_TREE}/mfs_tree ]; then
58984377Sluigi	log "Copy site-specific MFS tree..."
59072770Sluigi	MFS_TREE=${MY_TREE}/mfs_tree
59172770Sluigi    else
59284377Sluigi	log "Copy generic MFS tree..."
59372770Sluigi	MFS_TREE=${PICO_TREE}/mfs_tree
59472770Sluigi    fi
59572770Sluigi    (cd ${MFS_TREE} ; tar -cf - --exclude CVS . ) | \
59684377Sluigi	    (cd ${dst} ; tar x${o_tarv}f - )
59772770Sluigi
59884377Sluigi    if [ "${o_all_in_mfs}" = "yes" ]; then
59984377Sluigi	log "Copy generic floppy_tree into MFS..."
60084377Sluigi	cp -Rp ${BUILDDIR}/floppy.tree/* ${dst}/fd
60172770Sluigi    fi
60284377Sluigi
60384377Sluigi    [ "`id -u`" = "0" ] || cat <<__EOF
60484377Sluigi
60584377Sluigi### -------------------------------------------------------------------
60684377Sluigi###
60784377Sluigi### WARNING: You are not running with root permissions, so the next
60884377Sluigi### stages are likely to fail because they call commands such as
60984377Sluigi### chown, {vn|md}config, mount/umount which need adequate rights.
61084377Sluigi###
61184377Sluigi### The results of the compilation so far is in directory
61284377Sluigi###  ${BUILDDIR}
61384377Sluigi### which has the following content:
61484377Sluigi
61584377Sluigi`ls -l ${BUILDDIR}`
61684377Sluigi
61784377Sluigi###
61884377Sluigi### -------------------------------------------------------------------
61984377Sluigi
62084377Sluigi__EOF
62184377Sluigi
62284377Sluigi    if [ "${o_no_devfs}" != "" ] ; then
62384377Sluigi	# create device entries using MAKEDEV
62484377Sluigi	(cd ${dst}/dev
62584377Sluigi	ln -s ${l_makedev} ; chmod 555 MAKEDEV
62684377Sluigi	./MAKEDEV ${MY_DEVS}
62784377Sluigi	rm MAKEDEV
62884377Sluigi	)
62984377Sluigi    fi
63084377Sluigi    log "Fixing permissions"
63184377Sluigi    (cd ${dst}; chown -R root . )
63284377Sluigi
63384377Sluigi    if [ "${early_mfs_mount}" != "1" ] ; then
63484377Sluigi	create_mfs
63584377Sluigi	log "Copy mfs tree into file"
63684377Sluigi	(cd ${dst} ; tar cf - . ) | ( cd ${c_mnt} ; tar xf - )
63784377Sluigi    fi
63884377Sluigi    # now umount and fsck the filesystem.
63984377Sluigi    log "Status of mfs image"
64084377Sluigi    df -ik ${c_mnt}
64184377Sluigi    umount ${c_mnt}
64284377Sluigi    fsck -p /dev/${l_vndev}c
64383692Sluigi    free_vnode
64472770Sluigi}
64572770Sluigi
64672770Sluigifinal_cleanup() {
64784377Sluigi    log "final_cleanup()"
64872770Sluigi    free_vnode
64984377Sluigi    rm -rf ${c_mnt} ${c_reply} 2> /dev/null || true
65084377Sluigi    rm -f ${c_reply}
65172770Sluigi}
65272770Sluigi
65372770Sluigi# fail errno errcode
65472770Sluigi# This function is used to trap errors and print msgs
65572770Sluigi#
65672770Sluigifail() {
65784377Sluigi    local errno errocode where
65884377Sluigi
65972770Sluigi    errno=$1
66072770Sluigi    errcode=$2
66184377Sluigi    where=$3
66284377Sluigi    echo "---> fail: Error <${errno}> error code <${errcode}> in <${where}>"
66384377Sluigi    case ${errcode} in
66472770Sluigi    no_vnconfig)
66584377Sluigi	echo "Error in vnconfig on /dev/${l_vndev}..."
66684377Sluigi	echo "Either you are not running as root or your running kernel"
66784377Sluigi	echo "does not have the ${l_vn}(4) device."
66872770Sluigi	;;
66972770Sluigi    mfs_disklabel)
67084377Sluigi	echo "Error while labeling ${c_fs} size ${MFS_SIZE}"
67172770Sluigi	;;
67272770Sluigi    no_mount)
67384377Sluigi	echo "Error while mounting ${c_fs} (/dev/${l_vndev}c) on ${c_mnt}"
67472770Sluigi	;;
67572770Sluigi    mtree)
67684377Sluigi	echo "Error while making hierarchy in ${c_mnt}"
67772770Sluigi	;;
67872770Sluigi    crunch)
67972770Sluigi	echo "Error while building ${name}."
68072770Sluigi	;;
68172770Sluigi    floppy_disklabel)
68284377Sluigi	echo "Error while doing disklabel on of floppy.img size $fd_size"
68372770Sluigi	;;
68472770Sluigi    missing_kernel)
68575880Sjoe	echo "Error: you must build PICOBSD${suffix} kernel first"
68672770Sluigi	;;
68782917Sluigi    includes)
68882917Sluigi	echo "Error: failed while making includes"
68982917Sluigi	;;
69082917Sluigi    libraries)
69182917Sluigi	echo "Error: failed while making libraries"
69282917Sluigi	;;
69384377Sluigi    bad_type)
69484377Sluigi	echo "Error: unknown floppy type ${name}"
69584377Sluigi	;;
69684377Sluigi    no_space)
69784377Sluigi	echo "Error: no space left on device (${where})"
69884377Sluigi	;;
69972770Sluigi    "")
70072770Sluigi	echo "User break"
70184377Sluigi	errcode="userbreak"
70272770Sluigi	;;
70372770Sluigi    *)
70472770Sluigi	echo "unknown error, maybe user break: $errno $errcode"
70572770Sluigi	;;
70672770Sluigi    esac
70772770Sluigi    echo "---> Aborting $0"
70872770Sluigi    # try to cleanup the vnode.
70972770Sluigi    final_cleanup
71072770Sluigi    exit 2
71172770Sluigi}
71272770Sluigi
71372770Sluigi#
71472770Sluigi# Create a zero-filled disk image with a boot sector, and vnconfig it.
71572770Sluigi#
71672770Sluigi
71772770Sluigiinit_fs_image() { # filename size_in_kbytes
71884377Sluigi    local imgname imgsize
71984377Sluigi
72084377Sluigi    log "init_fs_image() $1 $2"
72172770Sluigi    imgname=$1 ; imgsize=$2
72272770Sluigi    dd if=/dev/zero of=${imgname} count=${imgsize} bs=1k 2> /dev/null
72384377Sluigi    dd if=${c_boot1}  of=${imgname} conv=notrunc 2> /dev/null
72472770Sluigi
72584377Sluigi    if [ "${l_vn}" = "vn" ] ; then
72684377Sluigi	vnconfig -c -s labels ${l_vndev} ${imgname} || fail $? no_vnconfig
72783692Sluigi    else
72884377Sluigi	mdconfig -a -t vnode -u ${l_vnum} -f ${imgname} || fail $? no_vnconfig
72983692Sluigi    fi
73072770Sluigi}
73172770Sluigi
73272770Sluigi
73372770Sluigifill_floppy_image() {
73484377Sluigi    local blocks sectors dst
73572770Sluigi
73684377Sluigi    log "fill_floppy_image()"
73784377Sluigi    dst=${c_mnt}	# where to create the image
73884377Sluigi
73984377Sluigi    log "Preparing ${fd_size}kB floppy filesystem..."
74084377Sluigi
74172770Sluigi    # correct block and number of sectors according to size.
74284377Sluigi    blocks=${fd_size}; sectors=18
74372770Sluigi    if [ "${blocks}" = "1720" ]; then
74472770Sluigi	blocks=1722 ; sectors=21
74572770Sluigi    elif [ "${blocks}" = "1480" ]; then
74672770Sluigi	blocks=1476 ;
74772770Sluigi    fi
74872770Sluigi
74984377Sluigi    init_fs_image ${BUILDDIR}/${c_img} ${blocks}
75072770Sluigi
75184377Sluigi    log "Labeling floppy image"
75276459Sluigi    b2=${BUILDDIR}/boot2 # modified boot2
75384377Sluigi    perl -pne 's/\/boot\/loader/\/kernel\0\0\0\0\0/' ${c_boot2} > ${b2}
75484377Sluigi    disklabel -Brw -b ${c_boot1} -s ${b2} ${l_vndev} fd${fd_size} || \
75572770Sluigi	fail $?  floppy_disklabel
75672770Sluigi
75784377Sluigi    log "Newfs floppy image"
75884377Sluigi    newfs -i ${fd_inodes} -m 0 -p 0 -o space /dev/${l_vndev}c > /dev/null
75972770Sluigi
76084377Sluigi    log "Mounting floppy image"
76184377Sluigi    mount /dev/${l_vndev}c ${dst}
76272770Sluigi
76372770Sluigi    (
76472770Sluigi    cd ${BUILDDIR}
76572770Sluigi    cc -o wmk ${PICO_TREE}/../write_mfs_in_kernel.c
76684377Sluigi    log "Preload kernel with file ${c_fs}"
76784377Sluigi    ./wmk kernel ${c_fs}
76872770Sluigi    rm wmk
76984377Sluigi    log "Compress with kgzip and copy to floppy image"
77072770Sluigi    kgzip -o kernel.gz kernel
77184377Sluigi    cp -p kernel.gz ${dst}/kernel || fail $? no_space "copying kernel"
77272770Sluigi
77384377Sluigi    log "now transfer floppy tree if needed"
77472770Sluigi    # now transfer the floppy tree. If it is already in mfs, dont bother.
77584377Sluigi    if [ "${o_all_in_mfs}" != "yes" ] ; then
77684377Sluigi	cp -Rp floppy.tree/* ${dst} || \
77784377Sluigi		fail $? no_space "copying floppy tree"
77872770Sluigi    fi
77972770Sluigi    )
78084377Sluigi    (log "Fixing permissions"; cd ${dst}; chown -R root *)
78172770Sluigi    rm -rf ${BUILDDIR}/floppy.tree || true # cleanup
78272770Sluigi
78384377Sluigi    df -ik ${dst} | colrm 70 > .build.reply
78472770Sluigi    free_vnode
78584377Sluigi    rm -rf ${dst}
78684377Sluigi    rm ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
78772770Sluigi}
78872770Sluigi
78984377Sluigi# This function creates variables which depend on the source tree in use:
79084377Sluigi# SRC, l_usrtree, l_objtree LIBS, CFLAGS
79184377Sluigi# Optionally creates libraries, includes and the like (for cross compiles,
79284377Sluigi# needs to be done once).
79384377Sluigi
79484377Sluigiset_build_parameters() {
79584377Sluigi    log "set_build_parameters() SRC is ${SRC}"
79684377Sluigi    if [ "${SRC}" = "/usr/src" ] ; then
79784377Sluigi	l_usrtree=${USR:-/usr}
79884377Sluigi    else
79984377Sluigi	l_usrtree=${USR:-${SRC}/../usr}
80084093Sluigi    fi
80184377Sluigi    l_objtree=${l_usrtree}/obj-pico
80284377Sluigi    PICO_TREE=${PICO_TREE:-${SRC}/release/picobsd}
80384093Sluigi
80484377Sluigi    if [ "${o_init_src}" != "" ] ; then
80584377Sluigi	create_includes_and_libraries
80684093Sluigi    fi
80784377Sluigi    # Create the right LIBS and CFLAGS for further builds.
80884093Sluigi    # and build the config program
80984377Sluigi    LIBS="-L${l_usrtree}/lib"
81084377Sluigi    CFLAGS="-nostdinc -I${l_usrtree}/include"
81184093Sluigi    export LIBS CFLAGS
81284377Sluigi    CONFIG=${l_usrtree}/sbin/config
81384093Sluigi}
81484093Sluigi
81584377Sluigi#-------------------------------------------------------------------
81684377Sluigi# Main entry of the script. Initialize variables, parse command line
81784377Sluigi# arguments.
81884093Sluigi
81984377Sluigiset_defaults
82072770Sluigiwhile [ true ]; do
82172770Sluigi    case $1 in
82278494Sluigi    --src)	# set the source path instead of /usr/src
82384627Sluigi	SRC=`(cd $2; pwd)`
82484093Sluigi	shift
82578494Sluigi	;;
82684377Sluigi    --init)
82784377Sluigi	o_init_src="YES"
82884377Sluigi	;;
82982917Sluigi
83072770Sluigi    --floppy_size)
83184377Sluigi	fd_size=$2
83272770Sluigi	shift
83372770Sluigi	;;
83484377Sluigi
83584377Sluigi    --all_in_mfs)
83684377Sluigi	o_all_in_mfs="yes"
83784377Sluigi	;;
83884377Sluigi
83984377Sluigi    --no_all_in_mfs)
84084377Sluigi	o_all_in_mfs=""
84184377Sluigi	;;
84284377Sluigi
84385833Sluigi    --modules)	# also build kernel modules
84485833Sluigi	o_do_modules="yes"
84585833Sluigi	;;
84672770Sluigi    -n)
84784377Sluigi	o_interactive="NO"
84872770Sluigi	;;
84984377Sluigi
85084377Sluigi    -clear|-clean|-c) # clean
85184377Sluigi	o_clean="YES"
85284377Sluigi	o_interactive="NO"
85372770Sluigi	;;
85484377Sluigi
85584377Sluigi    -v) # need -v -v to wait for user input
85684377Sluigi	o_verbose=$((${o_verbose}+1))	# verbose level
85784377Sluigi	o_tarv="v"			# tar verbose flag
85884377Sluigi	o_makeopts="-d l" # be verbose
85972770Sluigi	;;
86072770Sluigi    *)
86172770Sluigi	break ;
86272770Sluigi	;;
86372770Sluigi
86472770Sluigi    esac
86572770Sluigi    shift
86672770Sluigidone
86784377Sluigiset_build_parameters	# things that depend on ${SRC}
86884377Sluigiset_type $1 $2		# type and site, respectively
86972770Sluigi
87072770Sluigi# If $1="package", it creates a neat set of floppies
87172770Sluigi
87272770Sluigiif [ "$1" = "package" ] ; then
87372770Sluigi    build_package
87472770Sluigifi
87584377Sluigiif [ "${o_interactive}" != "NO" ] ; then
87672770Sluigi    main_dialog
87772770Sluigifi
87884377Sluigiif [ "${o_clean}" = "YES" ] ; then
87972770Sluigi    clean_tree
88072770Sluigielse
88172770Sluigi    build_image
88272770Sluigi    do_install
88372770Sluigifi
88472770Sluigifinal_cleanup
88572770Sluigiexit 0
886