]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/tools/nanobsd/nanobsd.sh
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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         rmdir tmp || true
363         rm tmp || true
364         ln -s var/tmp tmp
365
366         ) > ${NANO_OBJ}/_.dl 2>&1
367 )
368
369 setup_nanobsd_etc ( ) (
370         pprint 2 "configure nanobsd /etc"
371
372         (
373         cd ${NANO_WORLDDIR}
374
375         # create diskless marker file
376         touch etc/diskless
377
378         # Make root filesystem R/O by default
379         echo "root_rw_mount=NO" >> etc/defaults/rc.conf
380
381         # save config file for scripts
382         echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
383
384         echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab
385         echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab
386         mkdir -p cfg
387         )
388 )
389
390 prune_usr() (
391
392         # Remove all empty directories in /usr 
393         find ${NANO_WORLDDIR}/usr -type d -depth -print |
394                 while read d
395                 do
396                         rmdir $d > /dev/null 2>&1 || true 
397                 done
398 )
399
400 newfs_part ( ) (
401         local dev mnt lbl
402         dev=$1
403         mnt=$2
404         lbl=$3
405         echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev}
406         newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev}
407         mount -o async ${dev} ${mnt}
408 )
409
410 populate_slice ( ) (
411         local dev dir mnt lbl
412         dev=$1
413         dir=$2
414         mnt=$3
415         lbl=$4
416         test -z $2 && dir=${NANO_WORLDDIR}/var/empty
417         test -d $dir || dir=${NANO_WORLDDIR}/var/empty
418         echo "Creating ${dev} with ${dir} (mounting on ${mnt})"
419         newfs_part $dev $mnt $lbl
420         cd ${dir}
421         find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${mnt}
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 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 if=/dev/${MD} of=${IMG} bs=64k
568         fi
569
570         if ${do_copyout_partition} ; then
571                 echo "Writing out _.disk.image..."
572                 dd 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 )
592
593 #######################################################################
594 #
595 # Optional convenience functions.
596 #
597 #######################################################################
598
599 #######################################################################
600 # Common Flash device geometries
601 #
602
603 FlashDevice () {
604         if [ -d ${NANO_TOOLS} ] ; then
605                 . ${NANO_TOOLS}/FlashDevice.sub
606         else
607                 . ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub
608         fi
609         sub_FlashDevice $1 $2
610 }
611
612 #######################################################################
613 # USB device geometries
614 #
615 # Usage:
616 #       UsbDevice Generic 1000  # a generic flash key sold as having 1GB
617 #
618 # This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you.
619 #
620 # Note that the capacity of a flash key is usually advertised in MB or
621 # GB, *not* MiB/GiB. As such, the precise number of cylinders available
622 # for C/H/S geometry may vary depending on the actual flash geometry.
623 #
624 # The following generic device layouts are understood:
625 #  generic           An alias for generic-hdd.
626 #  generic-hdd       255H 63S/T xxxxC with no MBR restrictions.
627 #  generic-fdd       64H 32S/T xxxxC with no MBR restrictions.
628 #
629 # The generic-hdd device is preferred for flash devices larger than 1GB.
630 #
631
632 UsbDevice () {
633         a1=`echo $1 | tr '[:upper:]' '[:lower:]'`
634         case $a1 in
635         generic-fdd)
636                 NANO_HEADS=64
637                 NANO_SECTS=32
638                 NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
639                 ;;
640         generic|generic-hdd)
641                 NANO_HEADS=255
642                 NANO_SECTS=63
643                 NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
644                 ;;
645         *)
646                 echo "Unknown USB flash device"
647                 exit 2
648                 ;;
649         esac
650 }
651
652 #######################################################################
653 # Setup serial console
654
655 cust_comconsole () (
656         # Enable getty on console
657         sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys
658
659         # Disable getty on syscons devices
660         sed -i "" -e '/^ttyv[0-8]/s/    on/     off/' ${NANO_WORLDDIR}/etc/ttys
661
662         # Tell loader to use serial console early.
663         echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config
664 )
665
666 #######################################################################
667 # Allow root login via ssh
668
669 cust_allow_ssh_root () (
670         sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \
671             ${NANO_WORLDDIR}/etc/ssh/sshd_config
672 )
673
674 #######################################################################
675 # Install the stuff under ./Files
676
677 cust_install_files () (
678         cd ${NANO_TOOLS}/Files
679         find . -print | grep -Ev '/(CVS|\.svn)' | cpio -Ldumpv ${NANO_WORLDDIR}
680 )
681
682 #######################################################################
683 # Install packages from ${NANO_PACKAGE_DIR}
684
685 cust_pkg () (
686
687         # If the package directory doesn't exist, we're done.
688         if [ ! -d ${NANO_PACKAGE_DIR} ]; then
689                 echo "DONE 0 packages"
690                 return 0
691         fi
692
693         # Copy packages into chroot
694         mkdir -p ${NANO_WORLDDIR}/Pkg
695         (
696                 cd ${NANO_PACKAGE_DIR}
697                 find ${NANO_PACKAGE_LIST} -print |
698                     cpio -Ldumpv ${NANO_WORLDDIR}/Pkg
699         )
700
701         # Count & report how many we have to install
702         todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l`
703         echo "=== TODO: $todo"
704         ls ${NANO_WORLDDIR}/Pkg
705         echo "==="
706         while true
707         do
708                 # Record how many we have now
709                 have=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
710
711                 # Attempt to install more packages
712                 # ...but no more than 200 at a time due to pkg_add's internal
713                 # limitations.
714                 chroot ${NANO_WORLDDIR} sh -c \
715                         'ls Pkg/*tbz | xargs -n 200 pkg_add -F' || true
716
717                 # See what that got us
718                 now=`ls ${NANO_WORLDDIR}/var/db/pkg | wc -l`
719                 echo "=== NOW $now"
720                 ls ${NANO_WORLDDIR}/var/db/pkg
721                 echo "==="
722
723
724                 if [ $now -eq $todo ] ; then
725                         echo "DONE $now packages"
726                         break
727                 elif [ $now -eq $have ] ; then
728                         echo "FAILED: Nothing happened on this pass"
729                         exit 2
730                 fi
731         done
732         rm -rf ${NANO_WORLDDIR}/Pkg
733 )
734
735 #######################################################################
736 # Convenience function:
737 #       Register all args as customize function.
738
739 customize_cmd () {
740         NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*"
741 }
742
743 #######################################################################
744 # Convenience function:
745 #       Register all args as late customize function to run just before
746 #       image creation.
747
748 late_customize_cmd () {
749         NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*"
750 }
751
752 #######################################################################
753 #
754 # All set up to go...
755 #
756 #######################################################################
757
758 # Progress Print
759 #       Print $2 at level $1.
760 pprint() {
761     if [ "$1" -le $PPLEVEL ]; then
762         runtime=$(( `date +%s` - $NANO_STARTTIME ))
763         printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3
764     fi
765 }
766
767 usage () {
768         (
769         echo "Usage: $0 [-bfiknqvw] [-c config_file]"
770         echo "  -b      suppress builds (both kernel and world)"
771         echo "  -f      suppress code slice extraction"
772         echo "  -i      suppress disk image build"
773         echo "  -k      suppress buildkernel"
774         echo "  -n      add -DNO_CLEAN to buildworld, buildkernel, etc"
775         echo "  -q      make output more quiet"
776         echo "  -v      make output more verbose"
777         echo "  -w      suppress buildworld"
778         echo "  -c      specify config file"
779         ) 1>&2
780         exit 2
781 }
782
783 #######################################################################
784 # Parse arguments
785
786 do_clean=true
787 do_kernel=true
788 do_world=true
789 do_image=true
790 do_copyout_partition=true
791
792 set +e
793 args=`getopt bc:fhiknqvw $*`
794 if [ $? -ne 0 ] ; then
795         usage
796         exit 2
797 fi
798 set -e
799
800 set -- $args
801 for i
802 do
803         case "$i" 
804         in
805         -b)
806                 do_world=false
807                 do_kernel=false
808                 shift
809                 ;;
810         -k)
811                 do_kernel=false
812                 shift
813                 ;;
814         -c)
815                 . "$2"
816                 shift
817                 shift
818                 ;;
819         -f)
820                 do_copyout_partition=false
821                 shift
822                 ;;
823         -h)
824                 usage
825                 ;;
826         -i)
827                 do_image=false
828                 shift
829                 ;;
830         -n)
831                 do_clean=false
832                 shift
833                 ;;
834         -q)
835                 PPLEVEL=$(($PPLEVEL - 1))
836                 shift
837                 ;;
838         -v)
839                 PPLEVEL=$(($PPLEVEL + 1))
840                 shift
841                 ;;
842         -w)
843                 do_world=false
844                 shift
845                 ;;
846         --)
847                 shift
848                 break
849         esac
850 done
851
852 if [ $# -gt 0 ] ; then
853         echo "$0: Extraneous arguments supplied"
854         usage
855 fi
856
857 #######################################################################
858 # Setup and Export Internal variables
859 #
860 test -n "${NANO_OBJ}" || NANO_OBJ=/usr/obj/nanobsd.${NANO_NAME}/
861 test -n "${MAKEOBJDIRPREFIX}" || MAKEOBJDIRPREFIX=${NANO_OBJ}
862 test -n "${NANO_DISKIMGDIR}" || NANO_DISKIMGDIR=${NANO_OBJ}
863
864 NANO_WORLDDIR=${NANO_OBJ}/_.w
865 NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build
866 NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install
867
868 if [ -d ${NANO_TOOLS} ] ; then
869         true
870 elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then
871         NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS}
872 else
873         echo "NANO_TOOLS directory does not exist" 1>&2
874         exit 1
875 fi
876
877 if $do_clean ; then
878         true
879 else
880         NANO_PMAKE="${NANO_PMAKE} -DNO_CLEAN"
881 fi
882
883 # Override user's NANO_DRIVE if they specified a NANO_LABEL
884 if [ ! -z "${NANO_LABEL}" ]; then
885         NANO_DRIVE=ufs/${NANO_LABEL}
886 fi
887
888 export MAKEOBJDIRPREFIX
889
890 export NANO_ARCH
891 export NANO_CODESIZE
892 export NANO_CONFSIZE
893 export NANO_CUSTOMIZE
894 export NANO_DATASIZE
895 export NANO_DRIVE
896 export NANO_HEADS
897 export NANO_IMAGES
898 export NANO_IMGNAME
899 export NANO_MAKE_CONF_BUILD
900 export NANO_MAKE_CONF_INSTALL
901 export NANO_MEDIASIZE
902 export NANO_NAME
903 export NANO_NEWFS
904 export NANO_OBJ
905 export NANO_PMAKE
906 export NANO_SECTS
907 export NANO_SRC
908 export NANO_TOOLS
909 export NANO_WORLDDIR
910 export NANO_BOOT0CFG
911 export NANO_BOOTLOADER
912 export NANO_LABEL
913
914 #######################################################################
915 # And then it is as simple as that...
916
917 # File descriptor 3 is used for logging output, see pprint
918 exec 3>&1
919
920 NANO_STARTTIME=`date +%s`
921 pprint 1 "NanoBSD image ${NANO_NAME} build starting"
922
923 if $do_world ; then
924         if $do_clean ; then
925                 clean_build
926         else
927                 pprint 2 "Using existing build tree (as instructed)"
928         fi
929         make_conf_build
930         build_world
931 else
932         pprint 2 "Skipping buildworld (as instructed)"
933 fi
934
935 if $do_kernel ; then
936         if ! $do_world ; then
937                 make_conf_build
938         fi
939         build_kernel
940 else
941         pprint 2 "Skipping buildkernel (as instructed)"
942 fi
943
944 clean_world
945 make_conf_install
946 install_world
947 install_etc
948 setup_nanobsd_etc
949 install_kernel
950
951 run_customize
952 setup_nanobsd
953 prune_usr
954 run_late_customize
955 if $do_image ; then
956         create_${NANO_ARCH}_diskimage
957 else
958         pprint 2 "Skipping image build (as instructed)"
959 fi
960 last_orders
961
962 pprint 1 "NanoBSD image ${NANO_NAME} completed"