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