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 2006 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"
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
138	# copy the install menu to menu.lst so we have a menu
139	# on the install media
140	#
141	if [ -f "${MINIROOT}/boot/grub/install_menu" ] ; then
142		cp ${MINIROOT}/boot/grub/install_menu \
143		    ${MEDIA}/boot/grub/menu.lst
144	fi
145
146	(
147		cd "$MEDIA/$RELEASE/Tools/Boot"
148		ln -sf ../../../boot/x86.miniroot
149		ln -sf ../../../boot/multiboot
150		ln -sf ../../../boot/grub/pxegrub
151	)
152}
153
154unarchive_X()
155{
156	MEDIA="$1"
157	UNPACKED_ROOT="$2"
158
159	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
160	RELEASE=`basename "$RELEASE"`
161
162	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
163		CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra"
164	else
165		CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
166	fi
167
168	# unpack X
169	#
170	(
171		cd "$UNPACKED_ROOT/usr"
172		rm -rf dt openwin X11
173		bzcat "$CPIO_DIR/X.cpio.bz2" | cpio -icdmu 2> /dev/null
174	)
175}
176
177unpackmedia()
178{
179	MEDIA="$1"
180	UNPACKED_ROOT="$2"
181
182	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
183	RELEASE=`basename "$RELEASE"`
184
185	unarchive_X "$MEDIA" "$UNPACKED_ROOT"
186
187	# unpack package databases
188	#
189	(
190		cd "$UNPACKED_ROOT"
191		bzcat "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2" |
192		    cpio -icdmu 2> /dev/null
193	)
194}
195
196do_unpack()
197{
198	rm -rf "$UNPACKED_ROOT"
199	mkdir -p "$UNPACKED_ROOT"
200	(
201		cd $MNT
202		find . -print | cpio -pdum "$UNPACKED_ROOT" 2> /dev/null
203	)
204	umount $MNT
205}
206
207unpack()
208{
209
210	if [ ! -f "$MR" ] ; then
211		usage
212		exit 1
213	fi
214
215	gzcat "$MR" > $TMR
216
217	LOFIDEV=`/usr/sbin/lofiadm -a $TMR`
218	if [ $? != 0 ] ; then
219		echo lofi plumb failed
220		exit 2
221	fi
222
223	mkdir -p $MNT
224
225	FSTYP=`fstyp $LOFIDEV`
226
227	if [ "$FSTYP" = ufs ] ; then
228		/usr/sbin/mount -o ro,nologging $LOFIDEV $MNT
229		do_unpack
230	elif [ "$FSTYP" = hsfs ] ; then
231		/usr/sbin/mount -F hsfs -o ro $LOFIDEV $MNT
232		do_unpack
233	else
234		printf "invalid root archive\n"
235	fi
236
237	rmdir $MNT
238	lofiadm -d $TMR ; LOFIDEV=
239	rm $TMR
240}
241
242pack()
243{
244	if [ ! -d "$UNPACKED_ROOT" -o -z "$MR" ] ; then
245		usage
246		exit 1
247	fi
248
249	# Estimate image size and add %10 overhead for ufs stuff.
250	# Note, we can't use du here in case $UNPACKED_ROOT is on a filesystem,
251	# e.g. zfs, in which the disk usage is less than the sum of the file
252	# sizes.  The nawk code
253	#
254	#	{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
255	#
256	# below rounds up the size of a file/directory, in bytes, to the
257	# next multiple of 1024.  This mimics the behavior of ufs especially
258	# with directories.  This results in a total size that's slightly
259	# bigger than if du was called on a ufs directory.
260	size=$(find "$UNPACKED_ROOT" -ls | nawk '
261	    {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
262	    END {print int(t * 1.10 / 1024)}')
263
264	/usr/sbin/mkfile ${size}k "$TMR"
265
266	LOFIDEV=`/usr/sbin/lofiadm -a "$TMR"`
267	if [ $? != 0 ] ; then
268		echo lofi plumb failed
269		exit 2
270	fi
271
272	RLOFIDEV=`echo $LOFIDEV | sed s/lofi/rlofi/`
273	newfs $RLOFIDEV < /dev/null 2> /dev/null
274	mkdir -p $MNT
275	mount -o nologging $LOFIDEV $MNT
276	rmdir $MNT/lost+found
277	(
278		cd "$UNPACKED_ROOT"
279		find . -print | cpio -pdum $MNT 2> /dev/null
280	)
281	lockfs -f $MNT
282	umount $MNT
283	rmdir $MNT
284	lofiadm -d $LOFIDEV
285	LOFIDEV=
286
287	rm -f "$TMR.gz"
288	gzip -f "$TMR"
289	mv "$TMR.gz" "$MR"
290	chmod a+r "$MR"
291}
292
293# main
294#
295
296EXTRA_SPACE=0
297STRIP_AMD64=
298
299while getopts s:6 opt ; do
300	case $opt in
301	s)	EXTRA_SPACE="$OPTARG"
302		;;
303	6)	STRIP_AMD64=false
304		;;
305	*)	usage
306		exit 1
307		;;
308	esac
309done
310shift `expr $OPTIND - 1`
311
312if [ $# != 3 ] ; then
313	usage
314	exit 1
315fi
316
317UNPACKED_ROOT="$3"
318BASE="`pwd`"
319MNT=/tmp/mnt$$
320TMR=/tmp/mr$$
321LOFIDEV=
322MR="$2"
323
324if [ "`dirname $MR`" = . ] ; then
325	MR="$BASE/$MR"
326fi
327if [ "`dirname $UNPACKED_ROOT`" = . ] ; then
328	UNPACKED_ROOT="$BASE/$UNPACKED_ROOT"
329fi
330
331trap cleanup EXIT
332
333case $1 in
334	packmedia)
335		MEDIA="$MR"
336		MR="$MR/boot/x86.miniroot"
337
338		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
339			archive_X "$MEDIA" "$UNPACKED_ROOT"
340		else
341			packmedia "$MEDIA" "$UNPACKED_ROOT"
342			pack
343		fi ;;
344	unpackmedia)
345		MEDIA="$MR"
346		MR="$MR/boot/x86.miniroot"
347
348		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
349			unarchive_X "$MEDIA" "$UNPACKED_ROOT"
350		else
351			unpack
352			unpackmedia "$MEDIA" "$UNPACKED_ROOT"
353		fi ;;
354	pack)	pack ;;
355	unpack)	unpack ;;
356	*)	usage ;;
357esac
358