nanobsd.sh revision 209209
1279264Sdelphij#!/bin/sh
296593Smarkm#
396593Smarkm# Copyright (c) 2005 Poul-Henning Kamp.
4142429Snectar# All rights reserved.
596593Smarkm#
696593Smarkm# Redistribution and use in source and binary forms, with or without
796593Smarkm# modification, are permitted provided that the following conditions
896593Smarkm# are met:
996593Smarkm# 1. Redistributions of source code must retain the above copyright
1096593Smarkm#    notice, this list of conditions and the following disclaimer.
1196593Smarkm# 2. Redistributions in binary form must reproduce the above copyright
1296593Smarkm#    notice, this list of conditions and the following disclaimer in the
1396593Smarkm#    documentation and/or other materials provided with the distribution.
1496593Smarkm#
1596593Smarkm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1696593Smarkm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1796593Smarkm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1896593Smarkm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1996593Smarkm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20215698Ssimon# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21215698Ssimon# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22215698Ssimon# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23215698Ssimon# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24215698Ssimon# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2596593Smarkm# SUCH DAMAGE.
2696593Smarkm#
2796593Smarkm# $FreeBSD: head/tools/tools/nanobsd/nanobsd.sh 209209 2010-06-15 18:16:45Z imp $
2896593Smarkm#
2996593Smarkm
3096593Smarkmset -e
3196593Smarkm
3296593Smarkm#######################################################################
3396593Smarkm#
3496593Smarkm# Setup default values for all controlling variables.
3596593Smarkm# These values can be overridden from the config file(s)
3696593Smarkm#
3796593Smarkm#######################################################################
3896593Smarkm
3996593Smarkm# Name of this NanoBSD build.  (Used to construct workdir names)
4096593SmarkmNANO_NAME=full
41279264Sdelphij
42279264Sdelphij# Source tree directory
4396593SmarkmNANO_SRC=/usr/src
4496593Smarkm
45215698Ssimon# Where nanobsd additional files live under the source tree
46215698SsimonNANO_TOOLS=tools/tools/nanobsd
47215698Ssimon
48215698Ssimon# Where cust_pkg() finds packages to install
49142429SnectarNANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg
50215698SsimonNANO_PACKAGE_LIST="*"
51142429Snectar
52142429Snectar# Object tree directory
53279264Sdelphij# default is subdir of /usr/obj
54279264Sdelphij#NANO_OBJ=""
55279264Sdelphij
5696593Smarkm# The directory to put the final images
57279264Sdelphij# default is ${NANO_OBJ}
58279264Sdelphij#NANO_DISKIMGDIR=""
59279264Sdelphij
60279264Sdelphij# Parallel Make
61279264SdelphijNANO_PMAKE="make -j 3"
62279264Sdelphij
63215698Ssimon# The default name for any image we create.
64279264SdelphijNANO_IMGNAME="_.disk.full"
65279264Sdelphij
66279264Sdelphij# Options to put in make.conf during buildworld only
67279264SdelphijCONF_BUILD=' '
68279264Sdelphij
69215698Ssimon# Options to put in make.conf during installworld only
70279264SdelphijCONF_INSTALL=' '
7196593Smarkm
7296593Smarkm# Options to put in make.conf during both build- & installworld.
7396593SmarkmCONF_WORLD=' '
7496593Smarkm
7596593Smarkm# Kernel config file to use
7696593SmarkmNANO_KERNEL=GENERIC
7796593Smarkm
7896593Smarkm# Customize commands.
7996593SmarkmNANO_CUSTOMIZE=""
8096593Smarkm
8196593Smarkm# Late customize commands.
8296593SmarkmNANO_LATE_CUSTOMIZE=""
8396593Smarkm
8496593Smarkm# Newfs paramters to use
8596593SmarkmNANO_NEWFS="-b 4096 -f 512 -i 8192 -O1 -U"
8696593Smarkm
8796593Smarkm# The drive name of the media at runtime
8896593SmarkmNANO_DRIVE=ad0
8996593Smarkm
9096593Smarkm# Target media size in 512 bytes sectors
9196593SmarkmNANO_MEDIASIZE=1200000
9296593Smarkm
9396593Smarkm# Number of code images on media (1 or 2)
9496593SmarkmNANO_IMAGES=2
9596593Smarkm
9696593Smarkm# 0 -> Leave second image all zeroes so it compresses better.
9796593Smarkm# 1 -> Initialize second image with a copy of the first
9896593SmarkmNANO_INIT_IMG2=1
9996593Smarkm
10096593Smarkm# Size of code file system in 512 bytes sectors
10196593Smarkm# If zero, size will be as large as possible.
10296593SmarkmNANO_CODESIZE=0
10396593Smarkm
10496593Smarkm# Size of configuration file system in 512 bytes sectors
10596593Smarkm# Cannot be zero.
10696593SmarkmNANO_CONFSIZE=2048
10796593Smarkm
10896593Smarkm# Size of data file system in 512 bytes sectors
10996593Smarkm# If zero: no partition configured.
11096593Smarkm# If negative: max size possible
11196593SmarkmNANO_DATASIZE=0
11296593Smarkm
11396593Smarkm# Size of the /etc ramdisk in 512 bytes sectors
11496593SmarkmNANO_RAM_ETCSIZE=10240
11596593Smarkm
11696593Smarkm# Size of the /tmp+/var ramdisk in 512 bytes sectors
11796593SmarkmNANO_RAM_TMPVARSIZE=10240
11896593Smarkm
11996593Smarkm# Media geometry, only relevant if bios doesn't understand LBA.
12096593SmarkmNANO_SECTS=63
12196593SmarkmNANO_HEADS=16
12296593Smarkm
12396593Smarkm# boot0 flags/options and configuration
12496593SmarkmNANO_BOOT0CFG="-o packet -s 1 -m 3"
12596593SmarkmNANO_BOOTLOADER="boot/boot0sio"
12696593Smarkm
12796593Smarkm# Backing type of md(4) device
12896593Smarkm# Can be "file" or "swap"
12996593SmarkmNANO_MD_BACKING="file"
13096593Smarkm
13196593Smarkm# Progress Print level
13296593SmarkmPPLEVEL=3
133142429Snectar
13496593Smarkm#######################################################################
135100946Snectar# Architecture to build.  Corresponds to TARGET_ARCH in a buildworld.
136279264Sdelphij# Unfortunately, there's no way to set TARGET at this time, and it 
137215698Ssimon# conflates the two, so architectures where TARGET != TARGET_ARCH do
138215698Ssimon# not work.  This defaults to the arch of the current machine.
139215698Ssimon
140215698SsimonNANO_ARCH=`uname -p`
14196593Smarkm
142110010Smarkm#######################################################################
14396593Smarkm#
144142429Snectar# The functions which do the real work.
14596593Smarkm# Can be overridden from the config file(s)
14696593Smarkm#
14796593Smarkm#######################################################################
14896593Smarkm
149215698Ssimonclean_build ( ) (
150110010Smarkm	pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})"
151215698Ssimon
152110010Smarkm	if ! rm -rf ${MAKEOBJDIRPREFIX} > /dev/null 2>&1 ; then
153110010Smarkm		chflags -R noschg ${MAKEOBJDIRPREFIX}
154215698Ssimon		rm -r ${MAKEOBJDIRPREFIX}
15596593Smarkm	fi
156215698Ssimon	mkdir -p ${MAKEOBJDIRPREFIX}
157110010Smarkm	printenv > ${MAKEOBJDIRPREFIX}/_.env
158110010Smarkm)
159215698Ssimon
160110010Smarkmmake_conf_build ( ) (
161110010Smarkm	pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)"
162215698Ssimon
16396593Smarkm	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_BUILD}
16496593Smarkm	echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF_BUILD}
16596593Smarkm)
166215698Ssimon
167110010Smarkmbuild_world ( ) (
16896593Smarkm	pprint 2 "run buildworld"
16996593Smarkm	pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw"
17096593Smarkm
17196593Smarkm	cd ${NANO_SRC}
17296593Smarkm	env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} \
17396593Smarkm		__MAKE_CONF=${NANO_MAKE_CONF_BUILD} buildworld \
174110010Smarkm		> ${MAKEOBJDIRPREFIX}/_.bw 2>&1
17596593Smarkm)
17696593Smarkm
17796593Smarkmbuild_kernel ( ) (
17896593Smarkm	pprint 2 "build kernel ($NANO_KERNEL)"
17996593Smarkm	pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk"
18096593Smarkm
18196593Smarkm	if [ -f ${NANO_KERNEL} ] ; then
18296593Smarkm		cp ${NANO_KERNEL} ${NANO_SRC}/sys/${NANO_ARCH}/conf
18396593Smarkm	fi
18496593Smarkm
18596593Smarkm	(cd ${NANO_SRC};
18696593Smarkm	# unset these just in case to avoid compiler complaints
18796593Smarkm	# when cross-building
18896593Smarkm	unset TARGET_CPUTYPE
18996593Smarkm	unset TARGET_BIG_ENDIAN
19096593Smarkm	env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} buildkernel \
19196593Smarkm		__MAKE_CONF=${NANO_MAKE_CONF_BUILD} KERNCONF=`basename ${NANO_KERNEL}` \
19296593Smarkm		> ${MAKEOBJDIRPREFIX}/_.bk 2>&1
19396593Smarkm	)
194142429Snectar)
19596593Smarkm
19696593Smarkmclean_world ( ) (
19796593Smarkm	if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then
19896593Smarkm		pprint 2 "Clean and create object directory (${NANO_OBJ})"
199279264Sdelphij		if ! rm -rf ${NANO_OBJ} > /dev/null 2>&1 ; then
200279264Sdelphij			chflags -R noschg ${NANO_OBJ}
20196593Smarkm			rm -r ${NANO_OBJ}
20296593Smarkm		fi
20396593Smarkm		mkdir -p ${NANO_OBJ} ${NANO_WORLDDIR}
20496593Smarkm		printenv > ${NANO_OBJ}/_.env
20596593Smarkm	else
20696593Smarkm		pprint 2 "Clean and create world directory (${NANO_WORLDDIR})"
20796593Smarkm		if ! rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then
20896593Smarkm			chflags -R noschg ${NANO_WORLDDIR}
20996593Smarkm			rm -rf ${NANO_WORLDDIR}
21096593Smarkm		fi
21196593Smarkm		mkdir -p ${NANO_WORLDDIR}
21296593Smarkm	fi
21396593Smarkm)
21496593Smarkm
215279264Sdelphijmake_conf_install ( ) (
21696593Smarkm	pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)"
21796593Smarkm
21896593Smarkm	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_INSTALL}
21996593Smarkm	echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF_INSTALL}
220279264Sdelphij)
22196593Smarkm
22296593Smarkminstall_world ( ) (
22396593Smarkm	pprint 2 "installworld"
224279264Sdelphij	pprint 3 "log: ${NANO_OBJ}/_.iw"
22596593Smarkm
226279264Sdelphij	cd ${NANO_SRC}
22796593Smarkm	env TARGET_ARCH=${NANO_ARCH} \
22896593Smarkm	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} installworld \
22996593Smarkm		DESTDIR=${NANO_WORLDDIR} \
23096593Smarkm		> ${NANO_OBJ}/_.iw 2>&1
23196593Smarkm	chflags -R noschg ${NANO_WORLDDIR}
232110010Smarkm)
23396593Smarkm
23496593Smarkminstall_etc ( ) (
23596593Smarkm
23696593Smarkm	pprint 2 "install /etc"
23796593Smarkm	pprint 3 "log: ${NANO_OBJ}/_.etc"
23896593Smarkm
23996593Smarkm	cd ${NANO_SRC}
24096593Smarkm	env TARGET_ARCH=${NANO_ARCH} \
24196593Smarkm	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} distribution \
242142429Snectar		DESTDIR=${NANO_WORLDDIR} \
24396593Smarkm		> ${NANO_OBJ}/_.etc 2>&1
24496593Smarkm	# make.conf doesn't get created by default, but some ports need it
24596593Smarkm	# so they can spam it.
24696593Smarkm	cp /dev/null ${NANO_WORLDDIR}/etc/make.conf
247279264Sdelphij)
248142429Snectar
24996593Smarkminstall_kernel ( ) (
25096593Smarkm	pprint 2 "install kernel"
25196593Smarkm	pprint 3 "log: ${NANO_OBJ}/_.ik"
25296593Smarkm
25396593Smarkm	cd ${NANO_SRC}
25496593Smarkm	env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} installkernel \
25596593Smarkm		DESTDIR=${NANO_WORLDDIR} \
25696593Smarkm		__MAKE_CONF=${NANO_MAKE_CONF_INSTALL} KERNCONF=`basename ${NANO_KERNEL}` \
25796593Smarkm		> ${NANO_OBJ}/_.ik 2>&1
258142429Snectar)
25996593Smarkm
26096593Smarkmrun_customize() (
26196593Smarkm
26296593Smarkm	pprint 2 "run customize scripts"
26396593Smarkm	for c in $NANO_CUSTOMIZE
26496593Smarkm	do
26596593Smarkm		pprint 2 "customize \"$c\""
26696593Smarkm		pprint 3 "log: ${NANO_OBJ}/_.cust.$c"
26796593Smarkm		pprint 4 "`type $c`"
26896593Smarkm		( $c ) > ${NANO_OBJ}/_.cust.$c 2>&1
26996593Smarkm	done
270110010Smarkm)
271110010Smarkm
272110010Smarkmrun_late_customize() (
273279264Sdelphij
274110010Smarkm	pprint 2 "run late customize scripts"
275110010Smarkm	for c in $NANO_LATE_CUSTOMIZE
276110010Smarkm	do
277110010Smarkm		pprint 2 "late customize \"$c\""
278110010Smarkm		pprint 3 "log: ${NANO_OBJ}/_.late_cust.$c"
279110010Smarkm		pprint 4 "`type $c`"
280110010Smarkm		( $c ) > ${NANO_OBJ}/_.late_cust.$c 2>&1
28196593Smarkm	done
28296593Smarkm)
28396593Smarkm
28496593Smarkmsetup_nanobsd ( ) (
28596593Smarkm	pprint 2 "configure nanobsd setup"
28696593Smarkm	pprint 3 "log: ${NANO_OBJ}/_.dl"
28796593Smarkm
28896593Smarkm	(
28996593Smarkm	cd ${NANO_WORLDDIR}
29096593Smarkm
29196593Smarkm	# Move /usr/local/etc to /etc/local so that the /cfg stuff
29296593Smarkm	# can stomp on it.  Otherwise packages like ipsec-tools which
293215698Ssimon	# have hardcoded paths under ${prefix}/etc are not tweakable.
29496593Smarkm	if [ -d usr/local/etc ] ; then
29596593Smarkm		(
29696593Smarkm		mkdir -p etc/local
29796593Smarkm		cd usr/local/etc
29896593Smarkm		find . -print | cpio -dumpl ../../../etc/local
29996593Smarkm		cd ..
300215698Ssimon		rm -rf etc
30196593Smarkm		ln -s ../../etc/local etc
30296593Smarkm		)
30396593Smarkm	fi
30496593Smarkm
30596593Smarkm	for d in var etc
30696593Smarkm	do
30796593Smarkm		# link /$d under /conf
30896593Smarkm		# we use hard links so we have them both places.
30996593Smarkm		# the files in /$d will be hidden by the mount.
31096593Smarkm		# XXX: configure /$d ramdisk size
31196593Smarkm		mkdir -p conf/base/$d conf/default/$d
31296593Smarkm		find $d -print | cpio -dumpl conf/base/
31396593Smarkm	done
31496593Smarkm
31596593Smarkm	echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size
31696593Smarkm	echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size
31796593Smarkm
31896593Smarkm	# pick up config files from the special partition
31996593Smarkm	echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount
32096593Smarkm
32196593Smarkm	# Put /tmp on the /var ramdisk (could be symlink already)
32296593Smarkm	rmdir tmp || true
32396593Smarkm	rm tmp || true
324215698Ssimon	ln -s var/tmp tmp
32596593Smarkm
32696593Smarkm	) > ${NANO_OBJ}/_.dl 2>&1
32796593Smarkm)
32896593Smarkm
32996593Smarkmsetup_nanobsd_etc ( ) (
33096593Smarkm	pprint 2 "configure nanobsd /etc"
33196593Smarkm
33296593Smarkm	(
333	cd ${NANO_WORLDDIR}
334
335	# create diskless marker file
336	touch etc/diskless
337
338	# Make root filesystem R/O by default
339	echo "root_rw_mount=NO" >> etc/defaults/rc.conf
340
341	# save config file for scripts
342	echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
343
344	echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab
345	echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab
346	mkdir -p cfg
347	)
348)
349
350prune_usr() (
351
352	# Remove all empty directories in /usr 
353	find ${NANO_WORLDDIR}/usr -type d -depth -print |
354		while read d
355		do
356			rmdir $d > /dev/null 2>&1 || true 
357		done
358)
359
360create_i386_diskimage ( ) (
361	pprint 2 "build diskimage"
362	pprint 3 "log: ${NANO_OBJ}/_.di"
363
364	(
365	echo $NANO_MEDIASIZE $NANO_IMAGES \
366		$NANO_SECTS $NANO_HEADS \
367		$NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE |
368	awk '
369	{
370		printf "# %s\n", $0
371
372		# size of cylinder in sectors
373		cs = $3 * $4
374
375		# number of full cylinders on media
376		cyl = int ($1 / cs)
377
378		# output fdisk geometry spec, truncate cyls to 1023
379		if (cyl <= 1023)
380			print "g c" cyl " h" $4 " s" $3
381		else
382			print "g c" 1023 " h" $4 " s" $3
383
384		if ($7 > 0) { 
385			# size of data partition in full cylinders
386			dsl = int (($7 + cs - 1) / cs)
387		} else {
388			dsl = 0;
389		}
390
391		# size of config partition in full cylinders
392		csl = int (($6 + cs - 1) / cs)
393
394		if ($5 == 0) {
395			# size of image partition(s) in full cylinders
396			isl = int ((cyl - dsl - csl) / $2)
397		} else {
398			isl = int (($5 + cs - 1) / cs)
399		}
400
401		# First image partition start at second track
402		print "p 1 165 " $3, isl * cs - $3
403		c = isl * cs;
404
405		# Second image partition (if any) also starts offset one 
406		# track to keep them identical.
407		if ($2 > 1) {
408			print "p 2 165 " $3 + c, isl * cs - $3
409			c += isl * cs;
410		}
411
412		# Config partition starts at cylinder boundary.
413		print "p 3 165 " c, csl * cs
414		c += csl * cs
415
416		# Data partition (if any) starts at cylinder boundary.
417		if ($7 > 0) {
418			print "p 4 165 " c, dsl * cs
419		} else if ($7 < 0 && $1 > c) {
420			print "p 4 165 " c, $1 - c
421		} else if ($1 < c) {
422			print "Disk space overcommitted by", \
423			    c - $1, "sectors" > "/dev/stderr"
424			exit 2
425		}
426
427		# Force slice 1 to be marked active. This is necessary
428		# for booting the image from a USB device to work.
429		print "a 1"
430	}
431	' > ${NANO_OBJ}/_.fdisk
432
433	IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME}
434	MNT=${NANO_OBJ}/_.mnt
435	mkdir -p ${MNT}
436
437	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
438		MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \
439			-y ${NANO_HEADS}`
440	else
441		echo "Creating md backing file..."
442		dd if=/dev/zero of=${IMG} bs=${NANO_SECTS}b \
443			count=`expr ${NANO_MEDIASIZE} / ${NANO_SECTS}`
444		MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \
445			-y ${NANO_HEADS}`
446	fi
447
448	trap "echo 'Running exit trap code' ; df -i ${MNT} ; umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
449
450	fdisk -i -f ${NANO_OBJ}/_.fdisk ${MD}
451	fdisk ${MD}
452	# XXX: params
453	# XXX: pick up cached boot* files, they may not be in image anymore.
454	boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD}
455	bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}s1
456	bsdlabel ${MD}s1
457
458	# Create first image
459	newfs ${NANO_NEWFS} /dev/${MD}s1a
460	mount /dev/${MD}s1a ${MNT}
461	df -i ${MNT}
462	echo "Copying worlddir..."
463	( cd ${NANO_WORLDDIR} && find . -print | cpio -dump ${MNT} )
464	df -i ${MNT}
465	echo "Generating mtree..."
466	( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree
467	( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du
468	umount ${MNT}
469
470	if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then
471		# Duplicate to second image (if present)
472		echo "Duplicating to second image..."
473		dd if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k
474		mount /dev/${MD}s2a ${MNT}
475		for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab
476		do
477			sed -i "" "s/${NANO_DRIVE}s1/${NANO_DRIVE}s2/g" $f
478		done
479		umount ${MNT}
480	fi
481	
482	# Create Config slice
483	newfs ${NANO_NEWFS} /dev/${MD}s3
484	# XXX: fill from where ?
485
486	# Create Data slice, if any.
487	if [ $NANO_DATASIZE -ne 0 ] ; then
488		newfs ${NANO_NEWFS} /dev/${MD}s4
489		# XXX: fill from where ?
490	fi
491
492	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
493		echo "Writing out ${NANO_IMGNAME}..."
494		dd if=/dev/${MD} of=${IMG} bs=64k
495	fi
496
497	echo "Writing out _.disk.image..."
498	dd if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k
499	mdconfig -d -u $MD
500
501	trap - 1 2 15 EXIT
502
503	) > ${NANO_OBJ}/_.di 2>&1
504)
505
506# i386 and amd64 are identical for disk images
507create_amd64_diskimage ( ) (
508	create_i386_diskimage
509)
510
511last_orders () (
512	# Redefine this function with any last orders you may have
513	# after the build completed, for instance to copy the finished
514	# image to a more convenient place:
515	# cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk
516)
517
518#######################################################################
519#
520# Optional convenience functions.
521#
522#######################################################################
523
524#######################################################################
525# Common Flash device geometries
526#
527
528FlashDevice () {
529	if [ -d ${NANO_TOOLS} ] ; then
530		. ${NANO_TOOLS}/FlashDevice.sub
531	else
532		. ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub
533	fi
534	sub_FlashDevice $1 $2
535}
536
537#######################################################################
538# USB device geometries
539#
540# Usage:
541#	UsbDevice Generic 1000	# a generic flash key sold as having 1GB
542#
543# This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you.
544#
545# Note that the capacity of a flash key is usually advertised in MB or
546# GB, *not* MiB/GiB. As such, the precise number of cylinders available
547# for C/H/S geometry may vary depending on the actual flash geometry.
548#
549# The following generic device layouts are understood:
550#  generic           An alias for generic-hdd.
551#  generic-hdd       255H 63S/T xxxxC with no MBR restrictions.
552#  generic-fdd       64H 32S/T xxxxC with no MBR restrictions.
553#
554# The generic-hdd device is preferred for flash devices larger than 1GB.
555#
556
557UsbDevice () {
558	a1=`echo $1 | tr '[:upper:]' '[:lower:]'`
559	case $a1 in
560	generic-fdd)
561		NANO_HEADS=64
562		NANO_SECTS=32
563		NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
564		;;
565	generic|generic-hdd)
566		NANO_HEADS=255
567		NANO_SECTS=63
568		NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
569		;;
570	*)
571		echo "Unknown USB flash device"
572		exit 2
573		;;
574	esac
575}
576
577#######################################################################
578# Setup serial console
579
580cust_comconsole () (
581	# Enable getty on console
582	sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys
583
584	# Disable getty on syscons devices
585	sed -i "" -e '/^ttyv[0-8]/s/	on/	off/' ${NANO_WORLDDIR}/etc/ttys
586
587	# Tell loader to use serial console early.
588	echo " -h" > ${NANO_WORLDDIR}/boot.config
589)
590
591#######################################################################
592# Allow root login via ssh
593
594cust_allow_ssh_root () (
595	sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \
596	    ${NANO_WORLDDIR}/etc/ssh/sshd_config
597)
598
599#######################################################################
600# Install the stuff under ./Files
601
602cust_install_files () (
603	cd ${NANO_TOOLS}/Files
604	find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${NANO_WORLDDIR}
605)
606
607#######################################################################
608# Install packages from ${NANO_PACKAGE_DIR}
609
610cust_pkg () (
611
612	# Copy packages into chroot
613	mkdir -p ${NANO_WORLDDIR}/Pkg
614	(
615		cd ${NANO_PACKAGE_DIR}
616		find ${NANO_PACKAGE_LIST} -print |
617		    cpio -dumpv ${NANO_WORLDDIR}/Pkg
618	)
619
620	# Count & report how many we have to install
621	todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l`
622	echo "=== TODO: $todo"
623	ls ${NANO_WORLDDIR}/Pkg
624	echo "==="
625	while true
626	do
627		# Record how many we have now
628		have=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
629
630		# Attempt to install more packages
631		# ...but no more than 200 at a time due to pkg_add's internal
632		# limitations.
633		chroot ${NANO_WORLDDIR} sh -c \
634			'ls Pkg/*tbz | xargs -n 200 pkg_add -F' || true
635
636		# See what that got us
637		now=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
638		echo "=== NOW $now"
639		ls ${NANO_WORLDDIR}/var/db/pkg
640		echo "==="
641
642
643		if [ $now -eq $todo ] ; then
644			echo "DONE $now packages"
645			break
646		elif [ $now -eq $have ] ; then
647			echo "FAILED: Nothing happened on this pass"
648			exit 2
649		fi
650	done
651	rm -rf ${NANO_WORLDDIR}/Pkg
652)
653
654#######################################################################
655# Convenience function:
656# 	Register all args as customize function.
657
658customize_cmd () {
659	NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*"
660}
661
662#######################################################################
663# Convenience function:
664# 	Register all args as late customize function to run just before
665#	image creation.
666
667late_customize_cmd () {
668	NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*"
669}
670
671#######################################################################
672#
673# All set up to go...
674#
675#######################################################################
676
677# Progress Print
678#	Print $2 at level $1.
679pprint() {
680    if [ "$1" -le $PPLEVEL ]; then
681	runtime=$(( `date +%s` - $NANO_STARTTIME ))
682	printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3
683    fi
684}
685
686usage () {
687	(
688	echo "Usage: $0 [-biknqvw] [-c config_file]"
689	echo "	-b	suppress builds (both kernel and world)"
690	echo "	-i	suppress disk image build"
691	echo "	-k	suppress buildkernel"
692	echo "	-n	add -DNO_CLEAN to buildworld, buildkernel, etc"
693	echo "	-q	make output more quiet"
694	echo "	-v	make output more verbose"
695	echo "	-w	suppress buildworld"
696	echo "	-c	specify config file"
697	) 1>&2
698	exit 2
699}
700
701#######################################################################
702# Parse arguments
703
704do_clean=true
705do_kernel=true
706do_world=true
707do_image=true
708
709set +e
710args=`getopt bc:hiknqvw $*`
711if [ $? -ne 0 ] ; then
712	usage
713	exit 2
714fi
715set -e
716
717set -- $args
718for i
719do
720	case "$i" 
721	in
722	-b)
723		do_world=false
724		do_kernel=false
725		shift
726		;;
727	-k)
728		do_kernel=false
729		shift
730		;;
731	-c)
732		. "$2"
733		shift
734		shift
735		;;
736	-h)
737		usage
738		;;
739	-i)
740		do_image=false
741		shift
742		;;
743	-n)
744		do_clean=false
745		shift
746		;;
747	-q)
748		PPLEVEL=$(($PPLEVEL - 1))
749		shift
750		;;
751	-v)
752		PPLEVEL=$(($PPLEVEL + 1))
753		shift
754		;;
755	-w)
756		do_world=false
757		shift
758		;;
759	--)
760		shift
761		break
762	esac
763done
764
765if [ $# -gt 0 ] ; then
766	echo "$0: Extraneous arguments supplied"
767	usage
768fi
769
770#######################################################################
771# Setup and Export Internal variables
772#
773test -n "${NANO_OBJ}" || NANO_OBJ=/usr/obj/nanobsd.${NANO_NAME}/
774test -n "${MAKEOBJDIRPREFIX}" || MAKEOBJDIRPREFIX=${NANO_OBJ}
775test -n "${NANO_DISKIMGDIR}" || NANO_DISKIMGDIR=${NANO_OBJ}
776
777NANO_WORLDDIR=${NANO_OBJ}/_.w
778NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build
779NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install
780
781if [ -d ${NANO_TOOLS} ] ; then
782	true
783elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then
784	NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS}
785else
786	echo "NANO_TOOLS directory does not exist" 1>&2
787	exit 1
788fi
789
790if $do_clean ; then
791	true
792else
793	NANO_PMAKE="${NANO_PMAKE} -DNO_CLEAN"
794fi
795
796export MAKEOBJDIRPREFIX
797
798export NANO_ARCH
799export NANO_CODESIZE
800export NANO_CONFSIZE
801export NANO_CUSTOMIZE
802export NANO_DATASIZE
803export NANO_DRIVE
804export NANO_HEADS
805export NANO_IMAGES
806export NANO_IMGNAME
807export NANO_MAKE_CONF_BUILD
808export NANO_MAKE_CONF_INSTALL
809export NANO_MEDIASIZE
810export NANO_NAME
811export NANO_NEWFS
812export NANO_OBJ
813export NANO_PMAKE
814export NANO_SECTS
815export NANO_SRC
816export NANO_TOOLS
817export NANO_WORLDDIR
818export NANO_BOOT0CFG
819export NANO_BOOTLOADER
820
821#######################################################################
822# And then it is as simple as that...
823
824# File descriptor 3 is used for logging output, see pprint
825exec 3>&1
826
827NANO_STARTTIME=`date +%s`
828pprint 1 "NanoBSD image ${NANO_NAME} build starting"
829
830if $do_world ; then
831	if $do_clean ; then
832		clean_build
833	else
834		pprint 2 "Using existing build tree (as instructed)"
835	fi
836	make_conf_build
837	build_world
838else
839	pprint 2 "Skipping buildworld (as instructed)"
840fi
841
842if $do_kernel ; then
843	build_kernel
844else
845	pprint 2 "Skipping buildkernel (as instructed)"
846fi
847
848clean_world
849make_conf_install
850install_world
851install_etc
852setup_nanobsd_etc
853install_kernel
854
855run_customize
856setup_nanobsd
857prune_usr
858run_late_customize
859if $do_image ; then
860	create_${NANO_ARCH}_diskimage
861else
862	pprint 2 "Skipping image build (as instructed)"
863fi
864last_orders
865
866pprint 1 "NanoBSD image ${NANO_NAME} completed"
867