crypt-lib.sh: moved IFS=: from before 'read' to before 'while'
[dracut.git] / dracut-gencmdline
blob90e49065b4b43eb74ecefdd6980435b54e238904
1 #!/bin/bash --norc
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
5 # Copyright 2005-2009 Red Hat, Inc. All rights reserved.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 # code taken from mkinitrd
22 #. /usr/libexec/initrd-functions
24 IF_verbose=""
25 function set_verbose() {
26 case $1 in
27 1|true|yes|on)
28 IF_verbose="-v"
30 0|false|no|off)
31 IF_verbose=""
33 esac
36 function is_verbose() {
37 [ -n "$IF_verbose" ] && return 0
38 return 1
41 function get_verbose() {
42 echo "$IF_verbose"
43 is_verbose
47 function get_numeric_dev() {
49 fmt="%d:%d"
50 if [ "$1" == "hex" ]; then
51 fmt="%x:%x"
53 ls -lH "$2" | awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }'
54 ) 2>/dev/null
58 function error() {
59 echo "$@" >&2
62 function vecho() {
63 is_verbose && echo "$@"
66 # module dep finding and installation functions
67 moduledep() {
68 MPARGS=""
69 if [ "$1" == "--ignore-install" ]; then
70 MPARGS="$MPARGS --ignore-install"
71 shift
73 vecho -n "Looking for deps of module $1"
74 deps=""
75 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)
76 [ -n "$deps" ] && vecho ": $deps" || vecho
79 export MALLOC_PERTURB_=204
81 PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH
82 export PATH
84 # Set the umask. For iscsi, the initrd can contain plaintext
85 # password (chap secret), so only allow read by owner.
86 umask 077
88 VERSION=6.0.87
90 PROBE="yes"
91 MODULES=""
92 GRAPHICSMODS=""
93 PREMODS=""
94 DMRAIDS=""
95 ncryptodevs=0
96 ncryptoparts=0
97 ncryptolvs=0
98 ncryptoraids=0
99 root=""
100 scsi_wait_scan="no"
102 NET_LIST=""
103 LD_SO_CONF=/etc/ld.so.conf
104 LD_SO_CONF_D=/etc/ld.so.conf.d/
106 [ -e /etc/sysconfig/mkinitrd ] && . /etc/sysconfig/mkinitrd
108 CONFMODS="$MODULES"
109 MODULES=""
110 ARCH=$(uname -m | sed -e 's/s390x/s390/')
112 compress=1
113 allowmissing=""
114 target=""
115 kernel=""
116 force=""
117 img_vers=""
118 builtins=""
119 modulefile=/etc/modules.conf
120 [ "$ARCH" != "s390" ] && withusb=1
121 rc=0
122 nolvm=""
123 nodmraid=""
125 IMAGESIZE=8000
126 PRESCSIMODS=""
127 fstab="/etc/fstab"
129 vg_list=""
130 net_list="$NET_LIST"
132 usage () {
133 if [ "$1" == "-n" ]; then
134 cmd=echo
135 else
136 cmd=error
139 $cmd "usage: `basename $0` [--version] [--help] [-v] [-f]"
141 if [ "$1" == "-n" ]; then
142 exit 0
143 else
144 exit 1
149 qpushd() {
150 pushd "$1" >/dev/null 2>&1
153 qpopd() {
154 popd >/dev/null 2>&1
158 freadlink() {
159 readlink -f "$1"
162 resolve_device_name() {
163 if [ -z "${1##UUID=*}" ]; then
164 real=$(freadlink /dev/disk/by-uuid/${1##UUID=})
165 [ -b $real ] && { echo $real; return; }
167 if [ -z "${1##LABEL=*}" ]; then
168 real=$(freadlink /dev/disk/by-label/${1##LABEL=})
169 [ -b $real ] && { echo $real; return; }
171 echo "$1"
174 finddevnoinsys() {
175 majmin="$1"
176 if [ -n "$majmin" ]; then
177 dev=$(for x in /sys/block/* ; do find $x/ -name dev ; done | while read device ; do \
178 echo "$majmin" | cmp -s $device && echo $device ; done)
179 if [ -n "$dev" ]; then
180 dev=${dev%%/dev}
181 dev=${dev%%/}
182 echo "$dev"
183 return 0
186 return 1
189 finddevicedriverinsys () {
190 if is_iscsi $PWD; then
191 handleiscsi "$PWD"
192 return
194 while [ "$PWD" != "/sys/devices" ]; do
195 deps=
196 if [ -f modalias ]; then
197 MODALIAS=$(cat modalias)
198 if [ "${MODALIAS::7}" == "scsi:t-" ]; then
199 scsi_wait_scan=yes
201 moduledep $MODALIAS
202 unset MODALIAS
205 cd ..
206 done
209 findstoragedriverinsys () {
210 local sysfs=$(freadlink "$1")
212 # if its a partition look at the device holding the partition
213 if [ -f "$sysfs/start" ]; then
214 sysfs=$(freadlink ${sysfs%/*})
217 if [[ ! "$sysfs" =~ ^/sys/.*block/.*$ ]]; then
218 #error "WARNING: $sysfs is a not a block sysfs path, skipping"
219 return
222 case " $handleddevices " in
223 *" $sysfs "*)
224 return ;;
225 *) handleddevices="$handleddevices $sysfs" ;;
226 esac
228 if [[ "$sysfs" =~ ^/sys/.*block/md[0-9]+$ ]]; then
229 local raid=${sysfs##*/}
230 vecho "Found MDRAID component $raid"
231 handleraid $raid
233 if [[ "$sysfs" =~ ^/sys/.*block/dm-[0-9]+$ ]]; then
234 vecho "Found DeviceMapper component ${sysfs##*/}"
235 handledm $(cat $sysfs/dev |cut -d : -f 1) $(cat $sysfs/dev |cut -d : -f 2)
238 for slave in $(ls -d "$sysfs"/slaves/* 2>/dev/null) ; do
239 findstoragedriverinsys "$slave"
240 done
242 if [ -L "$sysfs/device" ]; then
243 qpushd $(freadlink "$sysfs/device")
244 finddevicedriverinsys
245 qpopd
249 findstoragedriver () {
250 local device="$1"
252 if [ ! -b "$device" ]; then
253 #error "WARNING: $device is a not a block device, skipping"
254 return
257 local majmin=$(get_numeric_dev dec "$device")
258 local sysfs=$(finddevnoinsys "$majmin")
260 if [ -z "$sysfs" ]; then
261 #error "WARNING: $device major:minor $majmin not found, skipping"
262 return
265 vecho "Looking for driver for $device in $sysfs"
266 findstoragedriverinsys "$sysfs"
269 iscsi_get_rec_val() {
271 # The open-iscsi 742 release changed to using flat files in
272 # /var/lib/iscsi.
274 result=$(grep "^${2} = " "$1" | sed -e s'/.* = //')
277 iscsi_set_parameters() {
278 path=$1
279 vecho setting iscsi parameters
281 tmpfile=$(mktemp)
283 # Check once before getting explicit values, so we can output a decent
284 # error message.
285 /sbin/iscsiadm --show -m session -r $path > $tmpfile
286 if [ ! -s $tmpfile ]; then
287 echo Unable to find iscsi record for $path
288 exit 1
291 nit_name=$(grep "^InitiatorName=" /etc/iscsi/initiatorname.iscsi | \
292 sed -e "s/^InitiatorName=//")
294 iscsi_get_rec_val $tmpfile "node.name"
295 tgt_name=${result}
296 iscsi_get_rec_val $tmpfile "node.tpgt"
297 tpgt=${result}
298 # iscsistart wants node.conn[0].address / port
299 iscsi_get_rec_val $tmpfile 'node.conn\[0\].address'
300 tgt_ipaddr=${result}
301 iscsi_get_rec_val $tmpfile 'node.conn\[0\].port'
302 tgt_port=${result}
304 # Note: we get chap secrets (passwords) in plaintext, and also store
305 # them in the initrd.
307 iscsi_get_rec_val $tmpfile "node.session.auth.username"
308 chap=${result}
309 if [ -n "${chap}" -a "${chap}" != "<empty>" ]; then
310 chap="-u ${chap}"
311 iscsi_get_rec_val $tmpfile "node.session.auth.password"
312 chap_pw="-w ${result}"
313 else
314 chap=""
317 iscsi_get_rec_val $tmpfile "node.session.auth.username_in"
318 chap_in=${result}
319 if [ -n "${chap_in}" -a "${chap_in}" != "<empty>" ]; then
320 chap_in="-U ${chap_in}"
321 iscsi_get_rec_val $tmpfile "node.session.auth.password_in"
322 chap_in_pw="-W ${result}"
323 else
324 chap_in=""
327 rm $tmpfile
330 emit_iscsi () {
331 if [ -n "${iscsi_devs}" ]; then
332 for dev in ${iscsi_devs}; do
333 iscsi_set_parameters $dev
334 # recid is not really used, just use 0 for it
335 echo "/bin/iscsistart -t ${tgt_name} -i ${nit_name} \
336 -g ${tpgt} -a ${tgt_ipaddr} ${chap} ${chap_pw} \
337 ${chap_in} ${chap_in_pw}"
338 done
342 is_iscsi() {
343 path=$1
344 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
345 return 0
346 else
347 return 1
351 handledm() {
352 major=$1
353 minor=$2
354 while read dmstart dmend dmtype r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 ; do
355 case "$dmtype" in
356 crypt)
357 # this device is encrypted; find the slave device and see
358 # whether the encryption is LUKS; if not, bail.
359 slavedev=$(finddevnoinsys $r3)
360 # get the basename, then s,!,/, in case it's a cciss device
361 slavedev=$(echo ${slavedev##*/} | tr '!' '/')
362 cryptsetup isLuks "/dev/$slavedev" 2>/dev/null || continue
363 find_base_dm_mods
364 dmname=$(dmsetup info -j $major -m $minor -c --noheadings -o name)
365 # do the device resolution dance to get /dev/mapper/foo
366 # since 'lvm lvs' doesn't like dm-X device nodes
367 if [[ "$slavedev" =~ ^dm- ]]; then
368 majmin=$(get_numeric_dev dec "/dev/$slavedev")
369 for dmdev in /dev/mapper/* ; do
370 dmnum=$(get_numeric_dev dev $dmdev)
371 if [ $dmnum = $majmin ]; then
372 slavedev=${dmdev#/dev/}
373 break
375 done
378 # determine if $slavedev is an LV
379 # if so, add the device to latecryptodevs
380 # if not, add the device to cryptodevs
381 local vg=$(lvshow /dev/$slavedev)
382 if [ -n "$vg" ]; then
383 eval cryptolv${ncryptolvs}='"'/dev/$slavedev $dmname'"'
384 let ncryptolvs++
385 elif grep -q "^$slavedev :" /proc/mdstat ; then
386 eval cryptoraid${ncryptoraids}='"'/dev/$slavedev $dmname'"'
387 let ncryptoraids++
388 else
389 eval cryptoparts${ncryptoparts}='"'/dev/$slavedev $dmname'"'
390 let ncryptoparts++
393 let ncryptodevs++
394 findstoragedriver "/dev/$slavedev"
396 esac
397 done << EOF
398 $(dmsetup table -j $major -m $minor 2>/dev/null)
400 local name=$(dmsetup info --noheadings -c -j $major -m $minor -o name)
401 local vg=$(lvshow "/dev/mapper/$name")
402 local raids=$(/sbin/dmraid -s -craidname 2>/dev/null | grep -vi "no raid disks")
403 if [ -n "$vg" ]; then
404 vg=`echo $vg` # strip whitespace
405 case " $vg_list " in
406 *" $vg "*) ;;
407 *) vg_list="$vg_list $vg"
408 [ -z "$nolvm" ] && find_base_dm_mods
410 esac
412 for raid in $raids ; do
413 if [ "$raid" == "$name" ]; then
414 case " $DMRAIDS " in
415 *" $raid "*) ;;
416 *) DMRAIDS="$DMRAIDS $raid"
417 [ -z "$nodmraid" ] && find_base_dm_mods
419 esac
420 break
422 done
425 handleiscsi() {
426 vecho "Found iscsi component $1"
428 # We call iscsi_set_parameters once here to figure out what network to
429 # use (it sets tgt_ipaddr), and once again to emit iscsi values,
430 # not very efficient.
431 iscsi_set_parameters $1
432 iscsi_devs="$iscsi_devs $1"
433 netdev=$(/sbin/ip route get to $tgt_ipaddr | \
434 sed 's|.*dev \(.*\).*|\1|g' | awk '{ print $1; exit }')
435 addnetdev $netdev
438 handleraid() {
439 local start=0
441 if [ -n "$noraid" -o ! -f /proc/mdstat ]; then
442 return 0
445 levels=$(awk "/^$1[ ]*:/ { print\$4 }" /proc/mdstat)
447 for level in $levels ; do
448 case $level in
449 linear)
450 start=1
452 multipath)
453 start=1
455 raid[01] | raid10)
456 start=1
458 raid[456])
459 start=1
462 error "raid level $level (in /proc/mdstat) not recognized"
464 esac
465 done
466 if [ "$start" = 1 ]; then
467 raiddevices="$raiddevices $1"
469 return $start
472 lvshow() {
473 lvm lvs --ignorelockingfailure --noheadings -o vg_name \
474 $1 2>/dev/null | egrep -v '^ *(WARNING:|Volume Groups with)'
477 vgdisplay() {
478 lvm vgdisplay --ignorelockingfailure -v $1 2>/dev/null |
479 sed -n 's/PV Name//p'
482 dmmods_found="n"
483 find_base_dm_mods()
485 [ "$dmmods_found" == "n" ] || return
486 dmmods_found="y"
489 savedargs=$*
490 while [ $# -gt 0 ]; do
491 case $1 in
492 --fstab*)
493 if [ "$1" != "${1##--fstab=}" ]; then
494 fstab=${1##--fstab=}
495 else
496 fstab=$2
497 shift
502 -v|--verbose)
503 set_verbose true
505 --net-dev*)
506 if [ "$1" != "${1##--net-dev=}" ]; then
507 net_list="$net_list ${1##--net-dev=}"
508 else
509 net_list="$net_list $2"
510 shift
513 --rootdev*)
514 if [ "$1" != "${1##--rootdev=}" ]; then
515 rootdev="${1##--rootdev=}"
516 else
517 rootdev="$2"
518 shift
521 --thawdev*)
522 if [ "$1" != "${1##--thawdev=}" ]; then
523 thawdev="${1##--thawdev=}"
524 else
525 thawdev="$2"
526 shift
529 --rootfs*)
530 if [ "$1" != "${1##--rootfs=}" ]; then
531 rootfs="${1##--rootfs=}"
532 else
533 rootfs="$2"
534 shift
537 --rootopts*)
538 if [ "$1" != "${1##--rootopts=}" ]; then
539 rootopts="${1##--rootopts=}"
540 else
541 rootopts="$2"
542 shift
545 --root*)
546 if [ "$1" != "${1##--root=}" ]; then
547 root="${1##--root=}"
548 else
549 root="$2"
550 shift
553 --loopdev*)
554 if [ "$1" != "${1##--loopdev=}" ]; then
555 loopdev="${1##--loopdev=}"
556 else
557 loopdev="$2"
558 shift
561 --loopfs*)
562 if [ "$1" != "${1##--loopfs=}" ]; then
563 loopfs="${1##--loopfs=}"
564 else
565 loopfs="$2"
566 shift
569 --loopopts*)
570 if [ "$1" != "${1##--loopopts=}" ]; then
571 loopopts="${1##--loopopts=}"
572 else
573 loopopts="$2"
574 shift
577 --looppath*)
578 if [ "$1" != "${1##--looppath=}" ]; then
579 looppath="${1##--looppath=}"
580 else
581 looppath="$2"
582 shift
585 --help)
586 usage -n
589 if [ -z "$target" ]; then
590 target=$1
591 elif [ -z "$kernel" ]; then
592 kernel=$1
593 else
594 usage
597 esac
599 shift
600 done
602 [ -z "$rootfs" ] && rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' $fstab)
603 [ -z "$rootopts" ] && rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' $fstab)
604 [ -z "$rootopts" ] && rootopts="defaults"
607 [ -z "$rootdev" ] && rootdev=$(awk '/^[ \t]*[^#]/ { if ($2 == "/") { print $1; }}' $fstab)
608 # check if it's nfsroot
609 physdev=""
610 if [ "$rootfs" == "nfs" ]; then
611 if [ "x$net_list" == "x" ]; then
612 handlenfs $rootdev
614 else
615 # check if it's root by label
616 rdev=$rootdev
617 rdev=$(resolve_device_name "$rdev")
618 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/')
619 findstoragedriver "$rdev"
622 # find the first swap dev which would get used for swsusp
623 [ -z "$thawdev" ] && thawdev=$(awk '/^[ \t]*[^#]/ { if ($3 == "swap") { print $1; exit }}' $fstab)
624 swsuspdev="$thawdev"
625 if [ -n "$swsuspdev" ]; then
626 swsuspdev=$(resolve_device_name "$swsuspdev")
627 findstoragedriver "$swsuspdev"
631 cemit()
633 cat
636 emit()
638 NONL=""
639 if [ "$1" == "-n" ]; then
640 NONL="-n"
641 shift
643 echo $NONL "$@"
646 emitdmraids()
648 if [ -z "$nodmraid" -a -n "$DMRAIDS" ]; then
649 for raid in $DMRAIDS; do
650 echo -n "rd_DM_UUID=$raid "
651 done
656 # HACK: module loading + device creation isn't necessarily synchronous...
657 # this will make sure that we have all of our devices before trying
658 # things like RAID or LVM
659 emitdmraids
661 emitcrypto()
663 local luksuuid=$(grep "^$2 " /etc/crypttab 2>/dev/null| awk '{ print $2 }')
664 if [ -z "$luksuuid" ]; then
665 luksuuid="$2"
667 luksuuid=${luksuuid##UUID=}
668 echo -n "rd_LUKS_UUID=$luksuuid "
671 if [ -n "$raiddevices" ]; then
672 for dev in $raiddevices; do
673 uid=$(udevadm info --query=env --name /dev/${dev}|grep MD_UUID)
674 uid=${uid##MD_UUID=}
675 [ -n "$uid" ] && echo -n "rd_MD_UUID=$uid "
676 done
677 else
678 echo -n "rd_NO_MD "
681 if [ -z "$nolvm" -a -n "$vg_list" ]; then
682 for vg in $vg_list; do
683 echo -n "rd_LVM_VG=$vg "
684 done
685 else
686 echo -n "rd_NO_LVM "
689 cryptdevs="$(echo ${!cryptoraid@} ${!cryptopart@} ${!cryptolv@})"
691 if [ -z "$cryptdevs" ]; then
692 echo -n "rd_NO_LUKS "
693 else
694 for cryptdev in ${!cryptoraid@} ${!cryptopart@} ${!cryptolv@} ; do
695 emitcrypto `eval echo '$'$cryptdev`
696 done
699 # output local keyboard/18n settings
700 [ -e /etc/sysconfig/keyboard ] && . /etc/sysconfig/keyboard
701 [ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n
703 for i in KEYTABLE SYSFONT SYSFONTACM UNIMAP LANG; do
704 val=$(eval echo \$$i)
705 [[ $val ]] && echo -n "$i=$val "
706 done
708 if [ -n "$KEYBOARDTYPE" -a "$KEYBOARDTYPE" != "pc" ]; then
709 echo -n "KEYBOARDTYPE=$KEYBOARDTYPE "
712 if [ -n "$rootdev" ]; then
713 echo -n "root=$rootdev "
716 echo