xref: /illumos-gate/usr/src/cmd/boot/scripts/root_archive.ksh (revision e38a713ad4e0a9c42f8cccd9350412b2c6ccccdb)
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        if [ "$REALTHING" != true ] ; then
67		rm -f "$TMR"
68	fi
69	rm -f "$TMR.gz"
70}
71
72archive_Gnome()
73{
74	MEDIA="$1"
75	MINIROOT="$2"
76
77	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
78	RELEASE=`basename "$RELEASE"`
79
80	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
81
82
83	# Create the gnome archive
84	#
85	(
86		# Prepopulate the gconf database. This needs to be done and
87		# done first for several reasons. 1) Archiving out the gnome
88		# libraries and binaries causes the gconftool-2 to not run
89		# appropriately at boot time. 2) The binaries and libraries
90		# needed to run this are big and thus we want to archive
91		# them separately. 3) Having schemas prepopluated in the
92		# miniroot means faster boot times.
93		#
94
95		cd "$MINIROOT"
96		HOME="./tmp/root"
97		export HOME
98		umask 0022
99		mumble=.tmp_proto/root/etc/gconf/gconf.xml.defaults
100		GCONF_CONFIG_SOURCE="xml:merged:$MINIROOT/$mumble"
101		export GCONF_CONFIG_SOURCE
102		SCHEMADIR="$MINIROOT/.tmp_proto/root/etc/gconf/schemas"
103		export SCHEMADIR
104		/usr/bin/gconftool-2 --makefile-install-rule \
105		    $SCHEMADIR/*.schemas >/dev/null 2>&1
106		echo '
107		xml:readwrite:/tmp/root/.gconf
108		xml:readonly:/etc/gconf/gconf.xml.defaults
109		' > /"$MINIROOT"/.tmp_proto/root/etc/gconf/2/path
110
111		# usr/share gnome stuff
112		cd "$MINIROOT"
113		find usr/share/GConf usr/share/application-registry \
114		    usr/share/autostart usr/share/dbus-1 usr/share/dtds \
115		    usr/share/emacs usr/share/gnome usr/share/gnome-2.0 \
116		    usr/share/gnome-background-properties \
117		    usr/share/gtk-engines usr/share/gui-install \
118		    usr/share/icon-naming-utils usr/share/control-center \
119		    usr/share/icons usr/share/locale usr/share/metacity \
120		    usr/share/mime usr/share/mime-info usr/share/pixmaps \
121		    usr/share/scrollkeeper usr/share/sgml usr/share/themes \
122		    usr/share/xml \
123		    -print > /tmp/gnome_share.$$ 2>/dev/null
124
125		if [ ! -f /tmp/gnome_share.$$ ] ; then
126			echo "/tmp/gnome_share.$$ file list not found."
127			return
128		fi
129
130		# usr/lib gnome stuff
131
132		find usr/lib/libgnome*\.so\.* \
133		    usr/lib/libgst*\.so\.* usr/lib/libgconf*\.so\.* \
134		    usr/lib/libgdk*\.so\.* usr/lib/libgtk*\.so\.* \
135		    usr/lib/libglade*\.so\.* usr/lib/libmetacity*\.so\.* \
136		    usr/lib/libfontconfig*\.so\.* usr/lib/libgmodule*\.so\.* \
137		    usr/lib/libgobject*\.so\.* usr/lib/libgthread*\.so\.* \
138		    usr/lib/libpopt*\.so\.* usr/lib/libstartup*\.so\.* \
139		    usr/lib/libexif*\.so\.* usr/lib/libtiff*\.so\.* \
140		    usr/lib/libdbus*\.so\.* usr/lib/libstartup*\.so\.* \
141		    usr/lib/libexif*\.so\.* usr/lib/libORBit*\.so\.* \
142	 	    usr/lib/libmlib*\.so\.* usr/lib/libxsl*\.so\.* \
143		    usr/lib/libpango*\.so\.* usr/lib/libpng*\.so\.* \
144		    usr/lib/liboil*\.so\.* usr/lib/libbonobo*\.so\.* \
145		    usr/lib/libart*\.so\.* usr/lib/libcairo*\.so\.* \
146		    usr/lib/libjpeg*\.so\.* \
147		    usr/lib/libpolkit*\.so\.* \
148			-print | egrep -v '\.so\.[0]$' > \
149		       /tmp/gnome_lib.$$ 2>/dev/null
150
151		find usr/lib/nautilus usr/lib/pango usr/lib/iconv \
152		    usr/lib/metacity-dialog usr/lib/window-manager-settings \
153		    usr/lib/bonobo-2.0 usr/lib/bononbo usr/lib/gtk-2.0 \
154		    usr/lib/GConf usr/lib/bonobo-activation-server \
155		    usr/lib/python2.4 usr/lib/gstreamer-0.10 \
156		    usr/lib/gconf-sanity-check-2 usr/lib/gconfd \
157		    usr/lib/gnome-vfs-2.0 usr/lib/dbus-daemon \
158		    usr/lib/gnome-vfs-daemon usr/lib/gnome-settings-daemon \
159		    usr/lib/gnome_segv2 usr/lib/orbit-2.0 \
160		    usr/lib/libmlib \
161		    print > /tmp/gnome_libdir.$$ 2>/dev/null
162
163		if [ ! -f /tmp/gnome_lib.$$  -a ! -f gnome_libdir.$$ ] ; then
164			echo "/tmp/gnome_lib.$$ file list not found."
165			return
166		fi
167
168		# /usr/sfw gnome stuff
169		find usr/sfw/bin usr/sfw/include usr/sfw/share usr/sfw/src \
170		    -print > /tmp/gnome_sfw.$$ 2>/dev/null
171
172		if [ ! -f /tmp/gnome_sfw.$$ ] ; then
173			echo "/tmp/gnome_sfw.$$ file list not found."
174			return
175		fi
176
177		# gnome app binaries usr/bin
178		find usr/bin/gnome* usr/bin/gui-install usr/bin/bonobo* \
179		    usr/bin/gtk-* usr/bin/fax* usr/bin/gdk* usr/bin/gif2tiff \
180		    usr/bin/install-lan \
181		    usr/bin/metacity* usr/bin/gst-* usr/bin/gconftool-2 \
182		    usr/bin/pango* usr/bin/desktop* usr/bin/djpeg \
183		    usr/bin/notify-send usr/bin/oil-bugreport \
184		    usr/bin/bmp2tiff usr/bin/thembus-theme-applier \
185		    usr/bin/thumbnail usr/lib/update-* \
186		    usr/bin/ras2tiff usr/bin/raw2tiff usr/bin/rdjpgcom \
187		    usr/bin/thumbnail usr/bin/dbus* \
188		    usr/bin/tiff* usr/bin/rgb2ycbcr \
189		    usr/bin/fc-cache usr/bin/fc-list \
190			-print > /tmp/gnome_bin.$$ 2>/dev/null
191
192		if [ ! -f /tmp/gnome_bin.$$ ] ; then
193			echo "/tmp/gnome_bin.$$ file list not found."
194			return
195		fi
196
197		# Cat all the files together and create the gnome archive
198		#
199
200		cat /tmp/gnome_libdir.$$ /tmp/gnome_lib.$$ \
201		     /tmp/gnome_share.$$ /tmp/gnome_sfw.$$ /tmp/gnome_bin.$$ \
202		    > /tmp/gnome.$$
203
204		if [ ! -f /tmp/gnome.$$ ] ; then
205			echo "/tmp/gnome.$$ file not found."
206			return
207		fi
208		# Save off this file in the miniroot for use later
209		# when unpacking. Clean up old cruft if there.
210		#
211
212		if [ -f .tmp_proto/gnome_saved ]; then
213			rm -f .tmp_proto/gnome_saved
214		fi
215
216		cp /tmp/gnome.$$ .tmp_proto/gnome_saved
217
218		# Create gnome archive
219		#
220
221		cpio -ocmPuB < /tmp/gnome.$$ 2>/dev/null | bzip2 > \
222		    "$CPIO_DIR/gnome.cpio.bz2"
223
224		# Remove files from miniroot that are in archive.
225		# Create symlinks for files in archive
226
227		rm -rf `cat /tmp/gnome_share.$$`
228
229		for i in `cat /tmp/gnome_share.$$`
230		do
231			ln -s /tmp/root/$i $i 2>/dev/null
232		done
233
234		rm -rf `cat /tmp/gnome_lib.$$`
235		for i in `cat /tmp/gnome_lib.$$`
236		do
237			ln -s /tmp/root/$i $i 2>/dev/null
238		done
239
240		rm -rf `cat /tmp/gnome_libdir.$$`
241		for i in `cat /tmp/gnome_libdir.$$`
242		do
243			ln -s /tmp/root/$i $i 2>/dev/null
244		done
245
246		rm -rf `cat /tmp/gnome_sfw.$$`
247		for i in `cat /tmp/gnome_sfw.$$`
248		do
249			ln -s /tmp/root/$i $i 2>/dev/null
250		done
251
252		rm -rf `cat /tmp/gnome_bin.$$`
253		for i in `cat /tmp/gnome_bin.$$`
254		do
255			ln -s /tmp/root/$i $i 2>/dev/null
256		done
257		rm -f /tmp/gnome_share.$$
258		rm -f /tmp/gnome_lib.$$
259		rm -f /tmp/gnome_libdir.$$
260		rm -f /tmp/gnome_bin.$$
261	)
262}
263
264archive_JavaGUI()
265{
266	MEDIA="$1"
267	MINIROOT="$2"
268
269	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
270	RELEASE=`basename "$RELEASE"`
271
272	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
273
274	# Archive the java wizard components that are only used in the
275	# non developer express path.
276	#
277	(
278		# path is usr/lib/install/data
279		cd "$MINIROOT"
280		find usr/lib/install/data/wizards \
281		    -print > /tmp/java_ui.$$ 2>/dev/null
282
283		if [ ! -f /tmp/java_ui.$$ ] ; then
284			echo "/tmp/java_ui.$$ file list not found."
285			return
286		fi
287
288		cpio -ocmPuB < /tmp/java_ui.$$ 2>/dev/null | bzip2 > \
289		    "$CPIO_DIR/javaui.cpio.bz2"
290
291		rm -rf `cat /tmp/java_ui.$$`
292		ln -s /tmp/root/usr/lib/install/data/wizards \
293		    usr/lib/install/data/wizards 2>/dev/null
294
295		rm -f /tmp/java_ui.$$
296
297	)
298}
299
300archive_Misc()
301{
302	MEDIA="$1"
303	MINIROOT="$2"
304
305	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
306	RELEASE=`basename "$RELEASE"`
307
308	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
309
310	# Archive misc stuff that is needed by non devex installer
311	#
312	(
313		# usr/lib stuff
314		cd "$MINIROOT"
315		find usr/lib/lp -print > /tmp/lp.$$ 2>/dev/null
316		if [ ! -f /tmp/lp.$$ ] ; then
317			echo "/tmp/lp.$$ file list not found."
318			return
319		fi
320
321		cpio -ocmPuB < /tmp/lp.$$ 2>/dev/null | bzip2 > \
322		    "$CPIO_DIR/lpmisc.cpio.bz2"
323
324		rm -rf `cat /tmp/lp.$$`
325		ln -s /tmp/root/usr/lib/lp usr/lib/lp 2>/dev/null
326
327		rm -f /tmp/lp.$$
328	)
329
330}
331
332archive_Perl()
333{
334	MEDIA="$1"
335	MINIROOT="$2"
336
337	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
338	RELEASE=`basename "$RELEASE"`
339
340	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
341
342	# Archive perl, it is only needed by gnome gui.
343	#
344	(
345		# in usr
346		cd "$MINIROOT"
347		find usr/perl5 -print > /tmp/perl.$$ 2>/dev/null
348
349		if [ ! -f /tmp/perl.$$ ] ; then
350			echo "/tmp/perl.$$ file list not found."
351			return
352		fi
353		cpio -ocmPuB < /tmp/perl.$$ 2>/dev/null | bzip2 > \
354		    "$CPIO_DIR/perl.cpio.bz2"
355
356		rm -rf `cat /tmp/perl.$$` 2>/dev/null
357		ln -s /tmp/root/usr/perl5 usr/perl5 2>/dev/null
358
359		rm -f /tmp/perl.$$
360	)
361}
362archive_X()
363{
364	MEDIA="$1"
365	MINIROOT="$2"
366
367	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
368	RELEASE=`basename "$RELEASE"`
369
370	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
371
372	# create the graphics and non-graphics X archive
373	#
374	(
375		cd "$MINIROOT"
376		find usr/openwin usr/dt usr/X11 -print 2> /dev/null |\
377		    cpio -ocmPuB 2> /dev/null | bzip2 > "$CPIO_DIR/X.cpio.bz2"
378
379		find usr/openwin/bin/mkfontdir \
380		     usr/openwin/lib/installalias \
381		     usr/openwin/server/lib/libfont.so.1 \
382		     usr/openwin/server/lib/libtypesclr.so.0 \
383			 -print | cpio -ocmPuB 2> /dev/null | bzip2 > \
384			 "$CPIO_DIR/X_small.cpio.bz2"
385
386		rm -rf usr/dt usr/openwin usr/X11
387		ln -s /tmp/root/usr/dt usr/dt
388		ln -s /tmp/root/usr/openwin usr/openwin
389		ln -s /tmp/root/usr/X11 usr/X11
390	)
391}
392
393archive_lu()
394{
395	MEDIA="$1"
396	MINIROOT="$2"
397
398	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
399	RELEASE=`basename "$RELEASE"`
400
401	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
402
403	(
404		cd "$MINIROOT"
405		find usr/lib/install usr/snadm usr/sbin | \
406		    cpio -ocmPuB 2> /dev/null | bzip2 > "$CPIO_DIR"/lu.cpio.bz2
407		ls platform > "$CPIO_DIR/lu.platforms"
408	)
409}
410
411packmedia()
412{
413	MEDIA="$1"
414	MINIROOT="$2"
415
416	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
417	RELEASE=`basename "$RELEASE"`
418
419	mkdir -p "$MEDIA/$RELEASE/Tools/Boot"
420
421	if [ -d "$MINIROOT/platform/i86pc" ] ; then
422		mkdir -p "$MEDIA/boot/amd64"
423		mkdir -p "$MEDIA/boot/platform/i86pc/kernel"
424		mkdir -p "$MEDIA/boot/platform/i86pc/kernel/amd64"
425		mkdir -p "$MEDIA/boot/platform/i86xpv/kernel"
426		mkdir -p "$MEDIA/boot/platform/i86xpv/kernel/amd64"
427		cp "$MINIROOT/platform/i86pc/multiboot" "$MEDIA/boot"
428		cp "$MINIROOT/platform/i86pc/kernel/unix" \
429		    "$MEDIA/boot/platform/i86pc/kernel/unix"
430		cp "$MINIROOT/platform/i86pc/kernel/amd64/unix" \
431		    "$MEDIA/boot/platform/i86pc/kernel/amd64/unix"
432		cp "$MINIROOT/platform/i86xpv/kernel/unix" \
433		    "$MEDIA/boot/platform/i86xpv/kernel/unix"
434		cp "$MINIROOT/platform/i86xpv/kernel/amd64/unix" \
435		    "$MEDIA/boot/platform/i86xpv/kernel/amd64/unix"
436		(
437			cd "$MEDIA/$RELEASE/Tools/Boot"
438			ln -sf ../../../boot/x86.miniroot
439			ln -sf ../../../boot/multiboot
440			ln -sf ../../../boot/platform/i86pc/kernel/unix
441			ln -sf ../../../boot/platform/i86pc/kernel/amd64/unix
442			ln -sf ../../../boot/platform/i86xpv/kernel/unix
443			ln -sf ../../../boot/platform/i86xpv/kernel/amd64/unix
444			ln -sf ../../../boot/grub/pxegrub
445		)
446	fi
447
448	if [ -d "$MINIROOT/platform/sun4u" ] ; then
449		mkdir -p "$MEDIA/boot"
450		dd if="$MINIROOT/usr/platform/sun4u/lib/fs/hsfs/bootblk" \
451		    of="$MEDIA/boot/hsfs.bootblock" \
452		    bs=1b oseek=1 count=15 conv=sync 2> /dev/null
453	fi
454
455	for arch in sun4u sun4v ; do
456		if [ -d "$MINIROOT/platform/$arch" ] ; then
457			archdir="$MEDIA/$RELEASE/Tools/Boot/platform/$arch"
458			mkdir -p $archdir
459			ln -sf ../../../../../boot/sparc.miniroot \
460			    "$archdir/boot_archive"
461			cp "$MINIROOT/usr/platform/$arch/lib/fs/nfs/inetboot" \
462			    "$archdir"
463			cp "$MINIROOT/platform/$arch/wanboot" \
464			    "$archdir"
465			mkdir -p "$MEDIA/platform/$arch"
466			ln -sf ../../boot/sparc.miniroot \
467			    "$MEDIA/platform/$arch/boot_archive"
468		fi
469	done
470
471	# archive package databases to conserve memory
472	#
473	(
474		cd "$MINIROOT"
475		find tmp/root/var/sadm/install tmp/root/var/sadm/pkg -print | \
476		    cpio -ocmPuB 2> /dev/null | bzip2 > \
477		    "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2"
478	)
479	rm -rf "$MINIROOT/tmp/root/var/sadm/install"
480	rm -rf "$MINIROOT/tmp/root/var/sadm/pkg"
481
482	if [ -d "$MINIROOT/kernel/drv/sparcv9" ] ; then
483		archive_lu "$MEDIA" "$MINIROOT"
484	fi
485
486	archive_X "$MEDIA" "$MINIROOT"
487
488	# Take out the gnome and java parts of the installer from
489	# the miniroot. These are not required to boot the system
490	# and start the installers.
491
492	if [ -d "$MINIROOT/platform/i86pc" ] ; then
493		archive_Gnome "$MEDIA" "$MINIROOT"
494		archive_JavaGUI "$MEDIA" "$MINIROOT"
495		archive_Misc "$MEDIA" "$MINIROOT"
496		archive_Perl "$MEDIA" "$MINIROOT"
497	fi
498
499	# copy the install menu to menu.lst so we have a menu
500	# on the install media
501	#
502	if [ -f "$MINIROOT/boot/grub/install_menu" ] ; then
503		cp $MINIROOT/boot/grub/install_menu \
504		    $MEDIA/boot/grub/menu.lst
505	fi
506}
507
508unarchive_X()
509{
510	MEDIA="$1"
511	UNPACKED_ROOT="$2"
512
513	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
514	RELEASE=`basename "$RELEASE"`
515
516	CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
517
518	# unpack X
519	#
520	(
521		cd "$UNPACKED_ROOT"
522		rm -rf usr/dt usr/openwin usr/X11
523		bzcat "$CPIO_DIR/X.cpio.bz2" | cpio -icdmu 2> /dev/null
524	)
525}
526
527unpackmedia()
528{
529	MEDIA="$1"
530	UNPACKED_ROOT="$2"
531
532	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
533	RELEASE=`basename "$RELEASE"`
534
535	unarchive_X "$MEDIA" "$UNPACKED_ROOT"
536
537	# unpack package databases
538	#
539	(
540		cd "$UNPACKED_ROOT"
541		bzcat "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2" |
542		    cpio -icdmu 2> /dev/null
543
544		# unpack gnome, perl, java and misc
545		# Remove symlinks left from unpacking x86.miniroot so that
546		# unpacking subsequent archives will populate appropriately.
547		#
548		rm -rf usr/perl5
549		rm -rf usr/lib/install/data/wizards
550		rm -rf usr/lib/lp
551
552		# Gnome list saved off from packmedia
553		for i in `cat .tmp_proto/gnome_saved`
554		do
555			rm -rf $i
556		done
557
558		bzcat "$MEDIA/$RELEASE/Tools/Boot/gnome.cpio.bz2" |
559		    cpio -icdmu 2>/dev/null
560		bzcat "$MEDIA/$RELEASE/Tools/Boot/javaui.cpio.bz2" |
561		    cpio -icdmu 2>/dev/null
562		bzcat "$MEDIA/$RELEASE/Tools/Boot/lpmisc.cpio.bz2" |
563		    cpio -icdmu 2>/dev/null
564		bzcat "$MEDIA/$RELEASE/Tools/Boot/perl.cpio.bz2" |
565		    cpio -icdmu 2>/dev/null
566	)
567}
568
569do_unpack()
570{
571	rm -rf "$UNPACKED_ROOT"
572	mkdir -p "$UNPACKED_ROOT"
573	(
574		cd $MNT
575		find . -print | cpio -pdum "$UNPACKED_ROOT" 2> /dev/null
576	)
577	umount $MNT
578}
579
580unpack()
581{
582
583	if [ ! -f "$MR" ] ; then
584		usage
585		exit 1
586	fi
587
588	if [ `basename $MR` = x86.miniroot ] ; then
589		gzcat "$MR" > $TMR
590	else
591		REALTHING=true ; export REALTHING
592		TMR="$MR"
593	fi
594
595	LOFIDEV=`/usr/sbin/lofiadm -a $TMR`
596	if [ $? != 0 ] ; then
597		echo lofi plumb failed
598		exit 2
599	fi
600
601	mkdir -p $MNT
602
603	FSTYP=`fstyp $LOFIDEV`
604
605	if [ "$FSTYP" = ufs ] ; then
606		/usr/sbin/mount -o ro,nologging $LOFIDEV $MNT
607		do_unpack
608	elif [ "$FSTYP" = hsfs ] ; then
609		/usr/sbin/mount -F hsfs -o ro $LOFIDEV $MNT
610		do_unpack
611	else
612		printf "invalid root archive\n"
613	fi
614
615
616	rmdir $MNT
617	lofiadm -d $TMR ; LOFIDEV=
618	if [ "$REALTHING" != true ] ; then
619		rm $TMR
620	fi
621}
622
623compress()
624{
625	SRC=$1
626	DST=$2
627
628	(
629		cd $SRC
630		filelist=`find .`
631
632		for file in $filelist ; do
633
634			file=`echo $file | sed s#^./##`
635
636			# copy all files over to preserve hard links
637			#
638			echo $file | cpio -pdum $DST 2> /dev/null
639
640			if [ -f $file ] && [ -s $file ] && [ ! -h $file ] ; then
641				fiocompress -mc $file $DST/$file &
642			fi
643
644		done
645
646		# now re-copy a couple of uncompressed files
647		#
648
649		find kernel platform -name unix | cpio -pdum $DST 2> /dev/null
650		find kernel platform -name genunix | cpio -pdum $DST \
651		    2> /dev/null
652		find kernel platform -name platmod | cpio -pdum $DST \
653		    2> /dev/null
654		find `find kernel platform -name cpu` | cpio -pdum $DST \
655		    2> /dev/null
656		find `find kernel platform -name kmdb\*` | cpio -pdum $DST \
657		    2> /dev/null
658		find kernel/misc/sparcv9/ctf kernel/fs/sparcv9/dcfs \
659		    etc/system etc/name_to_major etc/path_to_inst \
660		    etc/name_to_sysnum | cpio -pdum $DST 2> /dev/null
661	)
662}
663
664root_is_ramdisk()
665{
666	grep -v "set root_is_ramdisk=" "$UNPACKED_ROOT"/etc/system | \
667	    grep -v "set ramdisk_size=" > /tmp/system.$$
668	cat /tmp/system.$$ > "$UNPACKED_ROOT"/etc/system
669	rm /tmp/system.$$
670
671	echo set root_is_ramdisk=1 >> "$UNPACKED_ROOT"/etc/system
672	echo set ramdisk_size=$1 >> "$UNPACKED_ROOT"/etc/system
673}
674
675pack()
676{
677	if [ ! -d "$UNPACKED_ROOT" -o -z "$MR" ] ; then
678		usage
679		exit 1
680	fi
681
682	# always compress on sparc if fiocompress exists
683	#
684	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] && \
685	    [ -x /usr/sbin/fiocompress ] ; then
686		COMPRESS=true
687	fi
688
689	# Estimate image size and add %10 overhead for ufs stuff.
690	# Note, we can't use du here in case $UNPACKED_ROOT is on a filesystem,
691	# e.g. zfs, in which the disk usage is less than the sum of the file
692	# sizes.  The nawk code
693	#
694	#	{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
695	#
696	# below rounds up the size of a file/directory, in bytes, to the
697	# next multiple of 1024.  This mimics the behavior of ufs especially
698	# with directories.  This results in a total size that's slightly
699	# bigger than if du was called on a ufs directory.
700	#
701	# if the operation in turn is compressing the files the amount
702	# of typical shrinkage is used to come up with a useful archive
703	# size
704	size=$(find "$UNPACKED_ROOT" -ls | nawk '
705	    {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
706	    END {print int(t * 1.10 / 1024)}')
707	if [ "$COMPRESS" = true ] ; then
708		size=`echo $size | nawk '{s = $1} END {print int(s * .53)}'`
709	fi
710
711	/usr/sbin/mkfile ${size}k "$TMR"
712
713	LOFIDEV=`/usr/sbin/lofiadm -a "$TMR"`
714	if [ $? != 0 ] ; then
715		echo lofi plumb failed
716		exit 2
717	fi
718
719	RLOFIDEV=`echo $LOFIDEV | sed s/lofi/rlofi/`
720	newfs $RLOFIDEV < /dev/null 2> /dev/null
721	mkdir -p $MNT
722	mount -o nologging $LOFIDEV $MNT
723	rmdir $MNT/lost+found
724
725	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
726		root_is_ramdisk $size
727	fi
728
729	(
730		cd "$UNPACKED_ROOT"
731		if [ "$COMPRESS" = true ] ; then
732			compress . $MNT
733		else
734			find . -print | cpio -pdum $MNT 2> /dev/null
735		fi
736	)
737	lockfs -f $MNT
738	umount $MNT
739	rmdir $MNT
740
741	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
742		"$UNPACKED_ROOT/usr/sbin/installboot" \
743		    "$UNPACKED_ROOT/usr/platform/sun4u/lib/fs/ufs/bootblk" \
744		    $RLOFIDEV
745	fi
746
747	lofiadm -d $LOFIDEV
748	LOFIDEV=
749
750	rm -f "$TMR.gz"
751
752	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
753		mv "$TMR" "$MR"
754	else
755		gzip -f "$TMR"
756		mv "$TMR.gz" "$MR"
757	fi
758
759	chmod a+r "$MR"
760}
761
762strip_amd64()
763{
764	find "$UNPACKED_ROOT" -name amd64 -type directory | xargs rm -rf
765}
766
767# main
768#
769
770EXTRA_SPACE=0
771STRIP_AMD64=
772COMPRESS=
773
774PATH=/usr/sbin:/usr/bin:/opt/sfw/bin ; export PATH
775
776while getopts s:6c opt ; do
777	case $opt in
778	s)	EXTRA_SPACE="$OPTARG"
779		;;
780	6)	STRIP_AMD64=false
781		;;
782	c)	COMPRESS=true
783		;;
784	*)	usage
785		exit 1
786		;;
787	esac
788done
789shift `expr $OPTIND - 1`
790
791if [ $# != 3 ] ; then
792	usage
793	exit 1
794fi
795
796UNPACKED_ROOT="$3"
797BASE="`pwd`"
798MNT=/tmp/mnt$$
799TMR=/tmp/mr$$
800LOFIDEV=
801MR="$2"
802
803if [ "`dirname $MR`" = . ] ; then
804	MR="$BASE/$MR"
805fi
806if [ "`dirname $UNPACKED_ROOT`" = . ] ; then
807	UNPACKED_ROOT="$BASE/$UNPACKED_ROOT"
808fi
809
810
811MEDIA="$MR"
812
813trap cleanup EXIT
814
815case $1 in
816	packmedia)
817		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
818			ARCHIVE=sparc.miniroot
819		else
820			ARCHIVE=amd64/x86.miniroot
821		fi
822		MR="$MEDIA/boot/$ARCHIVE"
823
824		packmedia "$MEDIA" "$UNPACKED_ROOT"
825		pack
826
827		if [ -d "$MINIROOT/platform/i86pc" ] ; then
828			if [ "$STRIP_AMD64" = false ] ; then
829				ln $MR $MEDIA/boot/x86.miniroot
830			else
831				MR="$MEDIA/boot/x86.miniroot"
832				strip_amd64
833				pack
834			fi
835		fi
836
837		;;
838	unpackmedia)
839		if [ -f "$MEDIA/boot/sparc.miniroot" ] ; then
840			ARCHIVE=sparc.miniroot
841		else
842			ARCHIVE=x86.miniroot
843		fi
844		MR="$MEDIA/boot/$ARCHIVE"
845		unpack
846		unpackmedia "$MEDIA" "$UNPACKED_ROOT"
847		;;
848	pack)	pack
849		;;
850	unpack)	unpack
851		;;
852	*)	usage
853		;;
854esac
855