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 330Sstevel@tonic-gate 340Sstevel@tonic-gateBOOT_ARCHIVE=platform/i86pc/boot_archive 353446SmrjBOOT_ARCHIVE_64=platform/i86pc/amd64/boot_archive 360Sstevel@tonic-gate 372334Ssetjeexport PATH=$PATH:/usr/sbin:/usr/bin:/sbin 380Sstevel@tonic-gate 390Sstevel@tonic-gate# 400Sstevel@tonic-gate# Parse options 410Sstevel@tonic-gate# 423446Smrjwhile [ "$1" != "" ] 430Sstevel@tonic-gatedo 443446Smrj case $1 in 453446Smrj -R) shift 463446Smrj ALT_ROOT="$1" 470Sstevel@tonic-gate if [ "$ALT_ROOT" != "/" ]; then 482334Ssetje echo "Creating ram disk for $ALT_ROOT" 490Sstevel@tonic-gate fi 500Sstevel@tonic-gate ;; 513467Srscott -n|--nocompress) compress=no 523467Srscott ;; 533446Smrj *) echo Usage: ${0##*/}: [-R \<root\>] [--nocompress] 543467Srscott exit 553467Srscott ;; 560Sstevel@tonic-gate esac 573446Smrj shift 580Sstevel@tonic-gatedone 590Sstevel@tonic-gate 600Sstevel@tonic-gateif [ -x /usr/bin/mkisofs -o -x /tmp/bfubin/mkisofs ] ; then 610Sstevel@tonic-gate format=isofs 620Sstevel@tonic-gatefi 630Sstevel@tonic-gate 64621Svikram# 65621Svikram# mkisofs on s8 doesn't support functionality used by GRUB boot. 66621Svikram# Use ufs format for boot archive instead. 67621Svikram# 68621Svikramrelease=`uname -r` 69621Svikramif [ "$release" = "5.8" ]; then 703446Smrj format=ufs 71621Svikramfi 72621Svikram 730Sstevel@tonic-gateshift `expr $OPTIND - 1` 740Sstevel@tonic-gate 750Sstevel@tonic-gateif [ $# -eq 1 ]; then 762334Ssetje ALT_ROOT="$1" 772334Ssetje echo "Creating ram disk for $ALT_ROOT" 780Sstevel@tonic-gatefi 790Sstevel@tonic-gate 803446Smrjrundir=`dirname $0` 813555Srscottif [ ! -x "$rundir"/symdef ]; then 823446Smrj # Shouldn't happen 833446Smrj echo "Warning: $rundir/symdef not present." 843446Smrj echo "Creating single archive at $ALT_ROOT/platform/i86pc/boot_archive" 853446Smrj SPLIT=no 863446Smrj compress=no 873555Srscottelif "$rundir"/symdef "$ALT_ROOT"/platform/i86pc/kernel/unix \ 883446Smrj dboot_image 2>/dev/null; then 893446Smrj SPLIT=yes 903446Smrjelse 913446Smrj SPLIT=no 923446Smrj compress=no 933446Smrjfi 943446Smrj 953446Smrj[ -x /usr/bin/gzip ] || compress=no 963446Smrj 972334Ssetjefunction cleanup 982334Ssetje{ 993446Smrj umount -f "$rdmnt32" 2>/dev/null 1003446Smrj umount -f "$rdmnt64" 2>/dev/null 1013446Smrj lofiadm -d "$rdfile32" 2>/dev/null 1023446Smrj lofiadm -d "$rdfile64" 2>/dev/null 1032334Ssetje rm -fr "$rddir" 2> /dev/null 1040Sstevel@tonic-gate} 1050Sstevel@tonic-gate 1062334Ssetjefunction getsize 1072334Ssetje{ 1082511Sjongkis # Estimate image size and add %10 overhead for ufs stuff. 1092511Sjongkis # Note, we can't use du here in case we're on a filesystem, e.g. zfs, 1102511Sjongkis # in which the disk usage is less than the sum of the file sizes. 1112511Sjongkis # The nawk code 1122511Sjongkis # 1132511Sjongkis # {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7} 1142511Sjongkis # 1152511Sjongkis # below rounds up the size of a file/directory, in bytes, to the 1162511Sjongkis # next multiple of 1024. This mimics the behavior of ufs especially 1172511Sjongkis # with directories. This results in a total size that's slightly 1182511Sjongkis # bigger than if du was called on a ufs directory. 1192851Sjongkis total_size=$(cd "/$ALT_ROOT" 1203446Smrj find $filelist -ls 2>/dev/null | nawk ' 1212851Sjongkis {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7} 1222851Sjongkis END {print int(t * 1.10 / 1024)}') 1230Sstevel@tonic-gate} 1240Sstevel@tonic-gate 1253446Smrj# 1263555Srscott# Copies all desired files to a target directory. 1273555Srscott# 1283555Srscott# This function depends on several variables that must be set before calling: 1293555Srscott# $ALT_ROOT - the target directory 1303555Srscott# $filelist - the list of files and directories to search 1313555Srscott# $NO_AMD64 - the find(1) expression to exclude files, if desired 1323555Srscott# $which - One of "both", "32-bit", or "64-bit" 1333555Srscott# $compress - whether or not the files in the archives should be compressed 1343555Srscott# $rdmnt - the target directory 1353555Srscott# 1363555Srscottfunction find_and_copy 1373555Srscott{ 1383555Srscott cd "/$ALT_ROOT" 1393555Srscott 1403555Srscott # 1413555Srscott # If compress is set, the files are gzip'd and put in the correct 1423555Srscott # location in the loop. Nothing is printed, so the pipe and cpio 1433555Srscott # at the end is a nop. 1443555Srscott # 1453555Srscott # If compress is not set, the file names are printed, which causes 1463555Srscott # the cpio at the end to do the copy. 1473555Srscott # 1483555Srscott find $filelist $NO_AMD64 -type f -print 2>/dev/null | while read path 1493555Srscott do 1503555Srscott if [ "$which" = "both" ]; then 1513555Srscott if [ $compress = yes ]; then 1523555Srscott dir="${path%/*}" 1533555Srscott mkdir -p "$rdmnt/$dir" 1543555Srscott /usr/bin/gzip -c "$path" > "$rdmnt/$path" 1553555Srscott else 1563555Srscott print "$path" 1573555Srscott fi 1583555Srscott else 159*3614Ssetje filetype=`LC_MESSAGES=C file $path 2>/dev/null |\ 1603555Srscott awk '/ELF/ { print \$3 }'` 1613555Srscott if [ -z "$filetype" ] || [ "$filetype" = "$which" ] 1623555Srscott then 1633555Srscott if [ $compress = yes ]; then 1643555Srscott dir="${path%/*}" 1653555Srscott mkdir -p "$rdmnt/$dir" 1663555Srscott /usr/bin/gzip -c "$path" > \ 1673555Srscott "$rdmnt/$path" 1683555Srscott else 1693555Srscott print "$path" 1703555Srscott fi 1713555Srscott fi 1723555Srscott fi 1733555Srscott done | cpio -pdum "$rdmnt" 2>/dev/null 1743555Srscott} 1753555Srscott 1763555Srscott# 1773446Smrj# The first argument can be: 1783446Smrj# 1793446Smrj# "both" - create an archive with both 32-bit and 64-bit binaries 1803446Smrj# "32-bit" - create an archive with only 32-bit binaries 1813446Smrj# "64-bit" - create an archive with only 64-bit binaries 1823446Smrj# 1830Sstevel@tonic-gatefunction create_ufs 1840Sstevel@tonic-gate{ 1853446Smrj which=$1 1863446Smrj archive=$2 1873446Smrj lofidev=$3 1880Sstevel@tonic-gate 1893446Smrj # should we exclude amd64 binaries? 1903446Smrj if [ "$which" = "32-bit" ]; then 1913446Smrj NO_AMD64="-type d -name amd64 -prune -o" 1923446Smrj rdfile="$rdfile32" 1933446Smrj rdmnt="$rdmnt32" 1943446Smrj elif [ "$which" = "64-bit" ]; then 1953446Smrj NO_AMD64="" 1963446Smrj rdfile="$rdfile64" 1973446Smrj rdmnt="$rdmnt64" 1983446Smrj else 1993446Smrj NO_AMD64="" 2003446Smrj rdfile="$rdfile32" 2013446Smrj rdmnt="$rdmnt32" 2023446Smrj fi 2033446Smrj 2042334Ssetje newfs $lofidev < /dev/null 2> /dev/null 2052334Ssetje mkdir "$rdmnt" 2060Sstevel@tonic-gate mount -F mntfs mnttab /etc/mnttab > /dev/null 2>&1 2072334Ssetje mount -o nologging $lofidev "$rdmnt" 2083446Smrj files= 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate # do the actual copy 2113555Srscott find_and_copy 2122334Ssetje umount "$rdmnt" 2132334Ssetje rmdir "$rdmnt" 2142334Ssetje 2153446Smrj # 2162334Ssetje # Check if gzip exists in /usr/bin, so we only try to run gzip 2172334Ssetje # on systems that have gzip. Then run gzip out of the patch to 2182334Ssetje # pick it up from bfubin or something like that if needed. 2192334Ssetje # 2203446Smrj # If compress is set, the individual files in the archive are 2213446Smrj # compressed, and the final compression will accomplish very 2223446Smrj # little. To save time, we skip the gzip in this case. 2233446Smrj # 2243446Smrj if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then 2253446Smrj gzip -c "$rdfile" > "${archive}-new" 2262334Ssetje else 2273446Smrj cat "$rdfile" > "${archive}-new" 2282334Ssetje fi 2290Sstevel@tonic-gate} 2300Sstevel@tonic-gate 2313446Smrj# 2323446Smrj# The first argument can be: 2333446Smrj# 2343446Smrj# "both" - create an archive with both 32-bit and 64-bit binaries 2353446Smrj# "32-bit" - create an archive with only 32-bit binaries 2363446Smrj# "64-bit" - create an archive with only 64-bit binaries 2373446Smrj# 2380Sstevel@tonic-gatefunction create_isofs 2390Sstevel@tonic-gate{ 2403446Smrj which=$1 2413446Smrj archive=$2 2423446Smrj 2430Sstevel@tonic-gate # should we exclude amd64 binaries? 2443446Smrj if [ "$which" = "32-bit" ]; then 2453446Smrj NO_AMD64="-type d -name amd64 -prune -o" 2463446Smrj rdmnt="$rdmnt32" 2473446Smrj errlog="$errlog32" 2483446Smrj elif [ "$which" = "64-bit" ]; then 2493446Smrj NO_AMD64="" 2503446Smrj rdmnt="$rdmnt64" 2513446Smrj errlog="$errlog64" 2523446Smrj else 2533446Smrj NO_AMD64="" 2543446Smrj rdmnt="$rdmnt32" 2553446Smrj errlog="$errlog32" 2563446Smrj fi 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate # create image directory seed with graft points 2592334Ssetje mkdir "$rdmnt" 2600Sstevel@tonic-gate files= 2613446Smrj isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames" 2623446Smrj 2633555Srscott find_and_copy 2642334Ssetje isocmd="$isocmd \"$rdmnt\"" 2652334Ssetje rm -f "$errlog" 2662334Ssetje 2673446Smrj # 2682334Ssetje # Check if gzip exists in /usr/bin, so we only try to run gzip 2692334Ssetje # on systems that have gzip. Then run gzip out of the patch to 2702334Ssetje # pick it up from bfubin or something like that if needed. 2712334Ssetje # 2723446Smrj # If compress is set, the individual files in the archive are 2733446Smrj # compressed, and the final compression will accomplish very 2743446Smrj # little. To save time, we skip the gzip in this case. 2753446Smrj # 2763446Smrj if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then 2772334Ssetje ksh -c "$isocmd" 2> "$errlog" | \ 2783446Smrj gzip > "${archive}-new" 2792334Ssetje else 2803446Smrj ksh -c "$isocmd" 2> "$errlog" > "${archive}-new" 2812334Ssetje fi 2822334Ssetje 2832334Ssetje if [ -s "$errlog" ]; then 2842334Ssetje grep Error: "$errlog" >/dev/null 2>&1 285174Sjg if [ $? -eq 0 ]; then 2862334Ssetje grep Error: "$errlog" 2873446Smrj rm -f "${archive}-new" 288174Sjg fi 289174Sjg fi 2902334Ssetje rm -f "$errlog" 2910Sstevel@tonic-gate} 2920Sstevel@tonic-gate 2933446Smrjfunction create_archive 2943446Smrj{ 2953446Smrj which=$1 2963446Smrj archive=$2 2973446Smrj lofidev=$3 2983446Smrj 2993446Smrj echo "updating $archive...this may take a minute" 3003446Smrj 3013446Smrj if [ "$format" = "ufs" ]; then 3023446Smrj create_ufs "$which" "$archive" "$lofidev" 3033446Smrj else 3043446Smrj create_isofs "$which" "$archive" 3053446Smrj fi 3063446Smrj 3073446Smrj # sanity check the archive before moving it into place 3083446Smrj # 3093555Srscott ARCHIVE_SIZE=`ls -l "${archive}-new" | nawk '{ print $5 }'` 3103446Smrj if [ $compress = yes ] 3113446Smrj then 3123446Smrj # 3133446Smrj # 'file' will report "English text" for uncompressed 3143446Smrj # boot_archives. Checking for that doesn't seem stable, 3153446Smrj # so we just check that the file exists. 3163446Smrj # 3173446Smrj ls "${archive}-new" >/dev/null 2>&1 3183446Smrj else 3193446Smrj # 3203446Smrj # the file type check also establishes that the 3213446Smrj # file exists at all 3223446Smrj # 323*3614Ssetje LC_MESSAGES=C file "${archive}-new" | grep gzip > /dev/null 3243446Smrj fi 3253446Smrj 3263446Smrj if [ $? = 1 ] && [ -x /usr/bin/gzip ] || [ $ARCHIVE_SIZE -lt 5000 ] 3273446Smrj then 3283446Smrj # 3293446Smrj # Two of these functions may be run in parallel. We 3303446Smrj # need to allow the other to clean up, so we can't 3313446Smrj # exit immediately. Instead, we set a flag. 3323446Smrj # 3333446Smrj echo "update of $archive failed" 3343446Smrj ERROR=1 3353446Smrj else 3363446Smrj lockfs -f "/$ALT_ROOT" 2>/dev/null 3373446Smrj mv "${archive}-new" "$archive" 3383446Smrj lockfs -f "/$ALT_ROOT" 2>/dev/null 3393446Smrj fi 3403446Smrj 3413446Smrj} 3423446Smrj 3430Sstevel@tonic-gate# 3440Sstevel@tonic-gate# get filelist 3450Sstevel@tonic-gate# 3463555Srscottif [ ! -f "$ALT_ROOT/boot/solaris/filelist.ramdisk" ] && 3473555Srscott [ ! -f "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" ] 3482851Sjongkisthen 3492851Sjongkis print -u2 "Can't find filelist.ramdisk" 3502851Sjongkis exit 1 3510Sstevel@tonic-gatefi 3523555Srscottfilelist=$(cat "$ALT_ROOT/boot/solaris/filelist.ramdisk" \ 3533555Srscott "$ALT_ROOT/etc/boot/solaris/filelist.ramdisk" 2>/dev/null | sort -u) 3540Sstevel@tonic-gate 3552334Ssetjescratch=tmp 3562334Ssetje 3572334Ssetjeif [ $format = ufs ] ; then 3582334Ssetje # calculate image size 3592334Ssetje getsize 3602334Ssetje 3613446Smrj # We do two mkfile's of total_size, so double the space 3623446Smrj (( tmp_needed = total_size * 2 )) 3633446Smrj 3642334Ssetje # check to see if there is sufficient space in tmpfs 3652334Ssetje # 3662334Ssetje tmp_free=`df -b /tmp | tail -1 | awk '{ printf ($2) }'` 3672334Ssetje (( tmp_free = tmp_free / 2 )) 3682334Ssetje 3693446Smrj if [ $tmp_needed -gt $tmp_free ] ; then 3702334Ssetje # assumes we have enough scratch space on $ALT_ROOT 3712334Ssetje scratch="$ALT_ROOT" 3722334Ssetje fi 3732334Ssetjefi 3742334Ssetje 3752334Ssetjerddir="/$scratch/create_ramdisk.$$.tmp" 3763446Smrjrdfile32="$rddir/rd.file.32" 3773446Smrjrdfile64="$rddir/rd.file.64" 3783446Smrjrdmnt32="$rddir/rd.mount.32" 3793446Smrjrdmnt64="$rddir/rd.mount.64" 3803446Smrjerrlog32="$rddir/rd.errlog.32" 3813446Smrjerrlog64="$rddir/rd.errlog.64" 3823446Smrjlofidev32="" 3833446Smrjlofidev64="" 3842334Ssetje 3852334Ssetje# make directory for temp files safely 3862334Ssetjerm -rf "$rddir" 3872334Ssetjemkdir "$rddir" 3882334Ssetje 3892334Ssetje# Clean up upon exit. 3902334Ssetjetrap 'cleanup' EXIT 3912334Ssetje 3923446Smrjif [ $SPLIT = yes ]; then 3933446Smrj # 3943446Smrj # We can't run lofiadm commands in parallel, so we have to do 3953446Smrj # them here. 3963446Smrj # 3973446Smrj if [ "$format" = "ufs" ]; then 3983446Smrj mkfile ${total_size}k "$rdfile32" 3993446Smrj lofidev32=`lofiadm -a "$rdfile32"` 4003446Smrj mkfile ${total_size}k "$rdfile64" 4013446Smrj lofidev64=`lofiadm -a "$rdfile64"` 4023446Smrj fi 4033446Smrj create_archive "32-bit" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 & 4043446Smrj create_archive "64-bit" "$ALT_ROOT/$BOOT_ARCHIVE_64" $lofidev64 4053446Smrj wait 4063446Smrj if [ "$format" = "ufs" ]; then 4073446Smrj lofiadm -d "$rdfile32" 4083446Smrj lofiadm -d "$rdfile64" 4093446Smrj fi 4100Sstevel@tonic-gateelse 4113446Smrj if [ "$format" = "ufs" ]; then 4123446Smrj mkfile ${total_size}k "$rdfile32" 4133446Smrj lofidev32=`lofiadm -a "$rdfile32"` 4143446Smrj fi 4153446Smrj create_archive "both" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 4163446Smrj [ "$format" = "ufs" ] && lofiadm -d "$rdfile32" 4170Sstevel@tonic-gatefi 4183446Smrjif [ $ERROR = 1 ]; then 4193446Smrj cleanup 420174Sjg exit 1 421174Sjgfi 422174Sjg 4230Sstevel@tonic-gate# 4240Sstevel@tonic-gate# For the diskless case, hardlink archive to /boot to make it 4250Sstevel@tonic-gate# visible via tftp. /boot is lofs mounted under /tftpboot/<hostname>. 4263446Smrj# NOTE: this script must work on both client and server. 4270Sstevel@tonic-gate# 4282334Ssetjegrep "[ ]/[ ]*nfs[ ]" "$ALT_ROOT/etc/vfstab" > /dev/null 4290Sstevel@tonic-gateif [ $? = 0 ]; then 4303446Smrj rm -f "$ALT_ROOT/boot/boot_archive" "$ALT_ROOT/boot/amd64/boot_archive" 4312334Ssetje ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/boot_archive" 4323446Smrj ln "$ALT_ROOT/$BOOT_ARCHIVE_64" "$ALT_ROOT/boot/amd64/boot_archive" 4330Sstevel@tonic-gatefi 4342334Ssetjerm -rf "$rddir" 435