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.
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.
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]
23 # Copyright 2016 Toomas Soome <tsoome@me.com>
24 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
29 # Copyright (c) 2014 by Delphix. All rights reserved.
30 # Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
42 This utility is a component of the bootadm(1M) implementation and it is not
43 recommended for stand-alone use. Please use bootadm(1M) instead.
45 Usage: ${0##*/}: [-R <root>] [-p <platform>] [ -f <format> ] [--nocompress]
46 where <platform> is one of i86pc, sun4u or sun4v
47 and <format> is one of ufs, ufs-nocompress or cpio
52 # default platform is what we're running on
55 export PATH
=/usr
/sbin
:/usr
/bin
:/sbin
56 export GZIP_CMD
=/usr
/bin
/gzip
57 export CPIO_CMD
=/usr
/bin
/cpio
59 EXTRACT_FILELIST
="/boot/solaris/bin/extract_boot_filelist"
70 -n|
--nocompress) compress=no
74 EXTRACT_ARGS
="${EXTRACT_ARGS} -p ${PLATFORM}"
78 if [ "$ALT_ROOT" != "/" ]; then
79 echo "Creating boot_archive for $ALT_ROOT"
80 EXTRACT_ARGS
="${EXTRACT_ARGS} -R ${ALT_ROOT}"
81 EXTRACT_FILELIST
="${ALT_ROOT}${EXTRACT_FILELIST}"
90 shift `expr $OPTIND - 1`
94 echo "Creating boot_archive for $ALT_ROOT"
97 if [ -z "$FORMAT" ]; then
98 if [ -n "$ALT_ROOT" ]; then
99 SVCCFG_DTD
=/$ALT_ROOT/usr
/share
/lib
/xml
/dtd
/service_bundle.dtd
.1
100 SVCCFG_REPOSITORY
=/$ALT_ROOT/etc
/svc
/repository.db
101 export SVCCFG_DTD SVCCFG_REPOSITORY
103 FORMAT
=`svccfg -s system/boot-archive listprop config/format \
107 if [ $format_set -eq 0 -a "$FORMAT" = hsfs
]; then
108 if /sbin
/bootadm update-archive
-R ${ALT_ROOT:-/} -f -L -F hsfs
; then
111 echo "Failed to create HSFS archive, falling back."
115 [[ "$FORMAT" =~ ^
(cpio|ufs|ufs-nocompress
)$
]] || FORMAT
=ufs
118 i386|i86pc
) PLATFORM
=i86pc
121 BOOT_ARCHIVE_SUFFIX
=$ARCH64/boot_archive
123 sun4u|sun4v
) ISA
=sparc
125 BOOT_ARCHIVE_SUFFIX
=boot_archive
132 BOOT_ARCHIVE
=platform
/$PLATFORM/$BOOT_ARCHIVE_SUFFIX
140 [ -x $GZIP_CMD ] ||
compress=no
143 cpio) [ -x $CPIO_CMD ] || FORMAT
=ufs
;;
144 ufs-nocompress
) FORMAT
=ufs
; compress=no
;;
149 # Copies all desired files to a target directory. One argument should be
150 # passed: the file containing the list of files to copy. This function also
151 # depends on several variables that must be set before calling:
153 # $ALT_ROOT - the target directory
154 # $compress - whether or not the files in the archives should be compressed
155 # $rdmnt - the target directory
159 typeset listfile
="$1"
162 # If compress is set, the files are gzip'd and put in the correct
163 # location in the loop. Nothing is printed, so the pipe and cpio
164 # at the end is a nop.
166 # If compress is not set, the file names are printed, which causes
167 # the cpio at the end to do the copy.
170 if [ $compress = yes ]; then
172 [ -d "$rdmnt/$dir" ] || mkdir
-p "$rdmnt/$dir"
173 $GZIP_CMD -c "$path" > "$rdmnt/$path"
177 done <"$listfile" |
cpio -pdum "$rdmnt" 2>/dev
/null
179 if [ $ISA = sparc
] ; then
181 find $filelist -type l
-print 2>/dev
/null |\
182 cpio -pdum "$rdmnt" 2>/dev
/null
183 if [ $compress = yes ] ; then
184 # always copy unix uncompressed
185 find $filelist -name unix
-type f
-print 2>/dev
/null |\
186 cpio -pdum "$rdmnt" 2>/dev
/null
194 umount
-f "$rdmnt" 2>/dev
/null
195 lofiadm
-d "$rdfile" 2>/dev
/null
196 [ -n "$rddir" ] && rm -fr "$rddir" 2> /dev
/null
197 [ -n "$new_rddir" ] && rm -fr "$new_rddir" 2>/dev
/null
202 # Estimate image size and add 10% overhead for ufs stuff.
203 # Note, we can't use du here in case we're on a filesystem, e.g. zfs,
204 # in which the disk usage is less than the sum of the file sizes.
207 # {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5}
209 # below rounds up the size of a file/directory, in bytes, to the
210 # next multiple of 1024. This mimics the behavior of ufs especially
211 # with directories. This results in a total size that's slightly
212 # bigger than if du was called on a ufs directory.
213 size
=$
(cat "$list" |
xargs -I {} ls -lLd "{}" 2> /dev
/null |
214 nawk
'{t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5}
215 END {print int(t * 1.10 / 1024)}')
216 (( size
+= dirsize
))
217 (( total_size
= size
))
218 # If compression is enabled, then each file within the archive will
219 # be individually compressed. The compression ratio is around 60%
220 # across the archive so make the image smaller.
221 [ $compress = yes ] && (( total_size
= total_size
/ 2 ))
224 function create_ufs_archive
226 typeset archive
="$ALT_ROOT/$BOOT_ARCHIVE"
228 [ "$compress" = yes ] && \
229 echo "updating $archive (UFS)" || \
230 echo "updating $archive (UFS-nocompress)"
233 # We use /tmp/ for scratch space now. This will be changed later to
234 # $ALT_ROOT/var/tmp if there is insufficient space in /tmp/.
236 rddir
="/tmp/create_ramdisk.$$.tmp"
239 mkdir
"$rddir" || fatal_error
"Could not create directory $rddir"
241 # Clean up upon exit.
242 trap 'ufs_cleanup' EXIT
244 list
="$rddir/filelist"
246 cd "/$ALT_ROOT" || fatal_error
"Cannot chdir to $ALT_ROOT"
247 find $filelist -print 2>/dev
/null |
while read path
; do
248 if [ -d "$path" ]; then
249 size
=`ls -lLd "$path" | nawk '
250 {print ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5}'`
251 (( dirsize
+= size
/ 1024 ))
257 # calculate image size
260 # check to see if there is sufficient space in tmpfs
262 tmp_free
=`df -b /tmp | tail -1 | awk '{ print $2 }'`
263 (( tmp_free
= tmp_free
/ 3 ))
265 if [ $total_size -gt $tmp_free ] ; then
266 echo "Insufficient space in /tmp, using $ALT_ROOT/var/tmp"
267 # assumes we have enough scratch space on $ALT_ROOT
268 new_rddir
="/$ALT_ROOT/var/tmp/create_ramdisk.$$.tmp"
270 mkdir
"$new_rddir" || fatal_error \
271 "Could not create temporary directory $new_rddir"
273 # Save the file lists
274 mv "$list" "$new_rddir"/
275 list
="/$new_rddir/filelist"
277 # Remove the old $rddir and set the new value of rddir
283 rdfile
="$rddir/rd.file"
284 rdmnt
="$rddir/rd.mount"
285 errlog
="$rddir/rd.errlog"
288 mkfile
${total_size}k
"$rdfile" || \
289 fatal_error
"Could not create backing file"
290 lofidev
=`lofiadm -a "$rdfile"` || \
291 fatal_error
"Could not create lofi device"
293 NOINUSE_CHECK
=1 newfs
-m 0 $lofidev < /dev
/null
2> /dev
/null
295 mount
-F mntfs mnttab
/etc
/mnttab
> /dev
/null
2>&1
296 mount
-F ufs
-o nologging
$lofidev "$rdmnt"
297 rm -rf "$rdmnt/lost+found"
304 if [ $ISA = sparc
] ; then
305 rlofidev
="${lofidev/lofi/rlofi}"
306 bb
="/$ALT_ROOT/platform/$PLATFORM/lib/fs/ufs/bootblk"
307 # installboot is not available on all platforms
308 dd if=$bb of
=$rlofidev bs
=1b oseek
=1 count
=15 conv
=sync
2>&1
314 # Check if gzip exists in /usr/bin, so we only try to run gzip
315 # on systems that have gzip. Then run gzip out of the patch to
316 # pick it up from bfubin or something like that if needed.
318 # If compress is set, the individual files in the archive are
319 # compressed, and the final compression will accomplish very
320 # little. To save time, we skip the gzip in this case.
322 if [ $ISA = i386
] && [ $compress = no
] && [ -x $GZIP_CMD ] ; then
323 $GZIP_CMD -c "$rdfile" > "${archive}-new"
325 cat "$rdfile" > "${archive}-new"
328 if [ $?
-ne 0 ] ; then
329 rm -f "${archive}-new"
332 # sanity check the archive before moving it into place
334 ARCHIVE_SIZE
=`ls -l "${archive}-new" 2> /dev/null | nawk '{ print $5 }'`
335 if [ $compress = yes ] ||
[ $ISA = sparc
] ; then
337 # 'file' will report "English text" for uncompressed
338 # boot_archives. Checking for that doesn't seem stable,
339 # so we just check that the file exists.
341 ls "${archive}-new" >/dev
/null
2>&1
344 # the file type check also establishes that the
347 LC_MESSAGES
=C
file "${archive}-new" |
grep gzip > /dev
/null
350 if [ $?
= 1 ] && [ -x $GZIP_CMD ] ||
[ "$ARCHIVE_SIZE" -lt 10000 ]
352 fatal_error
"update of $archive failed"
354 lockfs
-f "/$ALT_ROOT" 2>/dev
/null
355 rm -f "$archive.hash"
356 mv "${archive}-new" "$archive"
357 digest
-a sha1
"$rdfile" > "$archive.hash"
358 lockfs
-f "/$ALT_ROOT" 2>/dev
/null
360 [ -n "$rddir" ] && rm -rf "$rddir"
363 function cpio_cleanup
365 rm -f "$tarchive" "$tarchive.cpio" "$tarchive.hash"
368 function create_cpio_archive
370 typeset archive
="$ALT_ROOT/$BOOT_ARCHIVE"
372 echo "updating $archive (CPIO)"
374 tarchive
="$archive.$$.new"
376 # Clean up upon exit.
377 trap 'cpio_cleanup' EXIT
379 cd "/$ALT_ROOT" || fatal_error
"Cannot chdir to $ALT_ROOT"
382 || fatal_error
"Cannot create temporary archive $tarchive"
384 find $filelist 2>/dev
/null |
cpio -qo -H odc
> "$tarchive.cpio" \
385 || fatal_error
"Problem creating archive"
387 [ -x /usr
/bin
/digest
] \
388 && /usr
/bin
/digest
-a sha1
"$tarchive.cpio" \
391 if [ -x "$GZIP_CMD" ]; then
392 $GZIP_CMD -c "$tarchive.cpio" > "$tarchive"
393 rm -f "$tarchive.cpio"
395 mv "$tarchive.cpio" "$tarchive"
398 # Move new archive into place
399 [ -f "$archive.hash" ] && rm -f "$archive.hash"
400 mv "$tarchive" "$archive"
401 [ $?
-eq 0 -a -f "$tarchive.hash" ] \
402 && mv "$tarchive.hash" "$archive.hash"
408 if [ ! -f "$ALT_ROOT/boot/solaris/filelist.ramdisk" ] &&
409 [ ! -f "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" ]
411 print
-u2 "Can't find filelist.ramdisk"
414 filelist
=$
($EXTRACT_FILELIST $EXTRACT_ARGS \
415 /boot
/solaris
/filelist.ramdisk \
416 /etc
/boot
/solaris
/filelist.ramdisk \
417 2>/dev
/null |
sort -u)
419 # Now that we have the list of files, we can create the archive.
422 cpio) create_cpio_archive
;;
423 ufs
) create_ufs_archive
;;
424 *) print
-u2 "Unknown boot archive format, $FORMAT"
430 # For the diskless case, hardlink archive to /boot to make it
431 # visible via tftp. /boot is lofs mounted under /tftpboot/<hostname>.
432 # NOTE: this script must work on both client and server.
434 grep "[ ]/[ ]*nfs[ ]" "$ALT_ROOT/etc/vfstab" > /dev
/null
436 rm -f "$ALT_ROOT/boot/$BOOT_ARCHIVE_SUFFIX"
437 mkdir
-p "$ALT_ROOT/boot/`dirname $BOOT_ARCHIVE_SUFFIX`"
438 ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/$BOOT_ARCHIVE_SUFFIX"