| #!/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 <http://www.gnu.org/licenses/>. |
| # |
| # 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}" != "<empty>" ]; 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}" != "<empty>" ]; 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 |