10Sstevel@tonic-gate#!/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
62334Ssetje# Common Development and Distribution License (the "License").
72334Ssetje# 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
232334Ssetje# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate# Use is subject to license terms.
250Sstevel@tonic-gate
262334Ssetje# ident	"%Z%%M%	%I%	%E% SMI"
27174Sjg
280Sstevel@tonic-gateformat=ufs
290Sstevel@tonic-gateALT_ROOT=
300Sstevel@tonic-gateNO_AMD64=
310Sstevel@tonic-gate
320Sstevel@tonic-gateBOOT_ARCHIVE=platform/i86pc/boot_archive
330Sstevel@tonic-gate
342334Ssetjeexport PATH=$PATH:/usr/sbin:/usr/bin:/sbin
350Sstevel@tonic-gate
360Sstevel@tonic-gate#
370Sstevel@tonic-gate# Parse options
380Sstevel@tonic-gate#
390Sstevel@tonic-gatewhile getopts R: OPT 2> /dev/null
400Sstevel@tonic-gatedo
410Sstevel@tonic-gate        case $OPT in
420Sstevel@tonic-gate        R)      ALT_ROOT="$OPTARG"
430Sstevel@tonic-gate		if [ "$ALT_ROOT" != "/" ]; then
442334Ssetje			echo "Creating ram disk for $ALT_ROOT"
450Sstevel@tonic-gate		fi
460Sstevel@tonic-gate		;;
470Sstevel@tonic-gate        ?)      echo Usage: ${0##*/}: [-R \<root\>]
480Sstevel@tonic-gate		exit ;;
490Sstevel@tonic-gate        esac
500Sstevel@tonic-gatedone
510Sstevel@tonic-gate
520Sstevel@tonic-gateif [ -x /usr/bin/mkisofs -o -x /tmp/bfubin/mkisofs ] ; then
530Sstevel@tonic-gate	format=isofs
540Sstevel@tonic-gatefi
550Sstevel@tonic-gate
56621Svikram#
57621Svikram# mkisofs on s8 doesn't support functionality used by GRUB boot.
58621Svikram# Use ufs format for boot archive instead.
59621Svikram#
60621Svikramrelease=`uname -r`
61621Svikramif [ "$release" = "5.8" ]; then
62621Svikram   format=ufs
63621Svikramfi
64621Svikram
650Sstevel@tonic-gateshift `expr $OPTIND - 1`
660Sstevel@tonic-gate
670Sstevel@tonic-gateif [ $# -eq 1 ]; then
682334Ssetje	ALT_ROOT="$1"
692334Ssetje	echo "Creating ram disk for $ALT_ROOT"
700Sstevel@tonic-gatefi
710Sstevel@tonic-gate
722334Ssetjefunction cleanup
732334Ssetje{
742334Ssetje	umount -f "$rdmnt" 2>/dev/null
752334Ssetje	lofiadm -d "$rdfile" 2>/dev/null
762334Ssetje	rm -fr "$rddir" 2> /dev/null
770Sstevel@tonic-gate}
780Sstevel@tonic-gate
792334Ssetjefunction getsize
802334Ssetje{
81*2851Sjongkis	# should we exclude amd64 binaries?
82*2851Sjongkis	[ $is_amd64 -eq 0 ] && NO_AMD64="-type d -name amd64 -prune -o"
83*2851Sjongkis
842511Sjongkis	# Estimate image size and add %10 overhead for ufs stuff.
852511Sjongkis	# Note, we can't use du here in case we're on a filesystem, e.g. zfs,
862511Sjongkis	# in which the disk usage is less than the sum of the file sizes.
872511Sjongkis	# The nawk code
882511Sjongkis	#
892511Sjongkis	#	{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
902511Sjongkis	#
912511Sjongkis	# below rounds up the size of a file/directory, in bytes, to the
922511Sjongkis	# next multiple of 1024.  This mimics the behavior of ufs especially
932511Sjongkis	# with directories.  This results in a total size that's slightly
942511Sjongkis	# bigger than if du was called on a ufs directory.
95*2851Sjongkis	total_size=$(cd "/$ALT_ROOT"
96*2851Sjongkis		find $filelist $NO_AMD64 -ls 2>/dev/null | nawk '
97*2851Sjongkis			{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
98*2851Sjongkis			END {print int(t * 1.10 / 1024)}')
990Sstevel@tonic-gate}
1000Sstevel@tonic-gate
1010Sstevel@tonic-gatefunction create_ufs
1020Sstevel@tonic-gate{
1030Sstevel@tonic-gate	# should we exclude amd64 binaries?
104*2851Sjongkis	[ $is_amd64 -eq 0 ] && NO_AMD64="-type d -name amd64 -prune -o"
1050Sstevel@tonic-gate
1062334Ssetje	mkfile ${total_size}k "$rdfile"
1072334Ssetje	lofidev=`lofiadm -a "$rdfile"`
1082334Ssetje	newfs $lofidev < /dev/null 2> /dev/null
1092334Ssetje	mkdir "$rdmnt"
1100Sstevel@tonic-gate	mount -F mntfs mnttab /etc/mnttab > /dev/null 2>&1
1112334Ssetje	mount -o nologging $lofidev "$rdmnt"
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate	# do the actual copy
1142334Ssetje	cd "/$ALT_ROOT"
1152334Ssetje
116*2851Sjongkis	find $filelist $NO_AMD64 -print 2> /dev/null | \
1172334Ssetje	     cpio -pdum "$rdmnt" 2> /dev/null
1182334Ssetje	umount "$rdmnt"
1192334Ssetje	lofiadm -d "$rdfile"
1202334Ssetje	rmdir "$rdmnt"
1212334Ssetje
1222334Ssetje	# Check if gzip exists in /usr/bin, so we only try to run gzip
1232334Ssetje	# on systems that have gzip. Then run gzip out of the patch to
1242334Ssetje	# pick it up from bfubin or something like that if needed.
1252334Ssetje	#
1262334Ssetje	if [ -x /usr/bin/gzip ] ; then
1272334Ssetje		gzip -c "$rdfile" > "$ALT_ROOT/$BOOT_ARCHIVE-new"
1282334Ssetje	else
1292334Ssetje		cat "$rdfile" > "$ALT_ROOT/$BOOT_ARCHIVE-new"
1302334Ssetje	fi
1310Sstevel@tonic-gate}
1320Sstevel@tonic-gate
1330Sstevel@tonic-gatefunction create_isofs
1340Sstevel@tonic-gate{
1350Sstevel@tonic-gate	# should we exclude amd64 binaries?
1360Sstevel@tonic-gate	[ $is_amd64 = 0 ] && NO_AMD64="-m amd64"
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate	# create image directory seed with graft points
1392334Ssetje	mkdir "$rdmnt"
1400Sstevel@tonic-gate	files=
1412334Ssetje	isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames $NO_AMD64"
1420Sstevel@tonic-gate	for path in $filelist
1430Sstevel@tonic-gate	do
1442334Ssetje		if [ -d "$ALT_ROOT/$path" ]; then
1452334Ssetje			isocmd="$isocmd $path/=\"$ALT_ROOT/$path\""
1462334Ssetje			mkdir -p "$rdmnt/$path"
1472334Ssetje		elif [ -f "$ALT_ROOT/$path" ]; then
1480Sstevel@tonic-gate			files="$files $path"
1490Sstevel@tonic-gate		fi
1500Sstevel@tonic-gate	done
1512334Ssetje	cd "/$ALT_ROOT"
1522334Ssetje	find $files 2> /dev/null | cpio -pdum "$rdmnt" 2> /dev/null
1532334Ssetje	isocmd="$isocmd \"$rdmnt\""
1542334Ssetje	rm -f "$errlog"
1552334Ssetje
1562334Ssetje	# Check if gzip exists in /usr/bin, so we only try to run gzip
1572334Ssetje	# on systems that have gzip. Then run gzip out of the patch to
1582334Ssetje	# pick it up from bfubin or something like that if needed.
1592334Ssetje	#
1602334Ssetje	if [ -x /usr/bin/gzip ] ; then
1612334Ssetje		ksh -c "$isocmd" 2> "$errlog" | \
1622334Ssetje		    gzip > "$ALT_ROOT/$BOOT_ARCHIVE-new"
1632334Ssetje	else
1642334Ssetje		ksh -c "$isocmd" 2> "$errlog" > "$ALT_ROOT/$BOOT_ARCHIVE-new"
1652334Ssetje	fi
1662334Ssetje
1672334Ssetje	if [ -s "$errlog" ]; then
1682334Ssetje		grep Error: "$errlog" >/dev/null 2>&1
169174Sjg		if [ $? -eq 0 ]; then
1702334Ssetje			grep Error: "$errlog"
1712334Ssetje			rm -f "$ALT_ROOT/$BOOT_ARCHIVE-new"
172174Sjg		fi
173174Sjg	fi
1742334Ssetje	rm -f "$errlog"
1750Sstevel@tonic-gate}
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate#
1780Sstevel@tonic-gate# get filelist
1790Sstevel@tonic-gate#
180*2851Sjongkisfiles=$(ls "$ALT_ROOT/boot/solaris/filelist.ramdisk" \
181*2851Sjongkis	"$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" 2>/dev/null)
182*2851Sjongkisif [[ -z "$files" ]]
183*2851Sjongkisthen
184*2851Sjongkis	print -u2 "Can't find filelist.ramdisk"
185*2851Sjongkis	exit 1
1860Sstevel@tonic-gatefi
187*2851Sjongkisfilelist=$(sort -u $files)
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate#
1900Sstevel@tonic-gate# decide if cpu is amd64 capable
1910Sstevel@tonic-gate#
1920Sstevel@tonic-gateprtconf -v /devices | grep CPU_not_amd64 > /dev/null 2>&1
1930Sstevel@tonic-gateis_amd64=$?
1940Sstevel@tonic-gate
1952334Ssetjescratch=tmp
1962334Ssetje
1972334Ssetjeif [ $format = ufs ] ; then
1982334Ssetje	# calculate image size
1992334Ssetje	getsize
2002334Ssetje
2012334Ssetje	# check to see if there is sufficient space in tmpfs
2022334Ssetje	#
2032334Ssetje	tmp_free=`df -b /tmp | tail -1 | awk '{ printf ($2) }'`
2042334Ssetje	(( tmp_free = tmp_free / 2 ))
2052334Ssetje
2062334Ssetje	if [ $total_size -gt $tmp_free  ] ; then
2072334Ssetje		# assumes we have enough scratch space on $ALT_ROOT
2082334Ssetje        	scratch="$ALT_ROOT"
2092334Ssetje	fi
2102334Ssetjefi
2112334Ssetje
2122334Ssetjerddir="/$scratch/create_ramdisk.$$.tmp"
2132334Ssetjerdfile="$rddir/rd.file"
2142334Ssetjerdmnt="$rddir/rd.mount"
2152334Ssetjeerrlog="$rddir/rd.errlog"
2162334Ssetje
2172334Ssetje# make directory for temp files safely
2182334Ssetjerm -rf "$rddir"
2192334Ssetjemkdir "$rddir"
2202334Ssetje
2212334Ssetje# Clean up upon exit.
2222334Ssetjetrap 'cleanup' EXIT
2232334Ssetje
2242334Ssetjeecho "updating $ALT_ROOT/$BOOT_ARCHIVE...this may take a minute"
2250Sstevel@tonic-gate
2260Sstevel@tonic-gateif [ $format = "ufs" ]; then
2270Sstevel@tonic-gate	create_ufs
2280Sstevel@tonic-gateelse
2290Sstevel@tonic-gate	create_isofs
2300Sstevel@tonic-gatefi
2310Sstevel@tonic-gate
232*2851Sjongkis# Make sure $BOOT_ARCHIVE-new created by either create_ufs or creat_isofs
233*2851Sjongkis# above is flushed to the backing store before we do anything with it.
234*2851Sjongkislockfs -f "/$ALT_ROOT"
235*2851Sjongkis
2362334Ssetje# sanity check the archive before moving it into place
2372334Ssetje# the file type check also establishes that the file exists at all
2382334Ssetje#
2392511SjongkisARCHIVE_SIZE=$(/bin/ls -l "$ALT_ROOT/$BOOT_ARCHIVE-new" |
2402511Sjongkis	nawk '{print int($5 / 1024)}')
2412334Ssetjefile "$ALT_ROOT/$BOOT_ARCHIVE-new" | grep gzip > /dev/null
2422334Ssetje
2432334Ssetjeif [ $? = 1 ] && [ -x /usr/bin/gzip ] || [ $ARCHIVE_SIZE -lt 5000 ]; then
2442334Ssetje	echo "update of $ALT_ROOT/$BOOT_ARCHIVE failed"
2452334Ssetje	rm -rf "$rddir"
246174Sjg	exit 1
247174Sjgfi
248174Sjg
2490Sstevel@tonic-gate#
2500Sstevel@tonic-gate# For the diskless case, hardlink archive to /boot to make it
2510Sstevel@tonic-gate# visible via tftp. /boot is lofs mounted under /tftpboot/<hostname>.
2520Sstevel@tonic-gate# NOTE: this script must work on both client and server
2530Sstevel@tonic-gate#
2542334Ssetjegrep "[	 ]/[	 ]*nfs[	 ]" "$ALT_ROOT/etc/vfstab" > /dev/null
2550Sstevel@tonic-gateif [ $? = 0 ]; then
2562334Ssetje	mv "$ALT_ROOT/$BOOT_ARCHIVE-new" "$ALT_ROOT/$BOOT_ARCHIVE"
2572334Ssetje	rm -f "$ALT_ROOT/boot/boot_archive"
2582334Ssetje	ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/boot_archive"
2592334Ssetje	rm -rf "$rddir"
2600Sstevel@tonic-gate	exit
2610Sstevel@tonic-gatefi
2620Sstevel@tonic-gate
2632334Ssetjemv "$ALT_ROOT/$BOOT_ARCHIVE-new" "$ALT_ROOT/$BOOT_ARCHIVE"
2642334Ssetjelockfs -f "/$ALT_ROOT"
265174Sjg
2662334Ssetjerm -rf "$rddir"
267