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