nanobsd.sh revision 150343
1#!/bin/sh
2# Copyright (c) 2005 Poul-Henning Kamp.
3#
4# See /usr/share/examples/etc/bsd-style-copyright for license terms.
5#
6# $FreeBSD: head/tools/tools/nanobsd/nanobsd.sh 150343 2005-09-19 20:55:44Z phk $
7#
8
9set -e
10
11# Name of this NanoBSD build.  (Used to construct workdir names)
12NANO_NAME=full
13
14# Source tree directory
15NANO_SRC=/usr/src
16
17# Object tree directory
18# default is subdir of /usr/obj
19# XXX: MAKEOBJDIRPREFIX handling... ?
20#NANO_OBJ=""
21
22# Parallel Make
23NANO_PMAKE="make -j 3"
24
25# Options to put in make.conf during buildworld only
26CONF_BUILD=' '
27
28# Options to put in make.conf during installworld only
29CONF_INSTALL=' '
30
31# Options to put in make.conf during both build- & installworld.
32CONF_WORLD=' '
33
34# Kernel config file to use
35NANO_KERNEL=GENERIC
36
37# Customize commands.
38NANO_CUSTOMIZE=""
39
40# Newfs paramters to use
41NANO_NEWFS="-b 4096 -f 512 -i 8192 -O1 -U"
42
43# The drive name of the media at runtime
44NANO_DRIVE=ad0
45
46# Target media size in 512 bytes sectors
47NANO_MEDIASIZE=1048576
48
49# Number of code images on media (1 or 2)
50NANO_IMAGES=2
51
52# Size of code file system in 512 bytes sectors
53# If zero, size will be as large as possible.
54NANO_CODESIZE=0
55
56# Size of configuration file system in 512 bytes sectors
57# Cannot be zero.
58NANO_CONFSIZE=2048
59
60# Size of data file system in 512 bytes sectors
61# If zero: no partition configured.
62# If negative: max size possible
63NANO_DATASIZE=0
64
65# Media geometry, only relevant if bios doesn't understand LBA.
66NANO_SECTS=32
67NANO_HEADS=16
68
69#######################################################################
70# Not a variable at this time
71
72NANO_ARCH=i386
73
74#######################################################################
75# Functions which can be overridden in configs.
76
77clean_build ( ) (
78	echo "## Clean and create object directory (${MAKEOBJDIRPREFIX})"
79
80	if rm -rf ${MAKEOBJDIRPREFIX} > /dev/null 2>&1 ; then
81		true
82	else
83		chflags -R noschg ${MAKEOBJDIRPREFIX}
84		rm -rf ${MAKEOBJDIRPREFIX}
85	fi
86	mkdir -p ${MAKEOBJDIRPREFIX}
87	printenv > ${MAKEOBJDIRPREFIX}/_.env
88)
89
90make_conf_build ( ) (
91	echo "## Construct build make.conf ($NANO_MAKE_CONF)"
92
93	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF}
94	echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF}
95)
96
97build_world ( ) (
98	echo "## run buildworld"
99	echo "### log: ${MAKEOBJDIRPREFIX}/_.bw"
100
101	cd ${NANO_SRC}
102	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} buildworld \
103		> ${MAKEOBJDIRPREFIX}/_.bw 2>&1
104)
105
106build_kernel ( ) (
107	echo "## build kernel ($NANO_KERNEL)"
108	echo "### log: ${MAKEOBJDIRPREFIX}/_.bk"
109
110	if [ -f ${NANO_KERNEL} ] ; then
111		cp ${NANO_KERNEL} ${NANO_SRC}/sys/${NANO_ARCH}/conf
112	fi
113
114	cd ${NANO_SRC}
115	${NANO_PMAKE} buildkernel \
116		__MAKE_CONF=${NANO_MAKE_CONF} KERNCONF=${NANO_KERNEL} \
117		> ${MAKEOBJDIRPREFIX}/_.bk 2>&1
118)
119
120clean_world ( ) (
121	echo "## Clean and create world directory (${NANO_WORLDDIR})"
122	if rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then
123		true
124	else
125		chflags -R noschg ${NANO_WORLDDIR}/
126		rm -rf ${NANO_WORLDDIR}/
127	fi
128	mkdir -p ${NANO_WORLDDIR}/
129)
130
131make_conf_install ( ) (
132	echo "## Construct install make.conf ($NANO_MAKE_CONF)"
133
134	echo "${CONF_WORLD}" > ${NANO_MAKE_CONF}
135	echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF}
136)
137
138install_world ( ) (
139	echo "## installworld"
140	echo "### log: ${MAKEOBJDIRPREFIX}/_.iw"
141
142	cd ${NANO_SRC}
143	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} installworld \
144		DESTDIR=${NANO_WORLDDIR} \
145		> ${MAKEOBJDIRPREFIX}/_.iw 2>&1
146	chflags -R noschg ${NANO_WORLDDIR}
147)
148
149install_etc ( ) (
150
151	echo "## install /etc"
152	echo "### log: ${MAKEOBJDIRPREFIX}/_.etc"
153
154	cd ${NANO_SRC}/etc
155	${NANO_PMAKE} __MAKE_CONF=${NANO_MAKE_CONF} distribution \
156		DESTDIR=${NANO_WORLDDIR} \
157		> ${MAKEOBJDIRPREFIX}/_.etc 2>&1
158)
159
160install_kernel ( ) (
161	echo "## install kernel"
162	echo "### log: ${MAKEOBJDIRPREFIX}/_.ik"
163
164	cd ${NANO_SRC}
165	${NANO_PMAKE} installkernel \
166		DESTDIR=${NANO_WORLDDIR} \
167		__MAKE_CONF=${NANO_MAKE_CONF} KERNCONF=${NANO_KERNEL} \
168		> ${MAKEOBJDIRPREFIX}/_.ik 2>&1
169)
170
171setup_diskless ( ) (
172	echo "## configure diskless setup"
173	echo "### log: ${MAKEOBJDIRPREFIX}/_.dl"
174
175	(
176	cd ${NANO_WORLDDIR}
177
178	# create diskless marker file
179	touch etc/diskless
180
181	echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab
182
183	for d in var etc
184	do
185		# link /$d under /conf
186		# we use hard links so we have them both places.
187		# the files in /$d will be hidden by the mount.
188		# XXX: configure /$d ramdisk size
189		mkdir -p conf/base/$d conf/default/$d
190		find $d -print | cpio -dumpl conf/base/
191	done
192
193	# pick up config files from the special partition
194	echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount
195
196	# Put /tmp on the /var ramdisk (could be symlink already)
197	rmdir tmp || true
198	rm tmp || true
199	ln -s var/tmp tmp
200
201	) > ${MAKEOBJDIRPREFIX}/_.dl 2>&1
202)
203
204run_customize() (
205
206	echo "## run customize scripts"
207	for c in $NANO_CUSTOMIZE
208	do
209		echo "## customize \"$c\""
210		echo "### log: ${MAKEOBJDIRPREFIX}/_.cust.$c"
211		echo "### `type $c`"
212		( $c ) 2>&1 | tee ${MAKEOBJDIRPREFIX}/_.cust.$c
213	done
214)
215
216prune_usr() (
217
218	# Remove all empty directories in /usr 
219	find ${NANO_WORLDDIR}/usr -type d -depth -print |
220		while read d
221		do
222			rmdir $d > /dev/null 2>&1 || true 
223		done
224)
225
226create_i386_diskimage ( ) (
227	echo "## build diskimage"
228	echo "### log: ${MAKEOBJDIRPREFIX}/_.di"
229
230	(
231	echo $NANO_MEDIASIZE $NANO_IMAGES \
232		$NANO_SECTS $NANO_HEADS \
233		$NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE |
234	awk '
235		{
236		printf "# %s\n", $0
237
238		# size of cylinder in sectors
239		cs = $3 * $4
240
241		# number of full cylinders on media
242		cyl = int ($1 / cs)
243
244		# output fdisk geometry spec, truncate cyls to 1023
245		if (cyl <= 1023)
246			print "g c" cyl " h" $4 " s" $3
247		else
248			print "g c" 1023 " h" $4 " s" $3
249
250		if ($7 > 0) { 
251			# size of data partition in full cylinders
252			dsl = int (($7 + cs - 1) / cs)
253		} else {
254			dsl = 0;
255		}
256
257		# size of config partition in full cylinders
258		csl = int (($6 + cs - 1) / cs)
259
260		if ($3 == 5) {
261			# size of image partition(s) in full cylinders
262			isl = int ((cyl - dsl - csl) / $2)
263		} else {
264			isl = int (($5 + cs - 1) / cs)
265		}
266
267		# First image partition start at second track
268		print "p 1 165 " $3, isl * cs - $3
269		c = isl * cs;
270
271		# Second image partition (if any) also starts offset one 
272		# track to keep them identical.
273		if ($2 > 1) {
274			print "p 2 165 " $3 + c, isl * cs - $3
275			c += isl * cs;
276		}
277
278		# Config partition starts at cylinder boundary.
279		print "p 3 165 " c, csl * cs
280		c += csl * cs
281
282		# Data partition (if any) starts at cylinder boundary.
283		if ($7 > 0) {
284			print "p 4 165 " c, dsl * cs
285		} else if ($7 < 0 && $1 > $c) {
286			print "p 4 165 " c, $1 - $c
287		}
288		}
289	' > ${MAKEOBJDIRPREFIX}/_.fdisk
290
291	IMG=${MAKEOBJDIRPREFIX}/_.disk.full
292	MNT=${MAKEOBJDIRPREFIX}/_.mnt
293	mkdir -p ${MNT}
294
295	dd if=/dev/zero of=${IMG} bs=${NANO_SECTS}b \
296	    count=`expr ${NANO_MEDIASIZE} / ${NANO_SECTS}`
297
298	MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} -y ${NANO_HEADS}`
299
300	trap "df -i ${MNT} ; umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
301
302	fdisk -i -f ${MAKEOBJDIRPREFIX}/_.fdisk ${MD}
303	fdisk ${MD}
304	# XXX: params
305	# XXX: pick up cached boot* files, they may not be in image anymore.
306	boot0cfg -B -b ${NANO_WORLDDIR}/boot/boot0sio -o packet -s 1 -m 3 ${MD}
307	bsdlabel -w -B ${MD}s1
308	bsdlabel ${MD}s1
309
310	# Create first image
311	newfs ${NANO_NEWFS} /dev/${MD}s1a
312	mount /dev/${MD}s1a ${MNT}
313	df -i ${MNT}
314	( cd ${NANO_WORLDDIR} && find . -print | cpio -dump ${MNT} )
315	df -i ${MNT}
316	( cd ${MNT} && mtree -c ) > ${MAKEOBJDIRPREFIX}/_.mtree
317	( cd ${MNT} && du -k ) > ${MAKEOBJDIRPREFIX}/_.du
318	umount ${MNT}
319
320	if [ $NANO_IMAGES -gt 1 ] ; then
321		# Duplicate to second image (if present)
322		dd if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k
323	fi
324	
325	# Create Config slice
326	newfs ${NANO_NEWFS} /dev/${MD}s3
327	# XXX: fill from where ?
328
329	# Create Data slice, if any.
330	if [ $NANO_DATASIZE -gt 0 ] ; then
331		newfs ${NANO_NEWFS} /dev/${MD}s4
332		# XXX: fill from where ?
333	fi
334
335	dd if=/dev/${MD}s1 of=${MAKEOBJDIRPREFIX}/_.disk.image bs=64k
336	mdconfig -d -u $MD
337	) > ${MAKEOBJDIRPREFIX}/_.di 2>&1
338)
339
340
341#######################################################################
342#
343# Heavy wizardry ahead, no user serviceable parts below.
344#
345#######################################################################
346
347#######################################################################
348
349customize_cmd () {
350	NANO_CUSTOMIZE="$NANO_CUSTOMIZE $1"
351}
352
353#######################################################################
354# Parse arguments
355
356args=`getopt c: $*`
357if [ $? -ne 0 ] ; then
358	echo "Usage: $0 [-c config file]" 1>&2
359	exit 2
360fi
361
362set -- $args
363for i
364do
365	case "$i" 
366	in
367	-c)
368		. "$2"
369		shift;
370		shift;
371		;;
372	--)
373		shift;
374		break;
375	esac
376done
377
378#######################################################################
379# Internal variables
380if [ "x${NANO_OBJ}" = "x" ] ; then
381	MAKEOBJDIRPREFIX=/usr/obj/nanobsd.${NANO_NAME}/
382	NANO_OBJ=${MAKEOBJDIRPREFIX}
383else
384	MAKEOBJDIRPREFIX=${NANO_OBJ}
385fi
386
387NANO_WORLDDIR=${MAKEOBJDIRPREFIX}/_.w
388NANO_MAKE_CONF=${MAKEOBJDIRPREFIX}/make.conf
389
390#######################################################################
391#
392export MAKEOBJDIRPREFIX
393
394export NANO_ARCH
395export NANO_CODESIZE
396export NANO_CONFSIZE
397export NANO_CUSTOMIZE
398export NANO_DATASIZE
399export NANO_DRIVE
400export NANO_HEADS
401export NANO_IMAGES
402export NANO_MAKE_CONF
403export NANO_MEDIASIZE
404export NANO_NAME
405export NANO_NEWFS
406export NANO_OBJ
407export NANO_PMAKE
408export NANO_SECTS
409export NANO_SRC
410export NANO_WORLDDIR
411
412#######################################################################
413# As simple as that...
414
415clean_build
416make_conf_build
417build_world
418build_kernel
419
420clean_world
421make_conf_install
422install_world
423install_etc
424install_kernel
425
426run_customize
427setup_diskless
428prune_usr
429create_${NANO_ARCH}_diskimage
430
431echo "# NanoBSD image completed"
432