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$ 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# where package metadata gets placed 53NANO_PKG_META_BASE=/var/db 54 55# Object tree directory 56# default is subdir of /usr/obj 57#NANO_OBJ="" 58 59# The directory to put the final images 60# default is ${NANO_OBJ} 61#NANO_DISKIMGDIR="" 62 63# Make & parallel Make 64NANO_MAKE="make" 65NANO_PMAKE="make -j 3" 66 67# The default name for any image we create. 68NANO_IMGNAME="_.disk.full" 69 70# Options to put in make.conf during buildworld only 71CONF_BUILD=' ' 72 73# Options to put in make.conf during installworld only 74CONF_INSTALL=' ' 75 76# Options to put in make.conf during both build- & installworld. 77CONF_WORLD=' ' 78 79# Kernel config file to use 80NANO_KERNEL=GENERIC 81 82# Kernel modules to install. If empty, no modules are installed. 83# Use "default" to install all built modules. 84NANO_MODULES= 85 86# Customize commands. 87NANO_CUSTOMIZE="" 88 89# Late customize commands. 90NANO_LATE_CUSTOMIZE="" 91 92# Newfs paramters to use 93NANO_NEWFS="-b 4096 -f 512 -i 8192 -U" 94 95# The drive name of the media at runtime 96NANO_DRIVE=ad0 97 98# Target media size in 512 bytes sectors 99NANO_MEDIASIZE=2000000 100 101# Number of code images on media (1 or 2) 102NANO_IMAGES=2 103 104# 0 -> Leave second image all zeroes so it compresses better. 105# 1 -> Initialize second image with a copy of the first 106NANO_INIT_IMG2=1 107 108# Size of code file system in 512 bytes sectors 109# If zero, size will be as large as possible. 110NANO_CODESIZE=0 111 112# Size of configuration file system in 512 bytes sectors 113# Cannot be zero. 114NANO_CONFSIZE=2048 115 116# Size of data file system in 512 bytes sectors 117# If zero: no partition configured. 118# If negative: max size possible 119NANO_DATASIZE=0 120 121# Size of the /etc ramdisk in 512 bytes sectors 122NANO_RAM_ETCSIZE=10240 123 124# Size of the /tmp+/var ramdisk in 512 bytes sectors 125NANO_RAM_TMPVARSIZE=10240 126 127# Media geometry, only relevant if bios doesn't understand LBA. 128NANO_SECTS=63 129NANO_HEADS=16 130 131# boot0 flags/options and configuration 132NANO_BOOT0CFG="-o packet -s 1 -m 3" 133NANO_BOOTLOADER="boot/boot0sio" 134 135# boot2 flags/options 136# default force serial console 137NANO_BOOT2CFG="-h" 138 139# Backing type of md(4) device 140# Can be "file" or "swap" 141NANO_MD_BACKING="file" 142 143# for swap type md(4) backing, write out the mbr only 144NANO_IMAGE_MBRONLY=true 145 146# Progress Print level 147PPLEVEL=3 148 149# Set NANO_LABEL to non-blank to form the basis for using /dev/ufs/label 150# in preference to /dev/${NANO_DRIVE} 151# Root partition will be ${NANO_LABEL}s{1,2} 152# /cfg partition will be ${NANO_LABEL}s3 153# /data partition will be ${NANO_LABEL}s4 154NANO_LABEL="" 155 156####################################################################### 157# Architecture to build. Corresponds to TARGET_ARCH in a buildworld. 158# Unfortunately, there's no way to set TARGET at this time, and it 159# conflates the two, so architectures where TARGET != TARGET_ARCH do 160# not work. This defaults to the arch of the current machine. 161 162NANO_ARCH=`uname -p` 163 164# Directory to populate /cfg from 165NANO_CFGDIR="" 166 167# Directory to populate /data from 168NANO_DATADIR="" 169 170# src.conf to use when building the image. Defaults to /dev/null for the sake 171# of determinism. 172SRCCONF=${SRCCONF:=/dev/null} 173 174####################################################################### 175# 176# The functions which do the real work. 177# Can be overridden from the config file(s) 178# 179####################################################################### 180 181# rm doesn't know -x prior to FreeBSD 10, so cope with a variety of build 182# hosts for now. 183nano_rm ( ) { 184 case $(uname -r) in 185 7*|8*|9*) rm $* ;; 186 *) rm -x $* ;; 187 esac 188} 189 190# run in the world chroot, errors fatal 191CR() 192{ 193 chroot ${NANO_WORLDDIR} /bin/sh -exc "$*" 194} 195 196# run in the world chroot, errors not fatal 197CR0() 198{ 199 chroot ${NANO_WORLDDIR} /bin/sh -c "$*" || true 200} 201 202nano_cleanup ( ) ( 203 if [ $? -ne 0 ]; then 204 echo "Error encountered. Check for errors in last log file." 1>&2 205 fi 206 exit $? 207) 208 209clean_build ( ) ( 210 pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})" 211 212 if ! nano_rm -rf ${MAKEOBJDIRPREFIX}/ > /dev/null 2>&1 ; then 213 chflags -R noschg ${MAKEOBJDIRPREFIX}/ 214 nano_rm -r ${MAKEOBJDIRPREFIX}/ 215 fi 216 mkdir -p ${MAKEOBJDIRPREFIX} 217 printenv > ${MAKEOBJDIRPREFIX}/_.env 218) 219 220make_conf_build ( ) ( 221 pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)" 222 223 echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_BUILD} 224 echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF_BUILD} 225) 226 227build_world ( ) ( 228 pprint 2 "run buildworld" 229 pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw" 230 231 cd ${NANO_SRC} 232 env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} \ 233 SRCCONF=${SRCCONF} \ 234 __MAKE_CONF=${NANO_MAKE_CONF_BUILD} buildworld \ 235 > ${MAKEOBJDIRPREFIX}/_.bw 2>&1 236) 237 238build_kernel ( ) ( 239 local extra 240 241 pprint 2 "build kernel ($NANO_KERNEL)" 242 pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk" 243 244 ( 245 if [ -f ${NANO_KERNEL} ] ; then 246 kernconfdir_arg="KERNCONFDIR='$(realpath $(dirname ${NANO_KERNEL}))'" 247 kernconf=$(basename ${NANO_KERNEL}) 248 else 249 kernconf=${NANO_KERNEL} 250 fi 251 252 cd ${NANO_SRC}; 253 # unset these just in case to avoid compiler complaints 254 # when cross-building 255 unset TARGET_CPUTYPE 256 # Note: We intentionally build all modules, not only the ones in 257 # NANO_MODULES so the built world can be reused by multiple images. 258 eval "TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} buildkernel \ 259 SRCCONF='${SRCCONF}' \ 260 __MAKE_CONF='${NANO_MAKE_CONF_BUILD}' \ 261 ${kernconfdir_arg} KERNCONF=${kernconf}" 262 ) > ${MAKEOBJDIRPREFIX}/_.bk 2>&1 263) 264 265clean_world ( ) ( 266 if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then 267 pprint 2 "Clean and create object directory (${NANO_OBJ})" 268 if ! nano_rm -rf ${NANO_OBJ}/ > /dev/null 2>&1 ; then 269 chflags -R noschg ${NANO_OBJ} 270 nano_rm -r ${NANO_OBJ}/ 271 fi 272 mkdir -p ${NANO_OBJ} ${NANO_WORLDDIR} 273 printenv > ${NANO_OBJ}/_.env 274 else 275 pprint 2 "Clean and create world directory (${NANO_WORLDDIR})" 276 if ! nano_rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then 277 chflags -R noschg ${NANO_WORLDDIR} 278 nano_rm -rf ${NANO_WORLDDIR}/ 279 fi 280 mkdir -p ${NANO_WORLDDIR} 281 fi 282) 283 284make_conf_install ( ) ( 285 pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)" 286 287 echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_INSTALL} 288 echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF_INSTALL} 289) 290 291install_world ( ) ( 292 pprint 2 "installworld" 293 pprint 3 "log: ${NANO_OBJ}/_.iw" 294 295 cd ${NANO_SRC} 296 env TARGET_ARCH=${NANO_ARCH} \ 297 ${NANO_MAKE} SRCCONF=${SRCCONF} \ 298 __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} installworld \ 299 DESTDIR=${NANO_WORLDDIR} \ 300 > ${NANO_OBJ}/_.iw 2>&1 301 chflags -R noschg ${NANO_WORLDDIR} 302) 303 304install_etc ( ) ( 305 306 pprint 2 "install /etc" 307 pprint 3 "log: ${NANO_OBJ}/_.etc" 308 309 cd ${NANO_SRC} 310 env TARGET_ARCH=${NANO_ARCH} \ 311 ${NANO_MAKE} SRCCONF=${SRCCONF} \ 312 __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} distribution \ 313 DESTDIR=${NANO_WORLDDIR} \ 314 > ${NANO_OBJ}/_.etc 2>&1 315 # make.conf doesn't get created by default, but some ports need it 316 # so they can spam it. 317 cp /dev/null ${NANO_WORLDDIR}/etc/make.conf 318) 319 320install_kernel ( ) ( 321 local extra 322 323 pprint 2 "install kernel ($NANO_KERNEL)" 324 pprint 3 "log: ${NANO_OBJ}/_.ik" 325 326 ( 327 if [ -f ${NANO_KERNEL} ] ; then 328 kernconfdir_arg="KERNCONFDIR='$(realpath $(dirname ${NANO_KERNEL}))'" 329 kernconf=$(basename ${NANO_KERNEL}) 330 else 331 kernconf=${NANO_KERNEL} 332 fi 333 334 # Install all built modules if NANO_MODULES=default, 335 # else install only listed modules (none if NANO_MODULES is empty). 336 if [ "${NANO_MODULES}" != "default" ]; then 337 modules_override_arg="MODULES_OVERRIDE='${NANO_MODULES}'" 338 fi 339 340 cd ${NANO_SRC} 341 eval "TARGET_ARCH=${NANO_ARCH} ${NANO_MAKE} installkernel \ 342 DESTDIR='${NANO_WORLDDIR}' \ 343 SRCCONF='${SRCCONF}' \ 344 __MAKE_CONF='${NANO_MAKE_CONF_INSTALL}' \ 345 ${kernconfdir_arg} KERNCONF=${kernconf} \ 346 ${modules_override_arg}" 347 ) > ${NANO_OBJ}/_.ik 2>&1 348) 349 350native_xtools ( ) ( 351 print 2 "Installing the optimized native build tools for cross env" 352 pprint 3 "log: ${NANO_OBJ}/_.native_xtools" 353 354 cd ${NANO_SRC} 355 env TARGET_ARCH=${NANO_ARCH} \ 356 ${NANO_MAKE} SRCCONF=${SRCCONF} \ 357 __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} native-xtools \ 358 DESTDIR=${NANO_WORLDDIR} \ 359 > ${NANO_OBJ}/_.native_xtools 2>&1 360) 361 362run_customize() ( 363 364 pprint 2 "run customize scripts" 365 for c in $NANO_CUSTOMIZE 366 do 367 pprint 2 "customize \"$c\"" 368 pprint 3 "log: ${NANO_OBJ}/_.cust.$c" 369 pprint 4 "`type $c`" 370 ( set -x ; $c ) > ${NANO_OBJ}/_.cust.$c 2>&1 371 done 372) 373 374run_late_customize() ( 375 376 pprint 2 "run late customize scripts" 377 for c in $NANO_LATE_CUSTOMIZE 378 do 379 pprint 2 "late customize \"$c\"" 380 pprint 3 "log: ${NANO_OBJ}/_.late_cust.$c" 381 pprint 4 "`type $c`" 382 ( set -x ; $c ) > ${NANO_OBJ}/_.late_cust.$c 2>&1 383 done 384) 385 386setup_nanobsd ( ) ( 387 pprint 2 "configure nanobsd setup" 388 pprint 3 "log: ${NANO_OBJ}/_.dl" 389 390 ( 391 cd ${NANO_WORLDDIR} 392 393 # Move /usr/local/etc to /etc/local so that the /cfg stuff 394 # can stomp on it. Otherwise packages like ipsec-tools which 395 # have hardcoded paths under ${prefix}/etc are not tweakable. 396 if [ -d usr/local/etc ] ; then 397 ( 398 mkdir -p etc/local 399 cd usr/local/etc 400 find . -print | cpio -dumpl ../../../etc/local 401 cd .. 402 nano_rm -rf etc 403 ln -s ../../etc/local etc 404 ) 405 fi 406 407 for d in var etc 408 do 409 # link /$d under /conf 410 # we use hard links so we have them both places. 411 # the files in /$d will be hidden by the mount. 412 # XXX: configure /$d ramdisk size 413 mkdir -p conf/base/$d conf/default/$d 414 find $d -print | cpio -dumpl conf/base/ 415 done 416 417 echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size 418 echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size 419 420 # pick up config files from the special partition 421 echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount 422 423 # Put /tmp on the /var ramdisk (could be symlink already) 424 nano_rm -rf tmp 425 ln -s var/tmp tmp 426 427 ) > ${NANO_OBJ}/_.dl 2>&1 428) 429 430setup_nanobsd_etc ( ) ( 431 pprint 2 "configure nanobsd /etc" 432 433 ( 434 cd ${NANO_WORLDDIR} 435 436 # create diskless marker file 437 touch etc/diskless 438 439 # Make root filesystem R/O by default 440 echo "root_rw_mount=NO" >> etc/defaults/rc.conf 441 442 # save config file for scripts 443 echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf 444 445 echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab 446 echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab 447 mkdir -p cfg 448 ) 449) 450 451prune_usr() ( 452 453 # Remove all empty directories in /usr 454 find ${NANO_WORLDDIR}/usr -type d -depth -print | 455 while read d 456 do 457 rmdir $d > /dev/null 2>&1 || true 458 done 459) 460 461newfs_part ( ) ( 462 local dev mnt lbl 463 dev=$1 464 mnt=$2 465 lbl=$3 466 echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} 467 newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} 468 mount -o async ${dev} ${mnt} 469) 470 471# Convenient spot to work around any umount issues that your build environment 472# hits by overriding this method. 473nano_umount () ( 474 umount ${1} 475) 476 477populate_slice ( ) ( 478 local dev dir mnt lbl 479 dev=$1 480 dir=$2 481 mnt=$3 482 lbl=$4 483 echo "Creating ${dev} (mounting on ${mnt})" 484 newfs_part ${dev} ${mnt} ${lbl} 485 if [ -n "${dir}" -a -d "${dir}" ]; then 486 echo "Populating ${lbl} from ${dir}" 487 cd ${dir} 488 find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${mnt} 489 fi 490 df -i ${mnt} 491 nano_umount ${mnt} 492) 493 494populate_cfg_slice ( ) ( 495 populate_slice "$1" "$2" "$3" "$4" 496) 497 498populate_data_slice ( ) ( 499 populate_slice "$1" "$2" "$3" "$4" 500) 501 502create_diskimage ( ) ( 503 pprint 2 "build diskimage" 504 pprint 3 "log: ${NANO_OBJ}/_.di" 505 506 ( 507 echo $NANO_MEDIASIZE $NANO_IMAGES \ 508 $NANO_SECTS $NANO_HEADS \ 509 $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | 510 awk ' 511 { 512 printf "# %s\n", $0 513 514 # size of cylinder in sectors 515 cs = $3 * $4 516 517 # number of full cylinders on media 518 cyl = int ($1 / cs) 519 520 # output fdisk geometry spec, truncate cyls to 1023 521 if (cyl <= 1023) 522 print "g c" cyl " h" $4 " s" $3 523 else 524 print "g c" 1023 " h" $4 " s" $3 525 526 if ($7 > 0) { 527 # size of data partition in full cylinders 528 dsl = int (($7 + cs - 1) / cs) 529 } else { 530 dsl = 0; 531 } 532 533 # size of config partition in full cylinders 534 csl = int (($6 + cs - 1) / cs) 535 536 if ($5 == 0) { 537 # size of image partition(s) in full cylinders 538 isl = int ((cyl - dsl - csl) / $2) 539 } else { 540 isl = int (($5 + cs - 1) / cs) 541 } 542 543 # First image partition start at second track 544 print "p 1 165 " $3, isl * cs - $3 545 c = isl * cs; 546 547 # Second image partition (if any) also starts offset one 548 # track to keep them identical. 549 if ($2 > 1) { 550 print "p 2 165 " $3 + c, isl * cs - $3 551 c += isl * cs; 552 } 553 554 # Config partition starts at cylinder boundary. 555 print "p 3 165 " c, csl * cs 556 c += csl * cs 557 558 # Data partition (if any) starts at cylinder boundary. 559 if ($7 > 0) { 560 print "p 4 165 " c, dsl * cs 561 } else if ($7 < 0 && $1 > c) { 562 print "p 4 165 " c, $1 - c 563 } else if ($1 < c) { 564 print "Disk space overcommitted by", \ 565 c - $1, "sectors" > "/dev/stderr" 566 exit 2 567 } 568 569 # Force slice 1 to be marked active. This is necessary 570 # for booting the image from a USB device to work. 571 print "a 1" 572 } 573 ' > ${NANO_OBJ}/_.fdisk 574 575 IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} 576 MNT=${NANO_OBJ}/_.mnt 577 mkdir -p ${MNT} 578 579 if [ "${NANO_MD_BACKING}" = "swap" ] ; then 580 MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ 581 -y ${NANO_HEADS}` 582 else 583 echo "Creating md backing file..." 584 nano_rm -f ${IMG} 585 dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 586 MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ 587 -y ${NANO_HEADS}` 588 fi 589 590 trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT 591 592 fdisk -i -f ${NANO_OBJ}/_.fdisk ${MD} 593 fdisk ${MD} 594 # XXX: params 595 # XXX: pick up cached boot* files, they may not be in image anymore. 596 if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then 597 boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD} 598 fi 599 if [ -f ${NANO_WORLDDIR}/boot/boot ]; then 600 bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}s1 601 else 602 bsdlabel -w ${MD}s1 603 fi 604 bsdlabel ${MD}s1 605 606 # Create first image 607 populate_slice /dev/${MD}s1a ${NANO_WORLDDIR} ${MNT} "s1a" 608 mount /dev/${MD}s1a ${MNT} 609 echo "Generating mtree..." 610 ( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree 611 ( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du 612 nano_umount ${MNT} 613 614 if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then 615 # Duplicate to second image (if present) 616 echo "Duplicating to second image..." 617 dd conv=sparse if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k 618 mount /dev/${MD}s2a ${MNT} 619 for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab 620 do 621 sed -i "" "s=${NANO_DRIVE}s1=${NANO_DRIVE}s2=g" $f 622 done 623 nano_umount ${MNT} 624 # Override the label from the first partition so we 625 # don't confuse glabel with duplicates. 626 if [ ! -z ${NANO_LABEL} ]; then 627 tunefs -L ${NANO_LABEL}"s2a" /dev/${MD}s2a 628 fi 629 fi 630 631 # Create Config slice 632 populate_cfg_slice /dev/${MD}s3 "${NANO_CFGDIR}" ${MNT} "s3" 633 634 # Create Data slice, if any. 635 if [ $NANO_DATASIZE -ne 0 ] ; then 636 populate_data_slice /dev/${MD}s4 "${NANO_DATADIR}" ${MNT} "s4" 637 fi 638 639 if [ "${NANO_MD_BACKING}" = "swap" ] ; then 640 if [ ${NANO_IMAGE_MBRONLY} ]; then 641 echo "Writing out _.disk.mbr..." 642 dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 643 else 644 echo "Writing out ${NANO_IMGNAME}..." 645 dd if=/dev/${MD} of=${IMG} bs=64k 646 fi 647 648 echo "Writing out ${NANO_IMGNAME}..." 649 dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k 650 fi 651 652 if ${do_copyout_partition} ; then 653 echo "Writing out _.disk.image..." 654 dd conv=sparse if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k 655 fi 656 mdconfig -d -u $MD 657 658 trap - 1 2 15 659 trap nano_cleanup EXIT 660 661 ) > ${NANO_OBJ}/_.di 2>&1 662) 663 664last_orders () ( 665 # Redefine this function with any last orders you may have 666 # after the build completed, for instance to copy the finished 667 # image to a more convenient place: 668 # cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk 669 true 670) 671 672####################################################################### 673# 674# Optional convenience functions. 675# 676####################################################################### 677 678####################################################################### 679# Common Flash device geometries 680# 681 682FlashDevice () { 683 if [ -d ${NANO_TOOLS} ] ; then 684 . ${NANO_TOOLS}/FlashDevice.sub 685 else 686 . ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub 687 fi 688 sub_FlashDevice $1 $2 689} 690 691####################################################################### 692# USB device geometries 693# 694# Usage: 695# UsbDevice Generic 1000 # a generic flash key sold as having 1GB 696# 697# This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you. 698# 699# Note that the capacity of a flash key is usually advertised in MB or 700# GB, *not* MiB/GiB. As such, the precise number of cylinders available 701# for C/H/S geometry may vary depending on the actual flash geometry. 702# 703# The following generic device layouts are understood: 704# generic An alias for generic-hdd. 705# generic-hdd 255H 63S/T xxxxC with no MBR restrictions. 706# generic-fdd 64H 32S/T xxxxC with no MBR restrictions. 707# 708# The generic-hdd device is preferred for flash devices larger than 1GB. 709# 710 711UsbDevice () { 712 a1=`echo $1 | tr '[:upper:]' '[:lower:]'` 713 case $a1 in 714 generic-fdd) 715 NANO_HEADS=64 716 NANO_SECTS=32 717 NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) 718 ;; 719 generic|generic-hdd) 720 NANO_HEADS=255 721 NANO_SECTS=63 722 NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) 723 ;; 724 *) 725 echo "Unknown USB flash device" 726 exit 2 727 ;; 728 esac 729} 730 731####################################################################### 732# Setup serial console 733 734cust_comconsole () ( 735 # Enable getty on console 736 sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys 737 738 # Disable getty on syscons devices 739 sed -i "" -e '/^ttyv[0-8]/s/ on/ off/' ${NANO_WORLDDIR}/etc/ttys 740 741 # Tell loader to use serial console early. 742 echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config 743) 744 745####################################################################### 746# Allow root login via ssh 747 748cust_allow_ssh_root () ( 749 sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \ 750 ${NANO_WORLDDIR}/etc/ssh/sshd_config 751) 752 753####################################################################### 754# Install the stuff under ./Files 755 756cust_install_files () ( 757 cd ${NANO_TOOLS}/Files 758 find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -Ldumpv ${NANO_WORLDDIR} 759) 760 761####################################################################### 762# Install packages from ${NANO_PACKAGE_DIR} 763 764cust_pkg () ( 765 766 # If the package directory doesn't exist, we're done. 767 if [ ! -d ${NANO_PACKAGE_DIR} ]; then 768 echo "DONE 0 packages" 769 return 0 770 fi 771 772 # Copy packages into chroot 773 mkdir -p ${NANO_WORLDDIR}/Pkg ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg 774 ( 775 cd ${NANO_PACKAGE_DIR} 776 find ${NANO_PACKAGE_LIST} -print | 777 cpio -Ldumpv ${NANO_WORLDDIR}/Pkg 778 ) 779 780 # Count & report how many we have to install 781 todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l` 782 echo "=== TODO: $todo" 783 ls ${NANO_WORLDDIR}/Pkg 784 echo "===" 785 while true 786 do 787 # Record how many we have now 788 have=`ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg | wc -l` 789 790 # Attempt to install more packages 791 # ...but no more than 200 at a time due to pkg_add's internal 792 # limitations. 793 CR0 'ls Pkg/*tbz | xargs -n 200 env PKG_DBDIR='${NANO_PKG_META_BASE}'/pkg pkg_add -v -F' 794 795 # See what that got us 796 now=`ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg | wc -l` 797 echo "=== NOW $now" 798 ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg 799 echo "===" 800 801 802 if [ $now -eq $todo ] ; then 803 echo "DONE $now packages" 804 break 805 elif [ $now -eq $have ] ; then 806 echo "FAILED: Nothing happened on this pass" 807 exit 2 808 fi 809 done 810 nano_rm -rf ${NANO_WORLDDIR}/Pkg 811) 812 813cust_pkgng () ( 814 815 # If the package directory doesn't exist, we're done. 816 if [ ! -d ${NANO_PACKAGE_DIR} ]; then 817 echo "DONE 0 packages" 818 return 0 819 fi 820 821 # Find a pkg-* package 822 for x in `find -s ${NANO_PACKAGE_DIR} -iname 'pkg-*'`; do 823 _NANO_PKG_PACKAGE=`basename "$x"` 824 done 825 if [ -z "${_NANO_PKG_PACKAGE}" -o ! -f "${NANO_PACKAGE_DIR}/${_NANO_PKG_PACKAGE}" ]; then 826 echo "FAILED: need a pkg/ package for bootstrapping" 827 exit 2 828 fi 829 830 # Copy packages into chroot 831 mkdir -p ${NANO_WORLDDIR}/Pkg 832 ( 833 cd ${NANO_PACKAGE_DIR} 834 find ${NANO_PACKAGE_LIST} -print | 835 cpio -Ldumpv ${NANO_WORLDDIR}/Pkg 836 ) 837 838 #Bootstrap pkg 839 CR env ASSUME_ALWAYS_YES=YES SIGNATURE_TYPE=none /usr/sbin/pkg add /Pkg/${_NANO_PKG_PACKAGE} 840 CR pkg -N >/dev/null 2>&1 841 if [ "$?" -ne "0" ]; then 842 echo "FAILED: pkg bootstrapping faied" 843 exit 2 844 fi 845 nano_rm -f ${NANO_WORLDDIR}/Pkg/pkg-* 846 847 # Count & report how many we have to install 848 todo=`ls ${NANO_WORLDDIR}/Pkg | /usr/bin/wc -l` 849 todo=$(expr $todo + 1) # add one for pkg since it is installed already 850 echo "=== TODO: $todo" 851 ls ${NANO_WORLDDIR}/Pkg 852 echo "===" 853 while true 854 do 855 # Record how many we have now 856 have=$(CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info | /usr/bin/wc -l) 857 858 # Attempt to install more packages 859 CR0 'ls 'Pkg/*txz' | xargs env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg add' 860 861 # See what that got us 862 now=$(CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info | /usr/bin/wc -l) 863 echo "=== NOW $now" 864 CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info 865 echo "===" 866 if [ $now -eq $todo ] ; then 867 echo "DONE $now packages" 868 break 869 elif [ $now -eq $have ] ; then 870 echo "FAILED: Nothing happened on this pass" 871 exit 2 872 fi 873 done 874 nano_rm -rf ${NANO_WORLDDIR}/Pkg 875) 876 877####################################################################### 878# Convenience function: 879# Register all args as customize function. 880 881customize_cmd () { 882 NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*" 883} 884 885####################################################################### 886# Convenience function: 887# Register all args as late customize function to run just before 888# image creation. 889 890late_customize_cmd () { 891 NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*" 892} 893 894####################################################################### 895# 896# All set up to go... 897# 898####################################################################### 899 900# Progress Print 901# Print $2 at level $1. 902pprint() ( 903 if [ "$1" -le $PPLEVEL ]; then 904 runtime=$(( `date +%s` - $NANO_STARTTIME )) 905 printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3 906 fi 907) 908 909usage () { 910 ( 911 echo "Usage: $0 [-bfiKknqvw] [-c config_file]" 912 echo " -K suppress installkernel" 913 echo " -b suppress builds (both kernel and world)" 914 echo " -c specify config file" 915 echo " -f suppress code slice extraction" 916 echo " -i suppress disk image build" 917 echo " -k suppress buildkernel" 918 echo " -n add -DNO_CLEAN to buildworld, buildkernel, etc" 919 echo " -q make output more quiet" 920 echo " -v make output more verbose" 921 echo " -w suppress buildworld" 922 ) 1>&2 923 exit 2 924} 925 926####################################################################### 927# Parse arguments 928 929do_clean=true 930do_kernel=true 931do_installkernel=true 932do_world=true 933do_image=true 934do_copyout_partition=true 935do_native_xtools=false 936 937set +e 938args=`getopt KXbc:fhiknqvw $*` 939if [ $? -ne 0 ] ; then 940 usage 941 exit 2 942fi 943set -e 944 945set -- $args 946for i 947do 948 case "$i" 949 in 950 -K) 951 do_installkernel=false 952 shift 953 ;; 954 -X) 955 do_native_xtools=true 956 shift 957 ;; 958 -b) 959 do_world=false 960 do_kernel=false 961 shift 962 ;; 963 -c) 964 # Make config file path available to the config file 965 # itself so that it can access additional files relative 966 # to its own location. 967 NANO_CONFIG=$2 968 . "$2" 969 shift 970 shift 971 ;; 972 -f) 973 do_copyout_partition=false 974 shift 975 ;; 976 -h) 977 usage 978 ;; 979 -i) 980 do_image=false 981 shift 982 ;; 983 -k) 984 do_kernel=false 985 shift 986 ;; 987 -n) 988 do_clean=false 989 shift 990 ;; 991 -q) 992 PPLEVEL=$(($PPLEVEL - 1)) 993 shift 994 ;; 995 -v) 996 PPLEVEL=$(($PPLEVEL + 1)) 997 shift 998 ;; 999 -w) 1000 do_world=false 1001 shift 1002 ;; 1003 --) 1004 shift 1005 break 1006 esac 1007done 1008 1009if [ $# -gt 0 ] ; then 1010 echo "$0: Extraneous arguments supplied" 1011 usage 1012fi 1013 1014trap nano_cleanup EXIT 1015 1016####################################################################### 1017# Setup and Export Internal variables 1018# 1019test -n "${NANO_OBJ}" || NANO_OBJ=/usr/obj/nanobsd.${NANO_NAME} 1020test -n "${MAKEOBJDIRPREFIX}" || MAKEOBJDIRPREFIX=${NANO_OBJ} 1021test -n "${NANO_DISKIMGDIR}" || NANO_DISKIMGDIR=${NANO_OBJ} 1022 1023NANO_WORLDDIR=${NANO_OBJ}/_.w 1024NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build 1025NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install 1026 1027if [ -d ${NANO_TOOLS} ] ; then 1028 true 1029elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then 1030 NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS} 1031else 1032 echo "NANO_TOOLS directory does not exist" 1>&2 1033 exit 1 1034fi 1035 1036if $do_clean ; then 1037 true 1038else 1039 NANO_MAKE="${NANO_MAKE} -DNO_CLEAN" 1040 NANO_PMAKE="${NANO_PMAKE} -DNO_CLEAN" 1041fi 1042 1043# Override user's NANO_DRIVE if they specified a NANO_LABEL 1044if [ ! -z "${NANO_LABEL}" ]; then 1045 NANO_DRIVE=ufs/${NANO_LABEL} 1046fi 1047 1048export MAKEOBJDIRPREFIX 1049 1050export NANO_ARCH 1051export NANO_CODESIZE 1052export NANO_CONFSIZE 1053export NANO_CUSTOMIZE 1054export NANO_DATASIZE 1055export NANO_DRIVE 1056export NANO_HEADS 1057export NANO_IMAGES 1058export NANO_IMGNAME 1059export NANO_MAKE 1060export NANO_MAKE_CONF_BUILD 1061export NANO_MAKE_CONF_INSTALL 1062export NANO_MEDIASIZE 1063export NANO_NAME 1064export NANO_NEWFS 1065export NANO_OBJ 1066export NANO_PMAKE 1067export NANO_SECTS 1068export NANO_SRC 1069export NANO_TOOLS 1070export NANO_WORLDDIR 1071export NANO_BOOT0CFG 1072export NANO_BOOTLOADER 1073export NANO_LABEL 1074 1075####################################################################### 1076# And then it is as simple as that... 1077 1078# File descriptor 3 is used for logging output, see pprint 1079exec 3>&1 1080 1081NANO_STARTTIME=`date +%s` 1082pprint 1 "NanoBSD image ${NANO_NAME} build starting" 1083 1084if $do_world ; then 1085 if $do_clean ; then 1086 clean_build 1087 else 1088 pprint 2 "Using existing build tree (as instructed)" 1089 fi 1090 make_conf_build 1091 build_world 1092else 1093 pprint 2 "Skipping buildworld (as instructed)" 1094fi 1095 1096if $do_kernel ; then 1097 if ! $do_world ; then 1098 make_conf_build 1099 fi 1100 build_kernel 1101else 1102 pprint 2 "Skipping buildkernel (as instructed)" 1103fi 1104 1105clean_world 1106make_conf_install 1107install_world 1108install_etc 1109if $do_native_xtools ; then 1110 native_xtools 1111fi 1112setup_nanobsd_etc 1113if $do_installkernel ; then 1114 install_kernel 1115else 1116 pprint 2 "Skipping installkernel (as instructed)" 1117fi 1118 1119run_customize 1120setup_nanobsd 1121prune_usr 1122run_late_customize 1123if $do_image ; then 1124 create_diskimage 1125else 1126 pprint 2 "Skipping image build (as instructed)" 1127fi 1128last_orders 1129 1130pprint 1 "NanoBSD image ${NANO_NAME} completed" 1131