xref: /src/tools/tools/nanobsd/legacy.sh (revision eced166af01565fb1d6278a8918e844ebc4412a6)
1#!/bin/sh
2#
3# Copyright (c) 2005 Poul-Henning Kamp All rights reserved.
4# Copyright (c) 2016 M. Warner Losh <imp@FreeBSD.org>
5#
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28#
29
30# Media geometry, only relevant if bios doesn't understand LBA.
31[ -n "$NANO_SECTS" ] || NANO_SECTS=63
32[ -n "$NANO_HEADS" ] || NANO_HEADS=16
33
34# Functions and variable definitions used by the legacy nanobsd
35# image building system.
36
37calculate_partitioning() {
38	echo $NANO_MEDIASIZE $NANO_IMAGES \
39		$NANO_SECTS $NANO_HEADS \
40		$NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE |
41	awk '
42	{
43		# size of cylinder in sectors
44		cs = $3 * $4
45
46		# number of full cylinders on media
47		cyl = int ($1 / cs)
48
49		if ($7 > 0) {
50			# size of data partition in full cylinders
51			dsl = int (($7 + cs - 1) / cs)
52		} else {
53			dsl = 0;
54		}
55
56		# size of config partition in full cylinders
57		csl = int (($6 + cs - 1) / cs)
58
59		# size of image partition(s) in full cylinders
60		if ($5 == 0) {
61			isl = int ((cyl - dsl - csl) / $2)
62		} else {
63			isl = int (($5 + cs - 1) / cs)
64		}
65
66		# First image partition start at second track
67		print $3, isl * cs - $3, 1
68		c = isl * cs;
69
70		# Second image partition (if any) also starts offset one
71		# track to keep them identical.
72		if ($2 > 1) {
73			print $3 + c, isl * cs - $3, 2
74			c += isl * cs;
75		}
76
77		# Config partition starts at cylinder boundary.
78		print c, csl * cs, 3
79		c += csl * cs
80
81		# Data partition (if any) starts at cylinder boundary.
82		if ($7 > 0) {
83			print c, dsl * cs, 4
84		} else if ($7 < 0 && $1 > c) {
85			print c, $1 - c, 4
86		} else if ($1 < c) {
87			print "Disk space overcommitted by", \
88			    c - $1, "sectors" > "/dev/stderr"
89			exit 2
90		}
91	}
92	' > ${NANO_LOG}/_.partitioning
93}
94
95_xxx_adjust_code_size()
96{
97	# XXX adjust the CODE_SIZE value by rounding it up to
98	# a bsize of 32768 (DFL_BLKSIZE).
99	# Otherwise makefs -s will fail because of the guard
100	# introduced in 5ad283b3c60d.
101	codesize=$1
102	bsize=32768
103	echo $(( ((codesize + (bsize - 1)) / bsize) * bsize ))
104}
105
106create_code_slice() {
107	pprint 2 "build code slice"
108	pprint 3 "log: ${NANO_OBJ}/_.cs"
109
110	(
111	IMG=${NANO_DISKIMGDIR}/_.disk.image
112	MNT=${NANO_OBJ}/_.mnt
113	mkdir -p ${MNT}
114	CODE_SIZE=`head -n 1 ${NANO_LOG}/_.partitioning | awk '{ print $2 }'`
115
116	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
117		MD=`mdconfig -a -t swap -s ${CODE_SIZE} -x ${NANO_SECTS} \
118			-y ${NANO_HEADS}`
119	else
120		echo "Creating md backing file..."
121		rm -f ${IMG}
122		dd if=/dev/zero of=${IMG} seek=${CODE_SIZE} count=0
123		MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \
124			-y ${NANO_HEADS}`
125	fi
126
127	trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
128
129	gpart create -s bsd "${MD}"
130	gpart add -t freebsd-ufs -b 16 "${MD}"
131	if [ -f ${NANO_WORLDDIR}/boot/boot ]; then
132	    echo "Making bootable partition"
133	    gpart bootcode -b ${NANO_WORLDDIR}/boot/boot ${MD}
134	else
135	    echo "Partition will not be bootable"
136	fi
137	gpart list ${MD}
138
139	# Create first image
140	populate_slice /dev/${MD}${NANO_PARTITION_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}"
141	mount /dev/${MD}a ${MNT}
142	echo "Generating mtree..."
143	( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree
144	( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du
145	nano_umount ${MNT}
146
147	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
148		echo "Writing out _.disk.image..."
149		dd conv=sparse if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.image bs=64k
150	fi
151	mdconfig -d -u $MD
152
153	trap - 1 2 15 EXIT
154
155	) > ${NANO_OBJ}/_.cs 2>&1
156}
157
158_create_code_slice() {
159	pprint 2 "build code slice"
160	pprint 3 "log: ${NANO_OBJ}/_.cs"
161
162	(
163	IMG=${NANO_DISKIMGDIR}/_.disk.image
164	CODE_SIZE=$(head -n 1 "${NANO_LOG}/_.partitioning" | awk '{ print $2 }')
165	CODE_SIZE=$(_xxx_adjust_code_size "$CODE_SIZE")
166
167	echo "Writing code image..."
168	if [ -f "${NANO_WORLDDIR}/boot/boot" ]; then
169		echo "Making bootable partition"
170		bootcode="-b ${NANO_WORLDDIR}/boot/boot"
171	else
172		echo "Partition will not be bootable"
173	fi
174	nano_makefs "-DxZ ${NANO_MAKEFS} -o minfree=0,optimization=space" \
175	    "${NANO_METALOG}" "${CODE_SIZE}" "${NANO_OBJ}/_.disk.part" \
176	    "${NANO_WORLDDIR}"
177	mkimg -s bsd \
178	    ${bootcode} \
179	    -p freebsd-ufs:="${NANO_OBJ}/_.disk.part" \
180	    -o "${NANO_DISKIMGDIR}/_.disk.image"
181	rm -f "${NANO_OBJ}/_.disk.part"
182
183	) > ${NANO_OBJ}/_.cs 2>&1
184}
185
186create_diskimage() {
187	pprint 2 "build diskimage"
188	pprint 3 "log: ${NANO_OBJ}/_.di"
189
190	(
191
192	IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME}
193	MNT=${NANO_OBJ}/_.mnt
194	mkdir -p ${MNT}
195
196	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
197		MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \
198			-y ${NANO_HEADS}`
199	else
200		echo "Creating md backing file..."
201		rm -f ${IMG}
202		dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0
203		MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \
204			-y ${NANO_HEADS}`
205	fi
206
207	awk '
208	BEGIN {
209		# Create MBR partition table
210		print "gpart create -s mbr $1"
211	}
212	{
213		# Make partition
214		print "gpart add -t freebsd -b ", $1, " -s ", $2, " -i ", $3, " $1"
215	}
216	END {
217		# Force slice 1 to be marked active. This is necessary
218		# for booting the image from a USB device to work.
219		print "gpart set -a active -i 1 $1"
220	}
221	' ${NANO_LOG}/_.partitioning > ${NANO_OBJ}/_.gpart
222
223	trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT
224
225	sh ${NANO_OBJ}/_.gpart ${MD}
226	gpart show ${MD}
227	# XXX: params
228	# XXX: pick up cached boot* files, they may not be in image anymore.
229	if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then
230		gpart bootcode -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOTFLAGS} ${MD}
231	fi
232
233	echo "Writing code image..."
234	dd conv=sparse if=${NANO_DISKIMGDIR}/_.disk.image of=/dev/${MD}${NANO_SLICE_ROOT} bs=64k
235
236	if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then
237		# Duplicate to second image (if present)
238		echo "Duplicating to second image..."
239		dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k
240		mount /dev/${MD}${NANO_ALTROOT} ${MNT}
241		for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab
242		do
243			sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f
244		done
245		nano_umount ${MNT}
246		# Override the label from the first partition so we
247		# don't confuse glabel with duplicates.
248		if [ -n "${NANO_LABEL}" ]; then
249			tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT}
250		fi
251	fi
252
253	# Create Config slice
254	populate_cfg_slice /dev/${MD}${NANO_SLICE_CFG} "${NANO_CFGDIR}" ${MNT} "${NANO_SLICE_CFG}"
255
256	# Create Data slice, if any.
257	if [ -n "$NANO_SLICE_DATA" -a "$NANO_SLICE_CFG" = "$NANO_SLICE_DATA" -a \
258	   "$NANO_DATASIZE" -ne 0 ]; then
259		pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix."
260		exit 2
261	fi
262	if [ $NANO_DATASIZE -ne 0 -a -n "$NANO_SLICE_DATA" ] ; then
263		populate_data_slice /dev/${MD}${NANO_SLICE_DATA} "${NANO_DATADIR}" ${MNT} "${NANO_SLICE_DATA}"
264	fi
265
266	if [ "${NANO_MD_BACKING}" = "swap" ] ; then
267		if [ ${NANO_IMAGE_MBRONLY} ]; then
268			echo "Writing out _.disk.mbr..."
269			dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1
270		else
271			echo "Writing out ${NANO_IMGNAME}..."
272			dd if=/dev/${MD} of=${IMG} bs=64k
273		fi
274
275		echo "Writing out ${NANO_IMGNAME}..."
276		dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k
277	fi
278
279	mdconfig -d -u $MD
280
281	trap - 1 2 15 EXIT
282
283	) > ${NANO_LOG}/_.di 2>&1
284}
285
286_create_diskimage() {
287	pprint 2 "build diskimage"
288	pprint 3 "log: ${NANO_OBJ}/_.di"
289
290	(
291	local altroot bootloader cfgimage dataimage diskimage
292
293	CODE_SIZE=$(head -n 1 "${NANO_LOG}/_.partitioning" | awk '{ print $2 }')
294	CODE_SIZE=$(_xxx_adjust_code_size "$CODE_SIZE")
295	IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME}
296
297	if [ -f "${NANO_WORLDDIR}/${NANO_BOOTLOADER}" ]; then
298		bootloader="-b ${NANO_WORLDDIR}/${NANO_BOOTLOADER}"
299	else
300		echo "Image will not be bootable"
301	fi
302
303	diskimage="-p freebsd:=${NANO_DISKIMGDIR}/_.disk.image"
304
305	if [ "$NANO_IMAGES" -gt 1 ] && [ "$NANO_INIT_IMG2" -gt 0 ] ; then
306		echo "Duplicating to second image..."
307		tgt_switch_root_fstab "${NANO_SLICE_ROOT}" "${NANO_SLICE_ALTROOT}"
308		nano_makefs "-DxZ ${NANO_MAKEFS} -o minfree=0,optimization=space" \
309		    "${NANO_METALOG}" "${CODE_SIZE}" "${NANO_OBJ}/_.altroot.part" \
310		    "${NANO_WORLDDIR}"
311		tgt_switch_root_fstab "${NANO_SLICE_ALTROOT}" "${NANO_SLICE_ROOT}"
312		if [ -f "${NANO_WORLDDIR}/boot/boot" ]; then
313			bootcode="-b ${NANO_WORLDDIR}/boot/boot"
314		fi
315		mkimg -s bsd \
316		    ${bootcode} \
317		    -p freebsd-ufs:="${NANO_OBJ}/_.altroot.part" \
318		    -o "${NANO_OBJ}/_.altroot.image"
319		altroot="-p freebsd:=${NANO_OBJ}/_.altroot.image"
320		rm -f "${NANO_OBJ}/_.altroot.part"
321	else
322		altroot="-p-"
323	fi
324	if [ "${NANO_INIT_IMG2}" -eq 0 ]; then
325		altroot="-p freebsd::${CODE_SIZE}b"
326	fi
327
328	# Create Config slice
329	_populate_cfg_part "${NANO_OBJ}/_.cfg.part" "${NANO_CFGDIR}" \
330	    "${NANO_SLICE_CFG}" "${NANO_CONFSIZE}" "${NANO_METALOG_CFG}"
331	cfgimage="-p freebsd:=${NANO_OBJ}/_.cfg.part"
332
333	# Create Data slice, if any.
334	if [ -n "${NANO_SLICE_DATA}" ] &&
335	    [ "${NANO_SLICE_CFG}" = "${NANO_SLICE_DATA}" ] &&
336	    [ "${NANO_DATASIZE}" -ne 0 ]; then
337		pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix."
338		exit 2
339	fi
340	if [ "${NANO_DATASIZE}" -ne 0 ] && [ -n "${NANO_SLICE_DATA}" ] ; then
341		_populate_data_part "${NANO_OBJ}/_.data.part" "${NANO_DATADIR}" \
342		    "${NANO_SLICE_DATA}" "${NANO_DATASIZE}" "${NANO_METALOG_DATA}"
343		dataimage="-p freebsd:=${NANO_OBJ}/_.data.part"
344	fi
345
346	echo "Writing out ${NANO_IMGNAME}..."
347	mkimg -s mbr \
348	    ${bootloader} \
349	    ${diskimage} \
350	    ${altroot} \
351	    ${cfgimage} \
352	    ${dataimage} \
353	    -o ${IMG}
354	exit
355
356	) > ${NANO_LOG}/_.di 2>&1
357}
358