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