picobsd revision 92063
1#!/bin/sh -
2#
3# $FreeBSD: head/release/picobsd/build/picobsd 92063 2002-03-11 05:54:22Z luigi $
4#
5# The new PicoBSD build script. Invoked as
6#
7# picobsd [options] floppy_type site_name
8#
9# Where floppy_type is a directory where the picobsd config info
10# is held, and ${floppy_type}/floppy.tree.${site_name} contains
11# optional site-specific configuration.
12#
13# For Options, see the bottom of the file where the processing is
14# done. The picobsd(8) manpage might be of some help, but code and docs
15# tend to lose sync over time...
16#
17# This script depends on the following files:
18#
19# in ${PICO_TREE} :
20#   Makefile.conf	Makefile used to build the kernel
21#   config		shell variables, sourced here.
22#   mfs.mtree		mtree config file
23#
24#   floppy.tree/	files which go on the floppy
25#   mfs_tree/		files which go onto the mfs
26#
27# in ${MY_TREE} :
28#   PICOBSD		kernel config file
29#   config		shell variables, sourced here.
30#   crunch.conf		crunchgen configuration
31#   floppy.tree.exclude	files from floppy.tree/ which we do not need here.
32#   floppy.tree/	local additions to the floppy.tree
33#   floppy.tree.${site}/ same as above, site specific.
34
35#
36#--- The main entry point is at the end.
37#
38
39# There are two set of initialization. The first one (set_defaults)
40# is done on entry to the script, and is used to set default values
41# for all variables which do not depend on floppy type and source tree.
42#
43# The second set is done after command line parsing, e.g.
44# to resolve dependencies on the source tree.
45#
46# Naming:
47# + variables that control operation (e.g. verbosity) and are generally
48#   set from the command line have o_ ("option") as a name prefix
49#
50# + variables which contain pathnames and values that should not change
51#   have c_ ("constant") as a name prefix
52#
53# + variables exported to Makefiles and subshells are CAPITAL
54#
55# + variables local to the script are lowercase, possibly with
56#   an l_ ("local") prefix
57
58# SRC points to your FreeBSD source tree.
59# l_usrtree points to the /usr subdir for the source tree.
60#     Normally /usr or ${SRC}/../usr
61# l_objtree points to the obj tree. Normally ${l_usrtree}/obj-pico
62# PICO_TREE is where standard picobsd stuff resides.
63#     Normally ${SRC}/release/picobsd
64# You can set SRC with --src <directory>
65# It is not recommended to override the other variables.
66
67# MY_TREE (set later) is where this floppy type resides.
68# BUILDDIR is the build directory
69
70# set some default values for variables.
71# needs to be done as the first thing in the script.
72
73# log something on stdout if verbose.
74o_verbose=0	# this needs to be here!
75log() {
76    if [ ${o_verbose} -gt 0 ] ; then
77	printf "\n*** %s\n" "$*"
78	if [ ${o_verbose}  -gt 1 ] ; then
79	    read -p "=== Press enter to continue" foo
80	fi
81    fi
82}
83
84logverbose() {
85    printf "\n*** %s\n" "$*"
86    read -p "=== Press enter to continue" foo
87}
88
89set_defaults() {
90    # no way to use logging in this function, variable not set yet.
91
92    # EDITOR is the editor you use
93    # fd_size  floppy size in KB (default to 1440). You can use 1480,
94    #	1720, 2880, etc. but beware that only 1440 and 1480 will boot
95    #	from 1.44M floppy drives (1480 will not work on vmware).
96    EDITOR=${EDITOR:-vi}
97    fd_size=${fd_size:-1440}
98
99    o_all_in_mfs="yes"		# put all files in mfs so you can boot and run
100				# the image via diskless boot.
101    o_clean=""			# do not clean
102    o_interactive=""		# default is interactive
103    o_verbose=0			# verbose level, 0 is silent
104    o_tarv=""			# tar verbose flag, "" or "v"
105    o_init_src=""		# non "" if we need to init libs and includes.
106    o_makeopts=${MAKEOPTS:--s}	# make options, be silent by default
107    o_no_devfs=yes		# we do not want devfs
108    o_do_modules=""		# do not build modules
109
110    SRC="/usr/src"		# default location for sources
111    c_startdir=`pwd`	# directory where we start
112			# used to lookup config and create BUILDDIR
113
114    c_boot1=/boot/boot1	# boot blocks (in case you want custom ones)
115    c_boot2=/boot/boot2
116
117    c_reply=${c_reply:-`mktemp "/tmp/reply.XXXXXXXXXX"`}
118    			# file where User replies will be put
119    c_mnt=`mktemp -d "/tmp/picobsd.XXXXXXXXXX"`
120    			# mountpoint used to build memory filesystems
121    c_fs=fs.PICOBSD	# filename used for the memory filesystem
122    c_img=picobsd.bin	# filename used for the picobsd image
123
124    # select the right memory disk name
125    case `uname -r` in
126	5.*)
127	    l_vn="md"
128	    l_makedev="${SRC}/etc/MAKEDEV"
129	    ;;
130	*)
131	    l_vn="vn"
132	    l_makedev="/dev/MAKEDEV"
133    esac
134    # Find a suitable vnode
135    l_vnum=`mount | awk "/${l_vn}/ { num++ } END { printf \"%d\", num }"`
136    l_vndev=${l_vn}${l_vnum}
137
138    set -e
139
140    trap fail 2
141    #trap fail 3
142    #trap fail 6
143    trap fail 15
144    free_vnode			# cleanup old vnodes
145}
146
147create_includes_and_libraries() {
148    log "create_includes_and_libraries() for ${SRC}"
149    # Optionally creates include directory and libraries.
150    mkdir -p ${l_usrtree}/include		# the include directory...
151    mkdir -p ${l_usrtree}/share/misc	# a few things go here
152    mkdir -p ${l_usrtree}/lib		# libraries
153    mkdir -p ${l_usrtree}/sbin		# some binaries
154    (cd ${SRC}; INCOWN=`id -un`  BINOWN=`id -un` DESTDIR=${SRC}/.. \
155		make -m ${SRC}/share/mk includes ) || fail $? includes
156    # libraries already have the include path in the Makefile
157    CFLAGS="-nostdinc" ; export CFLAGS
158
159    (cd ${SRC}
160	# $e is the invocation of make with correct environment
161	e="MAKEOBJDIRPREFIX=${l_objtree}/picobsd/libraries \
162	    INCOWN=`id -un` BINOWN=`id -un` DESTDIR=${SRC}/.. \
163	    make -m ${SRC}/share/mk \
164		-DNOHTML -DNOINFO -DNOMAN -DNOSHARE -DNOFSCHG "
165	log "do a 'make obj' in a few places."
166	# This is very version-specific... The following works for 5.0
167	for i in lib secure/lib gnu/lib usr.sbin/pcvt/keycap \
168		gnu/usr.bin/perl usr.bin/lex usr.sbin/config ; do
169	    (cd ${i}; eval $e obj)
170	done
171	log "now make the static libraries"
172	eval $e -DNOPROFILE -DNOPIC libraries
173	(cd ${SRC}/usr.sbin/config
174	eval $e		# build binary
175	eval $e	install	# install it
176	)
177    ) || fail $? "libraries"
178    log "Libraries done"
179}
180
181# set_type <type> looks in user or system directories for the floppy type
182# specified as first argument, and sets variables according to the config.
183# file. Also sets MY_TREE and BUILDDIR and SITE
184
185set_type() {
186    local a
187
188    log "set_type()"
189    THETYPE=$1
190    SITE=$2
191    a=$1
192    for i in ${c_startdir}/${a} ${PICO_TREE}/${a} ; do
193	log "set_type: checking $i"
194	if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ] ; then
195	    set -- `cat $i/PICOBSD | \
196	    awk '/^#PicoBSD/ {print $2, $3, $4, $5, $6}'`
197	    if [ "$1" != "" ]; then
198		MFS_SIZE=$1 ; init_name=$2
199		mfs_inodes=$3 ; fd_inodes=$4
200		name=`(cd $i ; pwd) `
201		name=`basename $name`
202		MY_TREE=$i
203		BUILDDIR=${c_startdir}/build_dir-${name}
204		log "Matching file $name in $i"
205		return ;
206	    fi
207	fi
208    done
209    echo "Type $a NOT FOUND"
210}
211
212clean_tree() {
213    log "clean_tree()"
214    if [ "${name}" = "" ] ; then
215	echo "---> Wrong floppy type"
216	exit 3
217    fi
218    rm -rf ${BUILDDIR}
219}
220
221# free as much as possible from the vnode
222free_vnode() {
223    log "free_vnode() ${l_vndev} "
224    umount ${c_mnt}    2> /dev/null || true
225    umount /dev/${l_vndev}       2> /dev/null || true
226    if [ "${l_vn}" = "vn" ] ; then
227	vnconfig -u ${l_vndev} 2> /dev/null || true
228    else
229	mdconfig -d -u ${l_vnum} 2> /dev/null || true
230    fi
231}
232
233# prepare a message to be printed in the dialog menus.
234set_msgs() {		# OK
235    log "set_msgs()"
236
237    MSG1="Type: ${THETYPE} name $name"
238
239    MSG="PicoBSD build -- Current parameters:\n\n\t1.  ${MSG1}\n\
240\t2.  MFS size: ${MFS_SIZE} kB\n\
241\t3.  Site-info: ${SITE}\n\t4.  Full-path: ${MY_TREE}\n"
242}
243
244
245# Main build procedure.
246build_image() {
247    log "build_image() <${name}>"
248    [ "${name}" != "" ] || fail $? bad_type
249    clear
250    set_msgs
251    printf "${MSG}---> We'll use the sources living in ${SRC}\n\n"
252
253    # read config variables from a global and then a type-specific file
254    # basically STAND_LINKS and MY_DEVS, but can also override other
255    # variables.
256    # 
257    . ${PICO_TREE}/build/config
258    if [ -f ${MY_TREE}/config ] ; then
259	. ${MY_TREE}/config
260    fi
261
262    # location of the object directory
263    PICO_OBJ=${l_objtree}/picobsd/${THETYPE}
264    log "PICO_OBJ is ${PICO_OBJ}"
265
266    # create build directory and subtree
267    mkdir -p ${BUILDDIR}/crunch
268    # remove any old stuff
269    rm -f ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
270    # invoke commands to build a kernel
271    do_kernel
272    # fill a subdirectory with things that go into the floppy
273    # (mostly /etc and similar stuff)
274    populate_floppy_fs
275    # populate it and produce a file with the MFS image
276    populate_mfs_tree		# things which go into mfs
277    # create, mount and fill a filesystem with floppy image
278    fill_floppy_image # copies everything into the floppy
279}
280
281build_package() {
282    local z msg
283
284    log "build_package()"
285    touch build.status
286    echo "##############################################" >>build.status
287    echo "## `date` ">>build.status
288    echo "##############################################" >>build.status
289    for z in bridge dial router net isp ; do
290	set_type ${z}
291	echo "---------------------------------------------">>build.status
292	echo "Building TYPE=${z}, SIZE=${MFS_SIZE}" >>build.status
293	msg="(ok)"	# error message
294	build_image || msg="** FAILED! **"
295        echo "	${msg}">>build.status
296	# where do i put things ?
297	# clean_tree
298    done
299    exit 0
300}
301
302# Set build parameters interactively
303
304main_dialog() {
305  local ans i l
306
307  log "main_dialog()"
308  while [ true ] ; do
309    set_msgs
310    rm ${c_reply}
311    dialog --menu "PicoBSD build menu -- (29 sep 2001)" 19 70 12 \
312	N "--> READY, build it <---" \
313	T "${MSG1}" \
314	K "edit Kernel config file" \
315	E "Edit crunch.conf file" \
316	S "MFS Size: ${MFS_SIZE}kB" \
317	I "Init type: ${init_name}" \
318	F "Floppy size: ${fd_size}kB" \
319	M "MFS bytes per inode: ${mfs_inodes}" \
320	U "UFS bytes per inode: ${fd_inodes}" \
321	$ "Site-info: ${SITE}" \
322	Q "Quit" \
323	2> ${c_reply}
324    ans=`cat ${c_reply}`
325    rm ${c_reply}
326    case ${ans} in
327    T)
328	l=""
329	for i in ${c_startdir} ${c_startdir}/* ${PICO_TREE}/* ; do
330	    if [ -d $i -a -f $i/PICOBSD -a -f $i/crunch.conf ]; then
331		l="$l `basename $i` `basename $i`"
332	    fi
333	done
334	log $l
335	{ dialog --menu "Setup the type of configuration" 12 70 5 $l \
336		2> ${c_reply} && set_type "`cat ${c_reply}`" ${SITE} ; } || true
337	;;
338    I)
339	{ dialog --menu "Choose your init(8) program" \
340	10 70 2 init "Standard init (requires getty)" \
341	oinit "small init from TinyWare" 2> ${c_reply} \
342		&& init_name=`cat ${c_reply}` ; } || true
343	;;
344
345    K) ${EDITOR} ${MY_TREE}/PICOBSD ;;
346
347    E) ${EDITOR} ${MY_TREE}/crunch.conf ;;
348
349    S)
350	{ dialog --title "MFS Size setup" --inputbox \
351"MFS size depends on what you need to put on the MFS image. Typically \
352ranges between 820kB (for very small bridge/router images) to \
353as much as 2500kB kB for a densely packed image. \
354Keep in mind that this memory is \
355totally lost to other programs. Usually you want to keep \
356this as small as possible. " 10 70 2> ${c_reply} \
357	&& MFS_SIZE=`cat ${c_reply}` ; } || true
358	;;
359
360    \$)
361	{ dialog --title "Site info setup" --inputbox \
362	"Please enter the full path to the directory \
363	containing site-specific setup. \
364	This directory tree must contain files that replace \
365	standard ones in floppy.tree/ and mfs.tree/ . " \
366	10 70 2> ${c_reply} && SITE=`cat ${c_reply}` ; } || true
367	;;
368
369    F)
370	{ dialog --menu "Set floppy size" 15 70 4 \
371	    1440 "1.44MB" 1720 "1.72MB" 2880 "2.88MB" 4096 "4MB" \
372		 2> ${c_reply} && fd_size=`cat ${c_reply}` ; } || true
373	;;
374
375    M)
376	{ dialog --title "MFS bytes per inode:" --inputbox \
377	"Enter MFS bytes per inode (typically 4096..65536). \
378	A larger value means fewer inodes but more space on MFS" \
379	10 70 2> ${c_reply} && mfs_inodes=`cat ${c_reply}`  ; } || true
380	;;
381
382    U)
383	{ dialog --title "Floppy bytes per inode:" --inputbox \
384	"Enter floppy bytes per inode (typically 3072..65536). \
385	A larger value means fewer inodes but more space on the floppy." \
386	10 70 2> ${c_reply} && fd_inodes=`cat ${c_reply}` ; } || true
387	;;
388
389    N) break 2
390	;;
391
392    Q) exit 0 ;;
393
394    *) echo "Unknown option \"${ans}\". Try again."
395	sleep 2
396	clear
397	;;
398    esac
399  done
400}
401
402# Call the build procedure
403# Install image
404do_install() {
405    log "do_install()"
406
407    if [ "${o_interactive}" = "NO" ] ; then
408	echo "+++ Build completed +++"
409	cat .build.reply
410	return
411    fi
412    dialog --title "Build ${THETYPE} completed" --inputbox \
413"\nThe build process was completed successfuly.\n\
414`cat .build.reply` \n\n\
415Now we are going to install the image on the floppy.\n\
416Please insert a blank floppy in /dev/fd0.\\n
417WARNING: the contents of the floppy will be permanently erased!\n\
418\n\
419Your options:\n\
420	* ^C or [Cancel] to abort,\n\
421	* Enter to install ${c_img},\n\
422" 20 80 2> ${c_reply}
423    if [ "$?" = "0" ]; then
424	echo "Writing ${c_img}..."
425	dd if=${BUILDDIR}/${c_img} of=/dev/fd0.${fd_size}
426    else
427	echo "Ok, the image is in ${c_img}"
428    fi
429    echo "Done."
430}
431
432
433#-------------------------------------------------------------------
434
435# invoke the Makefile to compile the kernel.
436do_kernel() {		# OK
437    log "do_kernel() Preparing kernel \"$name\" in $MY_TREE"
438    (cd $MY_TREE; export name SRC CONFIG BUILDDIR # used in this makefile ;
439	if [ "${o_do_modules}" = "yes" ] ; then
440		MODULES=""
441		export MODULES
442	fi
443	make -m ${SRC}/share/mk -v -f ${PICO_TREE}/build/Makefile.conf ) || \
444	fail $? missing_kernel
445}
446
447# Populate the variable part of the floppy filesystem. Must be done before
448# the MFS because its content might need to be copied there as well.
449#
450# This involves fetching files from three subtrees, in this order:
451#
452#  1. a standard one, from which type-specific files are excluded;
453#  2. a type-specific one;
454#  3. a site-specific one.
455#
456# Files are first copied to a local tree and then compressed.
457
458populate_floppy_fs() {		# OK
459    local dst excl srcdir
460
461    log "populate_floppy_fs()"
462    dst=${BUILDDIR}/floppy.tree
463    log "pwd=`pwd` Populating floppy filesystem..."
464
465    # clean relics from old compilations.
466    rm -rf ${dst} || true
467    mkdir ${dst}
468
469    excl=${MY_TREE}/floppy.tree.exclude
470    if [ -f ${excl} ] ; then
471	excl="--exclude-from ${excl}"
472	log "Files excluded from generic tree: `echo;cat ${excl}`"
473    else
474	excl=""
475    fi
476    (cd ${PICO_TREE}/floppy.tree ; tar -cf - --exclude CVS ${excl} . ) | \
477		(cd ${dst} ; tar x${o_tarv}f - )
478    log "Copied from generic floppy-tree `echo; ls -laR ${dst}`"
479
480    srcdir=${MY_TREE}/floppy.tree
481    if [ -d ${srcdir} ] ; then
482	log "update with type-specific files:"
483	(cd ${srcdir} ; tar -cf - --exclude CVS . ) | \
484	    (cd ${dst} ; tar x${o_tarv}f - )
485	log "Copied from type floppy-tree `echo; ls -laR ${dst}`"
486    else
487	log "No type-specific floppy-tree"
488    fi
489    if [ -d ${srcdir}.${SITE} ] ; then
490	log "Update with site-specific (${SITE}) files:"
491	(cd ${srcdir}.${SITE} ; tar -cf - --exclude CVS . ) | \
492	    (cd ${dst} ; tar x${o_tarv}f - )
493	log "Copied from site floppy-tree `echo; ls -laR ${dst}`"
494    else
495	log "No site-specific floppy-tree"
496    fi
497
498    # gzip returns an error if it fails to compress some file
499    (cd $dst ; gzip -9 etc/*
500	    log "Compressed files in etc/ `echo; ls -l etc`"
501    ) || true
502}
503
504create_mfs() {		# OK
505    log "create_mfs() Preparing MFS filesystem..."
506
507    free_vnode
508
509    # zero-fill the MFS image
510    init_fs_image ${BUILDDIR}/${c_fs} ${MFS_SIZE}
511
512    log "Labeling MFS image"
513    # Disklabel "auto" behaves strangely for sizes < 1024K. Basically
514    # it fails to install a label on the system. On the other hand,
515    # if you provide a specific disk type, the boot code is not
516    # installed so you have more space on the disk...
517    # For small image sizes, use std disktypes
518    if [ ${MFS_SIZE} -lt 1024 ] ; then
519	disklabel -rw ${l_vndev} fd${MFS_SIZE} || fail $? mfs_disklabel
520    else
521	disklabel -rw ${l_vndev} auto || fail $? mfs_disklabel
522    fi
523    newfs -i ${mfs_inodes} -m 0 -p 0 -o space -f 512 -b 4096 \
524	/dev/${l_vndev}c > /dev/null
525    mount /dev/${l_vndev}c ${c_mnt} || fail $? no_mount
526    log "`df /dev/${l_vndev}c`"
527}
528
529# Populate the memory filesystem with binaries and non-variable
530# configuration files.
531# First do an mtree pass, then create directory links and device entries,
532# then run crunchgen etc. to build the binary and create links.
533# Then copy the specific/generic mfs_tree.
534# Finally, if required, make a copy of the floppy.tree onto /fd
535
536populate_mfs_tree() {
537    local a dst
538
539    log "populate_mfs_tree()"
540    early_mfs_mount=0
541    if [ "${early_mfs_mount}" = "1" ] ; then
542	create_mfs
543        dst=${c_mnt}
544    else
545	dst=${BUILDDIR}/mfs.tree
546	# clean relics from old compilations.
547	rm -rf ${dst} || true
548	mkdir ${dst}
549    fi
550
551    log "pwd=`pwd`, Populating MFS tree..."
552
553    # use type-specific mfs.mtree, default to generic one.
554    a=${MY_TREE}/mfs.mtree
555    [ -f ${a} ] || a=${PICO_TREE}/build/mfs.mtree
556    log "Running mtree using $a..."
557    mtree -deU -f $a -p ${dst} > /dev/null || fail $? mtree
558
559    # XXX create links
560    for i in ${STAND_LINKS}; do
561	ln -s /stand ${dst}/$i
562    done
563    ln -s /dev/null ${dst}/var/run/log
564    ln -s /etc/termcap ${dst}/usr/share/misc/termcap
565
566
567    (
568    cd ${BUILDDIR}/crunch
569    log "Making and installing crunch1 from `pwd` src ${SRC}..."
570    a=${BUILDDIR}/crunch1.conf
571    ( export BUILDDIR SRC MY_TREE PICO_OBJ ;
572	make -m ${SRC}/share/mk \
573		-v -f ${PICO_TREE}/build/Makefile.conf ${BUILDDIR}/crunch.mk )
574    log "Libs are ${LIBS} "
575    export SRC LIBS CFLAGS # used by crunch.mk
576    log "Now make -f crunch.mk"
577    make -m ${SRC}/share/mk ${o_makeopts} -f ${BUILDDIR}/crunch.mk
578    strip --remove-section=.note --remove-section=.comment crunch1
579    mv crunch1 ${dst}/stand/crunch
580    chmod 555 ${dst}/stand/crunch
581    log "Making links for binaries..."
582    for i in `crunchgen -l $a` ; do
583	ln ${dst}/stand/crunch ${dst}/stand/${i};
584    done
585    # rm $a # do not remove!
586    ) || fail $? crunch
587
588    if [ -f ${dst}/stand/sshd ] ; then
589	log "Setting up host key for sshd:"
590	if [ -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key.gz ] ; then
591	    log "Using existing host key"
592	else
593	    log "Generating new host key" 
594	    ssh-keygen -f ${BUILDDIR}/floppy.tree/etc/ssh_host_key \
595		 -N "" -C "root@picobsd"
596	    gzip -9 ${BUILDDIR}/floppy.tree/etc/ssh_host_key* || true
597	fi
598    fi
599
600    log "Copy generic and site-specific MFS tree..."
601    for MFS_TREE in ${PICO_TREE}/mfs_tree ${MY_TREE}/mfs_tree ; do
602	if [ -d ${MFS_TREE} ] ; then
603	    log "Copy ${MFS_TREE} ..."
604	    (cd ${MFS_TREE} ; tar -cf - --exclude CVS . ) | \
605		    (cd ${dst} ; tar x${o_tarv}f - )
606	fi
607    done
608
609    if [ "${o_all_in_mfs}" = "yes" ]; then
610	log "Copy generic floppy_tree into MFS..."
611	cp -Rp ${BUILDDIR}/floppy.tree/* ${dst}/fd
612    fi
613
614    [ "`id -u`" = "0" ] || cat <<__EOF
615
616### -------------------------------------------------------------------
617###
618### WARNING: You are not running with root permissions, so the next
619### stages are likely to fail because they call commands such as
620### chown, {vn|md}config, mount/umount which need adequate rights.
621###
622### The results of the compilation so far is in directory
623###  ${BUILDDIR}
624### which has the following content:
625
626`ls -l ${BUILDDIR}`
627
628###
629### -------------------------------------------------------------------
630
631__EOF
632
633    if [ "${o_no_devfs}" != "" ] ; then
634	# create device entries using MAKEDEV
635	(cd ${dst}/dev
636	ln -s ${l_makedev} ; chmod 555 MAKEDEV
637	./MAKEDEV ${MY_DEVS}
638	rm MAKEDEV
639	)
640    fi
641    log "Fixing permissions"
642    (cd ${dst}; chown -R root . )
643
644    if [ "${early_mfs_mount}" != "1" ] ; then
645	create_mfs
646	log "Copy mfs tree into file"
647	(cd ${dst} ; tar cf - . ) | ( cd ${c_mnt} ; tar xf - )
648    fi
649    # now umount and fsck the filesystem.
650    log "Status of mfs image"
651    df -ik ${c_mnt}
652    umount ${c_mnt}
653    fsck -p /dev/${l_vndev}c
654    free_vnode
655}
656
657final_cleanup() {
658    log "final_cleanup()"
659    free_vnode
660    rm -rf ${c_mnt} ${c_reply} 2> /dev/null || true
661    rm -f ${c_reply}
662}
663
664# fail errno errcode
665# This function is used to trap errors and print msgs
666#
667fail() {
668    local errno errocode where
669
670    errno=$1
671    errcode=$2
672    where=$3
673    echo "---> fail: Error <${errno}> error code <${errcode}> in <${where}>"
674    case ${errcode} in
675    no_vnconfig)
676	echo "Error in vnconfig on /dev/${l_vndev}..."
677	echo "Either you are not running as root or your running kernel"
678	echo "does not have the ${l_vn}(4) device."
679	;;
680    mfs_disklabel)
681	echo "Error while labeling ${c_fs} size ${MFS_SIZE}"
682	;;
683    no_mount)
684	echo "Error while mounting ${c_fs} (/dev/${l_vndev}c) on ${c_mnt}"
685	;;
686    mtree)
687	echo "Error while making hierarchy in ${c_mnt}"
688	;;
689    crunch)
690	echo "Error while building ${name}."
691	;;
692    floppy_disklabel)
693	echo "Error while doing disklabel on of floppy.img size $fd_size"
694	;;
695    missing_kernel)
696	echo "Error: you must build PICOBSD${suffix} kernel first"
697	;;
698    includes)
699	echo "Error: failed while making includes"
700	;;
701    libraries)
702	echo "Error: failed while making libraries"
703	;;
704    bad_type)
705	echo "Error: unknown floppy type ${name}"
706	;;
707    no_space)
708	echo "Error: no space left on device (${where})"
709	;;
710    "")
711	echo "User break"
712	errcode="userbreak"
713	;;
714    *)
715	echo "unknown error, maybe user break: $errno $errcode"
716	;;
717    esac
718    echo "---> Aborting $0"
719    # try to cleanup the vnode.
720    final_cleanup
721    exit 2
722}
723
724#
725# Create a zero-filled disk image with a boot sector, and vnconfig it.
726#
727
728init_fs_image() { # filename size_in_kbytes
729    local imgname imgsize
730
731    log "init_fs_image() $1 $2"
732    imgname=$1 ; imgsize=$2
733    dd if=/dev/zero of=${imgname} count=${imgsize} bs=1k 2> /dev/null
734    dd if=${c_boot1}  of=${imgname} conv=notrunc 2> /dev/null
735
736    if [ "${l_vn}" = "vn" ] ; then
737	vnconfig -c -s labels ${l_vndev} ${imgname} || fail $? no_vnconfig
738    else
739	mdconfig -a -t vnode -u ${l_vnum} -f ${imgname} || fail $? no_vnconfig
740    fi
741}
742
743
744fill_floppy_image() {
745    local blocks sectors dst
746
747    log "fill_floppy_image()"
748    dst=${c_mnt}	# where to create the image
749
750    log "Preparing ${fd_size}kB floppy filesystem..."
751
752    # correct block and number of sectors according to size.
753    blocks=${fd_size}; sectors=18
754    if [ "${blocks}" = "1720" ]; then
755	blocks=1722 ; sectors=21
756    elif [ "${blocks}" = "1480" ]; then
757	blocks=1476 ;
758    fi
759
760    init_fs_image ${BUILDDIR}/${c_img} ${blocks}
761
762    log "Labeling floppy image"
763    b2=${BUILDDIR}/boot2 # modified boot2
764    perl -pne 's/\/boot\/loader/\/kernel\0\0\0\0\0/' ${c_boot2} > ${b2}
765
766    # create a disklabel ...
767    disklabel -Brw -b ${c_boot1} -s ${b2} ${l_vndev} auto || \
768	fail $?  floppy_disklabel
769
770    # and copy partition c: into partition a: using some sed magic
771    disklabel ${l_vndev} | sed -e '/  c:/{p;s/c:/a:/;}' | \
772	disklabel -R ${l_vndev} /dev/stdin
773
774    log "Newfs floppy image"
775    newfs -i ${fd_inodes} -m 0 -p 0 -o space -f 512 -b 4096 \
776	     /dev/${l_vndev}a > /dev/null
777
778    log "Mounting floppy image"
779    mount /dev/${l_vndev}a ${dst}
780
781    (
782    cd ${BUILDDIR}
783    log "Preload kernel with file ${c_fs}"
784if [ true ] ; then
785    if [ -f ${PICO_TREE}/build/write_mfs_in_kernel.c ] ; then
786	cc -o wmk ${PICO_TREE}/build/write_mfs_in_kernel.c
787    else
788	cc -o wmk ${PICO_TREE}/../write_mfs_in_kernel.c
789    fi
790    ./wmk kernel ${c_fs}
791    rm wmk
792else	# not working yet, just a reminder
793    objdump -h kernel
794    objcopy --remove-section=md_root kernel
795    objcopy --add-section md_root=${c_fs} kernel
796    objcopy --set-section-flags md_root=contents,alloc,load,data kernel
797    objdump -h kernel
798fi
799    log "Compress with kgzip and copy to floppy image"
800    kgzip -o kernel.gz kernel
801    cp -p kernel.gz ${dst}/kernel || fail $? no_space "copying kernel"
802
803    log "now transfer floppy tree if needed"
804    # now transfer the floppy tree. If it is already in mfs, dont bother.
805    if [ "${o_all_in_mfs}" != "yes" ] ; then
806	cp -Rp floppy.tree/* ${dst} || \
807		fail $? no_space "copying floppy tree"
808    fi
809    )
810    (log "Fixing permissions"; cd ${dst}; chown -R root *)
811    # rm -rf ${BUILDDIR}/floppy.tree || true # cleanup
812
813    df -ik ${dst} | colrm 70 > .build.reply
814    free_vnode
815    rm -rf ${dst}
816    rm ${BUILDDIR}/kernel.gz ${BUILDDIR}/${c_fs}
817}
818
819# This function creates variables which depend on the source tree in use:
820# SRC, l_usrtree, l_objtree LIBS, CFLAGS
821# Optionally creates libraries, includes and the like (for cross compiles,
822# needs to be done once).
823
824set_build_parameters() {
825    log "set_build_parameters() SRC is ${SRC}"
826    if [ "${SRC}" = "/usr/src" ] ; then
827	l_usrtree=${USR:-/usr}
828    else
829	l_usrtree=${USR:-${SRC}/../usr}
830    fi
831    l_objtree=${l_usrtree}/obj-pico
832    PICO_TREE=${PICO_TREE:-${SRC}/release/picobsd}
833
834    if [ "${o_init_src}" != "" ] ; then
835	create_includes_and_libraries
836    fi
837    # Create the right LIBS and CFLAGS for further builds.
838    # and build the config program
839    LIBS="-L${l_usrtree}/lib"
840    CFLAGS="-nostdinc -I${l_usrtree}/include"
841    export LIBS CFLAGS
842    CONFIG=${l_usrtree}/sbin/config
843}
844
845#-------------------------------------------------------------------
846# Main entry of the script. Initialize variables, parse command line
847# arguments.
848
849set_defaults
850while [ true ]; do
851    case $1 in
852    --src)	# set the source path instead of /usr/src
853	SRC=`(cd $2; pwd)`
854	shift
855	;;
856    --init)
857	o_init_src="YES"
858	;;
859
860    --floppy_size)
861	fd_size=$2
862	shift
863	;;
864
865    --all_in_mfs)
866	o_all_in_mfs="yes"
867	;;
868
869    --no_all_in_mfs)
870	o_all_in_mfs=""
871	;;
872
873    --modules)	# also build kernel modules
874	o_do_modules="yes"
875	;;
876    -n)
877	o_interactive="NO"
878	;;
879
880    -clear|-clean|-c) # clean
881	o_clean="YES"
882	o_interactive="NO"
883	;;
884
885    -v) # need -v -v to wait for user input
886	o_verbose=$((${o_verbose}+1))	# verbose level
887	o_tarv="v"			# tar verbose flag
888	o_makeopts="-d l" # be verbose
889	;;
890    *)
891	break ;
892	;;
893
894    esac
895    shift
896done
897set_build_parameters	# things that depend on ${SRC}
898set_type $1 $2		# type and site, respectively
899
900# If $1="package", it creates a neat set of floppies
901
902if [ "$1" = "package" ] ; then
903    build_package
904fi
905if [ "${o_interactive}" != "NO" ] ; then
906    main_dialog
907fi
908if [ "${o_clean}" = "YES" ] ; then
909    clean_tree
910else
911    build_image
912    do_install
913fi
914final_cleanup
915exit 0
916