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