12851Sjongkis#!/bin/ksh -p
20Sstevel@tonic-gate#
30Sstevel@tonic-gate# CDDL HEADER START
40Sstevel@tonic-gate#
50Sstevel@tonic-gate# The contents of this file are subject to the terms of the
61777Ssetje# Common Development and Distribution License (the "License").
71777Ssetje# You may not use this file except in compliance with the License.
80Sstevel@tonic-gate#
90Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate# See the License for the specific language governing permissions
120Sstevel@tonic-gate# and limitations under the License.
130Sstevel@tonic-gate#
140Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate#
200Sstevel@tonic-gate# CDDL HEADER END
210Sstevel@tonic-gate#
220Sstevel@tonic-gate
23*3446Smrj# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate# Use is subject to license terms.
250Sstevel@tonic-gate#
261777Ssetje# ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate# utility to pack and unpack a boot/root archive
290Sstevel@tonic-gate# both ufs and hsfs (iso9660) format archives are unpacked
300Sstevel@tonic-gate# only ufs archives are generated
310Sstevel@tonic-gate#
320Sstevel@tonic-gate# usage: pack   <archive> <root>
330Sstevel@tonic-gate#        unpack <archive> <root>
340Sstevel@tonic-gate#        packmedia   <solaris_image> <root>
350Sstevel@tonic-gate#        unpackmedia <solaris_image> <root>
360Sstevel@tonic-gate#
370Sstevel@tonic-gate#   Where <root> is the directory to unpack to and will be cleaned out
380Sstevel@tonic-gate#   if it exists.
390Sstevel@tonic-gate#
400Sstevel@tonic-gate#   In the case of (un)packmedia, the image is packed or unpacked to/from
410Sstevel@tonic-gate#   Solaris media and all the things that don't go into the ramdisk image
420Sstevel@tonic-gate#   are (un)cpio'd as well
430Sstevel@tonic-gate#
441777Ssetje# This utility is also used to pack parts (in essence the window system,
451777Ssetje# usr/dt and usr/openwin) of the non ramdisk SPARC
461777Ssetje# miniroot. (un)packmedia will recognize that they are being run a SPARC
471777Ssetje# miniroot and do the appropriate work.
481777Ssetje#
490Sstevel@tonic-gate
500Sstevel@tonic-gateusage()
510Sstevel@tonic-gate{
520Sstevel@tonic-gate	printf "usage: root_archive pack <archive> <root>\n"
530Sstevel@tonic-gate	printf "       root_archive unpack <archive> <root>\n"
540Sstevel@tonic-gate	printf "       root_archive packmedia   <solaris_image> <root>\n"
550Sstevel@tonic-gate	printf "       root_archive unpackmedia <solaris_image> <root>\n"
560Sstevel@tonic-gate}
570Sstevel@tonic-gate
582334Ssetjecleanup()
592334Ssetje{
602334Ssetje	if [ -d $MNT ] ; then
612334Ssetje		umount $MNT 2> /dev/null
622334Ssetje		rmdir $MNT
632334Ssetje	fi
642334Ssetje
652851Sjongkis	lofiadm -d "$TMR" 2>/dev/null
662851Sjongkis	rm -f "$TMR" "$TMR.gz"
672334Ssetje}
682334Ssetje
691777Ssetjearchive_X()
700Sstevel@tonic-gate{
711777Ssetje	MEDIA="$1"
721777Ssetje	MINIROOT="$2"
730Sstevel@tonic-gate
741777Ssetje	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
751777Ssetje	RELEASE=`basename "$RELEASE"`
760Sstevel@tonic-gate
771777Ssetje	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
781777Ssetje		CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra"
791777Ssetje		mkdir -p "$CPIO_DIR"
801777Ssetje	else
811777Ssetje		CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
821777Ssetje	fi
830Sstevel@tonic-gate
840Sstevel@tonic-gate	# create the graphics and non-graphics X archive
850Sstevel@tonic-gate	#
862851Sjongkis	(
872851Sjongkis		cd "$MINIROOT/usr"
882851Sjongkis		find openwin dt X11 -print 2> /dev/null |\
892851Sjongkis		    cpio -ocmPuB 2> /dev/null | bzip2 > "$CPIO_DIR/X.cpio.bz2"
900Sstevel@tonic-gate
912851Sjongkis		find openwin/bin/mkfontdir \
922851Sjongkis		     openwin/lib/installalias \
932851Sjongkis		     openwin/server/lib/libfont.so.1 \
942851Sjongkis		     openwin/server/lib/libtypesclr.so.0 \
952851Sjongkis			 -print | cpio -ocmPuB 2> /dev/null | bzip2 > \
962851Sjongkis			 "$CPIO_DIR/X_small.cpio.bz2"
970Sstevel@tonic-gate
982851Sjongkis		rm -rf dt openwin X11
992851Sjongkis		ln -s ../tmp/root/usr/dt
1002851Sjongkis		ln -s ../tmp/root/usr/openwin
1012851Sjongkis		ln -s ../tmp/root/usr/X11
1022851Sjongkis	)
1031777Ssetje}
1041777Ssetje
1051777Ssetjepackmedia()
1061777Ssetje{
1071777Ssetje	MEDIA="$1"
1081777Ssetje	MINIROOT="$2"
1091777Ssetje
1101777Ssetje	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
1111777Ssetje	RELEASE=`basename "$RELEASE"`
1121777Ssetje
1131777Ssetje	mkdir -p "$MEDIA/$RELEASE/Tools/Boot"
114*3446Smrj	mkdir -p "$MEDIA/boot/platform/i86pc/kernel"
1151777Ssetje
1161777Ssetje	# archive package databases to conserve memory
1171777Ssetje	#
1182851Sjongkis	(
1192851Sjongkis		cd "$MINIROOT"
1202851Sjongkis		find tmp/root/var/sadm/install tmp/root/var/sadm/pkg -print | \
1212851Sjongkis		    cpio -ocmPuB 2> /dev/null | bzip2 > \
1222851Sjongkis		    "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2"
1232851Sjongkis	)
1241777Ssetje
1251777Ssetje	rm -rf "$MINIROOT/tmp/root/var/sadm/install"
1261777Ssetje	rm -rf "$MINIROOT/tmp/root/var/sadm/pkg"
1271777Ssetje
1280Sstevel@tonic-gate	# clear out 64 bit support to conserve memory
1290Sstevel@tonic-gate	#
1302851Sjongkis	if [ "$STRIP_AMD64" != false ] ; then
1312334Ssetje		find "$MINIROOT" -name amd64 -type directory | xargs rm -rf
1322334Ssetje	fi
1330Sstevel@tonic-gate
1342595Ssetje	archive_X "$MEDIA" "$MINIROOT"
1352595Ssetje
1361777Ssetje	cp "$MINIROOT/platform/i86pc/multiboot" "$MEDIA/boot"
137*3446Smrj	cp "$MINIROOT/platform/i86pc/kernel/unix" \
138*3446Smrj	    "$MEDIA/boot/platform/i86pc/kernel/unix"
1390Sstevel@tonic-gate
1401821Ssetje	# copy the install menu to menu.lst so we have a menu
1411821Ssetje	# on the install media
1421821Ssetje	#
1431821Ssetje	if [ -f "${MINIROOT}/boot/grub/install_menu" ] ; then
1441821Ssetje		cp ${MINIROOT}/boot/grub/install_menu \
1451821Ssetje		    ${MEDIA}/boot/grub/menu.lst
1461821Ssetje	fi
1471821Ssetje
1482851Sjongkis	(
1492851Sjongkis		cd "$MEDIA/$RELEASE/Tools/Boot"
1502851Sjongkis		ln -sf ../../../boot/x86.miniroot
1512851Sjongkis		ln -sf ../../../boot/multiboot
1522851Sjongkis		ln -sf ../../../boot/grub/pxegrub
1532851Sjongkis	)
1541777Ssetje}
1550Sstevel@tonic-gate
1561777Ssetjeunarchive_X()
1571777Ssetje{
1581777Ssetje	MEDIA="$1"
1591777Ssetje	UNPACKED_ROOT="$2"
1601777Ssetje
1611777Ssetje	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
1621777Ssetje	RELEASE=`basename "$RELEASE"`
1631777Ssetje
1641777Ssetje	if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
1651777Ssetje		CPIO_DIR="$MEDIA/$RELEASE/Tools/miniroot_extra"
1661777Ssetje	else
1671777Ssetje		CPIO_DIR="$MEDIA/$RELEASE/Tools/Boot"
1680Sstevel@tonic-gate	fi
1691777Ssetje
1701777Ssetje	# unpack X
1711777Ssetje	#
1722851Sjongkis	(
1732851Sjongkis		cd "$UNPACKED_ROOT/usr"
1742851Sjongkis		rm -rf dt openwin X11
1752851Sjongkis		bzcat "$CPIO_DIR/X.cpio.bz2" | cpio -icdmu 2> /dev/null
1762851Sjongkis	)
1770Sstevel@tonic-gate}
1780Sstevel@tonic-gate
1790Sstevel@tonic-gateunpackmedia()
1801777Ssetje{
1811777Ssetje	MEDIA="$1"
1821777Ssetje	UNPACKED_ROOT="$2"
1830Sstevel@tonic-gate
1841777Ssetje	RELEASE=`/bin/ls -d "$MEDIA/Solaris_"*`
1851777Ssetje	RELEASE=`basename "$RELEASE"`
1861777Ssetje
1871777Ssetje	unarchive_X "$MEDIA" "$UNPACKED_ROOT"
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate	# unpack package databases
1900Sstevel@tonic-gate	#
1912851Sjongkis	(
1922851Sjongkis		cd "$UNPACKED_ROOT"
1932851Sjongkis		bzcat "$MEDIA/$RELEASE/Tools/Boot/pkg_db.cpio.bz2" |
1942851Sjongkis		    cpio -icdmu 2> /dev/null
1952851Sjongkis	)
1960Sstevel@tonic-gate}
1970Sstevel@tonic-gate
1980Sstevel@tonic-gatedo_unpack()
1990Sstevel@tonic-gate{
2001777Ssetje	rm -rf "$UNPACKED_ROOT"
2011777Ssetje	mkdir -p "$UNPACKED_ROOT"
2022851Sjongkis	(
2032851Sjongkis		cd $MNT
2042851Sjongkis		find . -print | cpio -pdum "$UNPACKED_ROOT" 2> /dev/null
2052851Sjongkis	)
2060Sstevel@tonic-gate	umount $MNT
2070Sstevel@tonic-gate}
2080Sstevel@tonic-gate
2090Sstevel@tonic-gateunpack()
2100Sstevel@tonic-gate{
2110Sstevel@tonic-gate
2121777Ssetje	if [ ! -f "$MR" ] ; then
2130Sstevel@tonic-gate		usage
2140Sstevel@tonic-gate		exit 1
2150Sstevel@tonic-gate	fi
2160Sstevel@tonic-gate
2171777Ssetje	gzcat "$MR" > $TMR
2180Sstevel@tonic-gate
2192334Ssetje	LOFIDEV=`/usr/sbin/lofiadm -a $TMR`
2200Sstevel@tonic-gate	if [ $? != 0 ] ; then
2210Sstevel@tonic-gate		echo lofi plumb failed
2220Sstevel@tonic-gate		exit 2
2230Sstevel@tonic-gate	fi
2240Sstevel@tonic-gate
2251777Ssetje	mkdir -p $MNT
2260Sstevel@tonic-gate
2272334Ssetje	FSTYP=`fstyp $LOFIDEV`
2280Sstevel@tonic-gate
2291777Ssetje	if [ "$FSTYP" = ufs ] ; then
2302334Ssetje		/usr/sbin/mount -o ro,nologging $LOFIDEV $MNT
2310Sstevel@tonic-gate		do_unpack
2321777Ssetje	elif [ "$FSTYP" = hsfs ] ; then
2332334Ssetje		/usr/sbin/mount -F hsfs -o ro $LOFIDEV $MNT
2340Sstevel@tonic-gate		do_unpack
2350Sstevel@tonic-gate	else
2360Sstevel@tonic-gate		printf "invalid root archive\n"
2370Sstevel@tonic-gate	fi
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate	rmdir $MNT
2402851Sjongkis	lofiadm -d $TMR ; LOFIDEV=
2410Sstevel@tonic-gate	rm $TMR
2420Sstevel@tonic-gate}
2430Sstevel@tonic-gate
2440Sstevel@tonic-gatepack()
2450Sstevel@tonic-gate{
2461777Ssetje	if [ ! -d "$UNPACKED_ROOT" -o -z "$MR" ] ; then
2470Sstevel@tonic-gate		usage
2480Sstevel@tonic-gate		exit 1
2490Sstevel@tonic-gate	fi
2500Sstevel@tonic-gate
2512511Sjongkis	# Estimate image size and add %10 overhead for ufs stuff.
2522511Sjongkis	# Note, we can't use du here in case $UNPACKED_ROOT is on a filesystem,
2532511Sjongkis	# e.g. zfs, in which the disk usage is less than the sum of the file
2542511Sjongkis	# sizes.  The nawk code
2552511Sjongkis	#
2562511Sjongkis	#	{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
2572511Sjongkis	#
2582511Sjongkis	# below rounds up the size of a file/directory, in bytes, to the
2592511Sjongkis	# next multiple of 1024.  This mimics the behavior of ufs especially
2602511Sjongkis	# with directories.  This results in a total size that's slightly
2612511Sjongkis	# bigger than if du was called on a ufs directory.
2622511Sjongkis	size=$(find "$UNPACKED_ROOT" -ls | nawk '
2632511Sjongkis	    {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
2642511Sjongkis	    END {print int(t * 1.10 / 1024)}')
2650Sstevel@tonic-gate
2662334Ssetje	/usr/sbin/mkfile ${size}k "$TMR"
2672334Ssetje
2682334Ssetje	LOFIDEV=`/usr/sbin/lofiadm -a "$TMR"`
2690Sstevel@tonic-gate	if [ $? != 0 ] ; then
2700Sstevel@tonic-gate		echo lofi plumb failed
2710Sstevel@tonic-gate		exit 2
2720Sstevel@tonic-gate	fi
2730Sstevel@tonic-gate
2742334Ssetje	RLOFIDEV=`echo $LOFIDEV | sed s/lofi/rlofi/`
2752334Ssetje	newfs $RLOFIDEV < /dev/null 2> /dev/null
2761777Ssetje	mkdir -p $MNT
2772334Ssetje	mount -o nologging $LOFIDEV $MNT
2781777Ssetje	rmdir $MNT/lost+found
2792851Sjongkis	(
2802851Sjongkis		cd "$UNPACKED_ROOT"
2812851Sjongkis		find . -print | cpio -pdum $MNT 2> /dev/null
2822851Sjongkis	)
2830Sstevel@tonic-gate	lockfs -f $MNT
2840Sstevel@tonic-gate	umount $MNT
2850Sstevel@tonic-gate	rmdir $MNT
2862334Ssetje	lofiadm -d $LOFIDEV
2872851Sjongkis	LOFIDEV=
2880Sstevel@tonic-gate
2892334Ssetje	rm -f "$TMR.gz"
2902334Ssetje	gzip -f "$TMR"
2912334Ssetje	mv "$TMR.gz" "$MR"
2921777Ssetje	chmod a+r "$MR"
2930Sstevel@tonic-gate}
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate# main
2960Sstevel@tonic-gate#
2970Sstevel@tonic-gate
2982334SsetjeEXTRA_SPACE=0
2992851SjongkisSTRIP_AMD64=
3002334Ssetje
3012334Ssetjewhile getopts s:6 opt ; do
3022334Ssetje	case $opt in
3032334Ssetje	s)	EXTRA_SPACE="$OPTARG"
3042334Ssetje		;;
3052334Ssetje	6)	STRIP_AMD64=false
3062334Ssetje		;;
3072334Ssetje	*)	usage
3082334Ssetje		exit 1
3092334Ssetje		;;
3102334Ssetje	esac
3112334Ssetjedone
3122334Ssetjeshift `expr $OPTIND - 1`
3132334Ssetje
3140Sstevel@tonic-gateif [ $# != 3 ] ; then
3150Sstevel@tonic-gate	usage
3160Sstevel@tonic-gate	exit 1
3170Sstevel@tonic-gatefi
3180Sstevel@tonic-gate
3191777SsetjeUNPACKED_ROOT="$3"
3201777SsetjeBASE="`pwd`"
3210Sstevel@tonic-gateMNT=/tmp/mnt$$
3222334SsetjeTMR=/tmp/mr$$
3232334SsetjeLOFIDEV=
3241777SsetjeMR="$2"
3250Sstevel@tonic-gate
3260Sstevel@tonic-gateif [ "`dirname $MR`" = . ] ; then
3271777Ssetje	MR="$BASE/$MR"
3280Sstevel@tonic-gatefi
3290Sstevel@tonic-gateif [ "`dirname $UNPACKED_ROOT`" = . ] ; then
3301777Ssetje	UNPACKED_ROOT="$BASE/$UNPACKED_ROOT"
3310Sstevel@tonic-gatefi
3320Sstevel@tonic-gate
3332334Ssetjetrap cleanup EXIT
3342334Ssetje
3350Sstevel@tonic-gatecase $1 in
3360Sstevel@tonic-gate	packmedia)
3371777Ssetje		MEDIA="$MR"
3381777Ssetje		MR="$MR/boot/x86.miniroot"
3391777Ssetje
3401777Ssetje		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
3411777Ssetje			archive_X "$MEDIA" "$UNPACKED_ROOT"
3421777Ssetje		else
3431777Ssetje			packmedia "$MEDIA" "$UNPACKED_ROOT"
3441777Ssetje			pack
3451777Ssetje		fi ;;
3460Sstevel@tonic-gate	unpackmedia)
3471777Ssetje		MEDIA="$MR"
3481777Ssetje		MR="$MR/boot/x86.miniroot"
3491777Ssetje
3501777Ssetje		if [ -d "$UNPACKED_ROOT/kernel/drv/sparcv9" ] ; then
3511777Ssetje			unarchive_X "$MEDIA" "$UNPACKED_ROOT"
3521777Ssetje		else
3531777Ssetje			unpack
3541777Ssetje			unpackmedia "$MEDIA" "$UNPACKED_ROOT"
3551777Ssetje		fi ;;
3560Sstevel@tonic-gate	pack)	pack ;;
3570Sstevel@tonic-gate	unpack)	unpack ;;
3580Sstevel@tonic-gate	*)	usage ;;
3590Sstevel@tonic-gateesac
360