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