nanobsd.sh revision 150511
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: head/tools/tools/nanobsd/nanobsd.sh 150511 2005-09-24 12:26:59Z simon $
28#
29
30set -e
31
32#######################################################################
33#
34# Setup default values for all controlling variables.
35# These values can be overridden from the config file(s)
36#
37#######################################################################
38
39# Name of this NanoBSD build.  (Used to construct workdir names)
40NANO_NAME=full
41
42# Source tree directory
43NANO_SRC=/usr/src
44
45# Where nanobsd additional files live under the source tree
46NANO_TOOLS=tools/tools/nanobsd
47
48# Object tree directory
49# default is subdir of /usr/obj
50# XXX: MAKEOBJDIRPREFIX handling... ?
51#NANO_OBJ=""
52
53# Parallel Make
54NANO_PMAKE="make -j 3"
55
56# Options to put in make.conf during buildworld only
57CONF_BUILD=' '
58
59# Options to put in make.conf during installworld only
60CONF_INSTALL=' '
61
62# Options to put in make.conf during both build- & installworld.
63CONF_WORLD=' '
64
65# Kernel config file to use
66NANO_KERNEL=GENERIC
67
68# Customize commands.
69NANO_CUSTOMIZE=""
70
71# Newfs paramters to use
72NANO_NEWFS="-b 4096 -f 512 -i 8192 -O1 -U"
73
74# The drive name of the media at runtime
75NANO_DRIVE=ad0
76
77# Target media size in 512 bytes sectors
78NANO_MEDIASIZE=1048576
79
80# Number of code images on media (1 or 2)
81NANO_IMAGES=2
82
83# Size of code file system in 512 bytes sectors
84# If zero, size will be as large as possible.
85NANO_CODESIZE=0
86
87# Size of configuration file system in 512 bytes sectors
88# Cannot be zero.
89NANO_CONFSIZE=2048
90
91# Size of data file system in 512 bytes sectors
92# If zero: no partition configured.
93# If negative: max size possible
94NANO_DATASIZE=0
95
96# Media geometry, only relevant if bios doesn't understand LBA.
97NANO_SECTS=32
98NANO_HEADS=16
99
100#######################################################################
101# Not a variable at this time
102
103NANO_ARCH=i386
104
105#######################################################################
106#
107# The functions which do the real work.
108# Can be overridden from the config file(s)
109#
110#######################################################################
111
112clean_build ( ) (
113	echo "## Clean and create object directory (${MAKEOBJDIRPREFIX})"
114
115	if rm -rf ${MAKEOBJDIRPREFIX} > /dev/null 2>&1 ; then
116		true
117	else
118		chflags -R noschg ${MAKEOBJDIRPREFIX}
119		rm -rf ${MAKEOBJDIRPREFIX}
120	fi
121	mkdir -p ${MAKEOBJDIRPREFIX}
122	printenv > ${MAKEOBJDIRPREFIX}/_.env
123)
124
125make_conf_build ( ) (
126	echo "## Construct build make.conf ($NANO_MAKE_CONF)"
127
128	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF}
129	echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF}
130)
131
132build_world ( ) (
133	echo "## run buildworld"
134	echo "### log: ${MAKEOBJDIRPREFIX}/_.bw"
135
136	cd ${NANO_SRC}
137	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} buildworld \
138		> ${MAKEOBJDIRPREFIX}/_.bw 2>&1
139)
140
141build_kernel ( ) (
142	echo "## build kernel ($NANO_KERNEL)"
143	echo "### log: ${MAKEOBJDIRPREFIX}/_.bk"
144
145	if [ -f ${NANO_KERNEL} ] ; then
146		cp ${NANO_KERNEL} ${NANO_SRC}/sys/${NANO_ARCH}/conf
147	fi
148
149	cd ${NANO_SRC}
150	${NANO_PMAKE} buildkernel \
151		__MAKE_CONF=${NANO_MAKE_CONF} KERNCONF=${NANO_KERNEL} \
152		> ${MAKEOBJDIRPREFIX}/_.bk 2>&1
153)
154
155clean_world ( ) (
156	echo "## Clean and create world directory (${NANO_WORLDDIR})"
157	if rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then
158		true
159	else
160		chflags -R noschg ${NANO_WORLDDIR}/
161		rm -rf ${NANO_WORLDDIR}/
162	fi
163	mkdir -p ${NANO_WORLDDIR}/
164)
165
166make_conf_install ( ) (
167	echo "## Construct install make.conf ($NANO_MAKE_CONF)"
168
169	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF}
170	echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF}
171)
172
173install_world ( ) (
174	echo "## installworld"
175	echo "### log: ${MAKEOBJDIRPREFIX}/_.iw"
176
177	cd ${NANO_SRC}
178	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} installworld \
179		DESTDIR=${NANO_WORLDDIR} \
180		> ${MAKEOBJDIRPREFIX}/_.iw 2>&1
181	chflags -R noschg ${NANO_WORLDDIR}
182)
183
184install_etc ( ) (
185
186	echo "## install /etc"
187	echo "### log: ${MAKEOBJDIRPREFIX}/_.etc"
188
189	cd ${NANO_SRC}/etc
190	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} distribution \
191		DESTDIR=${NANO_WORLDDIR} \
192		> ${MAKEOBJDIRPREFIX}/_.etc 2>&1
193)
194
195install_kernel ( ) (
196	echo "## install kernel"
197	echo "### log: ${MAKEOBJDIRPREFIX}/_.ik"
198
199	cd ${NANO_SRC}
200	${NANO_PMAKE} installkernel \
201		DESTDIR=${NANO_WORLDDIR} \
202		__MAKE_CONF=${NANO_MAKE_CONF} KERNCONF=${NANO_KERNEL} \
203		> ${MAKEOBJDIRPREFIX}/_.ik 2>&1
204)
205
206run_customize() (
207
208	echo "## run customize scripts"
209	for c in $NANO_CUSTOMIZE
210	do
211		echo "## customize \"$c\""
212		echo "### log: ${MAKEOBJDIRPREFIX}/_.cust.$c"
213		echo "### `type $c`"
214		( $c ) > ${MAKEOBJDIRPREFIX}/_.cust.$c 2>&1
215	done
216)
217
218setup_nanobsd ( ) (
219	echo "## configure nanobsd setup"
220	echo "### log: ${MAKEOBJDIRPREFIX}/_.dl"
221
222	(
223	cd ${NANO_WORLDDIR}
224
225	# create diskless marker file
226	touch etc/diskless
227
228	# save config file for scripts
229	echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
230
231	echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab
232	echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab
233	mkdir -p cfg
234
235	for d in var etc
236	do
237		# link /$d under /conf
238		# we use hard links so we have them both places.
239		# the files in /$d will be hidden by the mount.
240		# XXX: configure /$d ramdisk size
241		mkdir -p conf/base/$d conf/default/$d
242		find $d -print | cpio -dumpl conf/base/
243	done
244
245	# pick up config files from the special partition
246	echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount
247
248	# Put /tmp on the /var ramdisk (could be symlink already)
249	rmdir tmp || true
250	rm tmp || true
251	ln -s var/tmp tmp
252
253	) > ${MAKEOBJDIRPREFIX}/_.dl 2>&1
254)
255
256prune_usr() (
257
258	# Remove all empty directories in /usr 
259	find ${NANO_WORLDDIR}/usr -type d -depth -print |
260		while read d
261		do
262			rmdir $d > /dev/null 2>&1 || true 
263		done
264)
265
266create_i386_diskimage ( ) (
267	echo "## build diskimage"
268	echo "### log: ${MAKEOBJDIRPREFIX}/_.di"
269
270	(
271	echo $NANO_MEDIASIZE $NANO_IMAGES \
272		$NANO_SECTS $NANO_HEADS \
273		$NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE |
274	awk '
275		{
276		printf "# %s\n", $0
277
278		# size of cylinder in sectors
279		cs = $3 * $4
280
281		# number of full cylinders on media
282		cyl = int ($1 / cs)
283
284		# output fdisk geometry spec, truncate cyls to 1023
285		if (cyl <= 1023)
286			print "g c" cyl " h" $4 " s" $3
287		else
288			print "g c" 1023 " h" $4 " s" $3
289
290		if ($7 > 0) { 
291			# size of data partition in full cylinders
292			dsl = int (($7 + cs - 1) / cs)
293		} else {
294			dsl = 0;
295		}
296
297		# size of config partition in full cylinders
298		csl = int (($6 + cs - 1) / cs)
299
300		if ($3 == 5) {
301			# size of image partition(s) in full cylinders
302			isl = int ((cyl - dsl - csl) / $2)
303		} else {
304			isl = int (($5 + cs - 1) / cs)
305		}
306
307		# First image partition start at second track
308		print "p 1 165 " $3, isl * cs - $3
309		c = isl * cs;
310
311		# Second image partition (if any) also starts offset one 
312		# track to keep them identical.
313		if ($2 > 1) {
314			print "p 2 165 " $3 + c, isl * cs - $3
315			c += isl * cs;
316		}
317
318		# Config partition starts at cylinder boundary.
319		print "p 3 165 " c, csl * cs
320		c += csl * cs
321
322		# Data partition (if any) starts at cylinder boundary.
323		if ($7 > 0) {
324			print "p 4 165 " c, dsl * cs
325		} else if ($7 < 0 && $1 > $c) {
326			print "p 4 165 " c, $1 - $c
327		}
328		}
329	' > ${MAKEOBJDIRPREFIX}/_.fdisk
330
331	IMG=${MAKEOBJDIRPREFIX}/_.disk.full
332	MNT=${MAKEOBJDIRPREFIX}/_.mnt
333	mkdir -p ${MNT}
334
335	dd if=/dev/zero of=${IMG} bs=${NANO_SECTS}b \
336	    count=`expr ${NANO_MEDIASIZE} / ${NANO_SECTS}`
337
338	MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} -y ${NANO_HEADS}`
339
340	trap "df -i ${MNT} ; umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
341
342	fdisk -i -f ${MAKEOBJDIRPREFIX}/_.fdisk ${MD}
343	fdisk ${MD}
344	# XXX: params
345	# XXX: pick up cached boot* files, they may not be in image anymore.
346	boot0cfg -B -b ${NANO_WORLDDIR}/boot/boot0sio -o packet -s 1 -m 3 ${MD}
347	bsdlabel -w -B ${MD}s1
348	bsdlabel ${MD}s1
349
350	# Create first image
351	newfs ${NANO_NEWFS} /dev/${MD}s1a
352	mount /dev/${MD}s1a ${MNT}
353	df -i ${MNT}
354	( cd ${NANO_WORLDDIR} && find . -print | cpio -dump ${MNT} )
355	df -i ${MNT}
356	( cd ${MNT} && mtree -c ) > ${MAKEOBJDIRPREFIX}/_.mtree
357	( cd ${MNT} && du -k ) > ${MAKEOBJDIRPREFIX}/_.du
358	umount ${MNT}
359
360	if [ $NANO_IMAGES -gt 1 ] ; then
361		# Duplicate to second image (if present)
362		dd if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k
363	fi
364	
365	# Create Config slice
366	newfs ${NANO_NEWFS} /dev/${MD}s3
367	# XXX: fill from where ?
368
369	# Create Data slice, if any.
370	if [ $NANO_DATASIZE -gt 0 ] ; then
371		newfs ${NANO_NEWFS} /dev/${MD}s4
372		# XXX: fill from where ?
373	fi
374
375	dd if=/dev/${MD}s1 of=${MAKEOBJDIRPREFIX}/_.disk.image bs=64k
376	mdconfig -d -u $MD
377	) > ${MAKEOBJDIRPREFIX}/_.di 2>&1
378)
379
380#######################################################################
381#
382# Optional convenience functions.
383#
384#######################################################################
385
386#######################################################################
387# Common Flash device geometries
388#
389
390FlashDevice () {
391	. ${NANO_TOOLS}/FlashDevice.sub
392	sub_FlashDevice $1 $2
393}
394
395
396#######################################################################
397# Setup serial console
398
399cust_comconsole () (
400	# Enable getty on console
401	sed -i "" -e /ttyd0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys
402
403	# Disable getty on syscons devices
404	sed -i "" -e '/^ttyv[0-8]/s/	on/	off/' ${NANO_WORLDDIR}/etc/ttys
405
406	# Tell loader to use serial console early.
407	echo " -h" > ${NANO_WORLDDIR}/boot.config
408)
409
410#######################################################################
411# Allow root login via ssh
412
413cust_allow_ssh_root () (
414	sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \
415	    ${NANO_WORLDDIR}/etc/ssh/sshd_config
416)
417
418#######################################################################
419# Install the stuff under ./Files
420
421cust_install_files () (
422	cd ${NANO_TOOLS}/Files
423	find . -print | grep -v /CVS | cpio -dumpv ${NANO_WORLDDIR}
424)
425
426#######################################################################
427# Convenience function:
428# 	Register $1 as customize function.
429
430customize_cmd () {
431	NANO_CUSTOMIZE="$NANO_CUSTOMIZE $1"
432}
433
434#######################################################################
435#
436# All set up to go...
437#
438#######################################################################
439
440#######################################################################
441# Parse arguments
442
443do_build=true
444
445args=`getopt bc:h $*`
446if [ $? -ne 0 ] ; then
447	echo "Usage: $0 [-c config file]" 1>&2
448	exit 2
449fi
450
451set -- $args
452for i
453do
454	case "$i" 
455	in
456	-b)
457		shift;
458		do_build=false
459		;;
460	-c)
461		. "$2"
462		shift;
463		shift;
464		;;
465	-h)
466		echo "Usage: $0 [-b] [-c config file]"
467		exit 2
468		;;
469	--)
470		shift;
471		break;
472	esac
473done
474
475if [ $# -gt 0 ] ; then
476	echo "Extraneous arguments"
477	exit 2
478fi
479
480#######################################################################
481# Setup and Export Internal variables
482#
483if [ "x${NANO_OBJ}" = "x" ] ; then
484	MAKEOBJDIRPREFIX=/usr/obj/nanobsd.${NANO_NAME}/
485	NANO_OBJ=${MAKEOBJDIRPREFIX}
486else
487	MAKEOBJDIRPREFIX=${NANO_OBJ}
488fi
489
490NANO_WORLDDIR=${MAKEOBJDIRPREFIX}/_.w
491NANO_MAKE_CONF=${MAKEOBJDIRPREFIX}/make.conf
492
493if [ -d ${NANO_TOOLS} ] ; then
494	true
495elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then
496	NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS}
497else
498	echo "NANO_TOOLS directory does not exist" 1>&2
499	exit 1
500fi
501
502export MAKEOBJDIRPREFIX
503
504export NANO_ARCH
505export NANO_CODESIZE
506export NANO_CONFSIZE
507export NANO_CUSTOMIZE
508export NANO_DATASIZE
509export NANO_DRIVE
510export NANO_HEADS
511export NANO_IMAGES
512export NANO_MAKE_CONF
513export NANO_MEDIASIZE
514export NANO_NAME
515export NANO_NEWFS
516export NANO_OBJ
517export NANO_PMAKE
518export NANO_SECTS
519export NANO_SRC
520export NANO_TOOLS
521export NANO_WORLDDIR
522
523#######################################################################
524# And then it is as simple as that...
525
526if $do_build ; then
527	clean_build
528	make_conf_build
529	build_world
530	build_kernel
531else
532	echo "## Skipping build steps (as instructed)"
533fi
534
535clean_world
536make_conf_install
537install_world
538install_etc
539install_kernel
540
541run_customize
542setup_nanobsd
543prune_usr
544create_${NANO_ARCH}_diskimage
545
546echo "# NanoBSD image completed"
547