#!/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