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 233446Smrj# Copyright 2007 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= 303446Smrjcompress=yes 313446SmrjSPLIT=unknown 323446SmrjERROR=0 33*4213Srscottdirsize32=0 34*4213Srscottdirsize64=0 350Sstevel@tonic-gate 360Sstevel@tonic-gateBOOT_ARCHIVE=platform/i86pc/boot_archive 373446SmrjBOOT_ARCHIVE_64=platform/i86pc/amd64/boot_archive 380Sstevel@tonic-gate 392334Ssetjeexport PATH=$PATH:/usr/sbin:/usr/bin:/sbin 400Sstevel@tonic-gate 410Sstevel@tonic-gate# 420Sstevel@tonic-gate# Parse options 430Sstevel@tonic-gate# 443446Smrjwhile [ "$1" != "" ] 450Sstevel@tonic-gatedo 463446Smrj case $1 in 473446Smrj -R) shift 483446Smrj ALT_ROOT="$1" 490Sstevel@tonic-gate if [ "$ALT_ROOT" != "/" ]; then 502334Ssetje echo "Creating ram disk for $ALT_ROOT" 510Sstevel@tonic-gate fi 520Sstevel@tonic-gate ;; 533467Srscott -n|--nocompress) compress=no 543467Srscott ;; 553446Smrj *) echo Usage: ${0##*/}: [-R \<root\>] [--nocompress] 563467Srscott exit 573467Srscott ;; 580Sstevel@tonic-gate esac 593446Smrj shift 600Sstevel@tonic-gatedone 610Sstevel@tonic-gate 620Sstevel@tonic-gateif [ -x /usr/bin/mkisofs -o -x /tmp/bfubin/mkisofs ] ; then 630Sstevel@tonic-gate format=isofs 640Sstevel@tonic-gatefi 650Sstevel@tonic-gate 66621Svikram# 67621Svikram# mkisofs on s8 doesn't support functionality used by GRUB boot. 68621Svikram# Use ufs format for boot archive instead. 69621Svikram# 70621Svikramrelease=`uname -r` 71621Svikramif [ "$release" = "5.8" ]; then 723446Smrj format=ufs 73621Svikramfi 74621Svikram 750Sstevel@tonic-gateshift `expr $OPTIND - 1` 760Sstevel@tonic-gate 770Sstevel@tonic-gateif [ $# -eq 1 ]; then 782334Ssetje ALT_ROOT="$1" 792334Ssetje echo "Creating ram disk for $ALT_ROOT" 800Sstevel@tonic-gatefi 810Sstevel@tonic-gate 823446Smrjrundir=`dirname $0` 833555Srscottif [ ! -x "$rundir"/symdef ]; then 843446Smrj # Shouldn't happen 853446Smrj echo "Warning: $rundir/symdef not present." 863446Smrj echo "Creating single archive at $ALT_ROOT/platform/i86pc/boot_archive" 873446Smrj SPLIT=no 883446Smrj compress=no 893555Srscottelif "$rundir"/symdef "$ALT_ROOT"/platform/i86pc/kernel/unix \ 903446Smrj dboot_image 2>/dev/null; then 913446Smrj SPLIT=yes 923446Smrjelse 933446Smrj SPLIT=no 943446Smrj compress=no 953446Smrjfi 963446Smrj 973446Smrj[ -x /usr/bin/gzip ] || compress=no 983446Smrj 992334Ssetjefunction cleanup 1002334Ssetje{ 1013446Smrj umount -f "$rdmnt32" 2>/dev/null 1023446Smrj umount -f "$rdmnt64" 2>/dev/null 1033446Smrj lofiadm -d "$rdfile32" 2>/dev/null 1043446Smrj lofiadm -d "$rdfile64" 2>/dev/null 105*4213Srscott [ -n "$rddir" ] && rm -fr "$rddir" 2> /dev/null 106*4213Srscott [ -n "$new_rddir" ] && rm -fr "$new_rddir" 2>/dev/null 1070Sstevel@tonic-gate} 1080Sstevel@tonic-gate 1092334Ssetjefunction getsize 1102334Ssetje{ 111*4213Srscott # Estimate image size and add 10% overhead for ufs stuff. 1122511Sjongkis # Note, we can't use du here in case we're on a filesystem, e.g. zfs, 1132511Sjongkis # in which the disk usage is less than the sum of the file sizes. 1142511Sjongkis # The nawk code 1152511Sjongkis # 116*4213Srscott # {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} 1172511Sjongkis # 1182511Sjongkis # below rounds up the size of a file/directory, in bytes, to the 1192511Sjongkis # next multiple of 1024. This mimics the behavior of ufs especially 1202511Sjongkis # with directories. This results in a total size that's slightly 1212511Sjongkis # bigger than if du was called on a ufs directory. 122*4213Srscott size32=$(cat "$list32" | xargs -I {} ls -lLd "{}" | nawk ' 123*4213Srscott {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} 124*4213Srscott END {print int(t * 1.10 / 1024)}') 125*4213Srscott (( size32 += dirsize32 )) 126*4213Srscott size64=$(cat "$list64" | xargs -I {} ls -lLd "{}" | nawk ' 127*4213Srscott {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} 128*4213Srscott END {print int(t * 1.10 / 1024)}') 129*4213Srscott (( size64 += dirsize64 )) 130*4213Srscott (( total_size = size32 + size64 )) 1310Sstevel@tonic-gate} 1320Sstevel@tonic-gate 1333446Smrj# 134*4213Srscott# Copies all desired files to a target directory. One argument should be 135*4213Srscott# passed: the file containing the list of files to copy. This function also 136*4213Srscott# depends on several variables that must be set before calling: 1373555Srscott# 1383555Srscott# $ALT_ROOT - the target directory 1393555Srscott# $compress - whether or not the files in the archives should be compressed 1403555Srscott# $rdmnt - the target directory 1413555Srscott# 142*4213Srscottfunction copy_files 1433555Srscott{ 144*4213Srscott list="$1" 1453555Srscott 1463555Srscott # 1473555Srscott # If compress is set, the files are gzip'd and put in the correct 1483555Srscott # location in the loop. Nothing is printed, so the pipe and cpio 1493555Srscott # at the end is a nop. 1503555Srscott # 1513555Srscott # If compress is not set, the file names are printed, which causes 1523555Srscott # the cpio at the end to do the copy. 1533555Srscott # 154*4213Srscott while read path 1553555Srscott do 156*4213Srscott if [ $compress = yes ]; then 157*4213Srscott dir="${path%/*}" 158*4213Srscott mkdir -p "$rdmnt/$dir" 159*4213Srscott /usr/bin/gzip -c "$path" > "$rdmnt/$path" 1603555Srscott else 161*4213Srscott print "$path" 1623555Srscott fi 163*4213Srscott done <"$list" | cpio -pdum "$rdmnt" 2>/dev/null 1643555Srscott} 1653555Srscott 1663555Srscott# 1673446Smrj# The first argument can be: 1683446Smrj# 1693446Smrj# "both" - create an archive with both 32-bit and 64-bit binaries 1703446Smrj# "32-bit" - create an archive with only 32-bit binaries 1713446Smrj# "64-bit" - create an archive with only 64-bit binaries 1723446Smrj# 1730Sstevel@tonic-gatefunction create_ufs 1740Sstevel@tonic-gate{ 1753446Smrj which=$1 1763446Smrj archive=$2 1773446Smrj lofidev=$3 1780Sstevel@tonic-gate 1793446Smrj # should we exclude amd64 binaries? 1803446Smrj if [ "$which" = "32-bit" ]; then 1813446Smrj rdfile="$rdfile32" 1823446Smrj rdmnt="$rdmnt32" 183*4213Srscott list="$list32" 1843446Smrj elif [ "$which" = "64-bit" ]; then 1853446Smrj rdfile="$rdfile64" 1863446Smrj rdmnt="$rdmnt64" 187*4213Srscott list="$list64" 1883446Smrj else 1893446Smrj rdfile="$rdfile32" 1903446Smrj rdmnt="$rdmnt32" 191*4213Srscott list="$list32" 1923446Smrj fi 1933446Smrj 1942334Ssetje newfs $lofidev < /dev/null 2> /dev/null 1952334Ssetje mkdir "$rdmnt" 1960Sstevel@tonic-gate mount -F mntfs mnttab /etc/mnttab > /dev/null 2>&1 1972334Ssetje mount -o nologging $lofidev "$rdmnt" 1983446Smrj files= 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate # do the actual copy 201*4213Srscott copy_files "$list" 2022334Ssetje umount "$rdmnt" 2032334Ssetje rmdir "$rdmnt" 2042334Ssetje 2053446Smrj # 2062334Ssetje # Check if gzip exists in /usr/bin, so we only try to run gzip 2072334Ssetje # on systems that have gzip. Then run gzip out of the patch to 2082334Ssetje # pick it up from bfubin or something like that if needed. 2092334Ssetje # 2103446Smrj # If compress is set, the individual files in the archive are 2113446Smrj # compressed, and the final compression will accomplish very 2123446Smrj # little. To save time, we skip the gzip in this case. 2133446Smrj # 2143446Smrj if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then 2153446Smrj gzip -c "$rdfile" > "${archive}-new" 2162334Ssetje else 2173446Smrj cat "$rdfile" > "${archive}-new" 2182334Ssetje fi 2190Sstevel@tonic-gate} 2200Sstevel@tonic-gate 2213446Smrj# 2223446Smrj# The first argument can be: 2233446Smrj# 2243446Smrj# "both" - create an archive with both 32-bit and 64-bit binaries 2253446Smrj# "32-bit" - create an archive with only 32-bit binaries 2263446Smrj# "64-bit" - create an archive with only 64-bit binaries 2273446Smrj# 2280Sstevel@tonic-gatefunction create_isofs 2290Sstevel@tonic-gate{ 2303446Smrj which=$1 2313446Smrj archive=$2 2323446Smrj 2330Sstevel@tonic-gate # should we exclude amd64 binaries? 2343446Smrj if [ "$which" = "32-bit" ]; then 2353446Smrj rdmnt="$rdmnt32" 2363446Smrj errlog="$errlog32" 237*4213Srscott list="$list32" 2383446Smrj elif [ "$which" = "64-bit" ]; then 2393446Smrj rdmnt="$rdmnt64" 2403446Smrj errlog="$errlog64" 241*4213Srscott list="$list64" 2423446Smrj else 2433446Smrj rdmnt="$rdmnt32" 2443446Smrj errlog="$errlog32" 245*4213Srscott list="$list32" 2463446Smrj fi 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate # create image directory seed with graft points 2492334Ssetje mkdir "$rdmnt" 2500Sstevel@tonic-gate files= 2513446Smrj isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames" 2523446Smrj 253*4213Srscott copy_files "$list" 2542334Ssetje isocmd="$isocmd \"$rdmnt\"" 2552334Ssetje rm -f "$errlog" 2562334Ssetje 2573446Smrj # 2582334Ssetje # Check if gzip exists in /usr/bin, so we only try to run gzip 2592334Ssetje # on systems that have gzip. Then run gzip out of the patch to 2602334Ssetje # pick it up from bfubin or something like that if needed. 2612334Ssetje # 2623446Smrj # If compress is set, the individual files in the archive are 2633446Smrj # compressed, and the final compression will accomplish very 2643446Smrj # little. To save time, we skip the gzip in this case. 2653446Smrj # 2663446Smrj if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then 2672334Ssetje ksh -c "$isocmd" 2> "$errlog" | \ 2683446Smrj gzip > "${archive}-new" 2692334Ssetje else 2703446Smrj ksh -c "$isocmd" 2> "$errlog" > "${archive}-new" 2712334Ssetje fi 2722334Ssetje 2732334Ssetje if [ -s "$errlog" ]; then 2742334Ssetje grep Error: "$errlog" >/dev/null 2>&1 275174Sjg if [ $? -eq 0 ]; then 2762334Ssetje grep Error: "$errlog" 2773446Smrj rm -f "${archive}-new" 278174Sjg fi 279174Sjg fi 2802334Ssetje rm -f "$errlog" 2810Sstevel@tonic-gate} 2820Sstevel@tonic-gate 2833446Smrjfunction create_archive 2843446Smrj{ 2853446Smrj which=$1 2863446Smrj archive=$2 2873446Smrj lofidev=$3 2883446Smrj 2893446Smrj echo "updating $archive...this may take a minute" 2903446Smrj 2913446Smrj if [ "$format" = "ufs" ]; then 2923446Smrj create_ufs "$which" "$archive" "$lofidev" 2933446Smrj else 2943446Smrj create_isofs "$which" "$archive" 2953446Smrj fi 2963446Smrj 2973446Smrj # sanity check the archive before moving it into place 2983446Smrj # 2993555Srscott ARCHIVE_SIZE=`ls -l "${archive}-new" | nawk '{ print $5 }'` 3003446Smrj if [ $compress = yes ] 3013446Smrj then 3023446Smrj # 3033446Smrj # 'file' will report "English text" for uncompressed 3043446Smrj # boot_archives. Checking for that doesn't seem stable, 3053446Smrj # so we just check that the file exists. 3063446Smrj # 3073446Smrj ls "${archive}-new" >/dev/null 2>&1 3083446Smrj else 3093446Smrj # 3103446Smrj # the file type check also establishes that the 3113446Smrj # file exists at all 3123446Smrj # 3133614Ssetje LC_MESSAGES=C file "${archive}-new" | grep gzip > /dev/null 3143446Smrj fi 3153446Smrj 3163446Smrj if [ $? = 1 ] && [ -x /usr/bin/gzip ] || [ $ARCHIVE_SIZE -lt 5000 ] 3173446Smrj then 3183446Smrj # 3193446Smrj # Two of these functions may be run in parallel. We 3203446Smrj # need to allow the other to clean up, so we can't 3213446Smrj # exit immediately. Instead, we set a flag. 3223446Smrj # 3233446Smrj echo "update of $archive failed" 3243446Smrj ERROR=1 3253446Smrj else 3263446Smrj lockfs -f "/$ALT_ROOT" 2>/dev/null 3273446Smrj mv "${archive}-new" "$archive" 3283446Smrj lockfs -f "/$ALT_ROOT" 2>/dev/null 3293446Smrj fi 3303446Smrj 3313446Smrj} 3323446Smrj 333*4213Srscottfunction fatal_error 334*4213Srscott{ 335*4213Srscott print -u2 $* 336*4213Srscott exit 1 337*4213Srscott} 338*4213Srscott 3390Sstevel@tonic-gate# 3400Sstevel@tonic-gate# get filelist 3410Sstevel@tonic-gate# 3423555Srscottif [ ! -f "$ALT_ROOT/boot/solaris/filelist.ramdisk" ] && 3433555Srscott [ ! -f "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" ] 3442851Sjongkisthen 3452851Sjongkis print -u2 "Can't find filelist.ramdisk" 3462851Sjongkis exit 1 3470Sstevel@tonic-gatefi 3483555Srscottfilelist=$(cat "$ALT_ROOT/boot/solaris/filelist.ramdisk" \ 3493555Srscott "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" 2>/dev/null | sort -u) 3500Sstevel@tonic-gate 351*4213Srscott# 352*4213Srscott# We use /tmp/ for scratch space now. This may be changed later if there 353*4213Srscott# is insufficient space in /tmp/. 354*4213Srscott# 355*4213Srscottrddir="/tmp/create_ramdisk.$$.tmp" 356*4213Srscottnew_rddir= 357*4213Srscottrm -rf "$rddir" 358*4213Srscottmkdir "$rddir" || fatal_error "Could not create temporary directory $rddir" 359*4213Srscott 360*4213Srscott# Clean up upon exit. 361*4213Srscotttrap 'cleanup' EXIT 362*4213Srscott 363*4213Srscottlist32="$rddir/filelist.32" 364*4213Srscottlist64="$rddir/filelist.64" 365*4213Srscott 366*4213Srscott# 367*4213Srscott# This loop creates the 32-bit and 64-bit lists of files. The 32-bit list 368*4213Srscott# is written to stdout, which is redirected at the end of the loop. The 369*4213Srscott# 64-bit list is appended with each write. 370*4213Srscott# 371*4213Srscottcd "/$ALT_ROOT" 372*4213Srscottfind $filelist -print 2>/dev/null | while read path 373*4213Srscottdo 374*4213Srscott if [ $SPLIT = no ]; then 375*4213Srscott print "$path" 376*4213Srscott elif [ -d "$path" ]; then 377*4213Srscott if [ $format = ufs ]; then 378*4213Srscott size=`ls -lLd "$path" | nawk ' 379*4213Srscott {print ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5}'` 380*4213Srscott if [ `basename "$path"` != "amd64" ]; then 381*4213Srscott (( dirsize32 += size )) 382*4213Srscott fi 383*4213Srscott (( dirsize64 += size )) 384*4213Srscott fi 385*4213Srscott else 386*4213Srscott filetype=`LC_MESSAGES=C file "$path" 2>/dev/null |\ 387*4213Srscott awk '/ELF/ { print $3 }'` 388*4213Srscott if [ "$filetype" = "64-bit" ]; then 389*4213Srscott print "$path" >> "$list64" 390*4213Srscott elif [ "$filetype" = "32-bit" ]; then 391*4213Srscott print "$path" 392*4213Srscott else 393*4213Srscott # put in both lists 394*4213Srscott print "$path" 395*4213Srscott print "$path" >> "$list64" 396*4213Srscott fi 397*4213Srscott fi 398*4213Srscottdone >"$list32" 3992334Ssetje 4002334Ssetjeif [ $format = ufs ] ; then 4012334Ssetje # calculate image size 4022334Ssetje getsize 4032334Ssetje 4042334Ssetje # check to see if there is sufficient space in tmpfs 4052334Ssetje # 4062334Ssetje tmp_free=`df -b /tmp | tail -1 | awk '{ printf ($2) }'` 4072334Ssetje (( tmp_free = tmp_free / 2 )) 4082334Ssetje 409*4213Srscott if [ $total_size -gt $tmp_free ] ; then 4102334Ssetje # assumes we have enough scratch space on $ALT_ROOT 411*4213Srscott new_rddir="/$ALT_ROOT/create_ramdisk.$$.tmp" 412*4213Srscott rm -rf "$new_rddir" 413*4213Srscott mkdir "$new_rddir" || fatal_error \ 414*4213Srscott "Could not create temporary directory $new_rddir" 415*4213Srscott 416*4213Srscott # Save the file lists 417*4213Srscott mv "$list32" "$new_rddir"/ 418*4213Srscott mv "$list64" "$new_rddir"/ 419*4213Srscott list32="/$new_rddir/filelist.32" 420*4213Srscott list64="/$new_rddir/filelist.64" 421*4213Srscott 422*4213Srscott # Remove the old $rddir and set the new value of rddir 423*4213Srscott rm -rf "$rddir" 424*4213Srscott rddir="$new_rddir" 425*4213Srscott new_rddir= 4262334Ssetje fi 4272334Ssetjefi 4282334Ssetje 4293446Smrjrdfile32="$rddir/rd.file.32" 4303446Smrjrdfile64="$rddir/rd.file.64" 4313446Smrjrdmnt32="$rddir/rd.mount.32" 4323446Smrjrdmnt64="$rddir/rd.mount.64" 4333446Smrjerrlog32="$rddir/rd.errlog.32" 4343446Smrjerrlog64="$rddir/rd.errlog.64" 4353446Smrjlofidev32="" 4363446Smrjlofidev64="" 4372334Ssetje 4383446Smrjif [ $SPLIT = yes ]; then 4393446Smrj # 4403446Smrj # We can't run lofiadm commands in parallel, so we have to do 4413446Smrj # them here. 4423446Smrj # 4433446Smrj if [ "$format" = "ufs" ]; then 444*4213Srscott mkfile ${size32}k "$rdfile32" 4453446Smrj lofidev32=`lofiadm -a "$rdfile32"` 446*4213Srscott mkfile ${size64}k "$rdfile64" 4473446Smrj lofidev64=`lofiadm -a "$rdfile64"` 4483446Smrj fi 4493446Smrj create_archive "32-bit" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 & 4503446Smrj create_archive "64-bit" "$ALT_ROOT/$BOOT_ARCHIVE_64" $lofidev64 4513446Smrj wait 4523446Smrj if [ "$format" = "ufs" ]; then 4533446Smrj lofiadm -d "$rdfile32" 4543446Smrj lofiadm -d "$rdfile64" 4553446Smrj fi 4560Sstevel@tonic-gateelse 4573446Smrj if [ "$format" = "ufs" ]; then 4583446Smrj mkfile ${total_size}k "$rdfile32" 4593446Smrj lofidev32=`lofiadm -a "$rdfile32"` 4603446Smrj fi 4613446Smrj create_archive "both" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 4623446Smrj [ "$format" = "ufs" ] && lofiadm -d "$rdfile32" 4630Sstevel@tonic-gatefi 4643446Smrjif [ $ERROR = 1 ]; then 4653446Smrj cleanup 466174Sjg exit 1 467174Sjgfi 468174Sjg 4690Sstevel@tonic-gate# 4700Sstevel@tonic-gate# For the diskless case, hardlink archive to /boot to make it 4710Sstevel@tonic-gate# visible via tftp. /boot is lofs mounted under /tftpboot/<hostname>. 4723446Smrj# NOTE: this script must work on both client and server. 4730Sstevel@tonic-gate# 4742334Ssetjegrep "[ ]/[ ]*nfs[ ]" "$ALT_ROOT/etc/vfstab" > /dev/null 4750Sstevel@tonic-gateif [ $? = 0 ]; then 4763446Smrj rm -f "$ALT_ROOT/boot/boot_archive" "$ALT_ROOT/boot/amd64/boot_archive" 4772334Ssetje ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/boot_archive" 4783446Smrj ln "$ALT_ROOT/$BOOT_ARCHIVE_64" "$ALT_ROOT/boot/amd64/boot_archive" 4790Sstevel@tonic-gatefi 480*4213Srscott[ -n "$rddir" ] && rm -rf "$rddir" 481