nanobsd.sh revision 181459
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 181459 2008-08-09 09:27:06Z phk $
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
50
51# Object tree directory
52# default is subdir of /usr/obj
53# XXX: MAKEOBJDIRPREFIX handling... ?
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# Options to put in make.conf during buildworld only
64CONF_BUILD=' '
65
66# Options to put in make.conf during installworld only
67CONF_INSTALL=' '
68
69# Options to put in make.conf during both build- & installworld.
70CONF_WORLD=' '
71
72# Kernel config file to use
73NANO_KERNEL=GENERIC
74
75# Customize commands.
76NANO_CUSTOMIZE=""
77
78# Newfs paramters to use
79NANO_NEWFS="-b 4096 -f 512 -i 8192 -O1 -U"
80
81# The drive name of the media at runtime
82NANO_DRIVE=ad0
83
84# Target media size in 512 bytes sectors
85NANO_MEDIASIZE=1000000
86
87# Number of code images on media (1 or 2)
88NANO_IMAGES=2
89
90# 0 -> Leave second image all zeroes so it compresses better.
91# 1 -> Initialize second image with a copy of the first
92NANO_INIT_IMG2=1
93
94# Size of code file system in 512 bytes sectors
95# If zero, size will be as large as possible.
96NANO_CODESIZE=0
97
98# Size of configuration file system in 512 bytes sectors
99# Cannot be zero.
100NANO_CONFSIZE=2048
101
102# Size of data file system in 512 bytes sectors
103# If zero: no partition configured.
104# If negative: max size possible
105NANO_DATASIZE=0
106
107# Size of the /etc ramdisk in 512 bytes sectors
108NANO_RAM_ETCSIZE=10240
109
110# Size of the /tmp+/var ramdisk in 512 bytes sectors
111NANO_RAM_TMPVARSIZE=10240
112
113# Media geometry, only relevant if bios doesn't understand LBA.
114NANO_SECTS=63
115NANO_HEADS=16
116
117# boot0 flags/options and configuration
118NANO_BOOT0CFG="-o packet -s 1 -m 3"
119NANO_BOOTLOADER="boot/boot0sio"
120
121# Backing type of md(4) device
122# Can be "file" or "swap"
123NANO_MD_BACKING="file"
124
125#######################################################################
126# Not a variable at this time
127
128NANO_ARCH=i386
129
130#######################################################################
131#
132# The functions which do the real work.
133# Can be overridden from the config file(s)
134#
135#######################################################################
136
137clean_build ( ) (
138	echo "## Clean and create object directory (${MAKEOBJDIRPREFIX})"
139
140	if rm -rf ${MAKEOBJDIRPREFIX} > /dev/null 2>&1 ; then
141		true
142	else
143		chflags -R noschg ${MAKEOBJDIRPREFIX}
144		rm -rf ${MAKEOBJDIRPREFIX}
145	fi
146	mkdir -p ${MAKEOBJDIRPREFIX}
147	printenv > ${MAKEOBJDIRPREFIX}/_.env
148)
149
150make_conf_build ( ) (
151	echo "## Construct build make.conf ($NANO_MAKE_CONF)"
152
153	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF}
154	echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF}
155)
156
157build_world ( ) (
158	echo "## run buildworld"
159	echo "### log: ${MAKEOBJDIRPREFIX}/_.bw"
160
161	cd ${NANO_SRC}
162	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} buildworld \
163		> ${MAKEOBJDIRPREFIX}/_.bw 2>&1
164)
165
166build_kernel ( ) (
167	echo "## build kernel ($NANO_KERNEL)"
168	echo "### log: ${MAKEOBJDIRPREFIX}/_.bk"
169
170	if [ -f ${NANO_KERNEL} ] ; then
171		cp ${NANO_KERNEL} ${NANO_SRC}/sys/${NANO_ARCH}/conf
172	fi
173
174	(cd ${NANO_SRC};
175	# unset these just in case to avoid compiler complaints
176	# when cross-building
177	unset TARGET_CPUTYPE
178	unset TARGET_BIG_ENDIAN
179	${NANO_PMAKE} buildkernel \
180		__MAKE_CONF=${NANO_MAKE_CONF} KERNCONF=`basename ${NANO_KERNEL}` \
181		> ${MAKEOBJDIRPREFIX}/_.bk 2>&1
182	)
183)
184
185clean_world ( ) (
186	echo "## Clean and create world directory (${NANO_WORLDDIR})"
187	if rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then
188		true
189	else
190		chflags -R noschg ${NANO_WORLDDIR}/
191		rm -rf ${NANO_WORLDDIR}/
192	fi
193	mkdir -p ${NANO_WORLDDIR}/
194)
195
196make_conf_install ( ) (
197	echo "## Construct install make.conf ($NANO_MAKE_CONF)"
198
199	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF}
200	echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF}
201)
202
203install_world ( ) (
204	echo "## installworld"
205	echo "### log: ${MAKEOBJDIRPREFIX}/_.iw"
206
207	cd ${NANO_SRC}
208	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} installworld \
209		DESTDIR=${NANO_WORLDDIR} \
210		> ${MAKEOBJDIRPREFIX}/_.iw 2>&1
211	chflags -R noschg ${NANO_WORLDDIR}
212)
213
214install_etc ( ) (
215
216	echo "## install /etc"
217	echo "### log: ${MAKEOBJDIRPREFIX}/_.etc"
218
219	cd ${NANO_SRC}
220	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} distribution \
221		DESTDIR=${NANO_WORLDDIR} \
222		> ${MAKEOBJDIRPREFIX}/_.etc 2>&1
223)
224
225install_kernel ( ) (
226	echo "## install kernel"
227	echo "### log: ${MAKEOBJDIRPREFIX}/_.ik"
228
229	cd ${NANO_SRC}
230	${NANO_PMAKE} installkernel \
231		DESTDIR=${NANO_WORLDDIR} \
232		__MAKE_CONF=${NANO_MAKE_CONF} KERNCONF=`basename ${NANO_KERNEL}` \
233		> ${MAKEOBJDIRPREFIX}/_.ik 2>&1
234)
235
236run_customize() (
237
238	echo "## run customize scripts"
239	for c in $NANO_CUSTOMIZE
240	do
241		echo "## customize \"$c\""
242		echo "### log: ${MAKEOBJDIRPREFIX}/_.cust.$c"
243		echo "### `type $c`"
244		( $c ) > ${MAKEOBJDIRPREFIX}/_.cust.$c 2>&1
245	done
246)
247
248setup_nanobsd ( ) (
249	echo "## configure nanobsd setup"
250	echo "### log: ${MAKEOBJDIRPREFIX}/_.dl"
251
252	(
253	cd ${NANO_WORLDDIR}
254
255	# Move /usr/local/etc to /etc/local so that the /cfg stuff
256	# can stomp on it.  Otherwise packages like ipsec-tools which
257	# have hardcoded paths under ${prefix}/etc are not tweakable.
258	if [ -d usr/local/etc ] ; then
259		(
260		mkdir etc/local
261		cd usr/local/etc
262		find . -print | cpio -dumpl ../../../etc/local
263		cd ..
264		rm -rf etc
265		ln -s ../../etc/local etc
266		)
267	fi
268
269	for d in var etc
270	do
271		# link /$d under /conf
272		# we use hard links so we have them both places.
273		# the files in /$d will be hidden by the mount.
274		# XXX: configure /$d ramdisk size
275		mkdir -p conf/base/$d conf/default/$d
276		find $d -print | cpio -dumpl conf/base/
277	done
278
279	echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size
280	echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size
281
282	# pick up config files from the special partition
283	echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount
284
285	# Put /tmp on the /var ramdisk (could be symlink already)
286	rmdir tmp || true
287	rm tmp || true
288	ln -s var/tmp tmp
289
290	) > ${MAKEOBJDIRPREFIX}/_.dl 2>&1
291)
292
293setup_nanobsd_etc ( ) (
294	echo "## configure nanobsd /etc"
295
296	(
297	cd ${NANO_WORLDDIR}
298
299	# create diskless marker file
300	touch etc/diskless
301
302	# Make root filesystem R/O by default
303	echo "root_rw_mount=NO" >> etc/defaults/rc.conf
304
305	# save config file for scripts
306	echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
307
308	echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab
309	echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab
310	mkdir -p cfg
311	)
312)
313
314prune_usr() (
315
316	# Remove all empty directories in /usr 
317	find ${NANO_WORLDDIR}/usr -type d -depth -print |
318		while read d
319		do
320			rmdir $d > /dev/null 2>&1 || true 
321		done
322)
323
324create_i386_diskimage ( ) (
325	echo "## build diskimage"
326	echo "### log: ${MAKEOBJDIRPREFIX}/_.di"
327
328	(
329	echo $NANO_MEDIASIZE $NANO_IMAGES \
330		$NANO_SECTS $NANO_HEADS \
331		$NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE |
332	awk '
333	{
334		printf "# %s\n", $0
335
336		# size of cylinder in sectors
337		cs = $3 * $4
338
339		# number of full cylinders on media
340		cyl = int ($1 / cs)
341
342		# output fdisk geometry spec, truncate cyls to 1023
343		if (cyl <= 1023)
344			print "g c" cyl " h" $4 " s" $3
345		else
346			print "g c" 1023 " h" $4 " s" $3
347
348		if ($7 > 0) { 
349			# size of data partition in full cylinders
350			dsl = int (($7 + cs - 1) / cs)
351		} else {
352			dsl = 0;
353		}
354
355		# size of config partition in full cylinders
356		csl = int (($6 + cs - 1) / cs)
357
358		if ($5 == 0) {
359			# size of image partition(s) in full cylinders
360			isl = int ((cyl - dsl - csl) / $2)
361		} else {
362			isl = int (($5 + cs - 1) / cs)
363		}
364
365		# First image partition start at second track
366		print "p 1 165 " $3, isl * cs - $3
367		c = isl * cs;
368
369		# Second image partition (if any) also starts offset one 
370		# track to keep them identical.
371		if ($2 > 1) {
372			print "p 2 165 " $3 + c, isl * cs - $3
373			c += isl * cs;
374		}
375
376		# Config partition starts at cylinder boundary.
377		print "p 3 165 " c, csl * cs
378		c += csl * cs
379
380		# Data partition (if any) starts at cylinder boundary.
381		if ($7 > 0) {
382			print "p 4 165 " c, dsl * cs
383		} else if ($7 < 0 && $1 > c) {
384			print "p 4 165 " c, $1 - c
385		} else if ($1 < c) {
386			print "Disk space overcommitted by", \
387			    c - $1, "sectors" > "/dev/stderr"
388			exit 2
389		}
390	}
391	' > ${MAKEOBJDIRPREFIX}/_.fdisk
392
393	IMG=${NANO_DISKIMGDIR}/_.disk.full
394	MNT=${MAKEOBJDIRPREFIX}/_.mnt
395	mkdir -p ${MNT}
396
397	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
398		MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \
399			-y ${NANO_HEADS}`
400	else
401		echo "Creating md backing file..."
402		dd if=/dev/zero of=${IMG} bs=${NANO_SECTS}b \
403			count=`expr ${NANO_MEDIASIZE} / ${NANO_SECTS}`
404		MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \
405			-y ${NANO_HEADS}`
406	fi
407
408	trap "df -i ${MNT} ; umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
409
410	fdisk -i -f ${MAKEOBJDIRPREFIX}/_.fdisk ${MD}
411	fdisk ${MD}
412	# XXX: params
413	# XXX: pick up cached boot* files, they may not be in image anymore.
414	boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD}
415	bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}s1
416	bsdlabel ${MD}s1
417
418	# Create first image
419	newfs ${NANO_NEWFS} /dev/${MD}s1a
420	mount /dev/${MD}s1a ${MNT}
421	df -i ${MNT}
422	echo "Copying worlddir..."
423	( cd ${NANO_WORLDDIR} && find . -print | cpio -dump ${MNT} )
424	df -i ${MNT}
425	echo "Generating mtree..."
426	( cd ${MNT} && mtree -c ) > ${MAKEOBJDIRPREFIX}/_.mtree
427	( cd ${MNT} && du -k ) > ${MAKEOBJDIRPREFIX}/_.du
428	umount ${MNT}
429
430	if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then
431		# Duplicate to second image (if present)
432		echo "Duplicating to second image..."
433		dd if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k
434		mount /dev/${MD}s2a ${MNT}
435		for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab
436		do
437			sed -i "" "s/${NANO_DRIVE}s1/${NANO_DRIVE}s2/g" $f
438		done
439		umount ${MNT}
440
441	fi
442	
443	# Create Config slice
444	newfs ${NANO_NEWFS} /dev/${MD}s3
445	# XXX: fill from where ?
446
447	# Create Data slice, if any.
448	if [ $NANO_DATASIZE -gt 0 ] ; then
449		newfs ${NANO_NEWFS} /dev/${MD}s4
450		# XXX: fill from where ?
451	fi
452
453	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
454		echo "Writing out _.disk.full..."
455		dd if=/dev/${MD} of=${IMG} bs=64k
456	fi
457
458	echo "Writing out _.disk.image..."
459	dd if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k
460	mdconfig -d -u $MD
461	) > ${MAKEOBJDIRPREFIX}/_.di 2>&1
462)
463
464last_orders () (
465	# Redefine this function with any last orders you may have
466	# after the build completed, for instance to copy the finished
467	# image to a more convenient place:
468	# cp ${MAKEOBJDIRPREFIX}/_.disk.image /home/ftp/pub/nanobsd.disk
469)
470
471#######################################################################
472#
473# Optional convenience functions.
474#
475#######################################################################
476
477#######################################################################
478# Common Flash device geometries
479#
480
481FlashDevice () {
482	if [ -d ${NANO_TOOLS} ] ; then
483		. ${NANO_TOOLS}/FlashDevice.sub
484	else
485		. ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub
486	fi
487	sub_FlashDevice $1 $2
488}
489
490
491#######################################################################
492# Setup serial console
493
494cust_comconsole () (
495	# Enable getty on console
496	sed -i "" -e /ttyu0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys
497
498	# Disable getty on syscons devices
499	sed -i "" -e '/^ttyv[0-8]/s/	on/	off/' ${NANO_WORLDDIR}/etc/ttys
500
501	# Tell loader to use serial console early.
502	echo " -h" > ${NANO_WORLDDIR}/boot.config
503)
504
505#######################################################################
506# Allow root login via ssh
507
508cust_allow_ssh_root () (
509	sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \
510	    ${NANO_WORLDDIR}/etc/ssh/sshd_config
511)
512
513#######################################################################
514# Install the stuff under ./Files
515
516cust_install_files () (
517	cd ${NANO_TOOLS}/Files
518	find . -print | grep -v /CVS | cpio -dumpv ${NANO_WORLDDIR}
519)
520
521#######################################################################
522# Install packages from ${NANO_PACKAGE_DIR}
523
524cust_pkg () (
525
526	# Copy packages into chroot
527	mkdir -p ${NANO_WORLDDIR}/Pkg
528	cp ${NANO_PACKAGE_DIR}/* ${NANO_WORLDDIR}/Pkg
529
530	# Count & report how many we have to install
531	todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l`
532	echo "=== TODO: $todo"
533	ls ${NANO_WORLDDIR}/Pkg
534	echo "==="
535	while true
536	do
537		# Record how may we have now
538		have=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
539
540		# Attempt to install more packages
541		# ...but no more than 200 at a time due to pkg_add's internal
542		# limitations.
543		chroot ${NANO_WORLDDIR} sh -c \
544			'ls Pkg/*tbz | xargs -n 200 pkg_add -F' || true
545
546		# See what that got us
547		now=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
548		echo "=== NOW $now"
549		ls ${NANO_WORLDDIR}/var/db/pkg
550		echo "==="
551
552
553		if [ $now -eq $todo ] ; then
554			echo "DONE $now packages"
555			break
556		elif [ $now -eq $have ] ; then
557			echo "FAILED: Nothing happened on this pass"
558			exit 2
559		fi
560	done
561	rm -rf ${NANO_WORLDDIR}/Pkg
562)
563
564#######################################################################
565# Convenience function:
566# 	Register $1 as customize function.
567
568customize_cmd () {
569	NANO_CUSTOMIZE="$NANO_CUSTOMIZE $1"
570}
571
572#######################################################################
573#
574# All set up to go...
575#
576#######################################################################
577
578usage () {
579	(
580	echo "Usage: $0 [-b/-k/-w] [-c config_file]"
581	echo "	-b	suppress builds (both kernel and world)"
582	echo "	-k	suppress buildkernel"
583	echo "	-w	suppress buildworld"
584	echo "	-c	specify config file"
585	) 1>&2
586	exit 2
587}
588
589#######################################################################
590# Parse arguments
591
592do_kernel=true
593do_world=true
594
595set +e
596args=`getopt bc:hkw $*`
597if [ $? -ne 0 ] ; then
598	usage
599	exit 2
600fi
601set -e
602
603set -- $args
604for i
605do
606	case "$i" 
607	in
608	-b)
609		shift;
610		do_world=false
611		do_kernel=false
612		;;
613	-k)
614		shift;
615		do_kernel=false
616		;;
617	-c)
618		. "$2"
619		shift;
620		shift;
621		;;
622	-h)
623		usage
624		;;
625	-w)
626		shift;
627		do_world=false
628		;;
629	--)
630		shift;
631		break;
632	esac
633done
634
635if [ $# -gt 0 ] ; then
636	echo "$0: Extraneous arguments supplied"
637	usage
638fi
639
640#######################################################################
641# Setup and Export Internal variables
642#
643if [ "x${NANO_OBJ}" = "x" ] ; then
644	MAKEOBJDIRPREFIX=/usr/obj/nanobsd.${NANO_NAME}/
645	NANO_OBJ=${MAKEOBJDIRPREFIX}
646else
647	MAKEOBJDIRPREFIX=${NANO_OBJ}
648fi
649
650if [ "x${NANO_DISKIMGDIR}" = "x" ] ; then
651	NANO_DISKIMGDIR=${MAKEOBJDIRPREFIX}
652fi
653
654NANO_WORLDDIR=${MAKEOBJDIRPREFIX}/_.w
655NANO_MAKE_CONF=${MAKEOBJDIRPREFIX}/make.conf
656
657if [ -d ${NANO_TOOLS} ] ; then
658	true
659elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then
660	NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS}
661else
662	echo "NANO_TOOLS directory does not exist" 1>&2
663	exit 1
664fi
665
666export MAKEOBJDIRPREFIX
667
668export NANO_ARCH
669export NANO_CODESIZE
670export NANO_CONFSIZE
671export NANO_CUSTOMIZE
672export NANO_DATASIZE
673export NANO_DRIVE
674export NANO_HEADS
675export NANO_IMAGES
676export NANO_MAKE_CONF
677export NANO_MEDIASIZE
678export NANO_NAME
679export NANO_NEWFS
680export NANO_OBJ
681export NANO_PMAKE
682export NANO_SECTS
683export NANO_SRC
684export NANO_TOOLS
685export NANO_WORLDDIR
686export NANO_BOOT0CFG
687export NANO_BOOTLOADER
688
689#######################################################################
690# And then it is as simple as that...
691
692if $do_world ; then
693	clean_build
694	make_conf_build
695	build_world
696else
697	echo "## Skipping buildworld (as instructed)"
698fi
699
700if $do_kernel ; then
701	build_kernel
702else
703	echo "## Skipping buildkernel (as instructed)"
704fi
705
706clean_world
707make_conf_install
708install_world
709install_etc
710setup_nanobsd_etc
711install_kernel
712
713run_customize
714setup_nanobsd
715prune_usr
716create_${NANO_ARCH}_diskimage
717last_orders
718
719echo "# NanoBSD image completed"
720