nanobsd.sh revision 207436
1#!/bin/sh
2#
3# Copyright (c) 2005 Poul-Henning Kamp.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD: head/tools/tools/nanobsd/nanobsd.sh 207436 2010-04-30 15:12:30Z philip $
28#
29
30set -e
31
32#######################################################################
33#
34# Setup default values for all controlling variables.
35# These values can be overridden from the config file(s)
36#
37#######################################################################
38
39# Name of this NanoBSD build.  (Used to construct workdir names)
40NANO_NAME=full
41
42# Source tree directory
43NANO_SRC=/usr/src
44
45# Where nanobsd additional files live under the source tree
46NANO_TOOLS=tools/tools/nanobsd
47
48# Where cust_pkg() finds packages to install
49NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg
50NANO_PACKAGE_LIST="*"
51
52# Object tree directory
53# default is subdir of /usr/obj
54#NANO_OBJ=""
55
56# The directory to put the final images
57# default is ${NANO_OBJ}
58#NANO_DISKIMGDIR=""
59
60# Parallel Make
61NANO_PMAKE="make -j 3"
62
63# The default name for any image we create.
64NANO_IMGNAME="_.disk.full"
65
66# Options to put in make.conf during buildworld only
67CONF_BUILD=' '
68
69# Options to put in make.conf during installworld only
70CONF_INSTALL=' '
71
72# Options to put in make.conf during both build- & installworld.
73CONF_WORLD=' '
74
75# Kernel config file to use
76NANO_KERNEL=GENERIC
77
78# Customize commands.
79NANO_CUSTOMIZE=""
80
81# Late customize commands.
82NANO_LATE_CUSTOMIZE=""
83
84# Newfs paramters to use
85NANO_NEWFS="-b 4096 -f 512 -i 8192 -O1 -U"
86
87# The drive name of the media at runtime
88NANO_DRIVE=ad0
89
90# Target media size in 512 bytes sectors
91NANO_MEDIASIZE=1200000
92
93# Number of code images on media (1 or 2)
94NANO_IMAGES=2
95
96# 0 -> Leave second image all zeroes so it compresses better.
97# 1 -> Initialize second image with a copy of the first
98NANO_INIT_IMG2=1
99
100# Size of code file system in 512 bytes sectors
101# If zero, size will be as large as possible.
102NANO_CODESIZE=0
103
104# Size of configuration file system in 512 bytes sectors
105# Cannot be zero.
106NANO_CONFSIZE=2048
107
108# Size of data file system in 512 bytes sectors
109# If zero: no partition configured.
110# If negative: max size possible
111NANO_DATASIZE=0
112
113# Size of the /etc ramdisk in 512 bytes sectors
114NANO_RAM_ETCSIZE=10240
115
116# Size of the /tmp+/var ramdisk in 512 bytes sectors
117NANO_RAM_TMPVARSIZE=10240
118
119# Media geometry, only relevant if bios doesn't understand LBA.
120NANO_SECTS=63
121NANO_HEADS=16
122
123# boot0 flags/options and configuration
124NANO_BOOT0CFG="-o packet -s 1 -m 3"
125NANO_BOOTLOADER="boot/boot0sio"
126
127# Backing type of md(4) device
128# Can be "file" or "swap"
129NANO_MD_BACKING="file"
130
131# Progress Print level
132PPLEVEL=3
133
134#######################################################################
135# Architecture to build.  Corresponds to TARGET_ARCH in a buildworld.
136# Unfortunately, there's no way to set TARGET at this time, and it 
137# conflates the two, so architectures where TARGET != TARGET_ARCH do
138# not work.  This defaults to the arch of the current machine.
139
140NANO_ARCH=`uname -p`
141
142#######################################################################
143#
144# The functions which do the real work.
145# Can be overridden from the config file(s)
146#
147#######################################################################
148
149clean_build ( ) (
150	pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})"
151
152	if ! rm -rf ${MAKEOBJDIRPREFIX} > /dev/null 2>&1 ; then
153		chflags -R noschg ${MAKEOBJDIRPREFIX}
154		rm -r ${MAKEOBJDIRPREFIX}
155	fi
156	mkdir -p ${MAKEOBJDIRPREFIX}
157	printenv > ${MAKEOBJDIRPREFIX}/_.env
158)
159
160make_conf_build ( ) (
161	pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)"
162
163	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_BUILD}
164	echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF_BUILD}
165)
166
167build_world ( ) (
168	pprint 2 "run buildworld"
169	pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw"
170
171	cd ${NANO_SRC}
172	env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} \
173		__MAKE_CONF=${NANO_MAKE_CONF_BUILD} buildworld \
174		> ${MAKEOBJDIRPREFIX}/_.bw 2>&1
175)
176
177build_kernel ( ) (
178	pprint 2 "build kernel ($NANO_KERNEL)"
179	pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk"
180
181	if [ -f ${NANO_KERNEL} ] ; then
182		cp ${NANO_KERNEL} ${NANO_SRC}/sys/${NANO_ARCH}/conf
183	fi
184
185	(cd ${NANO_SRC};
186	# unset these just in case to avoid compiler complaints
187	# when cross-building
188	unset TARGET_CPUTYPE
189	unset TARGET_BIG_ENDIAN
190	env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} buildkernel \
191		__MAKE_CONF=${NANO_MAKE_CONF_BUILD} KERNCONF=`basename ${NANO_KERNEL}` \
192		> ${MAKEOBJDIRPREFIX}/_.bk 2>&1
193	)
194)
195
196clean_world ( ) (
197	if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then
198		pprint 2 "Clean and create object directory (${NANO_OBJ})"
199		if ! rm -rf ${NANO_OBJ} > /dev/null 2>&1 ; then
200			chflags -R noschg ${NANO_OBJ}
201			rm -r ${NANO_OBJ}
202		fi
203		mkdir -p ${NANO_OBJ} ${NANO_WORLDDIR}
204		printenv > ${NANO_OBJ}/_.env
205	else
206		pprint 2 "Clean and create world directory (${NANO_WORLDDIR})"
207		if ! rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then
208			chflags -R noschg ${NANO_WORLDDIR}
209			rm -rf ${NANO_WORLDDIR}
210		fi
211		mkdir -p ${NANO_WORLDDIR}
212	fi
213)
214
215make_conf_install ( ) (
216	pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)"
217
218	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_INSTALL}
219	echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF_INSTALL}
220)
221
222install_world ( ) (
223	pprint 2 "installworld"
224	pprint 3 "log: ${NANO_OBJ}/_.iw"
225
226	cd ${NANO_SRC}
227	env TARGET_ARCH=${NANO_ARCH} \
228	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} installworld \
229		DESTDIR=${NANO_WORLDDIR} \
230		> ${NANO_OBJ}/_.iw 2>&1
231	chflags -R noschg ${NANO_WORLDDIR}
232)
233
234install_etc ( ) (
235
236	pprint 2 "install /etc"
237	pprint 3 "log: ${NANO_OBJ}/_.etc"
238
239	cd ${NANO_SRC}
240	env TARGET_ARCH=${NANO_ARCH} \
241	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} distribution \
242		DESTDIR=${NANO_WORLDDIR} \
243		> ${NANO_OBJ}/_.etc 2>&1
244)
245
246install_kernel ( ) (
247	pprint 2 "install kernel"
248	pprint 3 "log: ${NANO_OBJ}/_.ik"
249
250	cd ${NANO_SRC}
251	env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} installkernel \
252		DESTDIR=${NANO_WORLDDIR} \
253		__MAKE_CONF=${NANO_MAKE_CONF_INSTALL} KERNCONF=`basename ${NANO_KERNEL}` \
254		> ${NANO_OBJ}/_.ik 2>&1
255)
256
257run_customize() (
258
259	pprint 2 "run customize scripts"
260	for c in $NANO_CUSTOMIZE
261	do
262		pprint 2 "customize \"$c\""
263		pprint 3 "log: ${NANO_OBJ}/_.cust.$c"
264		pprint 4 "`type $c`"
265		( $c ) > ${NANO_OBJ}/_.cust.$c 2>&1
266	done
267)
268
269run_late_customize() (
270
271	pprint 2 "run late customize scripts"
272	for c in $NANO_LATE_CUSTOMIZE
273	do
274		pprint 2 "late customize \"$c\""
275		pprint 3 "log: ${NANO_OBJ}/_.late_cust.$c"
276		pprint 4 "`type $c`"
277		( $c ) > ${NANO_OBJ}/_.late_cust.$c 2>&1
278	done
279)
280
281setup_nanobsd ( ) (
282	pprint 2 "configure nanobsd setup"
283	pprint 3 "log: ${NANO_OBJ}/_.dl"
284
285	(
286	cd ${NANO_WORLDDIR}
287
288	# Move /usr/local/etc to /etc/local so that the /cfg stuff
289	# can stomp on it.  Otherwise packages like ipsec-tools which
290	# have hardcoded paths under ${prefix}/etc are not tweakable.
291	if [ -d usr/local/etc ] ; then
292		(
293		mkdir -p etc/local
294		cd usr/local/etc
295		find . -print | cpio -dumpl ../../../etc/local
296		cd ..
297		rm -rf etc
298		ln -s ../../etc/local etc
299		)
300	fi
301
302	for d in var etc
303	do
304		# link /$d under /conf
305		# we use hard links so we have them both places.
306		# the files in /$d will be hidden by the mount.
307		# XXX: configure /$d ramdisk size
308		mkdir -p conf/base/$d conf/default/$d
309		find $d -print | cpio -dumpl conf/base/
310	done
311
312	echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size
313	echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size
314
315	# pick up config files from the special partition
316	echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount
317
318	# Put /tmp on the /var ramdisk (could be symlink already)
319	rmdir tmp || true
320	rm tmp || true
321	ln -s var/tmp tmp
322
323	) > ${NANO_OBJ}/_.dl 2>&1
324)
325
326setup_nanobsd_etc ( ) (
327	pprint 2 "configure nanobsd /etc"
328
329	(
330	cd ${NANO_WORLDDIR}
331
332	# create diskless marker file
333	touch etc/diskless
334
335	# Make root filesystem R/O by default
336	echo "root_rw_mount=NO" >> etc/defaults/rc.conf
337
338	# save config file for scripts
339	echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
340
341	echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab
342	echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab
343	mkdir -p cfg
344	)
345)
346
347prune_usr() (
348
349	# Remove all empty directories in /usr 
350	find ${NANO_WORLDDIR}/usr -type d -depth -print |
351		while read d
352		do
353			rmdir $d > /dev/null 2>&1 || true 
354		done
355)
356
357create_i386_diskimage ( ) (
358	pprint 2 "build diskimage"
359	pprint 3 "log: ${NANO_OBJ}/_.di"
360
361	(
362	echo $NANO_MEDIASIZE $NANO_IMAGES \
363		$NANO_SECTS $NANO_HEADS \
364		$NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE |
365	awk '
366	{
367		printf "# %s\n", $0
368
369		# size of cylinder in sectors
370		cs = $3 * $4
371
372		# number of full cylinders on media
373		cyl = int ($1 / cs)
374
375		# output fdisk geometry spec, truncate cyls to 1023
376		if (cyl <= 1023)
377			print "g c" cyl " h" $4 " s" $3
378		else
379			print "g c" 1023 " h" $4 " s" $3
380
381		if ($7 > 0) { 
382			# size of data partition in full cylinders
383			dsl = int (($7 + cs - 1) / cs)
384		} else {
385			dsl = 0;
386		}
387
388		# size of config partition in full cylinders
389		csl = int (($6 + cs - 1) / cs)
390
391		if ($5 == 0) {
392			# size of image partition(s) in full cylinders
393			isl = int ((cyl - dsl - csl) / $2)
394		} else {
395			isl = int (($5 + cs - 1) / cs)
396		}
397
398		# First image partition start at second track
399		print "p 1 165 " $3, isl * cs - $3
400		c = isl * cs;
401
402		# Second image partition (if any) also starts offset one 
403		# track to keep them identical.
404		if ($2 > 1) {
405			print "p 2 165 " $3 + c, isl * cs - $3
406			c += isl * cs;
407		}
408
409		# Config partition starts at cylinder boundary.
410		print "p 3 165 " c, csl * cs
411		c += csl * cs
412
413		# Data partition (if any) starts at cylinder boundary.
414		if ($7 > 0) {
415			print "p 4 165 " c, dsl * cs
416		} else if ($7 < 0 && $1 > c) {
417			print "p 4 165 " c, $1 - c
418		} else if ($1 < c) {
419			print "Disk space overcommitted by", \
420			    c - $1, "sectors" > "/dev/stderr"
421			exit 2
422		}
423
424		# Force slice 1 to be marked active. This is necessary
425		# for booting the image from a USB device to work.
426		print "a 1"
427	}
428	' > ${NANO_OBJ}/_.fdisk
429
430	IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME}
431	MNT=${NANO_OBJ}/_.mnt
432	mkdir -p ${MNT}
433
434	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
435		MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \
436			-y ${NANO_HEADS}`
437	else
438		echo "Creating md backing file..."
439		dd if=/dev/zero of=${IMG} bs=${NANO_SECTS}b \
440			count=`expr ${NANO_MEDIASIZE} / ${NANO_SECTS}`
441		MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \
442			-y ${NANO_HEADS}`
443	fi
444
445	trap "echo 'Running exit trap code' ; df -i ${MNT} ; umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
446
447	fdisk -i -f ${NANO_OBJ}/_.fdisk ${MD}
448	fdisk ${MD}
449	# XXX: params
450	# XXX: pick up cached boot* files, they may not be in image anymore.
451	boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD}
452	bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}s1
453	bsdlabel ${MD}s1
454
455	# Create first image
456	newfs ${NANO_NEWFS} /dev/${MD}s1a
457	mount /dev/${MD}s1a ${MNT}
458	df -i ${MNT}
459	echo "Copying worlddir..."
460	( cd ${NANO_WORLDDIR} && find . -print | cpio -dump ${MNT} )
461	df -i ${MNT}
462	echo "Generating mtree..."
463	( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree
464	( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du
465	umount ${MNT}
466
467	if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then
468		# Duplicate to second image (if present)
469		echo "Duplicating to second image..."
470		dd if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k
471		mount /dev/${MD}s2a ${MNT}
472		for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab
473		do
474			sed -i "" "s/${NANO_DRIVE}s1/${NANO_DRIVE}s2/g" $f
475		done
476		umount ${MNT}
477	fi
478	
479	# Create Config slice
480	newfs ${NANO_NEWFS} /dev/${MD}s3
481	# XXX: fill from where ?
482
483	# Create Data slice, if any.
484	if [ $NANO_DATASIZE -ne 0 ] ; then
485		newfs ${NANO_NEWFS} /dev/${MD}s4
486		# XXX: fill from where ?
487	fi
488
489	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
490		echo "Writing out ${NANO_IMGNAME}..."
491		dd if=/dev/${MD} of=${IMG} bs=64k
492	fi
493
494	echo "Writing out _.disk.image..."
495	dd if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k
496	mdconfig -d -u $MD
497
498	trap - 1 2 15 EXIT
499
500	) > ${NANO_OBJ}/_.di 2>&1
501)
502
503# i386 and amd64 are identical for disk images
504create_amd64_diskimage ( ) (
505	create_i386_diskimage
506)
507
508last_orders () (
509	# Redefine this function with any last orders you may have
510	# after the build completed, for instance to copy the finished
511	# image to a more convenient place:
512	# cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk
513)
514
515#######################################################################
516#
517# Optional convenience functions.
518#
519#######################################################################
520
521#######################################################################
522# Common Flash device geometries
523#
524
525FlashDevice () {
526	if [ -d ${NANO_TOOLS} ] ; then
527		. ${NANO_TOOLS}/FlashDevice.sub
528	else
529		. ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub
530	fi
531	sub_FlashDevice $1 $2
532}
533
534#######################################################################
535# USB device geometries
536#
537# Usage:
538#	UsbDevice Generic 1000	# a generic flash key sold as having 1GB
539#
540# This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you.
541#
542# Note that the capacity of a flash key is usually advertised in MB or
543# GB, *not* MiB/GiB. As such, the precise number of cylinders available
544# for C/H/S geometry may vary depending on the actual flash geometry.
545#
546# The following generic device layouts are understood:
547#  generic           An alias for generic-hdd.
548#  generic-hdd       255H 63S/T xxxxC with no MBR restrictions.
549#  generic-fdd       64H 32S/T xxxxC with no MBR restrictions.
550#
551# The generic-hdd device is preferred for flash devices larger than 1GB.
552#
553
554UsbDevice () {
555	a1=`echo $1 | tr '[:upper:]' '[:lower:]'`
556	case $a1 in
557	generic-fdd)
558		NANO_HEADS=64
559		NANO_SECTS=32
560		NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
561		;;
562	generic|generic-hdd)
563		NANO_HEADS=255
564		NANO_SECTS=63
565		NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
566		;;
567	*)
568		echo "Unknown USB flash device"
569		exit 2
570		;;
571	esac
572}
573
574#######################################################################
575# Setup serial console
576
577cust_comconsole () (
578	# Enable getty on console
579	sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys
580
581	# Disable getty on syscons devices
582	sed -i "" -e '/^ttyv[0-8]/s/	on/	off/' ${NANO_WORLDDIR}/etc/ttys
583
584	# Tell loader to use serial console early.
585	echo " -h" > ${NANO_WORLDDIR}/boot.config
586)
587
588#######################################################################
589# Allow root login via ssh
590
591cust_allow_ssh_root () (
592	sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \
593	    ${NANO_WORLDDIR}/etc/ssh/sshd_config
594)
595
596#######################################################################
597# Install the stuff under ./Files
598
599cust_install_files () (
600	cd ${NANO_TOOLS}/Files
601	find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${NANO_WORLDDIR}
602)
603
604#######################################################################
605# Install packages from ${NANO_PACKAGE_DIR}
606
607cust_pkg () (
608
609	# Copy packages into chroot
610	mkdir -p ${NANO_WORLDDIR}/Pkg
611	(
612		cd ${NANO_PACKAGE_DIR}
613		find ${NANO_PACKAGE_LIST} -print |
614		    cpio -dumpv ${NANO_WORLDDIR}/Pkg
615	)
616
617	# Count & report how many we have to install
618	todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l`
619	echo "=== TODO: $todo"
620	ls ${NANO_WORLDDIR}/Pkg
621	echo "==="
622	while true
623	do
624		# Record how many we have now
625		have=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
626
627		# Attempt to install more packages
628		# ...but no more than 200 at a time due to pkg_add's internal
629		# limitations.
630		chroot ${NANO_WORLDDIR} sh -c \
631			'ls Pkg/*tbz | xargs -n 200 pkg_add -F' || true
632
633		# See what that got us
634		now=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
635		echo "=== NOW $now"
636		ls ${NANO_WORLDDIR}/var/db/pkg
637		echo "==="
638
639
640		if [ $now -eq $todo ] ; then
641			echo "DONE $now packages"
642			break
643		elif [ $now -eq $have ] ; then
644			echo "FAILED: Nothing happened on this pass"
645			exit 2
646		fi
647	done
648	rm -rf ${NANO_WORLDDIR}/Pkg
649)
650
651#######################################################################
652# Convenience function:
653# 	Register $1 as customize function.
654
655customize_cmd () {
656	NANO_CUSTOMIZE="$NANO_CUSTOMIZE $1"
657}
658
659#######################################################################
660# Convenience function:
661# 	Register $1 as late customize function to run just before
662#	image creation.
663
664late_customize_cmd () {
665	NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $1"
666}
667
668#######################################################################
669#
670# All set up to go...
671#
672#######################################################################
673
674# Progress Print
675#	Print $2 at level $1.
676pprint() {
677    if [ "$1" -le $PPLEVEL ]; then
678	runtime=$(( `date +%s` - $NANO_STARTTIME ))
679	printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3
680    fi
681}
682
683usage () {
684	(
685	echo "Usage: $0 [-biknqvw] [-c config_file]"
686	echo "	-b	suppress builds (both kernel and world)"
687	echo "	-i	suppress disk image build"
688	echo "	-k	suppress buildkernel"
689	echo "	-n	add -DNO_CLEAN to buildworld, buildkernel, etc"
690	echo "	-q	make output more quiet"
691	echo "	-v	make output more verbose"
692	echo "	-w	suppress buildworld"
693	echo "	-c	specify config file"
694	) 1>&2
695	exit 2
696}
697
698#######################################################################
699# Parse arguments
700
701do_clean=true
702do_kernel=true
703do_world=true
704do_image=true
705
706set +e
707args=`getopt bc:hiknqvw $*`
708if [ $? -ne 0 ] ; then
709	usage
710	exit 2
711fi
712set -e
713
714set -- $args
715for i
716do
717	case "$i" 
718	in
719	-b)
720		do_world=false
721		do_kernel=false
722		shift
723		;;
724	-k)
725		do_kernel=false
726		shift
727		;;
728	-c)
729		. "$2"
730		shift
731		shift
732		;;
733	-h)
734		usage
735		;;
736	-i)
737		do_image=false
738		shift
739		;;
740	-n)
741		do_clean=false
742		shift
743		;;
744	-q)
745		PPLEVEL=$(($PPLEVEL - 1))
746		shift
747		;;
748	-v)
749		PPLEVEL=$(($PPLEVEL + 1))
750		shift
751		;;
752	-w)
753		do_world=false
754		shift
755		;;
756	--)
757		shift
758		break
759	esac
760done
761
762if [ $# -gt 0 ] ; then
763	echo "$0: Extraneous arguments supplied"
764	usage
765fi
766
767#######################################################################
768# Setup and Export Internal variables
769#
770test -n "${NANO_OBJ}" || NANO_OBJ=/usr/obj/nanobsd.${NANO_NAME}/
771test -n "${MAKEOBJDIRPREFIX}" || MAKEOBJDIRPREFIX=${NANO_OBJ}
772test -n "${NANO_DISKIMGDIR}" || NANO_DISKIMGDIR=${NANO_OBJ}
773
774NANO_WORLDDIR=${NANO_OBJ}/_.w
775NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build
776NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install
777
778if [ -d ${NANO_TOOLS} ] ; then
779	true
780elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then
781	NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS}
782else
783	echo "NANO_TOOLS directory does not exist" 1>&2
784	exit 1
785fi
786
787if $do_clean ; then
788	true
789else
790	NANO_PMAKE="${NANO_PMAKE} -DNO_CLEAN"
791fi
792
793export MAKEOBJDIRPREFIX
794
795export NANO_ARCH
796export NANO_CODESIZE
797export NANO_CONFSIZE
798export NANO_CUSTOMIZE
799export NANO_DATASIZE
800export NANO_DRIVE
801export NANO_HEADS
802export NANO_IMAGES
803export NANO_IMGNAME
804export NANO_MAKE_CONF_BUILD
805export NANO_MAKE_CONF_INSTALL
806export NANO_MEDIASIZE
807export NANO_NAME
808export NANO_NEWFS
809export NANO_OBJ
810export NANO_PMAKE
811export NANO_SECTS
812export NANO_SRC
813export NANO_TOOLS
814export NANO_WORLDDIR
815export NANO_BOOT0CFG
816export NANO_BOOTLOADER
817
818#######################################################################
819# And then it is as simple as that...
820
821# File descriptor 3 is used for logging output, see pprint
822exec 3>&1
823
824NANO_STARTTIME=`date +%s`
825pprint 1 "NanoBSD image ${NANO_NAME} build starting"
826
827if $do_world ; then
828	if $do_clean ; then
829		clean_build
830	else
831		pprint 2 "Using existing build tree (as instructed)"
832	fi
833	make_conf_build
834	build_world
835else
836	pprint 2 "Skipping buildworld (as instructed)"
837fi
838
839if $do_kernel ; then
840	build_kernel
841else
842	pprint 2 "Skipping buildkernel (as instructed)"
843fi
844
845clean_world
846make_conf_install
847install_world
848install_etc
849setup_nanobsd_etc
850install_kernel
851
852run_customize
853setup_nanobsd
854prune_usr
855run_late_customize
856if $do_image ; then
857	create_${NANO_ARCH}_diskimage
858else
859	pprint 2 "Skipping image build (as instructed)"
860fi
861last_orders
862
863pprint 1 "NanoBSD image ${NANO_NAME} completed"
864