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