#!/bin/bash --norc # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh # # Copyright 2005-2009 Red Hat, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # code taken from mkinitrd # #. /usr/libexec/initrd-functions IF_verbose="" function set_verbose() { case $1 in 1|true|yes|on) IF_verbose="-v" ;; 0|false|no|off) IF_verbose="" ;; esac } function is_verbose() { [ -n "$IF_verbose" ] && return 0 return 1 } function get_verbose() { echo "$IF_verbose" is_verbose } function get_numeric_dev() { ( fmt="%d:%d" if [ "$1" == "hex" ]; then fmt="%x:%x" fi ls -lH "$2" | awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }' ) 2>/dev/null } function error() { echo "$@" >&2 } function vecho() { is_verbose && echo "$@" } # module dep finding and installation functions moduledep() { MPARGS="" if [ "$1" == "--ignore-install" ]; then MPARGS="$MPARGS --ignore-install" shift fi vecho -n "Looking for deps of module $1" deps="" deps=$(modprobe $MPARGS --set-version $kernel --quiet --show-depends $1 | awk '/^insmod / { print gensub(".*/","","g",$2) }' | while read foo ; do [ "${foo%%.ko}" != "$1" ] && echo -n "${foo%%.ko} " ; done) [ -n "$deps" ] && vecho ": $deps" || vecho } export MALLOC_PERTURB_=204 PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH export PATH # Set the umask. For iscsi, the initrd can contain plaintext # password (chap secret), so only allow read by owner. umask 077 VERSION=6.0.87 PROBE="yes" MODULES="" GRAPHICSMODS="" PREMODS="" DMRAIDS="" ncryptodevs=0 ncryptoparts=0 ncryptolvs=0 ncryptoraids=0 root="" scsi_wait_scan="no" NET_LIST="" LD_SO_CONF=/etc/ld.so.conf LD_SO_CONF_D=/etc/ld.so.conf.d/ [ -e /etc/sysconfig/mkinitrd ] && . /etc/sysconfig/mkinitrd CONFMODS="$MODULES" MODULES="" ARCH=$(uname -m | sed -e 's/s390x/s390/') compress=1 allowmissing="" target="" kernel="" force="" img_vers="" builtins="" modulefile=/etc/modules.conf [ "$ARCH" != "s390" ] && withusb=1 rc=0 nolvm="" nodmraid="" IMAGESIZE=8000 PRESCSIMODS="" fstab="/etc/fstab" vg_list="" net_list="$NET_LIST" usage () { if [ "$1" == "-n" ]; then cmd=echo else cmd=error fi $cmd "usage: `basename $0` [--version] [--help] [-v] [-f]" if [ "$1" == "-n" ]; then exit 0 else exit 1 fi } qpushd() { pushd "$1" >/dev/null 2>&1 } qpopd() { popd >/dev/null 2>&1 } freadlink() { readlink -f "$1" } resolve_device_name() { if [ -z "${1##UUID=*}" ]; then real=$(freadlink /dev/disk/by-uuid/${1##UUID=}) [ -b $real ] && { echo $real; return; } fi if [ -z "${1##LABEL=*}" ]; then real=$(freadlink /dev/disk/by-label/${1##LABEL=}) [ -b $real ] && { echo $real; return; } fi echo "$1" } finddevnoinsys() { majmin="$1" if [ -n "$majmin" ]; then dev=$(for x in /sys/block/* ; do find $x/ -name dev ; done | while read device ; do \ echo "$majmin" | cmp -s $device && echo $device ; done) if [ -n "$dev" ]; then dev=${dev%%/dev} dev=${dev%%/} echo "$dev" return 0 fi fi return 1 } finddevicedriverinsys () { if is_iscsi $PWD; then handleiscsi "$PWD" return fi while [ "$PWD" != "/sys/devices" ]; do deps= if [ -f modalias ]; then MODALIAS=$(cat modalias) if [ "${MODALIAS::7}" == "scsi:t-" ]; then scsi_wait_scan=yes fi moduledep $MODALIAS unset MODALIAS fi cd .. done } findstoragedriverinsys () { local sysfs=$(freadlink "$1") # if its a partition look at the device holding the partition if [ -f "$sysfs/start" ]; then sysfs=$(freadlink ${sysfs%/*}) fi if [[ ! "$sysfs" =~ ^/sys/.*block/.*$ ]]; then #error "WARNING: $sysfs is a not a block sysfs path, skipping" return fi case " $handleddevices " in *" $sysfs "*) return ;; *) handleddevices="$handleddevices $sysfs" ;; esac if [[ "$sysfs" =~ ^/sys/.*block/md[0-9]+$ ]]; then local raid=${sysfs##*/} vecho "Found MDRAID component $raid" handleraid $raid fi if [[ "$sysfs" =~ ^/sys/.*block/dm-[0-9]+$ ]]; then vecho "Found DeviceMapper component ${sysfs##*/}" handledm $(cat $sysfs/dev |cut -d : -f 1) $(cat $sysfs/dev |cut -d : -f 2) fi for slave in $(ls -d "$sysfs"/slaves/* 2>/dev/null) ; do findstoragedriverinsys "$slave" done if [ -L "$sysfs/device" ]; then qpushd $(freadlink "$sysfs/device") finddevicedriverinsys qpopd fi } findstoragedriver () { local device="$1" if [ ! -b "$device" ]; then #error "WARNING: $device is a not a block device, skipping" return fi local majmin=$(get_numeric_dev dec "$device") local sysfs=$(finddevnoinsys "$majmin") if [ -z "$sysfs" ]; then #error "WARNING: $device major:minor $majmin not found, skipping" return fi vecho "Looking for driver for $device in $sysfs" findstoragedriverinsys "$sysfs" } iscsi_get_rec_val() { # The open-iscsi 742 release changed to using flat files in # /var/lib/iscsi. result=$(grep "^${2} = " "$1" | sed -e s'/.* = //') } iscsi_set_parameters() { path=$1 vecho setting iscsi parameters tmpfile=$(mktemp) # Check once before getting explicit values, so we can output a decent # error message. /sbin/iscsiadm --show -m session -r $path > $tmpfile if [ ! -s $tmpfile ]; then echo Unable to find iscsi record for $path exit 1 fi nit_name=$(grep "^InitiatorName=" /etc/iscsi/initiatorname.iscsi | \ sed -e "s/^InitiatorName=//") iscsi_get_rec_val $tmpfile "node.name" tgt_name=${result} iscsi_get_rec_val $tmpfile "node.tpgt" tpgt=${result} # iscsistart wants node.conn[0].address / port iscsi_get_rec_val $tmpfile 'node.conn\[0\].address' tgt_ipaddr=${result} iscsi_get_rec_val $tmpfile 'node.conn\[0\].port' tgt_port=${result} # Note: we get chap secrets (passwords) in plaintext, and also store # them in the initrd. iscsi_get_rec_val $tmpfile "node.session.auth.username" chap=${result} if [ -n "${chap}" -a "${chap}" != "" ]; then chap="-u ${chap}" iscsi_get_rec_val $tmpfile "node.session.auth.password" chap_pw="-w ${result}" else chap="" fi iscsi_get_rec_val $tmpfile "node.session.auth.username_in" chap_in=${result} if [ -n "${chap_in}" -a "${chap_in}" != "" ]; then chap_in="-U ${chap_in}" iscsi_get_rec_val $tmpfile "node.session.auth.password_in" chap_in_pw="-W ${result}" else chap_in="" fi rm $tmpfile } emit_iscsi () { if [ -n "${iscsi_devs}" ]; then for dev in ${iscsi_devs}; do iscsi_set_parameters $dev # recid is not really used, just use 0 for it echo "/bin/iscsistart -t ${tgt_name} -i ${nit_name} \ -g ${tpgt} -a ${tgt_ipaddr} ${chap} ${chap_pw} \ ${chap_in} ${chap_in_pw}" done fi } is_iscsi() { path=$1 if echo $path | grep -q "/platform/host[0-9]*/session[0-9]*/target[0-9]*:[0-9]*:[0-9]*/[0-9]*:[0-9]*:[0-9]*:[0-9]*"; then return 0 else return 1 fi } handledm() { major=$1 minor=$2 while read dmstart dmend dmtype r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 ; do case "$dmtype" in crypt) # this device is encrypted; find the slave device and see # whether the encryption is LUKS; if not, bail. slavedev=$(finddevnoinsys $r3) # get the basename, then s,!,/, in case it's a cciss device slavedev=$(echo ${slavedev##*/} | tr '!' '/') cryptsetup isLuks "/dev/$slavedev" 2>/dev/null || continue find_base_dm_mods dmname=$(dmsetup info -j $major -m $minor -c --noheadings -o name) # do the device resolution dance to get /dev/mapper/foo # since 'lvm lvs' doesn't like dm-X device nodes if [[ "$slavedev" =~ ^dm- ]]; then majmin=$(get_numeric_dev dec "/dev/$slavedev") for dmdev in /dev/mapper/* ; do dmnum=$(get_numeric_dev dev $dmdev) if [ $dmnum = $majmin ]; then slavedev=${dmdev#/dev/} break fi done fi # determine if $slavedev is an LV # if so, add the device to latecryptodevs # if not, add the device to cryptodevs local vg=$(lvshow /dev/$slavedev) if [ -n "$vg" ]; then eval cryptolv${ncryptolvs}='"'/dev/$slavedev $dmname'"' let ncryptolvs++ elif grep -q "^$slavedev :" /proc/mdstat ; then eval cryptoraid${ncryptoraids}='"'/dev/$slavedev $dmname'"' let ncryptoraids++ else eval cryptoparts${ncryptoparts}='"'/dev/$slavedev $dmname'"' let ncryptoparts++ fi let ncryptodevs++ findstoragedriver "/dev/$slavedev" ;; esac done << EOF $(dmsetup table -j $major -m $minor 2>/dev/null) EOF local name=$(dmsetup info --noheadings -c -j $major -m $minor -o name) local vg=$(lvshow "/dev/mapper/$name") local raids=$(/sbin/dmraid -s -craidname 2>/dev/null | grep -vi "no raid disks") if [ -n "$vg" ]; then vg=`echo $vg` # strip whitespace case " $vg_list " in *" $vg "*) ;; *) vg_list="$vg_list $vg" [ -z "$nolvm" ] && find_base_dm_mods ;; esac fi for raid in $raids ; do if [ "$raid" == "$name" ]; then case " $DMRAIDS " in *" $raid "*) ;; *) DMRAIDS="$DMRAIDS $raid" [ -z "$nodmraid" ] && find_base_dm_mods ;; esac break fi done } handleiscsi() { vecho "Found iscsi component $1" # We call iscsi_set_parameters once here to figure out what network to # use (it sets tgt_ipaddr), and once again to emit iscsi values, # not very efficient. iscsi_set_parameters $1 iscsi_devs="$iscsi_devs $1" netdev=$(/sbin/ip route get to $tgt_ipaddr | \ sed 's|.*dev \(.*\).*|\1|g' | awk '{ print $1; exit }') addnetdev $netdev } handleraid() { local start=0 if [ -n "$noraid" -o ! -f /proc/mdstat ]; then return 0 fi levels=$(awk "/^$1[ ]*:/ { print\$4 }" /proc/mdstat) for level in $levels ; do case $level in linear) start=1 ;; multipath) start=1 ;; raid[01] | raid10) start=1 ;; raid[456]) start=1 ;; *) error "raid level $level (in /proc/mdstat) not recognized" ;; esac done if [ "$start" = 1 ]; then raiddevices="$raiddevices $1" fi return $start } lvshow() { lvm lvs --ignorelockingfailure --noheadings -o vg_name \ $1 2>/dev/null | egrep -v '^ *(WARNING:|Volume Groups with)' } vgdisplay() { lvm vgdisplay --ignorelockingfailure -v $1 2>/dev/null | sed -n 's/PV Name//p' } dmmods_found="n" find_base_dm_mods() { [ "$dmmods_found" == "n" ] || return dmmods_found="y" } savedargs=$* while [ $# -gt 0 ]; do case $1 in --fstab*) if [ "$1" != "${1##--fstab=}" ]; then fstab=${1##--fstab=} else fstab=$2 shift fi ;; -v|--verbose) set_verbose true ;; --net-dev*) if [ "$1" != "${1##--net-dev=}" ]; then net_list="$net_list ${1##--net-dev=}" else net_list="$net_list $2" shift fi ;; --rootdev*) if [ "$1" != "${1##--rootdev=}" ]; then rootdev="${1##--rootdev=}" else rootdev="$2" shift fi ;; --thawdev*) if [ "$1" != "${1##--thawdev=}" ]; then thawdev="${1##--thawdev=}" else thawdev="$2" shift fi ;; --rootfs*) if [ "$1" != "${1##--rootfs=}" ]; then rootfs="${1##--rootfs=}" else rootfs="$2" shift fi ;; --rootopts*) if [ "$1" != "${1##--rootopts=}" ]; then rootopts="${1##--rootopts=}" else rootopts="$2" shift fi ;; --root*) if [ "$1" != "${1##--root=}" ]; then root="${1##--root=}" else root="$2" shift fi ;; --loopdev*) if [ "$1" != "${1##--loopdev=}" ]; then loopdev="${1##--loopdev=}" else loopdev="$2" shift fi ;; --loopfs*) if [ "$1" != "${1##--loopfs=}" ]; then loopfs="${1##--loopfs=}" else loopfs="$2" shift fi ;; --loopopts*) if [ "$1" != "${1##--loopopts=}" ]; then loopopts="${1##--loopopts=}" else loopopts="$2" shift fi ;; --looppath*) if [ "$1" != "${1##--looppath=}" ]; then looppath="${1##--looppath=}" else looppath="$2" shift fi ;; --help) usage -n ;; *) if [ -z "$target" ]; then target=$1 elif [ -z "$kernel" ]; then kernel=$1 else usage fi ;; esac shift done [ -z "$rootfs" ] && rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' $fstab) [ -z "$rootopts" ] && rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' $fstab) [ -z "$rootopts" ] && rootopts="defaults" [ -z "$rootdev" ] && rootdev=$(awk '/^[ \t]*[^#]/ { if ($2 == "/") { print $1; }}' $fstab) # check if it's nfsroot physdev="" if [ "$rootfs" == "nfs" ]; then if [ "x$net_list" == "x" ]; then handlenfs $rootdev fi else # check if it's root by label rdev=$rootdev rdev=$(resolve_device_name "$rdev") rootopts=$(echo $rootopts | sed -e 's/^r[ow],//' -e 's/,_netdev//' -e 's/_netdev//' -e 's/,_rnetdev//' -e 's/_rnetdev//' -e 's/,r[ow],$//' -e 's/,r[ow],/,/' -e 's/^r[ow]$/defaults/' -e 's/$/,ro/') findstoragedriver "$rdev" fi # find the first swap dev which would get used for swsusp [ -z "$thawdev" ] && thawdev=$(awk '/^[ \t]*[^#]/ { if ($3 == "swap") { print $1; exit }}' $fstab) swsuspdev="$thawdev" if [ -n "$swsuspdev" ]; then swsuspdev=$(resolve_device_name "$swsuspdev") findstoragedriver "$swsuspdev" fi cemit() { cat } emit() { NONL="" if [ "$1" == "-n" ]; then NONL="-n" shift fi echo $NONL "$@" } emitdmraids() { if [ -z "$nodmraid" -a -n "$DMRAIDS" ]; then for raid in $DMRAIDS; do echo -n "rd_DM_UUID=$raid " done fi } # HACK: module loading + device creation isn't necessarily synchronous... # this will make sure that we have all of our devices before trying # things like RAID or LVM emitdmraids emitcrypto() { local luksuuid=$(grep "^$2 " /etc/crypttab 2>/dev/null| awk '{ print $2 }') if [ -z "$luksuuid" ]; then luksuuid="$2" fi luksuuid=${luksuuid##UUID=} echo -n "rd_LUKS_UUID=$luksuuid " } if [ -n "$raiddevices" ]; then for dev in $raiddevices; do uid=$(udevadm info --query=env --name /dev/${dev}|grep MD_UUID) uid=${uid##MD_UUID=} [ -n "$uid" ] && echo -n "rd_MD_UUID=$uid " done else echo -n "rd_NO_MD " fi if [ -z "$nolvm" -a -n "$vg_list" ]; then for vg in $vg_list; do echo -n "rd_LVM_VG=$vg " done else echo -n "rd_NO_LVM " fi cryptdevs="$(echo ${!cryptoraid@} ${!cryptopart@} ${!cryptolv@})" if [ -z "$cryptdevs" ]; then echo -n "rd_NO_LUKS " else for cryptdev in ${!cryptoraid@} ${!cryptopart@} ${!cryptolv@} ; do emitcrypto `eval echo '$'$cryptdev` done fi # output local keyboard/18n settings [ -e /etc/sysconfig/keyboard ] && . /etc/sysconfig/keyboard [ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n for i in KEYTABLE SYSFONT SYSFONTACM UNIMAP LANG; do val=$(eval echo \$$i) [[ $val ]] && echo -n "$i=$val " done if [ -n "$KEYBOARDTYPE" -a "$KEYBOARDTYPE" != "pc" ]; then echo -n "KEYBOARDTYPE=$KEYBOARDTYPE " fi if [ -n "$rootdev" ]; then echo -n "root=$rootdev " fi echo