xref: /illumos-gate/usr/src/cmd/boot/scripts/create_ramdisk.ksh (revision 60405de4d8688d96dd05157c28db3ade5c9bc234)
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
28format=ufs
29ALT_ROOT=
30NO_AMD64=
31
32BOOT_ARCHIVE=platform/i86pc/boot_archive
33
34export PATH=$PATH:/usr/sbin:/usr/bin:/sbin
35
36#
37# Parse options
38#
39while getopts R: OPT 2> /dev/null
40do
41        case $OPT in
42        R)      ALT_ROOT="$OPTARG"
43		if [ "$ALT_ROOT" != "/" ]; then
44			echo "Creating ram disk for $ALT_ROOT"
45		fi
46		;;
47        ?)      echo Usage: ${0##*/}: [-R \<root\>]
48		exit ;;
49        esac
50done
51
52if [ -x /usr/bin/mkisofs -o -x /tmp/bfubin/mkisofs ] ; then
53	format=isofs
54fi
55
56#
57# mkisofs on s8 doesn't support functionality used by GRUB boot.
58# Use ufs format for boot archive instead.
59#
60release=`uname -r`
61if [ "$release" = "5.8" ]; then
62   format=ufs
63fi
64
65shift `expr $OPTIND - 1`
66
67if [ $# -eq 1 ]; then
68	ALT_ROOT="$1"
69	echo "Creating ram disk for $ALT_ROOT"
70fi
71
72function cleanup
73{
74	umount -f "$rdmnt" 2>/dev/null
75	lofiadm -d "$rdfile" 2>/dev/null
76	rm -fr "$rddir" 2> /dev/null
77}
78
79function getsize
80{
81	# Estimate image size and add %10 overhead for ufs stuff.
82	# Note, we can't use du here in case we're on a filesystem, e.g. zfs,
83	# in which the disk usage is less than the sum of the file sizes.
84	# The nawk code
85	#
86	#	{t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
87	#
88	# below rounds up the size of a file/directory, in bytes, to the
89	# next multiple of 1024.  This mimics the behavior of ufs especially
90	# with directories.  This results in a total size that's slightly
91	# bigger than if du was called on a ufs directory.
92	total_size=$(cd "/$ALT_ROOT"; find $filelist -ls 2>/dev/null | nawk '
93	    {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7}
94	    END {print int(t * 1.10 / 1024)}')
95}
96
97function create_ufs
98{
99	# should we exclude amd64 binaries?
100	[ $is_amd64 -eq 0 ] && NO_AMD64="-name amd64 -prune"
101
102
103	mkfile ${total_size}k "$rdfile"
104	lofidev=`lofiadm -a "$rdfile"`
105	newfs $lofidev < /dev/null 2> /dev/null
106	mkdir "$rdmnt"
107	mount -F mntfs mnttab /etc/mnttab > /dev/null 2>&1
108	mount -o nologging $lofidev "$rdmnt"
109
110	# do the actual copy
111	cd "/$ALT_ROOT"
112
113	find $filelist -print $NO_AMD64 2> /dev/null | \
114	     cpio -pdum "$rdmnt" 2> /dev/null
115	umount "$rdmnt"
116	lofiadm -d "$rdfile"
117	rmdir "$rdmnt"
118
119	# Check if gzip exists in /usr/bin, so we only try to run gzip
120	# on systems that have gzip. Then run gzip out of the patch to
121	# pick it up from bfubin or something like that if needed.
122	#
123	if [ -x /usr/bin/gzip ] ; then
124		gzip -c "$rdfile" > "$ALT_ROOT/$BOOT_ARCHIVE-new"
125	else
126		cat "$rdfile" > "$ALT_ROOT/$BOOT_ARCHIVE-new"
127	fi
128}
129
130function create_isofs
131{
132	# should we exclude amd64 binaries?
133	[ $is_amd64 = 0 ] && NO_AMD64="-m amd64"
134
135	# create image directory seed with graft points
136	mkdir "$rdmnt"
137	files=
138	isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames $NO_AMD64"
139	for path in $filelist
140	do
141		if [ -d "$ALT_ROOT/$path" ]; then
142			isocmd="$isocmd $path/=\"$ALT_ROOT/$path\""
143			mkdir -p "$rdmnt/$path"
144		elif [ -f "$ALT_ROOT/$path" ]; then
145			files="$files $path"
146		fi
147	done
148	cd "/$ALT_ROOT"
149	find $files 2> /dev/null | cpio -pdum "$rdmnt" 2> /dev/null
150	isocmd="$isocmd \"$rdmnt\""
151	rm -f "$errlog"
152
153	# Check if gzip exists in /usr/bin, so we only try to run gzip
154	# on systems that have gzip. Then run gzip out of the patch to
155	# pick it up from bfubin or something like that if needed.
156	#
157	if [ -x /usr/bin/gzip ] ; then
158		ksh -c "$isocmd" 2> "$errlog" | \
159		    gzip > "$ALT_ROOT/$BOOT_ARCHIVE-new"
160	else
161		ksh -c "$isocmd" 2> "$errlog" > "$ALT_ROOT/$BOOT_ARCHIVE-new"
162	fi
163
164	if [ -s "$errlog" ]; then
165		grep Error: "$errlog" >/dev/null 2>&1
166		if [ $? -eq 0 ]; then
167			grep Error: "$errlog"
168			rm -f "$ALT_ROOT/$BOOT_ARCHIVE-new"
169		fi
170	fi
171	rm -f "$errlog"
172}
173
174#
175# get filelist
176#
177filelist=`cat "$ALT_ROOT/boot/solaris/filelist.ramdisk"`
178if [ -f "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" ]; then
179	filelistI=`cat "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk"`
180fi
181filelist=`echo $filelist $filelistI | sort -u`
182
183#
184# decide if cpu is amd64 capable
185#
186prtconf -v /devices | grep CPU_not_amd64 > /dev/null 2>&1
187is_amd64=$?
188
189scratch=tmp
190
191if [ $format = ufs ] ; then
192	# calculate image size
193	getsize
194
195	# check to see if there is sufficient space in tmpfs
196	#
197	tmp_free=`df -b /tmp | tail -1 | awk '{ printf ($2) }'`
198	(( tmp_free = tmp_free / 2 ))
199
200	if [ $total_size -gt $tmp_free  ] ; then
201		# assumes we have enough scratch space on $ALT_ROOT
202        	scratch="$ALT_ROOT"
203	fi
204fi
205
206rddir="/$scratch/create_ramdisk.$$.tmp"
207rdfile="$rddir/rd.file"
208rdmnt="$rddir/rd.mount"
209errlog="$rddir/rd.errlog"
210
211# make directory for temp files safely
212rm -rf "$rddir"
213mkdir "$rddir"
214
215# Clean up upon exit.
216trap 'cleanup' EXIT
217
218echo "updating $ALT_ROOT/$BOOT_ARCHIVE...this may take a minute"
219
220if [ $format = "ufs" ]; then
221	create_ufs
222else
223	create_isofs
224fi
225
226# sanity check the archive before moving it into place
227# the file type check also establishes that the file exists at all
228#
229ARCHIVE_SIZE=$(/bin/ls -l "$ALT_ROOT/$BOOT_ARCHIVE-new" |
230	nawk '{print int($5 / 1024)}')
231file "$ALT_ROOT/$BOOT_ARCHIVE-new" | grep gzip > /dev/null
232
233if [ $? = 1 ] && [ -x /usr/bin/gzip ] || [ $ARCHIVE_SIZE -lt 5000 ]; then
234	echo "update of $ALT_ROOT/$BOOT_ARCHIVE failed"
235	rm -rf "$rddir"
236	exit 1
237fi
238
239#
240# For the diskless case, hardlink archive to /boot to make it
241# visible via tftp. /boot is lofs mounted under /tftpboot/<hostname>.
242# NOTE: this script must work on both client and server
243#
244grep "[	 ]/[	 ]*nfs[	 ]" "$ALT_ROOT/etc/vfstab" > /dev/null
245if [ $? = 0 ]; then
246	mv "$ALT_ROOT/$BOOT_ARCHIVE-new" "$ALT_ROOT/$BOOT_ARCHIVE"
247	rm -f "$ALT_ROOT/boot/boot_archive"
248	ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/boot_archive"
249	rm -rf "$rddir"
250	exit
251fi
252
253lockfs -f "/$ALT_ROOT"
254mv "$ALT_ROOT/$BOOT_ARCHIVE-new" "$ALT_ROOT/$BOOT_ARCHIVE"
255lockfs -f "/$ALT_ROOT"
256
257rm -rf "$rddir"
258