1#!/bin/ksh -p
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26# ident	"%Z%%M%	%I%	%E% SMI"
27
28# utility to pack and unpack a boot/root archive
29# both ufs and hsfs (iso9660) format archives are unpacked
30# only ufs archives are generated
31#
32# usage: pack   <archive> <root>
33#        unpack <archive> <root>
34#        packmedia   <solaris_image> <root>
35#        unpackmedia <solaris_image> <root>
36#
37#   Where <root> is the directory to unpack to and will be cleaned out
38#   if it exists.
39#
40#   In the case of (un)packmedia, the image is packed or unpacked to/from
41#   Solaris media and all the things that don't go into the ramdisk image
42#   are (un)cpio'd as well
43#
44# This utility is also used to pack parts (in essence the window system,
45# usr/dt and usr/openwin) of the non ramdisk SPARC
46# miniroot. (un)packmedia will recognize that they are being run a SPARC
47# miniroot and do the appropriate work.
48#
49
50usage()
51{
52	printf "usage: root_archive pack <archive> <root>\n"
53	printf "       root_archive unpack <archive> <root>\n"
54	printf "       root_archive packmedia   <solaris_image> <root>\n"
55	printf "       root_archive unpackmedia <solaris_image> <root>\n"
56}
57
58cleanup()
59{
60	if [ -d $MNT ] ; then
61		umount $MNT 2> /dev/null
62		rmdir $MNT
63	fi
64
65	lofiadm -d "$TMR" 2>/dev/null
66	rm -f "$TMR" "$TMR.gz"
67}
68
69archive_X()
70{
71	MEDIA="$1"
72	MINIROOT="$2"
73
74	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
75	RELEASE=`basename "$RELEASE"`
76
77	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
78		CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra"
79		mkdir -p "$CPIO_DIR"
80	else
81		CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
82	fi
83
84	# create the graphics and non-graphics X archive
85	#
86	(
87		cd "$MINIROOT/usr"
88		find openwin dt X11 -print 2> /dev/null |\
89		    cpio -ocmPuB 2> /dev/null | bzip2 > "$CPIO_DIR/X.cpio.bz2"
90
91		find openwin/bin/mkfontdir \
92		     openwin/lib/installalias \
93		     openwin/server/lib/libfont.so.1 \
94		     openwin/server/lib/libtypesclr.so.0 \
95			 -print | cpio -ocmPuB 2> /dev/null | bzip2 > \
96			 "$CPIO_DIR/X_small.cpio.bz2"
97
98		rm -rf dt openwin X11
99		ln -s ../tmp/root/usr/dt
100		ln -s ../tmp/root/usr/openwin
101		ln -s ../tmp/root/usr/X11
102	)
103}
104
105packmedia()
106{
107	MEDIA="$1"
108	MINIROOT="$2"
109
110	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
111	RELEASE=`basename "$RELEASE"`
112
113	mkdir -p "$MEDIA/$RELEASE/Tools/Boot"
114	mkdir -p "$MEDIA/boot/platform/i86pc/kernel"
115
116	# archive package databases to conserve memory
117	#
118	(
119		cd "$MINIROOT"
120		find tmp/root/var/sadm/install tmp/root/var/sadm/pkg -print | \
121		    cpio -ocmPuB 2> /dev/null | bzip2 > \
122		    "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2"
123	)
124
125	rm -rf "$MINIROOT/tmp/root/var/sadm/install"
126	rm -rf "$MINIROOT/tmp/root/var/sadm/pkg"
127
128	# clear out 64 bit support to conserve memory
129	#
130	if [ "$STRIP_AMD64" != false ] ; then
131		find "$MINIROOT" -name amd64 -type directory | xargs rm -rf
132	fi
133
134	archive_X "$MEDIA" "$MINIROOT"
135
136	cp "$MINIROOT/platform/i86pc/multiboot" "$MEDIA/boot"
137	cp "$MINIROOT/platform/i86pc/kernel/unix" \
138	    "$MEDIA/boot/platform/i86pc/kernel/unix"
139
140	# copy the install menu to menu.lst so we have a menu
141	# on the install media
142	#
143	if [ -f "${MINIROOT}/boot/grub/install_menu" ] ; then
144		cp ${MINIROOT}/boot/grub/install_menu \
145		    ${MEDIA}/boot/grub/menu.lst
146	fi
147
148	(
149		cd "$MEDIA/$RELEASE/Tools/Boot"
150		ln -sf ../../../boot/x86.miniroot
151		ln -sf ../../../boot/multiboot
152		ln -sf ../../../boot/grub/pxegrub
153	)
154}
155
156unarchive_X()
157{
158	MEDIA="$1"
159	UNPACKED_ROOT="$2"
160
161	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
162	RELEASE=`basename "$RELEASE"`
163
164	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
165		CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra"
166	else
167		CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
168	fi
169
170	# unpack X
171	#
172	(
173		cd "$UNPACKED_ROOT/usr"
174		rm -rf dt openwin X11
175		bzcat "$CPIO_DIR/X.cpio.bz2" | cpio -icdmu 2> /dev/null
176	)
177}
178
179unpackmedia()
180{
181	MEDIA="$1"
182	UNPACKED_ROOT="$2"
183
184	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
185	RELEASE=`basename "$RELEASE"`
186
187	unarchive_X "$MEDIA" "$UNPACKED_ROOT"
188
189	# unpack package databases
190	#
191	(
192		cd "$UNPACKED_ROOT"
193		bzcat "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2" |
194		    cpio -icdmu 2> /dev/null
195	)
196}
197
198do_unpack()
199{
200	rm -rf "$UNPACKED_ROOT"
201	mkdir -p "$UNPACKED_ROOT"
202	(
203		cd $MNT
204		find . -print | cpio -pdum "$UNPACKED_ROOT" 2> /dev/null
205	)
206	umount $MNT
207}
208
209unpack()
210{
211
212	if [ ! -f "$MR" ] ; then
213		usage
214		exit 1
215	fi
216
217	gzcat "$MR" > $TMR
218
219	LOFIDEV=`/usr/sbin/lofiadm -a $TMR`
220	if [ $? != 0 ] ; then
221		echo lofi plumb failed
222		exit 2
223	fi
224
225	mkdir -p $MNT
226
227	FSTYP=`fstyp $LOFIDEV`
228
229	if [ "$FSTYP" = ufs ] ; then
230		/usr/sbin/mount -o ro,nologging $LOFIDEV $MNT
231		do_unpack
232	elif [ "$FSTYP" = hsfs ] ; then
233		/usr/sbin/mount -F hsfs -o ro $LOFIDEV $MNT
234		do_unpack
235	else
236		printf "invalid root archive\n"
237	fi
238
239	rmdir $MNT
240	lofiadm -d $TMR ; LOFIDEV=
241	rm $TMR
242}
243
244pack()
245{
246	if [ ! -d "$UNPACKED_ROOT" -o -z "$MR" ] ; then
247		usage
248		exit 1
249	fi
250
251	# Estimate image size and add %10 overhead for ufs stuff.
252	# Note, we can't use du here in case $UNPACKED_ROOT is on a filesystem,
253	# e.g. zfs, in which the disk usage is less than the sum of the file
254	# sizes.  The nawk code
255	#
256	#	{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
257	#
258	# below rounds up the size of a file/directory, in bytes, to the
259	# next multiple of 1024.  This mimics the behavior of ufs especially
260	# with directories.  This results in a total size that's slightly
261	# bigger than if du was called on a ufs directory.
262	size=$(find "$UNPACKED_ROOT" -ls | nawk '
263	    {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
264	    END {print int(t * 1.10 / 1024)}')
265
266	/usr/sbin/mkfile ${size}k "$TMR"
267
268	LOFIDEV=`/usr/sbin/lofiadm -a "$TMR"`
269	if [ $? != 0 ] ; then
270		echo lofi plumb failed
271		exit 2
272	fi
273
274	RLOFIDEV=`echo $LOFIDEV | sed s/lofi/rlofi/`
275	newfs $RLOFIDEV < /dev/null 2> /dev/null
276	mkdir -p $MNT
277	mount -o nologging $LOFIDEV $MNT
278	rmdir $MNT/lost+found
279	(
280		cd "$UNPACKED_ROOT"
281		find . -print | cpio -pdum $MNT 2> /dev/null
282	)
283	lockfs -f $MNT
284	umount $MNT
285	rmdir $MNT
286	lofiadm -d $LOFIDEV
287	LOFIDEV=
288
289	rm -f "$TMR.gz"
290	gzip -f "$TMR"
291	mv "$TMR.gz" "$MR"
292	chmod a+r "$MR"
293}
294
295# main
296#
297
298EXTRA_SPACE=0
299STRIP_AMD64=
300
301while getopts s:6 opt ; do
302	case $opt in
303	s)	EXTRA_SPACE="$OPTARG"
304		;;
305	6)	STRIP_AMD64=false
306		;;
307	*)	usage
308		exit 1
309		;;
310	esac
311done
312shift `expr $OPTIND - 1`
313
314if [ $# != 3 ] ; then
315	usage
316	exit 1
317fi
318
319UNPACKED_ROOT="$3"
320BASE="`pwd`"
321MNT=/tmp/mnt$$
322TMR=/tmp/mr$$
323LOFIDEV=
324MR="$2"
325
326if [ "`dirname $MR`" = . ] ; then
327	MR="$BASE/$MR"
328fi
329if [ "`dirname $UNPACKED_ROOT`" = . ] ; then
330	UNPACKED_ROOT="$BASE/$UNPACKED_ROOT"
331fi
332
333trap cleanup EXIT
334
335case $1 in
336	packmedia)
337		MEDIA="$MR"
338		MR="$MR/boot/x86.miniroot"
339
340		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
341			archive_X "$MEDIA" "$UNPACKED_ROOT"
342		else
343			packmedia "$MEDIA" "$UNPACKED_ROOT"
344			pack
345		fi ;;
346	unpackmedia)
347		MEDIA="$MR"
348		MR="$MR/boot/x86.miniroot"
349
350		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
351			unarchive_X "$MEDIA" "$UNPACKED_ROOT"
352		else
353			unpack
354			unpackmedia "$MEDIA" "$UNPACKED_ROOT"
355		fi ;;
356	pack)	pack ;;
357	unpack)	unpack ;;
358	*)	usage ;;
359esac
360