xref: /src/tools/tools/nanobsd/defaults.sh (revision 4f093770b5d55e176786db27d6f99639ae42a40e)
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#
28
29set -e
30
31#######################################################################
32#
33# Setup default values for all controlling variables.
34# These values can be overridden from the config file(s)
35#
36#######################################################################
37
38# Name of this NanoBSD build.  (Used to construct workdir names)
39NANO_NAME=full
40
41# Source tree directory
42NANO_SRC=/usr/src
43
44# Where nanobsd additional files live under the source tree
45NANO_TOOLS=tools/tools/nanobsd
46
47# Where cust_pkgng() finds packages to install
48NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg
49NANO_PACKAGE_LIST="*"
50
51# where package metadata gets placed
52NANO_PKG_META_BASE=/var/db
53
54# Path to mtree file to apply to anything copied by cust_install_files().
55# If you specify this, the mtree file *must* have an entry for every file and
56# directory located in Files.
57#NANO_CUST_FILES_MTREE=""
58
59# Use the time of the last commit as a timestamp when doing a NO_PRIV build.
60NANO_TIMESTAMP=$(git log -1 --format=%ct || true)
61
62# Object tree directory
63# default is subdir of /usr/obj
64#NANO_OBJ=""
65
66# The directory to put the final images
67# default is ${NANO_OBJ}
68#NANO_DISKIMGDIR=""
69
70# Make & parallel Make
71NANO_MAKE="make"
72NANO_NCPU=$(sysctl -n hw.ncpu)
73
74# The default name for any image we create.
75NANO_IMGNAME="_.disk.full"
76NANO_IMG1NAME="_.disk.image"
77
78# Options to put in make.conf during buildworld only
79CONF_BUILD=' '
80
81# Options to put in make.conf during installworld only
82CONF_INSTALL=' '
83
84# Options to put in make.conf during both build- & installworld.
85CONF_WORLD='
86WITHOUT_DEBUG_FILES=true
87WITHOUT_LIB32=true
88WITHOUT_KERNEL_SYMBOLS=true
89WITHOUT_TESTS=true
90'
91
92# Kernel config file to use
93NANO_KERNEL=GENERIC
94
95# Kernel modules to install. If empty, no modules are installed.
96# Use "default" to install all built modules.
97NANO_MODULES=
98
99# Early customize commands.
100NANO_EARLY_CUSTOMIZE=""
101
102# Customize commands.
103NANO_CUSTOMIZE=""
104
105# Late customize commands.
106NANO_LATE_CUSTOMIZE=""
107
108# Newfs parameters to use
109NANO_NEWFS="-b 4096 -f 512 -i 8192 -U"
110NANO_MAKEFS="-o bsize=4096,density=8192,fsize=512,softupdates=1,version=2"
111
112# The drive name of the media at runtime
113NANO_DRIVE=ada0
114
115# Target media size in 512 bytes sectors
116NANO_MEDIASIZE=4000000
117
118# Number of code images on media (1 or 2)
119NANO_IMAGES=2
120
121# 0 -> Leave second image all zeroes so it compresses better.
122# 1 -> Initialize second image with a copy of the first
123NANO_INIT_IMG2=1
124
125# Size of code file system in 512 bytes sectors
126# If zero, size will be as large as possible.
127NANO_CODESIZE=0
128
129# Size of configuration file system in 512 bytes sectors
130# Cannot be zero.
131NANO_CONFSIZE=2048
132
133# Size of data file system in 512 bytes sectors
134# If zero: no partition configured.
135# If negative: max size possible
136NANO_DATASIZE=0
137
138# Size of the /etc ramdisk in 512 bytes sectors
139NANO_RAM_ETCSIZE=10240
140
141# Size of the /tmp+/var ramdisk in 512 bytes sectors
142NANO_RAM_TMPVARSIZE=10240
143
144# boot0 flags/options and configuration
145NANO_BOOT0CFG="-o packet -s 1 -m 3"
146NANO_BOOTLOADER="boot/boot0sio"
147
148# boot2 flags/options
149# default force serial console
150NANO_BOOT2CFG="-h -S115200"
151
152# Backing type of md(4) device
153# Can be "file" or "swap"
154NANO_MD_BACKING="file"
155
156# for swap type md(4) backing, write out the mbr only
157NANO_IMAGE_MBRONLY=true
158
159# Progress Print level
160PPLEVEL=3
161
162# Set NANO_LABEL to non-blank to form the basis for using /dev/ufs/label
163# in preference to /dev/${NANO_DRIVE}
164# Root partition will be ${NANO_LABEL}s{1,2}
165# /cfg partition will be ${NANO_LABEL}s3
166# /data partition will be ${NANO_LABEL}s4
167NANO_LABEL=""
168NANO_SLICE_ROOT=s1
169NANO_SLICE_ALTROOT=s2
170NANO_SLICE_CFG=s3
171NANO_SLICE_DATA=s4
172NANO_PARTITION_ROOT=a
173NANO_PARTITION_ALTROOT=a
174NANO_ROOT=s1a
175NANO_ALTROOT=s2a
176
177# Default ownership for nopriv build
178NANO_DEF_UNAME=root
179NANO_DEF_GNAME=wheel
180
181#######################################################################
182# Architecture to build.  Corresponds to TARGET_ARCH in a buildworld.
183# Unfortunately, there's no way to set TARGET at this time, and it
184# conflates the two, so architectures where TARGET != TARGET_ARCH and
185# TARGET can't be guessed from TARGET_ARCH do not work.  This defaults
186# to the arch of the current machine.
187NANO_ARCH=`uname -p`
188
189# CPUTYPE defaults to "" which is the default when CPUTYPE isn't
190# defined.
191NANO_CPUTYPE=""
192
193# Directory to populate /cfg from
194NANO_CFGDIR=""
195NANO_METALOG_CFG=""
196
197# Directory to populate /data from
198NANO_DATADIR=""
199NANO_METALOG_DATA=""
200
201# We don't need SRCCONF or SRC_ENV_CONF. NanoBSD puts everything we
202# need for the build in files included with __MAKE_CONF. Override in your
203# config file if you really must. We set them unconditionally here, though
204# in case they are stray in the build environment
205SRCCONF=/dev/null
206SRC_ENV_CONF=/dev/null
207
208# Comment this out if /usr/obj is a symlink
209# CPIO_SYMLINK=--insecure
210
211#######################################################################
212#
213# The functions which do the real work.
214# Can be overridden from the config file(s)
215#
216#######################################################################
217
218# Export values into the shell.
219# We set __MAKE_CONF as a global since it is easier to get quoting
220# right for paths with spaces in them.
221make_export() {
222	# Similar to export_var, except puts the data out to stdout
223	local var=$1
224	eval val=\$$var
225	echo "Setting variable: $var=\"$val\""
226	export $1
227}
228
229nano_make_build_env() {
230	__MAKE_CONF="${NANO_MAKE_CONF_BUILD}"
231	make_export __MAKE_CONF
232}
233
234nano_make_install_env() {
235	__MAKE_CONF="${NANO_MAKE_CONF_INSTALL}"
236	make_export __MAKE_CONF
237}
238
239# Extra environment variables for kernel builds
240nano_make_kernel_env() {
241	if [ -f "${NANO_KERNEL}" ] ; then
242		KERNCONFDIR="$(realpath $(dirname ${NANO_KERNEL}))"
243		KERNCONF="$(basename ${NANO_KERNEL})"
244		make_export KERNCONFDIR
245		make_export KERNCONF
246	else
247		export KERNCONF="${NANO_KERNEL}"
248		make_export KERNCONF
249	fi
250}
251
252nano_global_make_env() {
253	# global settings for the make.conf file, if set
254	[ -z "${NANO_ARCH}" ] || echo TARGET_ARCH="${NANO_ARCH}"
255	[ -z "${NANO_CPUTYPE}" ] || echo TARGET_CPUTYPE="${NANO_CPUTYPE}"
256}
257
258#
259# Create empty files in the target tree, and record the fact.  All paths
260# are relative to NANO_WORLDDIR.
261#
262tgt_touch() (
263	cd "${NANO_WORLDDIR}"
264	for i; do
265		touch $i
266		if [ -n "$NANO_METALOG" ]; then
267			echo "./${i} type=file" \
268			    "uname=${NANO_DEF_UNAME} gname=${NANO_DEF_GNAME}" \
269			    "mode=0644" >> "${NANO_METALOG}"
270		fi
271	done
272)
273
274#
275# Convert a directory into a symlink. Takes three arguments, the current
276# directory, what it should become a symlink to, and optionally, the mode.
277# The directory is removed and a symlink is created. If we're doing
278# a nopriv build, then append this fact to the metalog
279#
280tgt_dir2symlink() (
281	local dir=$1
282	local symlink=$2
283	local mode=${3:-0777}
284
285	cd "${NANO_WORLDDIR}"
286	rm -xrf "$dir"
287	ln -sf "$symlink" "$dir"
288	if [ -n "$NANO_METALOG" ]; then
289		echo "./${dir} type=link" \
290		    "uname=${NANO_DEF_UNAME} gname=${NANO_DEF_GNAME}" \
291		    "mode=${mode} link=${symlink}" >> ${NANO_METALOG}
292	fi
293)
294
295#
296# Create directories in the target tree, and record the fact.  All paths
297# are relative to NANO_WORLDDIR.
298#
299tgt_dir() {
300	for i; do
301		mkdir -p "${NANO_WORLDDIR}/${i}"
302
303		if [ -n "$NANO_METALOG" ]; then
304			path=""
305			for dir in $(echo "$i" | tr "/" " "); do
306				path="${path}/${dir}"
307				echo ".${path} type=dir uname=${NANO_DEF_UNAME}" \
308				    "gname=${NANO_DEF_GNAME} mode=0755" >> "${NANO_METALOG}"
309			done
310		fi
311	done
312}
313
314#
315# Switch the current root partition in the target file system tab.
316# Takes two arguments: the current, and the new partition.
317#
318tgt_switch_root_fstab()
319{
320	local current new
321	current="$1"
322	new="$2"
323
324	for f in ${NANO_WORLDDIR}/etc/fstab ${NANO_WORLDDIR}/conf/base/etc/fstab
325	do
326		sed -i "" "s=${NANO_DRIVE}${current}=${NANO_DRIVE}${new}=g" "${f}"
327	done
328}
329
330# run in the world chroot, errors fatal
331CR() {
332	chroot "${NANO_WORLDDIR}" /bin/sh -exc "$*"
333}
334
335# run in the world chroot, errors not fatal
336CR0() {
337	chroot "${NANO_WORLDDIR}" /bin/sh -c "$*" || true
338}
339
340clean_build() {
341	pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})"
342
343	if ! rm -xrf ${MAKEOBJDIRPREFIX}/ > /dev/null 2>&1 ; then
344		chflags -R noschg ${MAKEOBJDIRPREFIX}/
345		rm -xr ${MAKEOBJDIRPREFIX}/
346	fi
347}
348
349make_conf_build() {
350	pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)"
351
352	mkdir -p ${MAKEOBJDIRPREFIX}
353	printenv > ${MAKEOBJDIRPREFIX}/_.env
354
355	# Make sure we get all the global settings that NanoBSD wants
356	# in addition to the user's global settings
357	(
358	nano_global_make_env
359	echo "${CONF_WORLD}"
360	echo "${CONF_BUILD}"
361	if [ -n "${NANO_NOPRIV_BUILD}" ]; then
362		echo NO_ROOT=true
363		echo METALOG="${NANO_METALOG}"
364	fi
365	) > ${NANO_MAKE_CONF_BUILD}
366}
367
368build_world() {
369	pprint 2 "run buildworld"
370	pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw"
371
372	(
373	nano_make_build_env
374	set -o xtrace
375	cd "${NANO_SRC}"
376	${NANO_PMAKE} buildworld
377	) > ${MAKEOBJDIRPREFIX}/_.bw 2>&1
378}
379
380build_kernel() {
381	pprint 2 "build kernel ($NANO_KERNEL)"
382	pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk"
383
384	(
385	nano_make_build_env
386	nano_make_kernel_env
387
388	# Note: We intentionally build all modules, not only the ones in
389	# NANO_MODULES so the built world can be reused by multiple images.
390	# Although MODULES_OVERRIDE can be defined in the kernel config
391	# file to override this behavior. Just set NANO_MODULES=default.
392	set -o xtrace
393	cd "${NANO_SRC}"
394	${NANO_PMAKE} buildkernel
395	) > ${MAKEOBJDIRPREFIX}/_.bk 2>&1
396}
397
398clean_world() {
399	if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then
400		pprint 2 "Clean and create object directory (${NANO_OBJ})"
401		if ! rm -xrf ${NANO_OBJ}/ > /dev/null 2>&1 ; then
402			chflags -R noschg ${NANO_OBJ}
403			rm -xr ${NANO_OBJ}/
404		fi
405		mkdir -p "${NANO_OBJ}" "${NANO_WORLDDIR}"
406		printenv > ${NANO_LOG}/_.env
407	else
408		pprint 2 "Clean and create world directory (${NANO_WORLDDIR})"
409		if ! rm -xrf "${NANO_WORLDDIR}/" > /dev/null 2>&1 ; then
410			chflags -R noschg "${NANO_WORLDDIR}"
411			rm -xrf "${NANO_WORLDDIR}/"
412		fi
413		mkdir -p "${NANO_WORLDDIR}"
414	fi
415}
416
417make_conf_install() {
418	pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)"
419
420	# Make sure we get all the global settings that NanoBSD wants
421	# in addition to the user's global settings
422	(
423	nano_global_make_env
424	echo "${CONF_WORLD}"
425	echo "${CONF_INSTALL}"
426	if [ -n "${NANO_NOPRIV_BUILD}" ]; then
427	    echo NO_ROOT=t
428	    echo METALOG=${NANO_METALOG}
429	fi
430	) >  ${NANO_MAKE_CONF_INSTALL}
431}
432
433install_world() {
434	pprint 2 "installworld"
435	pprint 3 "log: ${NANO_LOG}/_.iw"
436
437	(
438	nano_make_install_env
439	set -o xtrace
440	cd "${NANO_SRC}"
441	${NANO_MAKE} installworld DESTDIR="${NANO_WORLDDIR}" DB_FROM_SRC=yes
442	chflags -R noschg "${NANO_WORLDDIR}"
443	) > ${NANO_LOG}/_.iw 2>&1
444}
445
446install_etc() {
447	pprint 2 "install /etc"
448	pprint 3 "log: ${NANO_LOG}/_.etc"
449
450	(
451	nano_make_install_env
452	set -o xtrace
453	cd "${NANO_SRC}"
454	${NANO_MAKE} distribution DESTDIR="${NANO_WORLDDIR}" DB_FROM_SRC=yes
455	# make.conf doesn't get created by default, but some ports need it
456	# so they can spam it.
457	cp /dev/null "${NANO_WORLDDIR}"/etc/make.conf
458	) > ${NANO_LOG}/_.etc 2>&1
459}
460
461install_kernel() {
462	pprint 2 "install kernel ($NANO_KERNEL)"
463	pprint 3 "log: ${NANO_LOG}/_.ik"
464
465	(
466
467	nano_make_install_env
468	nano_make_kernel_env
469
470	if [ "${NANO_MODULES}" != "default" ]; then
471		MODULES_OVERRIDE="${NANO_MODULES}"
472		make_export MODULES_OVERRIDE
473	fi
474
475	set -o xtrace
476	cd "${NANO_SRC}"
477	${NANO_MAKE} installkernel DESTDIR="${NANO_WORLDDIR}" DB_FROM_SRC=yes
478
479	) > ${NANO_LOG}/_.ik 2>&1
480}
481
482native_xtools() {
483	pprint 2 "Installing the optimized native build tools for cross env"
484	pprint 3 "log: ${NANO_LOG}/_.native_xtools"
485
486	(
487
488	nano_make_install_env
489	set -o xtrace
490	cd "${NANO_SRC}"
491	${NANO_MAKE} native-xtools
492	${NANO_MAKE} native-xtools-install DESTDIR="${NANO_WORLDDIR}"
493
494	) > ${NANO_LOG}/_.native_xtools 2>&1
495}
496
497#
498# Run the requested set of early customization scripts, run before
499# buildworld.
500#
501run_early_customize() {
502	pprint 2 "run early customize scripts"
503	for c in $NANO_EARLY_CUSTOMIZE
504	do
505		pprint 2 "early customize \"$c\""
506		pprint 3 "log: ${NANO_LOG}/_.early_cust.$c"
507		pprint 4 "`type $c`"
508		{ t=$(set -o | awk '$1 == "xtrace" && $2 == "off" { print "set +o xtrace"}');
509		  set -o xtrace ;
510		  $c ;
511		  eval $t
512		} >${NANO_LOG}/_.early_cust.$c 2>&1
513	done
514}
515
516#
517# Run the requested set of customization scripts, run after we've
518# done an installworld, installed the etc files, installed the kernel
519# and tweaked them in the standard way.
520#
521run_customize() {
522
523	pprint 2 "run customize scripts"
524	for c in $NANO_CUSTOMIZE
525	do
526		pprint 2 "customize \"$c\""
527		pprint 3 "log: ${NANO_LOG}/_.cust.$c"
528		pprint 4 "`type $c`"
529		( set -o xtrace ; $c ) > ${NANO_LOG}/_.cust.$c 2>&1
530	done
531}
532
533#
534# Run any last-minute customization commands after we've had a chance to
535# setup nanobsd, prune empty dirs from /usr, etc
536#
537run_late_customize() {
538	pprint 2 "run late customize scripts"
539	for c in $NANO_LATE_CUSTOMIZE
540	do
541		pprint 2 "late customize \"$c\""
542		pprint 3 "log: ${NANO_LOG}/_.late_cust.$c"
543		pprint 4 "`type $c`"
544		( set -o xtrace ; $c ) > ${NANO_LOG}/_.late_cust.$c 2>&1
545	done
546}
547
548#
549# Hook called after we run all the late customize commands, but
550# before we invoke the disk imager. The nopriv build uses it to
551# read in the meta log, apply the changes other parts of nanobsd
552# have been recording their actions. It's not anticipated that
553# a user's cfg file would override this.
554#
555fixup_before_diskimage() {
556	# Run the deduplication script that takes the metalog journal and
557	# combines multiple entries for the same file (see source for details).
558	# We take the extra step of removing the size and time keywords. This
559	# script, and many of the user scripts, copies, appends and otherwise
560	# modifies files in the build, changing their sizes.  These actions are
561	# impossible to trap, so go ahead remove the size= keyword. For this
562	# narrow use, it doesn't buy us any protection and just gets in the way.
563	# The dedup tool's output must be sorted due to limitations in awk.
564	if [ -n "${NANO_METALOG}" ]; then
565		pprint 2 "Fixing metalog"
566		cp ${NANO_METALOG} ${NANO_METALOG}.pre
567		echo "/set uname=${NANO_DEF_UNAME} gname=${NANO_DEF_GNAME}" > ${NANO_METALOG}
568		cat ${NANO_METALOG}.pre | ${NANO_TOOLS}/mtree-dedup.awk | \
569		    sort -u | mtree -C -K uname,gname,tags -R size,time >> ${NANO_METALOG}
570	fi
571}
572
573setup_nanobsd() {
574	pprint 2 "configure nanobsd setup"
575	pprint 3 "log: ${NANO_LOG}/_.dl"
576
577	(
578	cd "${NANO_WORLDDIR}"
579
580	# Move /usr/local/etc to /etc/local so that the /cfg stuff
581	# can stomp on it.  Otherwise packages like ipsec-tools which
582	# have hardcoded paths under ${prefix}/etc are not tweakable.
583	if [ -d usr/local/etc ] ; then
584		(
585		cd usr/local/etc
586		find . -print | cpio ${CPIO_SYMLINK} -dumpl ../../../etc/local
587		cd ..
588		rm -xrf etc
589		)
590	fi
591
592	# Always setup the usr/local/etc -> etc/local symlink.
593	# usr/local/etc gets created by packages, but if no packages
594	# are installed by this point, but are later in the process,
595	# the symlink not being here causes problems. It never hurts
596	# to have the symlink in error though.
597	tgt_dir2symlink usr/local/etc ../../etc/local 0755
598
599	for d in var etc
600	do
601		# link /$d under /conf
602		# we use hard links so we have them both places.
603		# the files in /$d will be hidden by the mount.
604		tgt_dir conf/base/$d conf/default/$d
605		find $d -print | cpio ${CPIO_SYMLINK} -dumpl conf/base/
606		if [ -n "$NANO_METALOG" ]; then
607			grep "^.\/${d}\/" "${NANO_METALOG}" |
608			    sed -e "s=^./${d}=./conf/base/${d}=g" |
609			    sort | uniq >> "${NANO_METALOG}.conf"
610		fi
611	done
612
613	if [ -n "$NANO_METALOG" ]; then
614		cat "${NANO_METALOG}.conf" >> "${NANO_METALOG}"
615		rm -f "${NANO_METALOG}.conf"
616	fi
617
618	echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size
619	echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size
620	tgt_touch conf/base/etc/md_size
621	tgt_touch conf/base/var/md_size
622
623	# pick up config files from the special partition
624	echo "mount -o ro /dev/${NANO_DRIVE}${NANO_SLICE_CFG}" > conf/default/etc/remount
625	tgt_touch conf/default/etc/remount
626
627	# Put /tmp on the /var ramdisk (could be symlink already)
628	tgt_dir2symlink tmp var/tmp 1777
629
630	) > ${NANO_LOG}/_.dl 2>&1
631}
632
633setup_nanobsd_etc() {
634	pprint 2 "configure nanobsd /etc"
635
636	(
637	cd "${NANO_WORLDDIR}"
638
639	# create diskless marker file
640	tgt_touch etc/diskless
641
642	[ -n "${NANO_NOPRIV_BUILD}" ] && chmod 666 boot/defaults/loader.conf
643	{
644		echo
645		echo '###  NanoBSD configuration  ##################################'
646		echo 'hostuuid_load="NO"'
647		echo 'entropy_cache_load="NO"		# Disable loading cached entropy at boot time.'
648		echo 'kern.random.initial_seeding.disable_bypass_warnings="1"	# Do not log a warning'
649		echo "				# if the 'bypass_before_seeding' knob is enabled"
650		echo "				# and a request is submitted prior to initial"
651		echo "				# seeding."
652	} >> boot/defaults/loader.conf
653	[ -n "${NANO_NOPRIV_BUILD}" ] && chmod 444 boot/defaults/loader.conf
654
655	[ -n "${NANO_NOPRIV_BUILD}" ] && chmod 666 etc/defaults/rc.conf
656	if ! ed -s etc/defaults/rc.conf <<\EOF
657/^### Define source_rc_confs, the mechanism used by \/etc\/rc\.\* ##$/i
658###  NanoBSD options  ########################################
659##############################################################
660
661kldxref_enable="NO"	# Disable building linker.hints files with kldxref(8).
662root_rw_mount="NO"	# Inhibit remounting root read-write.
663entropy_boot_file="NO"	# Disable very early (used at early boot time)
664			# entropy caching through reboots.
665entropy_file="NO"	# Disable late (used when going multi-user)
666			# entropy through reboots.
667entropy_dir="NO"	# Disable caching entropy via cron.
668
669##############################################################
670.
671w
672q
673EOF
674	then
675		echo "Regular expression pattern not found"
676		exit 2
677	fi
678	[ -n "${NANO_NOPRIV_BUILD}" ] && chmod 444 etc/defaults/rc.conf
679
680	# save config file for scripts
681	echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
682	tgt_touch etc/nanobsd.conf
683
684	echo "/dev/${NANO_DRIVE}${NANO_ROOT} / ufs ro 1 1" > etc/fstab
685	echo "/dev/${NANO_DRIVE}${NANO_SLICE_CFG} /cfg ufs rw,noauto 2 2" >> etc/fstab
686	tgt_touch etc/fstab
687	tgt_dir cfg
688
689	# Create directory for eventual /usr/local/etc contents
690	tgt_dir etc/local
691	)
692}
693
694prune_usr() {
695	# Remove all empty directories in /usr
696	find "${NANO_WORLDDIR}"/usr -type d -depth -print |
697		while read d
698		do
699			rmdir $d > /dev/null 2>&1 || true
700		done
701}
702
703newfs_part() {
704	local dev mnt lbl
705	dev=$1
706	mnt=$2
707	lbl=$3
708	echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev}
709	newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev}
710	mount -o async ${dev} ${mnt}
711}
712
713nano_makefs() {
714	local dir image metalog options size
715	options=$1
716	metalog=$2
717	size=$3
718	image=$4
719	dir=$5
720
721	makefs ${options} -F "${metalog}" -N "${NANO_WORLDDIR}/etc" \
722	    -s "${size}b" -T "${NANO_TIMESTAMP}" -t ffs "${image}" "${dir}"
723}
724
725# Convenient spot to work around any umount issues that your build environment
726# hits by overriding this method.
727nano_umount() {
728	umount ${1}
729}
730
731populate_slice() {
732	local dev dir mnt lbl
733	dev=$1
734	dir=$2
735	mnt=$3
736	lbl=$4
737	echo "Creating ${dev} (mounting on ${mnt})"
738	newfs_part ${dev} ${mnt} ${lbl}
739	if [ -n "${dir}" -a -d "${dir}" ]; then
740		echo "Populating ${lbl} from ${dir}"
741		cd "${dir}"
742		find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)/' | cpio ${CPIO_SYMLINK} -dumpv ${mnt}
743	fi
744	df -i ${mnt}
745	nano_umount ${mnt}
746}
747
748_populate_part() {
749	local dir fs lbl metalog size type
750	type=$1
751	fs=$2
752	dir=$3
753	lbl=$4
754	size=$5
755	metalog=$6
756
757	echo "Creating ${fs}"
758
759	# Use the directory provided, otherwise create an empty one temporarily.
760	if [ -n "${dir}" ] && [ -d "${dir}" ]; then
761		echo "Populating ${lbl} from ${dir}"
762	else
763		if [ "${type}" = "cfg" ]; then
764			dir=$(mktemp -d -p "${NANO_OBJ}" -t "${type}")
765			trap "rm -rf ${dir}" 1 2 15 EXIT
766		fi
767	fi
768
769	if [ -d "${dir}" ]; then
770		# If there is no metalog, create one using the default
771		# NANO_DEF_UNAME and NANO_DEF_GNAME for all entries in the spec.
772		if [ -z "${metalog}" ]; then
773			metalog="${NANO_METALOG}.${type}"
774			echo "/set type=dir uname=${NANO_DEF_UNAME}" \
775			    "gname=${NANO_DEF_GNAME} mode=0755" > "${metalog}"
776			echo ". type=dir uname=${NANO_DEF_UNAME}" \
777			    "gname=${NANO_DEF_GNAME} mode=0755" >> "${metalog}"
778			(
779				cd "${dir}"
780				mtree -bc -k flags,gid,gname,link,mode,uid,uname |
781				    mtree -C | tail -n +2 |
782				    sed "s/uid=[[:digit:]]*/uname=${NANO_DEF_UNAME}/g" |
783				    sed "s/gid=[[:digit:]]*/gname=${NANO_DEF_GNAME}/g" >> "${metalog}"
784			)
785		fi
786
787		nano_makefs "-DxZ ${NANO_MAKEFS}" "${metalog}" "${size}" "${fs}" "${dir}"
788	fi
789}
790
791populate_cfg_slice() {
792	populate_slice "$1" "$2" "$3" "$4"
793}
794
795_populate_cfg_part() {
796	_populate_part "cfg" "$1" "$2" "$3" "$4" "$5"
797}
798
799populate_data_slice() {
800	populate_slice "$1" "$2" "$3" "$4"
801}
802
803_populate_data_part() {
804	_populate_part "data" "$1" "$2" "$3" "$4" "$5"
805}
806
807last_orders() {
808	# Redefine this function with any last orders you may have
809	# after the build completed, for instance to copy the finished
810	# image to a more convenient place:
811	# cp ${NANO_DISKIMGDIR}/${NANO_IMG1NAME} /home/ftp/pub/nanobsd.disk
812	true
813}
814
815#######################################################################
816#
817# Optional convenience functions.
818#
819#######################################################################
820
821#######################################################################
822# Common Flash device geometries
823#
824
825FlashDevice() {
826	if [ -d ${NANO_TOOLS} ] ; then
827		. ${NANO_TOOLS}/FlashDevice.sub
828	else
829		. ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub
830	fi
831	sub_FlashDevice $1 $2
832}
833
834#######################################################################
835# USB device geometries
836#
837# Usage:
838#	UsbDevice Generic 1000	# a generic flash key sold as having 1GB
839#
840# This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you.
841#
842# Note that the capacity of a flash key is usually advertised in MB or
843# GB, *not* MiB/GiB. As such, the precise number of cylinders available
844# for C/H/S geometry may vary depending on the actual flash geometry.
845#
846# The following generic device layouts are understood:
847#  generic           An alias for generic-hdd.
848#  generic-hdd       255H 63S/T xxxxC with no MBR restrictions.
849#  generic-fdd       64H 32S/T xxxxC with no MBR restrictions.
850#
851# The generic-hdd device is preferred for flash devices larger than 1GB.
852#
853
854UsbDevice() {
855	local a1=`echo $1 | tr '[:upper:]' '[:lower:]'`
856	case $a1 in
857	generic-fdd)
858		NANO_HEADS=64
859		NANO_SECTS=32
860		NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
861		;;
862	generic|generic-hdd)
863		NANO_HEADS=255
864		NANO_SECTS=63
865		NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 ))
866		;;
867	*)
868		echo "Unknown USB flash device"
869		exit 2
870		;;
871	esac
872}
873
874#######################################################################
875# Setup serial console
876
877cust_comconsole() {
878	# Enable getty on console
879	sed -i "" -e '/^tty[du]0/s/off/onifconsole/' ${NANO_WORLDDIR}/etc/ttys
880
881	# Disable getty on syscons or vt devices
882	sed -i "" -E '/^ttyv[0-8]/s/\ton(ifexists)?/\toff/' ${NANO_WORLDDIR}/etc/ttys
883
884	# Tell loader to use serial console early.
885	echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config
886}
887
888#######################################################################
889# Allow root login via ssh
890
891cust_allow_ssh_root() {
892	sed -i "" -E 's/^#?PermitRootLogin.*/PermitRootLogin yes/' \
893	    ${NANO_WORLDDIR}/etc/ssh/sshd_config
894}
895
896#######################################################################
897# Install the stuff under ./Files
898
899cust_install_files() (
900	cd "${NANO_TOOLS}/Files"
901	find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)/' | cpio ${CPIO_SYMLINK} -Ldumpv ${NANO_WORLDDIR}
902
903	if [ -n "${NANO_CUST_FILES_MTREE}" -a -f ${NANO_CUST_FILES_MTREE} ]; then
904		CR "mtree -eiU -p /" <${NANO_CUST_FILES_MTREE}
905	fi
906
907	tgt_touch $(find * -type f)
908)
909
910#######################################################################
911# Install packages from ${NANO_PACKAGE_DIR}
912
913cust_pkgng() {
914	mkdir -p ${NANO_WORLDDIR}/usr/local/etc
915	local PKG_CONF="${NANO_WORLDDIR}/usr/local/etc/pkg.conf"
916	local PKGCMD="env BATCH=YES ASSUME_ALWAYS_YES=YES PKG_DBDIR=${NANO_PKG_META_BASE}/pkg SIGNATURE_TYPE=none /usr/sbin/pkg"
917
918	# Ensure pkg.conf points pkg to where the package meta data lives.
919	touch ${PKG_CONF}
920	if grep -Eiq '^PKG_DBDIR:.*' ${PKG_CONF}; then
921		sed -i -e "\|^PKG_DBDIR:.*|Is||PKG_DBDIR: "\"${NANO_PKG_META_BASE}/pkg\""|" ${PKG_CONF}
922	else
923		echo "PKG_DBDIR: \"${NANO_PKG_META_BASE}/pkg\"" >> ${PKG_CONF}
924	fi
925
926	# If the package directory doesn't exist, we're done.
927	NANO_PACKAGE_DIR="$(realpath $NANO_PACKAGE_DIR)"
928	if [ ! -d ${NANO_PACKAGE_DIR} ]; then
929		echo "DONE 0 packages"
930		return 0
931	fi
932
933	# Find a pkg-* package
934	for x in `find -s ${NANO_PACKAGE_DIR} -iname 'pkg-*'`; do
935		_NANO_PKG_PACKAGE=`basename "$x"`
936	done
937	if [ -z "${_NANO_PKG_PACKAGE}" -o ! -f "${NANO_PACKAGE_DIR}/${_NANO_PKG_PACKAGE}" ]; then
938		echo "FAILED: need a pkg/ package for bootstrapping"
939		exit 2
940	fi
941
942	# Mount packages into chroot
943	mkdir -p ${NANO_WORLDDIR}/_.p
944	mount -t nullfs -o noatime -o ro ${NANO_PACKAGE_DIR} ${NANO_WORLDDIR}/_.p
945	mount -t devfs devfs ${NANO_WORLDDIR}/dev
946
947	trap "nano_umount ${NANO_WORLDDIR}/dev; nano_umount ${NANO_WORLDDIR}/_.p ; rm -xrf ${NANO_WORLDDIR}/_.p" 1 2 15 EXIT
948
949	# Install pkg-* package
950	CR "${PKGCMD} add /_.p/${_NANO_PKG_PACKAGE}"
951
952	(
953		# Expand any glob characters in package list
954		cd "${NANO_PACKAGE_DIR}"
955		_PKGS=`find ${NANO_PACKAGE_LIST} -not -name "${_NANO_PKG_PACKAGE}" -print | sort | uniq`
956
957		# Show todo
958		todo=`echo "$_PKGS" | wc -l`
959		echo "=== TODO: $todo"
960		echo "$_PKGS"
961		echo "==="
962
963		# Install packages
964		for _PKG in $_PKGS; do
965			CR "${PKGCMD} add /_.p/${_PKG}"
966		done
967	)
968
969	CR0 "${PKGCMD} info"
970
971	trap - 1 2 15 EXIT
972	nano_umount ${NANO_WORLDDIR}/dev
973	nano_umount ${NANO_WORLDDIR}/_.p
974	rm -xrf ${NANO_WORLDDIR}/_.p
975}
976
977#######################################################################
978# Convenience function:
979#	Register all args as early customize function to run just before
980#	build commences.
981
982early_customize_cmd() {
983	NANO_EARLY_CUSTOMIZE="$NANO_EARLY_CUSTOMIZE $*"
984}
985
986#######################################################################
987# Convenience function:
988# 	Register all args as customize function.
989
990customize_cmd() {
991	NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*"
992}
993
994#######################################################################
995# Convenience function:
996# 	Register all args as late customize function to run just before
997#	image creation.
998
999late_customize_cmd() {
1000	NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*"
1001}
1002
1003#######################################################################
1004#
1005# All set up to go...
1006#
1007#######################################################################
1008
1009# Progress Print
1010#	Print $2 at level $1.
1011pprint() {
1012    if [ "$1" -le $PPLEVEL ]; then
1013	runtime=$(( `date +%s` - $NANO_STARTTIME ))
1014	printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3
1015    fi
1016}
1017
1018usage() {
1019	(
1020	echo "Usage: $0 [-BbfhIiKknpqUvWwX] [-c config_file]"
1021	echo "	-B	suppress installs (both kernel and world)"
1022	echo "	-b	suppress builds (both kernel and world)"
1023	echo "	-c	specify config file"
1024	echo "	-f	suppress code slice extraction (implies -i)"
1025	echo "	-h	print this help summary page"
1026	echo "	-I	build disk image from existing build/install"
1027	echo "	-i	suppress disk image build"
1028	echo "	-K	suppress installkernel"
1029	echo "	-k	suppress buildkernel"
1030	echo "	-n	add -DNO_CLEAN to buildworld, buildkernel, etc"
1031	echo "	-p	suppress preparing the image"
1032	echo "	-q	make output more quiet"
1033	echo "	-U	add -DNO_ROOT to build without root privileges"
1034	echo "	-v	make output more verbose"
1035	echo "	-W	suppress installworld"
1036	echo "	-w	suppress buildworld"
1037	echo "	-X	make native-xtools"
1038	) 1>&2
1039	exit 2
1040}
1041
1042#######################################################################
1043# Setup and Export Internal variables
1044#
1045
1046export_var() {
1047	var=$1
1048	# Lookup value of the variable.
1049	eval val=\$$var
1050	pprint 3 "Setting variable: $var=\"$val\""
1051	export $1
1052}
1053
1054# Call this function to set defaults _after_ parsing options.
1055set_defaults_and_export() {
1056	: ${NANO_OBJ:=/usr/obj/nanobsd.${NANO_NAME}${NANO_LAYOUT:+.${NANO_LAYOUT}}}
1057	: ${MAKEOBJDIRPREFIX:=${NANO_OBJ}}
1058	: ${NANO_DISKIMGDIR:=${NANO_OBJ}}
1059	: ${NANO_WORLDDIR:=${NANO_OBJ}/_.w}
1060	: ${NANO_LOG:=${NANO_OBJ}}
1061	: ${NANO_PMAKE:="${NANO_MAKE} -j ${NANO_NCPU}"}
1062	if ! $do_clean; then
1063		NANO_PMAKE="${NANO_PMAKE} -DNO_CLEAN"
1064	fi
1065	if ! $do_root; then
1066		NANO_PMAKE="${NANO_PMAKE} -DNO_ROOT"
1067	fi
1068	NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build
1069	NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install
1070
1071	# Override user's NANO_DRIVE if they specified a NANO_LABEL
1072	[ -n "${NANO_LABEL}" ] && NANO_DRIVE="ufs/${NANO_LABEL}" || true
1073
1074	# Set a default NANO_TOOLS to NANO_SRC/NANO_TOOLS if it exists.
1075	[ ! -d "${NANO_TOOLS}" ] && [ -d "${NANO_SRC}/${NANO_TOOLS}" ] && \
1076		NANO_TOOLS="${NANO_SRC}/${NANO_TOOLS}" || true
1077
1078	if [ -n "${NANO_NOPRIV_BUILD}" ] && [ -z "${NANO_METALOG}" ]; then
1079		NANO_METALOG=${NANO_OBJ}/_.metalog
1080	fi
1081
1082	NANO_STARTTIME=`date +%s`
1083	: ${NANO_TIMESTAMP:=${NANO_STARTTIME}}
1084	pprint 3 "Exporting NanoBSD variables"
1085	export_var MAKEOBJDIRPREFIX
1086	export_var NANO_ARCH
1087	export_var NANO_CODESIZE
1088	export_var NANO_CONFSIZE
1089	export_var NANO_CUSTOMIZE
1090	export_var NANO_DATASIZE
1091	export_var NANO_DRIVE
1092	export_var NANO_HEADS
1093	export_var NANO_IMAGES
1094	export_var NANO_IMGNAME
1095	export_var NANO_IMG1NAME
1096	export_var NANO_MAKE
1097	export_var NANO_MAKEFS
1098	export_var NANO_MAKE_CONF_BUILD
1099	export_var NANO_MAKE_CONF_INSTALL
1100	export_var NANO_MEDIASIZE
1101	export_var NANO_NAME
1102	export_var NANO_NCPU
1103	export_var NANO_NEWFS
1104	export_var NANO_OBJ
1105	export_var NANO_PMAKE
1106	export_var NANO_SECTS
1107	export_var NANO_SRC
1108	export_var NANO_TIMESTAMP
1109	export_var NANO_TOOLS
1110	export_var NANO_WORLDDIR
1111	export_var NANO_BOOT0CFG
1112	export_var NANO_BOOTLOADER
1113	export_var NANO_LABEL
1114	export_var NANO_MODULES
1115	export_var NANO_NOPRIV_BUILD
1116	export_var NANO_METALOG
1117	export_var NANO_LOG
1118	export_var SRCCONF
1119	export_var SRC_ENV_CONF
1120}
1121