picobsd revision 180012
172770Sluigi#!/bin/sh -
272770Sluigi#
372770Sluigi# $FreeBSD: head/release/picobsd/build/picobsd 180012 2008-06-25 21:33:28Z ru $
4155136Sluigi# This file requires sysutils/makefs to run
572770Sluigi#
672770Sluigi# The new PicoBSD build script. Invoked as
772770Sluigi#
872770Sluigi# picobsd [options] floppy_type site_name
972770Sluigi#
1072770Sluigi# Where floppy_type is a directory where the picobsd config info
1172770Sluigi# is held, and ${floppy_type}/floppy.tree.${site_name} contains
1272770Sluigi# optional site-specific configuration.
1372770Sluigi#
1472770Sluigi# For Options, see the bottom of the file where the processing is
1578494Sluigi# done. The picobsd(8) manpage might be of some help, but code and docs
1678494Sluigi# tend to lose sync over time...
1772770Sluigi#
1872770Sluigi# This script depends on the following files:
1972770Sluigi#
2072770Sluigi# in ${PICO_TREE} :
2172770Sluigi#   Makefile.conf	Makefile used to build the kernel
2272770Sluigi#   config		shell variables, sourced here.
2372770Sluigi#   mfs.mtree		mtree config file
2472770Sluigi#
2572770Sluigi#   floppy.tree/	files which go on the floppy
2672770Sluigi#   mfs_tree/		files which go onto the mfs
2772770Sluigi#
2872770Sluigi# in ${MY_TREE} :
2972770Sluigi#   PICOBSD		kernel config file
3072770Sluigi#   config		shell variables, sourced here.
3172770Sluigi#   crunch.conf		crunchgen configuration
3272770Sluigi#   floppy.tree.exclude	files from floppy.tree/ which we do not need here.
3372770Sluigi#   floppy.tree/	local additions to the floppy.tree
3472770Sluigi#   floppy.tree.${site}/ same as above, site specific.
35122229Ssimokawa#   mfs_tree/		local additions to the mfs_free
3672770Sluigi
3772770Sluigi#
3872770Sluigi#--- The main entry point is at the end.
3972770Sluigi#
4072770Sluigi
4184377Sluigi# There are two set of initialization. The first one (set_defaults)
4284377Sluigi# is done on entry to the script, and is used to set default values
4384377Sluigi# for all variables which do not depend on floppy type and source tree.
4484377Sluigi#
4584377Sluigi# The second set is done after command line parsing, e.g.
4684377Sluigi# to resolve dependencies on the source tree.
4784377Sluigi#
4884377Sluigi# Naming:
4984377Sluigi# + variables that control operation (e.g. verbosity) and are generally
5084377Sluigi#   set from the command line have o_ ("option") as a name prefix
5184377Sluigi#
5284377Sluigi# + variables which contain pathnames and values that should not change
5384377Sluigi#   have c_ ("constant") as a name prefix
5484377Sluigi#
5584377Sluigi# + variables exported to Makefiles and subshells are CAPITAL
5684377Sluigi#
5784377Sluigi# + variables local to the script are lowercase, possibly with
5884377Sluigi#   an l_ ("local") prefix
5972770Sluigi
6084377Sluigi# SRC points to your FreeBSD source tree.
6184377Sluigi# l_usrtree points to the /usr subdir for the source tree.
6284377Sluigi#     Normally /usr or ${SRC}/../usr
6384377Sluigi# l_objtree points to the obj tree. Normally ${l_usrtree}/obj-pico
6484377Sluigi# PICO_TREE is where standard picobsd stuff resides.
6584377Sluigi#     Normally ${SRC}/release/picobsd
6684377Sluigi# You can set SRC with --src <directory>
6784377Sluigi# It is not recommended to override the other variables.
6872770Sluigi
6984377Sluigi# MY_TREE (set later) is where this floppy type resides.
7084377Sluigi# BUILDDIR is the build directory
7172770Sluigi
7284377Sluigi# set some default values for variables.
7384377Sluigi# needs to be done as the first thing in the script.
7472770Sluigi
7584377Sluigi# log something on stdout if verbose.
7684377Sluigio_verbose=0	# this needs to be here!
7784377Sluigilog() {
78173602Sluigi    local foo
79173602Sluigi    [ ${o_verbose} -gt 0 ] && printf "\n*** %s\n" "$*"
80173602Sluigi    [ ${o_verbose}  -gt 1 ] && read -p "=== Press enter to continue" foo
81173602Sluigi    return 0
8284377Sluigi}
8383723Sjoe
8491846Sluigilogverbose() {
85127266Sluigi    local foo
8691846Sluigi    printf "\n*** %s\n" "$*"
8791846Sluigi    read -p "=== Press enter to continue" foo
88173602Sluigi    return 0
8991846Sluigi}
9091846Sluigi
9184377Sluigiset_defaults() {
9284377Sluigi    # no way to use logging in this function, variable not set yet.
9372770Sluigi
9472770Sluigi    # EDITOR is the editor you use
9584377Sluigi    # fd_size  floppy size in KB (default to 1440). You can use 1480,
9672770Sluigi    #	1720, 2880, etc. but beware that only 1440 and 1480 will boot
9772770Sluigi    #	from 1.44M floppy drives (1480 will not work on vmware).
9872770Sluigi    EDITOR=${EDITOR:-vi}
9984377Sluigi    fd_size=${fd_size:-1440}
10072770Sluigi
10184377Sluigi    o_all_in_mfs="yes"		# put all files in mfs so you can boot and run
10284377Sluigi				# the image via diskless boot.
10384377Sluigi    o_clean=""			# do not clean
10484377Sluigi    o_interactive=""		# default is interactive
10584377Sluigi    o_verbose=0			# verbose level, 0 is silent
10684377Sluigi    o_tarv=""			# tar verbose flag, "" or "v"
10784377Sluigi    o_init_src=""		# non "" if we need to init libs and includes.
10884377Sluigi    o_makeopts=${MAKEOPTS:--s}	# make options, be silent by default
10984377Sluigi    o_no_devfs=yes		# we do not want devfs
11085833Sluigi    o_do_modules=""		# do not build modules
11172770Sluigi
11284377Sluigi    SRC="/usr/src"		# default location for sources
113155136Sluigi    c_startdir=`pwd`		# directory where we start
114155136Sluigi				# used to lookup config and create BUILDDIR
11584377Sluigi
116155136Sluigi    # XXX 6.x/7.x have a single /boot/boot block, which is the concatenation
117155136Sluigi    # of the old two. For the time being, we keep these, but this should
118155136Sluigi    # be fixed at some point.
119155136Sluigi
120155136Sluigi    # blocks
121127266Sluigi    c_boot1=/boot/boot1		# boot blocks (in case you want custom ones)
12284377Sluigi    c_boot2=/boot/boot2
12384377Sluigi
12484377Sluigi    c_reply=${c_reply:-`mktemp "/tmp/reply.XXXXXXXXXX"`}
125155136Sluigi    				# file where User replies will be put
12684377Sluigi    c_mnt=`mktemp -d "/tmp/picobsd.XXXXXXXXXX"`
127155136Sluigi    				# mountpoint used to build memory filesystems
128155136Sluigi    c_fs=fs.PICOBSD		# filename used for the memory filesystem
129155136Sluigi    c_img=picobsd.bin		# filename used for the picobsd image
13084377Sluigi
13184377Sluigi    # select the right memory disk name
13284377Sluigi    case `uname -r` in
133155136Sluigi	7.*|6.*|5.*)
134155136Sluigi	    l_label="bsdlabel"
13584377Sluigi	    ;;
13684377Sluigi	*)
137155136Sluigi	    l_label="disklabel"
138127266Sluigi	    ;;
13984377Sluigi    esac
14072770Sluigi
14172770Sluigi    set -e
14272770Sluigi
14384377Sluigi    trap fail 2
14484377Sluigi    #trap fail 3
14584377Sluigi    #trap fail 6
14684377Sluigi    trap fail 15
14772770Sluigi}
14872770Sluigi
14999946Sluigicreate_includes_and_libraries2() {
150155136Sluigi    local no
15199946Sluigi    log "create_includes_and_libraries2() for ${SRC}"
152155136Sluigi    if [ ${OSVERSION} -ge 600000 ] ; then
153155136Sluigi	no="-DNO_CLEAN -DNO_PROFILE -DNO_GAMES -DNO_LIBC_R"
154155136Sluigi    else
155155136Sluigi	no="-DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R"
156155136Sluigi    fi
15799946Sluigi    MAKEOBJDIRPREFIX=${l_objtree}
15899946Sluigi    export MAKEOBJDIRPREFIX
15999946Sluigi    ( cd ${SRC};
160155136Sluigi    # make -DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R -DPICOBSD buildworld
161155136Sluigi    make _+_= $no toolchain
16299946Sluigi    )
16399946Sluigi}
16499946Sluigi
165173602Sluigi# entry for 4.x and earlier trees
16684377Sluigicreate_includes_and_libraries() {
167127266Sluigi    local e i
168127266Sluigi
16984377Sluigi    log "create_includes_and_libraries() for ${SRC}"
17084377Sluigi    # Optionally creates include directory and libraries.
17184377Sluigi    mkdir -p ${l_usrtree}/include		# the include directory...
17284377Sluigi    mkdir -p ${l_usrtree}/share/misc	# a few things go here
17384377Sluigi    mkdir -p ${l_usrtree}/lib		# libraries
17484377Sluigi    mkdir -p ${l_usrtree}/sbin		# some binaries
175127266Sluigi    # override variables for ownershiip and destinations
176127266Sluigi    # BINOWN:BINGRP are also used for include files
177127266Sluigi    (cd ${SRC}; \
178127266Sluigi	BINOWN=`id -un` BINGRP=`id -gn` \
179127266Sluigi	DESTDIR=${l_usrtree}/.. \
180127266Sluigi	make -m ${SRC}/share/mk includes ) || fail $? includes
18192964Sru    # Pick up the correct headers for libraries.
18292964Sru    CFLAGS="-nostdinc -I${l_usrtree}/include" ; export CFLAGS
18384377Sluigi
18484377Sluigi    (cd ${SRC}
18584377Sluigi	# $e is the invocation of make with correct environment
186155136Sluigi	# XXX check the NO* options below, maybe system dependent.
18784377Sluigi	e="MAKEOBJDIRPREFIX=${l_objtree}/picobsd/libraries \
188127266Sluigi	    BINOWN=`id -un` BINGRP=`id -gn` \
189127266Sluigi	    DESTDIR=${l_usrtree}/.. \
19086876Sluigi	    make -m ${SRC}/share/mk \
191155136Sluigi		-DNOHTML -DNOINFO -DNOMAN -DNOSHARE -DNOFSCHG "
19292063Sluigi	log "do a 'make obj' in a few places."
19392063Sluigi	# This is very version-specific... The following works for 5.0
194158687Sphk	for i in lib secure/lib gnu/lib \
19584377Sluigi		gnu/usr.bin/perl usr.bin/lex usr.sbin/config ; do
19684377Sluigi	    (cd ${i}; eval $e obj)
19784377Sluigi	done
19892063Sluigi	log "now make the static libraries"
199155136Sluigi	eval $e -DNOPROFILE -DNOPIC libraries
20084377Sluigi	(cd ${SRC}/usr.sbin/config
20184377Sluigi	eval $e		# build binary
20284377Sluigi	eval $e	install	# install it
20384377Sluigi	)
20484377Sluigi    ) || fail $? "libraries"
20584377Sluigi    log "Libraries done"
20672770Sluigi}
20772770Sluigi
20884377Sluigi# set_type <type> looks in user or system directories for the floppy type
20984377Sluigi# specified as first argument, and sets variables according to the config.
210173602Sluigi# file. Sets THETYPE, SITE, name, MY_TREE and BUILDDIR
21172770Sluigi
21284377Sluigiset_type() {
213127266Sluigi    local a i
21484377Sluigi
215173602Sluigi    log "set_type() : Type '$1' site '$2'"
21684377Sluigi    THETYPE=$1
21784377Sluigi    SITE=$2
21872770Sluigi    a=$1
219173602Sluigi    name=""	# clear in case of errors
22084377Sluigi    for i in ${c_startdir}/${a} ${PICO_TREE}/${a} ; do
22178494Sluigi	log "set_type: checking $i"
222173602Sluigi	[ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ] || continue
223173602Sluigi	set -- `cat $i/PICOBSD | \
22472770Sluigi	    awk '/^#PicoBSD/ {print $2, $3, $4, $5, $6}'`
225173602Sluigi	[ x"$1" != "x" ] || continue
226173602Sluigi	MFS_SIZE=$1 ; init_name=$2
227173602Sluigi	mfs_inodes=$3 ; fd_inodes=$4
228173602Sluigi	name=`(cd $i ; pwd) `
229173602Sluigi	name=`basename $name`
230173602Sluigi	MY_TREE=$i
231173602Sluigi	BUILDDIR=${c_startdir}/build_dir-${name}
232173602Sluigi	log "Matching file $name in $i"
233173602Sluigi	return ;
23472770Sluigi    done
235173602Sluigi    logverbose "Type $a NOT FOUND"
23672770Sluigi}
23772770Sluigi
23872770Sluigiclean_tree() {
23984377Sluigi    log "clean_tree()"
24072770Sluigi    if [ "${name}" = "" ] ; then
24184377Sluigi	echo "---> Wrong floppy type"
24272770Sluigi	exit 3
24372770Sluigi    fi
24472770Sluigi    rm -rf ${BUILDDIR}
24572770Sluigi}
24672770Sluigi
24772770Sluigi# prepare a message to be printed in the dialog menus.
24872770Sluigiset_msgs() {		# OK
24984377Sluigi    log "set_msgs()"
25084377Sluigi
25172770Sluigi    MSG1="Type: ${THETYPE} name $name"
25272770Sluigi
25372770Sluigi    MSG="PicoBSD build -- Current parameters:\n\n\t1.  ${MSG1}\n\
25472770Sluigi\t2.  MFS size: ${MFS_SIZE} kB\n\
25572770Sluigi\t3.  Site-info: ${SITE}\n\t4.  Full-path: ${MY_TREE}\n"
25672770Sluigi}
25772770Sluigi
25872770Sluigi
25972770Sluigi# Main build procedure.
26072770Sluigibuild_image() {
26184377Sluigi    log "build_image() <${name}>"
26284377Sluigi    [ "${name}" != "" ] || fail $? bad_type
26372770Sluigi    clear
26472770Sluigi    set_msgs
26584377Sluigi    printf "${MSG}---> We'll use the sources living in ${SRC}\n\n"
26672770Sluigi
26784377Sluigi    # read config variables from a global and then a type-specific file
26884377Sluigi    # basically STAND_LINKS and MY_DEVS, but can also override other
26984377Sluigi    # variables.
27084377Sluigi    # 
27184377Sluigi    . ${PICO_TREE}/build/config
27284377Sluigi    if [ -f ${MY_TREE}/config ] ; then
27384377Sluigi	. ${MY_TREE}/config
27484377Sluigi    fi
27584377Sluigi
27684377Sluigi    # location of the object directory
27784377Sluigi    PICO_OBJ=${l_objtree}/picobsd/${THETYPE}
27884377Sluigi    log "PICO_OBJ is ${PICO_OBJ}"
27984377Sluigi
28099946Sluigi    if [ ${OSVERSION} -ge 500035 ] ; then
281173602Sluigi	export MAKEOBJDIRPREFIX=${l_objtree}
282173597Sluigi	eval "export BINMAKE=\"`cd ${SRC}; make -f Makefile -V BINMAKE`\""
283173597Sluigi	eval export `cd ${SRC}; ${BINMAKE} -f Makefile.inc1 -V WMAKEENV`
28499946Sluigi    fi
28584377Sluigi    # create build directory and subtree
28684377Sluigi    mkdir -p ${BUILDDIR}/crunch
28784377Sluigi    # remove any old stuff
28884377Sluigi    rm -f ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
28984377Sluigi    # invoke commands to build a kernel
29072770Sluigi    do_kernel
29184377Sluigi    # fill a subdirectory with things that go into the floppy
29284377Sluigi    # (mostly /etc and similar stuff)
29384377Sluigi    populate_floppy_fs
29484377Sluigi    # populate it and produce a file with the MFS image
29584377Sluigi    populate_mfs_tree		# things which go into mfs
29684377Sluigi    # create, mount and fill a filesystem with floppy image
29772770Sluigi    fill_floppy_image # copies everything into the floppy
29872770Sluigi}
29972770Sluigi
30072770Sluigibuild_package() {
30184377Sluigi    local z msg
30284377Sluigi
30384377Sluigi    log "build_package()"
304173602Sluigi    rm -rf build.status
30572770Sluigi    echo "##############################################" >>build.status
30672770Sluigi    echo "## `date` ">>build.status
30772770Sluigi    echo "##############################################" >>build.status
30876380Sluigi    for z in bridge dial router net isp ; do
30972770Sluigi	set_type ${z}
310173602Sluigi        if [ "${name}" = "" ] ; then
311173602Sluigi	    echo "*** TYPE=${z} not found" >>build.status
312173602Sluigi	    continue
313173602Sluigi	fi
31472770Sluigi	echo "---------------------------------------------">>build.status
31572770Sluigi	echo "Building TYPE=${z}, SIZE=${MFS_SIZE}" >>build.status
31684377Sluigi	msg="(ok)"	# error message
31784377Sluigi	build_image || msg="** FAILED! **"
31884377Sluigi        echo "	${msg}">>build.status
31984377Sluigi	# where do i put things ?
32084377Sluigi	# clean_tree
32172770Sluigi    done
32272770Sluigi    exit 0
32372770Sluigi}
32472770Sluigi
32572770Sluigi# Set build parameters interactively
32672770Sluigi
32772770Sluigimain_dialog() {
32884377Sluigi  local ans i l
32984377Sluigi
33084377Sluigi  log "main_dialog()"
33172770Sluigi  while [ true ] ; do
33272770Sluigi    set_msgs
33384377Sluigi    rm ${c_reply}
33484377Sluigi    dialog --menu "PicoBSD build menu -- (29 sep 2001)" 19 70 12 \
33572770Sluigi	N "--> READY, build it <---" \
33672770Sluigi	T "${MSG1}" \
33772770Sluigi	K "edit Kernel config file" \
33872770Sluigi	E "Edit crunch.conf file" \
33972770Sluigi	S "MFS Size: ${MFS_SIZE}kB" \
34084377Sluigi	I "Init type: ${init_name}" \
34184377Sluigi	F "Floppy size: ${fd_size}kB" \
34284377Sluigi	M "MFS bytes per inode: ${mfs_inodes}" \
34384377Sluigi	U "UFS bytes per inode: ${fd_inodes}" \
34472770Sluigi	$ "Site-info: ${SITE}" \
34572770Sluigi	Q "Quit" \
34684377Sluigi	2> ${c_reply}
34784377Sluigi    ans=`cat ${c_reply}`
34884377Sluigi    rm ${c_reply}
34972770Sluigi    case ${ans} in
35072770Sluigi    T)
35172770Sluigi	l=""
35284377Sluigi	for i in ${c_startdir} ${c_startdir}/* ${PICO_TREE}/* ; do
35372770Sluigi	    if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ]; then
35472770Sluigi		l="$l `basename $i` `basename $i`"
35572770Sluigi	    fi
35672770Sluigi	done
35772770Sluigi	log $l
35890659Sluigi	{ dialog --menu "Setup the type of configuration" 12 70 5 $l \
35990659Sluigi		2> ${c_reply} && set_type "`cat ${c_reply}`" ${SITE} ; } || true
36072770Sluigi	;;
36172770Sluigi    I)
36290659Sluigi	{ dialog --menu "Choose your init(8) program" \
36372770Sluigi	10 70 2 init "Standard init (requires getty)" \
36484377Sluigi	oinit "small init from TinyWare" 2> ${c_reply} \
36590659Sluigi		&& init_name=`cat ${c_reply}` ; } || true
36672770Sluigi	;;
36772770Sluigi
36872770Sluigi    K) ${EDITOR} ${MY_TREE}/PICOBSD ;;
36972770Sluigi
37072770Sluigi    E) ${EDITOR} ${MY_TREE}/crunch.conf ;;
37172770Sluigi
37272770Sluigi    S)
37390659Sluigi	{ dialog --title "MFS Size setup" --inputbox \
37472770Sluigi"MFS size depends on what you need to put on the MFS image. Typically \
37572770Sluigiranges between 820kB (for very small bridge/router images) to \
37672770Sluigias much as 2500kB kB for a densely packed image. \
37772770SluigiKeep in mind that this memory is \
37872770Sluigitotally lost to other programs. Usually you want to keep \
37984377Sluigithis as small as possible. " 10 70 2> ${c_reply} \
38090659Sluigi	&& MFS_SIZE=`cat ${c_reply}` ; } || true
38172770Sluigi	;;
38272770Sluigi
38372770Sluigi    \$)
38490659Sluigi	{ dialog --title "Site info setup" --inputbox \
38572770Sluigi	"Please enter the full path to the directory \
38672770Sluigi	containing site-specific setup. \
38772770Sluigi	This directory tree must contain files that replace \
38872770Sluigi	standard ones in floppy.tree/ and mfs.tree/ . " \
38990659Sluigi	10 70 2> ${c_reply} && SITE=`cat ${c_reply}` ; } || true
39072770Sluigi	;;
39172770Sluigi
39272770Sluigi    F)
39391846Sluigi	{ dialog --menu "Set floppy size" 15 70 4 \
39484377Sluigi	    1440 "1.44MB" 1720 "1.72MB" 2880 "2.88MB" 4096 "4MB" \
39591846Sluigi		 2> ${c_reply} && fd_size=`cat ${c_reply}` ; } || true
39672770Sluigi	;;
39772770Sluigi
39872770Sluigi    M)
39991846Sluigi	{ dialog --title "MFS bytes per inode:" --inputbox \
40072770Sluigi	"Enter MFS bytes per inode (typically 4096..65536). \
40172770Sluigi	A larger value means fewer inodes but more space on MFS" \
40292063Sluigi	10 70 2> ${c_reply} && mfs_inodes=`cat ${c_reply}`  ; } || true
40372770Sluigi	;;
40472770Sluigi
40572770Sluigi    U)
40691846Sluigi	{ dialog --title "Floppy bytes per inode:" --inputbox \
40772770Sluigi	"Enter floppy bytes per inode (typically 3072..65536). \
40872770Sluigi	A larger value means fewer inodes but more space on the floppy." \
40991846Sluigi	10 70 2> ${c_reply} && fd_inodes=`cat ${c_reply}` ; } || true
41072770Sluigi	;;
41172770Sluigi
41272770Sluigi    N) break 2
41372770Sluigi	;;
41472770Sluigi
41572770Sluigi    Q) exit 0 ;;
41672770Sluigi
41772770Sluigi    *) echo "Unknown option \"${ans}\". Try again."
41872770Sluigi	sleep 2
41972770Sluigi	clear
42072770Sluigi	;;
42172770Sluigi    esac
42272770Sluigi  done
42372770Sluigi}
42472770Sluigi
42572770Sluigi# Call the build procedure
42672770Sluigi# Install image
42772770Sluigido_install() {
42884377Sluigi    log "do_install()"
42984377Sluigi
43085833Sluigi    if [ "${o_interactive}" = "NO" ] ; then
43185833Sluigi	echo "+++ Build completed +++"
432155136Sluigi	cat .build.reply || true
43385833Sluigi	return
43485833Sluigi    fi
43582747Sluigi    dialog --title "Build ${THETYPE} completed" --inputbox \
43672770Sluigi"\nThe build process was completed successfuly.\n\
43772770Sluigi`cat .build.reply` \n\n\
43872770SluigiNow we are going to install the image on the floppy.\n\
43972770SluigiPlease insert a blank floppy in /dev/fd0.\\n
44072770SluigiWARNING: the contents of the floppy will be permanently erased!\n\
44172770Sluigi\n\
44272770SluigiYour options:\n\
44372770Sluigi	* ^C or [Cancel] to abort,\n\
44484377Sluigi	* Enter to install ${c_img},\n\
44584377Sluigi" 20 80 2> ${c_reply}
44672770Sluigi    if [ "$?" = "0" ]; then
44784377Sluigi	echo "Writing ${c_img}..."
44884377Sluigi	dd if=${BUILDDIR}/${c_img} of=/dev/fd0.${fd_size}
44972770Sluigi    else
45084377Sluigi	echo "Ok, the image is in ${c_img}"
45172770Sluigi    fi
45272770Sluigi    echo "Done."
45372770Sluigi}
45472770Sluigi
45572770Sluigi
45672770Sluigi#-------------------------------------------------------------------
45772770Sluigi
458173602Sluigi# invoke the picobsd Makefile to compile the kernel.
459173602Sluigi# if MODULES is set (value is irrelevant) the makefile will build modules.
46072770Sluigido_kernel() {		# OK
46184377Sluigi    log "do_kernel() Preparing kernel \"$name\" in $MY_TREE"
46299946Sluigi    (cd $MY_TREE; export name SRC BUILDDIR # used in this makefile ;
46399946Sluigi	# export CONFIG
464173602Sluigi	[ "${o_do_modules}" = "yes" ] && export MODULES=""
465173597Sluigi	${BINMAKE} -v -f ${PICO_TREE}/build/Makefile.conf ) || \
46672770Sluigi	fail $? missing_kernel
46772770Sluigi}
46872770Sluigi
46984377Sluigi# Populate the variable part of the floppy filesystem. Must be done before
47084377Sluigi# the MFS because its content might need to be copied there as well.
47172770Sluigi#
47284377Sluigi# This involves fetching files from three subtrees, in this order:
47372770Sluigi#
47484377Sluigi#  1. a standard one, from which type-specific files are excluded;
47572770Sluigi#  2. a type-specific one;
47672770Sluigi#  3. a site-specific one.
47772770Sluigi#
47872770Sluigi# Files are first copied to a local tree and then compressed.
47972770Sluigi
48072770Sluigipopulate_floppy_fs() {		# OK
48183692Sluigi    local dst excl srcdir
48272770Sluigi
48384377Sluigi    log "populate_floppy_fs()"
48472770Sluigi    dst=${BUILDDIR}/floppy.tree
48584377Sluigi    log "pwd=`pwd` Populating floppy filesystem..."
48672770Sluigi
48783692Sluigi    # clean relics from old compilations.
48883692Sluigi    rm -rf ${dst} || true
48983692Sluigi    mkdir ${dst}
49072770Sluigi
49172770Sluigi    excl=${MY_TREE}/floppy.tree.exclude
49272770Sluigi    if [ -f ${excl} ] ; then
493173597Sluigi	log "Files excluded from generic tree: `echo;cat ${excl}`"
49472770Sluigi	excl="--exclude-from ${excl}"
49572770Sluigi    else
49672770Sluigi	excl=""
49772770Sluigi    fi
498180012Sru    (cd ${PICO_TREE}/floppy.tree ; tar -cf - --exclude CVS --exclude .svn \
499180012Sru    		${excl} . ) | \
50084377Sluigi		(cd ${dst} ; tar x${o_tarv}f - )
50184377Sluigi    log "Copied from generic floppy-tree `echo; ls -laR ${dst}`"
50272770Sluigi
50372770Sluigi    srcdir=${MY_TREE}/floppy.tree
50472770Sluigi    if [ -d ${srcdir} ] ; then
50584377Sluigi	log "update with type-specific files:"
506180012Sru	(cd ${srcdir} ; tar -cf - --exclude CVS --exclude .svn . ) | \
50784377Sluigi	    (cd ${dst} ; tar x${o_tarv}f - )
50884377Sluigi	log "Copied from type floppy-tree `echo; ls -laR ${dst}`"
50972770Sluigi    else
51084377Sluigi	log "No type-specific floppy-tree"
51172770Sluigi    fi
51272770Sluigi    if [ -d ${srcdir}.${SITE} ] ; then
51384377Sluigi	log "Update with site-specific (${SITE}) files:"
514180012Sru	(cd ${srcdir}.${SITE} ; tar -cf - --exclude CVS --exclude .svn . ) | \
51584377Sluigi	    (cd ${dst} ; tar x${o_tarv}f - )
51684377Sluigi	log "Copied from site floppy-tree `echo; ls -laR ${dst}`"
51772770Sluigi    else
51884377Sluigi	log "No site-specific floppy-tree"
51972770Sluigi    fi
52092063Sluigi
52172770Sluigi    # gzip returns an error if it fails to compress some file
52284377Sluigi    (cd $dst ; gzip -9 etc/*
52384377Sluigi	    log "Compressed files in etc/ `echo; ls -l etc`"
52472770Sluigi    ) || true
52572770Sluigi}
52672770Sluigi
52772770Sluigi# Populate the memory filesystem with binaries and non-variable
52872770Sluigi# configuration files.
52972770Sluigi# First do an mtree pass, then create directory links and device entries,
53072770Sluigi# then run crunchgen etc. to build the binary and create links.
53172770Sluigi# Then copy the specific/generic mfs_tree.
53272770Sluigi# Finally, if required, make a copy of the floppy.tree onto /fd
53372770Sluigi
53484377Sluigipopulate_mfs_tree() {
53584377Sluigi    local a dst
53672770Sluigi
53784377Sluigi    log "populate_mfs_tree()"
538155136Sluigi    dst=${BUILDDIR}/mfs.tree
539155136Sluigi    # clean relics from old compilations.
540155136Sluigi    rm -rf ${dst} || true
541155136Sluigi    mkdir ${dst}
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 ;
564173597Sluigi	${BINMAKE} \
56586876Sluigi		-v -f ${PICO_TREE}/build/Makefile.conf ${BUILDDIR}/crunch.mk )
56684377Sluigi    log "Libs are ${LIBS} "
56799946Sluigi    export SRC # used by crunch.mk
56899946Sluigi    # export LIBS CFLAGS
56972770Sluigi    log "Now make -f crunch.mk"
570173597Sluigi    ${BINMAKE} ${o_makeopts} -f ${BUILDDIR}/crunch.mk
57172770Sluigi    strip --remove-section=.note --remove-section=.comment crunch1
57284377Sluigi    mv crunch1 ${dst}/stand/crunch
57384377Sluigi    chmod 555 ${dst}/stand/crunch
57484377Sluigi    log "Making links for binaries..."
57572770Sluigi    for i in `crunchgen -l $a` ; do
57684377Sluigi	ln ${dst}/stand/crunch ${dst}/stand/${i};
57772770Sluigi    done
57878541Sluigi    # rm $a # do not remove!
57972770Sluigi    ) || fail $? crunch
58072770Sluigi
58184377Sluigi    if [ -f ${dst}/stand/sshd ] ; then
58292063Sluigi	log "Setting up host key for sshd:"
58392063Sluigi	if [ -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key.gz ] ; then
58484627Sluigi	    log "Using existing host key"
58584627Sluigi	else
58692063Sluigi	    log "Generating new host key" 
587127266Sluigi	    ssh-keygen -t rsa1 -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key \
58892063Sluigi		 -N "" -C "root@picobsd"
58992063Sluigi	    gzip -9 ${BUILDDIR}/floppy.tree/etc/ssh_host_key* || true
59084627Sluigi	fi
59172770Sluigi    fi
59272770Sluigi
59391846Sluigi    log "Copy generic and site-specific MFS tree..."
59491846Sluigi    for MFS_TREE in ${PICO_TREE}/mfs_tree ${MY_TREE}/mfs_tree ; do
59591846Sluigi	if [ -d ${MFS_TREE} ] ; then
59691846Sluigi	    log "Copy ${MFS_TREE} ..."
597180012Sru	    (cd ${MFS_TREE} ; tar -cf - --exclude CVS --exclude .svn . ) | \
59892063Sluigi		    (cd ${dst} ; tar x${o_tarv}f - )
59991846Sluigi	fi
60091846Sluigi    done
60172770Sluigi
60284377Sluigi    if [ "${o_all_in_mfs}" = "yes" ]; then
60384377Sluigi	log "Copy generic floppy_tree into MFS..."
604155136Sluigi	# this may fail in case the floppy is empty
605155136Sluigi	cp -Rp ${BUILDDIR}/floppy.tree/* ${dst}/fd || true
60672770Sluigi    fi
60784377Sluigi
60884377Sluigi    if [ "${o_no_devfs}" != "" ] ; then
60984377Sluigi	# create device entries using MAKEDEV
61084377Sluigi	(cd ${dst}/dev
611155136Sluigi	ln -s ${SRC}/etc/MAKEDEV ; chmod 555 MAKEDEV
612155136Sluigi	# log `pwd`
613155136Sluigi	sh ./MAKEDEV ${MY_DEVS}
61484377Sluigi	rm MAKEDEV
61584377Sluigi	)
61684377Sluigi    fi
617155136Sluigi    if [ "`id -u`" = "0" ] ; then
618155136Sluigi	log "Fixing permissions"
619155136Sluigi	(cd ${dst}; chown -R root . )
620155136Sluigi    fi
62184377Sluigi
62292853Sluigi    if [ -n "${import_files}" ] ; then
62392853Sluigi	log "importing ${import_files} into mfs"
62492853Sluigi	# We do it in a chroot environment on the target so
62592853Sluigi	# symlinks are followed correctly.
62692853Sluigi	cp `which tar` ${dst}/my_copy_of_tar
62792853Sluigi	(cd ${l_usrtree}/.. ; tar cf - ${import_files} ) | \
62892853Sluigi	    (chroot ${dst} /my_copy_of_tar xf - )
62992853Sluigi	rm ${dst}/my_copy_of_tar
63092853Sluigi    fi
63192853Sluigi
632155136Sluigi    (cd ${BUILDDIR}
633155136Sluigi	# override the owner
634155136Sluigi	echo "/set uid=0 gid=0" > mtree.out
635155136Sluigi	mtree -c -p ${dst} -k "" >> mtree.out
636155136Sluigi	log "mtre.out at ${BUILDDIR}/mtree.out"
637155136Sluigi	makefs -t ffs -o bsize=4096 -o fsize=512 \
638155136Sluigi		-s ${MFS_SIZE}k -f 100 -F mtree.out ${c_fs} ${dst}
639155136Sluigi	ls -l ${c_fs} )
640155136Sluigi    log "done mfs image"
64172770Sluigi}
64272770Sluigi
64372770Sluigifinal_cleanup() {
64484377Sluigi    log "final_cleanup()"
64584377Sluigi    rm -rf ${c_mnt} ${c_reply} 2> /dev/null || true
64684377Sluigi    rm -f ${c_reply}
64772770Sluigi}
64872770Sluigi
64972770Sluigi# fail errno errcode
65072770Sluigi# This function is used to trap errors and print msgs
65172770Sluigi#
65272770Sluigifail() {
65384377Sluigi    local errno errocode where
65484377Sluigi
65572770Sluigi    errno=$1
65672770Sluigi    errcode=$2
65784377Sluigi    where=$3
65884377Sluigi    echo "---> fail: Error <${errno}> error code <${errcode}> in <${where}>"
65984377Sluigi    case ${errcode} in
66072770Sluigi    mtree)
66184377Sluigi	echo "Error while making hierarchy in ${c_mnt}"
66272770Sluigi	;;
66372770Sluigi    crunch)
66472770Sluigi	echo "Error while building ${name}."
66572770Sluigi	;;
66672770Sluigi    missing_kernel)
66775880Sjoe	echo "Error: you must build PICOBSD${suffix} kernel first"
66872770Sluigi	;;
66982917Sluigi    includes)
67082917Sluigi	echo "Error: failed while making includes"
67182917Sluigi	;;
67282917Sluigi    libraries)
67382917Sluigi	echo "Error: failed while making libraries"
67482917Sluigi	;;
67584377Sluigi    bad_type)
67684377Sluigi	echo "Error: unknown floppy type ${name}"
67784377Sluigi	;;
67884377Sluigi    no_space)
67984377Sluigi	echo "Error: no space left on device (${where})"
68084377Sluigi	;;
68192853Sluigi    no_mfs)
68292853Sluigi	echo "Error: while writing MFS into the kernel."
68392853Sluigi	;;
68472770Sluigi    "")
68572770Sluigi	echo "User break"
68684377Sluigi	errcode="userbreak"
68772770Sluigi	;;
68872770Sluigi    *)
68972770Sluigi	echo "unknown error, maybe user break: $errno $errcode"
69072770Sluigi	;;
69172770Sluigi    esac
69272770Sluigi    echo "---> Aborting $0"
69372770Sluigi    # try to cleanup the vnode.
69472770Sluigi    final_cleanup
69572770Sluigi    exit 2
69672770Sluigi}
69772770Sluigi
69872770Sluigifill_floppy_image() {
699155136Sluigi    local blocks dst mfs_start mfs_end mfs_size img_size
70072770Sluigi
70184377Sluigi    log "fill_floppy_image()"
70284377Sluigi    dst=${c_mnt}	# where to create the image
70384377Sluigi
70484377Sluigi    log "Preparing ${fd_size}kB floppy filesystem..."
70584377Sluigi
706155136Sluigi    # correct blocks according to size.
707155136Sluigi    blocks=${fd_size};
70872770Sluigi    if [ "${blocks}" = "1720" ]; then
709155136Sluigi	blocks=1722
71072770Sluigi    elif [ "${blocks}" = "1480" ]; then
711155136Sluigi	blocks=1476
71272770Sluigi    fi
71372770Sluigi
71484377Sluigi    log "Labeling floppy image"
715155136Sluigi    log "patch ${c_boot2} to boot /kernel right away"
716127266Sluigi    b2=${BUILDDIR}/boot2 # modified boot2
717155136Sluigi    cp -f ${c_boot2} ${b2}
718127266Sluigi    chmod 0644 ${b2}
719155136Sluigi
720127266Sluigi    set `strings -at d ${b2} | grep "/boot/loader"`
721155136Sluigi    echo -e "/kernel\0\0\0\0\0" | \
722155136Sluigi	dd of=${b2} obs=$1 oseek=1 conv=notrunc 2>/dev/null
723127266Sluigi    chmod 0444 ${b2}
72491846Sluigi
725155136Sluigi    dst=${BUILDDIR}/image.tree
726155136Sluigi    rm -rf ${dst}
727155136Sluigi    mkdir -p ${dst}
72872770Sluigi    (
72972770Sluigi    cd ${BUILDDIR}
730155136Sluigi    set 0 0 # reset variables
73199946Sluigi    # $1 takes the offset of the MFS filesystem
73299946Sluigi    set `strings -at d kernel | grep "MFS Filesystem goes here"`
733155136Sluigi    mfs_start=$1
734155136Sluigi    set 0 0 # reset variables
735155136Sluigi    set `strings -at d kernel | grep "MFS Filesystem had better"`
736155136Sluigi    mfs_end=$1
737155136Sluigi    mfs_size="$((${mfs_end} - ${mfs_start}))"
738155136Sluigi    set -- `ls -l ${c_fs}`; imgsize="$5"
739155136Sluigi    if [ ${mfs_start} -gt 0 -a ${mfs_size} -ge ${imgsize} ] ; then
740155136Sluigi	mfs_ofs=$((${mfs_start} + 8192))
741155136Sluigi	log "Preload kernel with file ${c_fs} at ${mfs_ofs}"
742155136Sluigi	dd if=${c_fs} ibs=8192 iseek=1 of=kernel obs=${mfs_ofs} \
743155136Sluigi	    oseek=1 conv=notrunc 2> /dev/null
744155136Sluigi    else
745155136Sluigi    	log "not loading mfs, size ${mfs_size} img ${imgsize}"
746155136Sluigi    fi
74784377Sluigi    log "Compress with kgzip and copy to floppy image"
74872770Sluigi    kgzip -o kernel.gz kernel
74984377Sluigi    cp -p kernel.gz ${dst}/kernel || fail $? no_space "copying kernel"
75072770Sluigi
751155136Sluigi    log "Now transfer floppy tree if not already in MFS image"
75272770Sluigi    # now transfer the floppy tree. If it is already in mfs, dont bother.
75384377Sluigi    if [ "${o_all_in_mfs}" != "yes" ] ; then
75484377Sluigi	cp -Rp floppy.tree/* ${dst} || \
75584377Sluigi		fail $? no_space "copying floppy tree"
75672770Sluigi    fi
75772770Sluigi    )
758155136Sluigi    (cd ${BUILDDIR}
759155136Sluigi    makefs -t ffs -o bsize=4096 -o fsize=512 \
760155136Sluigi	-s ${blocks}k -f 50 ${c_img} ${dst}
761155136Sluigi    # ${l_label} -f `pwd`/${c_img}
762155136Sluigi    ${l_label} -w -f `pwd`/${c_img} auto # write in a label
763155136Sluigi    # copy partition c: into a: with some sed magic
764155136Sluigi    ${l_label} -f `pwd`/${c_img} | sed -e '/  c:/{p;s/c:/a:/;}' | \
765155136Sluigi	${l_label} -R -f `pwd`/${c_img} /dev/stdin
766155136Sluigi    ${l_label} -f `pwd`/${c_img}
767155136Sluigi    ls -l ${c_img}
768155136Sluigi	logverbose "after disklabel"
769155136Sluigi	 )
770155136Sluigi    # dump the primary and secondary boot
771155136Sluigi    # XXX primary is 512 bytes
772155136Sluigi    dd if=${c_boot1} of=${BUILDDIR}/${c_img} conv=notrunc 2>/dev/null
773155136Sluigi    # XXX secondary starts after the 0x114 = dec 276 bytes of the label
774155136Sluigi    # so we skip 276 from the source, and 276+512=788 from dst
775155136Sluigi    # the old style blocks used 512 and 1024 respectively
77672770Sluigi
777155136Sluigi    dd if=${b2} iseek=1 ibs=276 2> /dev/null | \
778155136Sluigi	dd of=${BUILDDIR}/${c_img} oseek=1 obs=788 conv=notrunc 2>/dev/null
779155136Sluigi    logverbose "done floppy image"
780155136Sluigi    # XXX (log "Fixing permissions"; cd ${dst}; chown -R root *)
781155136Sluigi    rm -rf ${BUILDDIR}/floppy.tree || true # cleanup
782155136Sluigi    # df -ik ${dst} | colrm 70 > .build.reply
78384377Sluigi    rm -rf ${dst}
78484377Sluigi    rm ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
78572770Sluigi}
78672770Sluigi
78784377Sluigi# This function creates variables which depend on the source tree in use:
78899946Sluigi# SRC, l_usrtree, l_objtree
78984377Sluigi# Optionally creates libraries, includes and the like (for cross compiles,
79084377Sluigi# needs to be done once).
79184377Sluigi
79284377Sluigiset_build_parameters() {
79384377Sluigi    log "set_build_parameters() SRC is ${SRC}"
79484377Sluigi    if [ "${SRC}" = "/usr/src" ] ; then
79584377Sluigi	l_usrtree=${USR:-/usr}
79684377Sluigi    else
79784377Sluigi	l_usrtree=${USR:-${SRC}/../usr}
79884093Sluigi    fi
79984377Sluigi    l_objtree=${l_usrtree}/obj-pico
80084377Sluigi    PICO_TREE=${PICO_TREE:-${SRC}/release/picobsd}
80199946Sluigi    set `grep "#define[\t ]__FreeBSD_version" ${SRC}/sys/sys/param.h`
80299946Sluigi    OSVERSION=$3
80399951Sluigi    log "OSVERSION is ${OSVERSION}"
80484377Sluigi    if [ "${o_init_src}" != "" ] ; then
80599946Sluigi	if [ ${OSVERSION} -lt 500035 ] ; then
80699946Sluigi	    create_includes_and_libraries
80799946Sluigi	else
80899946Sluigi	    create_includes_and_libraries2
80999946Sluigi	fi
81084093Sluigi    fi
81199946Sluigi    if [ ${OSVERSION} -lt 500035 ] ; then
81299946Sluigi	# Create the right LIBS and CFLAGS for further builds.
81399946Sluigi	# and build the config program
81499946Sluigi	LIBS="-L${l_usrtree}/lib"
81599946Sluigi	CFLAGS="-nostdinc -I${l_usrtree}/include"
81699946Sluigi	export LIBS CFLAGS
81799946Sluigi	CONFIG=${l_usrtree}/sbin/config
81899946Sluigi	export CONFIG
81999946Sluigi    fi
82084093Sluigi}
82184093Sluigi
82284377Sluigi#-------------------------------------------------------------------
82384377Sluigi# Main entry of the script. Initialize variables, parse command line
82484377Sluigi# arguments.
82584093Sluigi
82684377Sluigiset_defaults
827173602Sluigiargs=""
828173602Sluigiwhile [ x"$1" != x ]; do
82972770Sluigi    case $1 in
83078494Sluigi    --src)	# set the source path instead of /usr/src
83184627Sluigi	SRC=`(cd $2; pwd)`
83284093Sluigi	shift
83378494Sluigi	;;
83484377Sluigi    --init)
83584377Sluigi	o_init_src="YES"
83684377Sluigi	;;
83782917Sluigi
83872770Sluigi    --floppy_size)
83984377Sluigi	fd_size=$2
84072770Sluigi	shift
84172770Sluigi	;;
84284377Sluigi
84384377Sluigi    --all_in_mfs)
84484377Sluigi	o_all_in_mfs="yes"
84584377Sluigi	;;
84684377Sluigi
84784377Sluigi    --no_all_in_mfs)
84884377Sluigi	o_all_in_mfs=""
84984377Sluigi	;;
85084377Sluigi
85185833Sluigi    --modules)	# also build kernel modules
85285833Sluigi	o_do_modules="yes"
85385833Sluigi	;;
85472770Sluigi    -n)
85584377Sluigi	o_interactive="NO"
85672770Sluigi	;;
85784377Sluigi
85884377Sluigi    -clear|-clean|-c) # clean
85984377Sluigi	o_clean="YES"
86084377Sluigi	o_interactive="NO"
86172770Sluigi	;;
86284377Sluigi
86384377Sluigi    -v) # need -v -v to wait for user input
86484377Sluigi	o_verbose=$((${o_verbose}+1))	# verbose level
86584377Sluigi	o_tarv="v"			# tar verbose flag
86684377Sluigi	o_makeopts="-d l" # be verbose
86772770Sluigi	;;
86872770Sluigi    *)
869173602Sluigi	args="$args $1"			# accumulate args
87072770Sluigi	;;
87172770Sluigi
87272770Sluigi    esac
87372770Sluigi    shift
87472770Sluigidone
87584377Sluigiset_build_parameters	# things that depend on ${SRC}
87672770Sluigi
87772770Sluigi# If $1="package", it creates a neat set of floppies
878173602Sluigiset -- ${args}
879173602Sluigi[ "$1" = "package" ] && build_package
88072770Sluigi
881173602Sluigiset_type $args		# type and site, respectively
882173602Sluigi
883173602Sluigi[ "${o_interactive}" != "NO" ] && main_dialog
884173602Sluigi
88584377Sluigiif [ "${o_clean}" = "YES" ] ; then
88672770Sluigi    clean_tree
88772770Sluigielse
88872770Sluigi    build_image
88972770Sluigi    do_install
89072770Sluigifi
89172770Sluigifinal_cleanup
89272770Sluigiexit 0
893