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