c909e27bfd0547eb8cf2e2e45211f86a88c654c8
[platform/upstream/dracut.git] / dracut-gencmdline
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
4 #
5 # Copyright 2005-2009 Red Hat, Inc.  All rights reserved.
6 #
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.
11 #
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.
16 #
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/>.
19 #
20 # code taken from mkinitrd
21 #
22 #. /usr/libexec/initrd-functions
23
24 IF_verbose=""
25 function set_verbose() {
26     case $1 in
27         1|true|yes|on)
28             IF_verbose="-v"
29             ;;
30         0|false|no|off)
31             IF_verbose=""
32             ;;
33     esac
34 }
35
36 function is_verbose() {
37     [ -n "$IF_verbose" ] && return 0
38     return 1
39 }
40
41 function get_verbose() {
42     echo "$IF_verbose"
43     is_verbose
44 }
45
46
47 function get_numeric_dev() {
48     (
49         fmt="%d:%d"
50         if [ "$1" == "hex" ]; then
51             fmt="%x:%x"
52         fi
53         ls -lH "$2" | awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }'
54     ) 2>/dev/null
55 }
56
57
58 function error() {
59     echo "$@" >&2
60 }
61
62 function vecho() {
63     is_verbose && echo "$@"
64 }
65
66 # module dep finding and installation functions
67 moduledep() {
68     MPARGS=""
69     if [ "$1" == "--ignore-install" ]; then
70         MPARGS="$MPARGS --ignore-install"
71         shift
72     fi
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
77 }
78
79 export MALLOC_PERTURB_=204
80
81 PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH
82 export PATH
83
84 # Set the umask. For iscsi, the initrd can contain plaintext
85 # password (chap secret), so only allow read by owner.
86 umask 077
87
88 VERSION=6.0.87
89
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"
101
102 NET_LIST=""
103 LD_SO_CONF=/etc/ld.so.conf
104 LD_SO_CONF_D=/etc/ld.so.conf.d/
105
106 [ -e /etc/sysconfig/mkinitrd ] && . /etc/sysconfig/mkinitrd
107
108 CONFMODS="$MODULES"
109 MODULES=""
110 ARCH=$(uname -m | sed -e 's/s390x/s390/')
111
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=""
124
125 IMAGESIZE=8000
126 PRESCSIMODS=""
127 fstab="/etc/fstab"
128
129 vg_list=""
130 net_list="$NET_LIST"
131
132 usage () {
133     if [ "$1" == "-n" ]; then
134         cmd=echo
135     else
136         cmd=error
137     fi
138
139     $cmd "usage: `basename $0` [--version] [--help] [-v] [-f]"
140
141     if [ "$1" == "-n" ]; then
142         exit 0
143     else
144         exit 1
145     fi
146 }
147
148
149 qpushd() {
150     pushd "$1" >/dev/null 2>&1
151 }
152
153 qpopd() {
154     popd >/dev/null 2>&1
155 }
156
157
158 freadlink() {
159     readlink -f "$1"
160 }
161
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; }
166     fi
167     if [ -z "${1##LABEL=*}" ]; then
168         real=$(freadlink /dev/disk/by-label/${1##LABEL=})
169         [ -b $real ] && { echo $real; return; }
170     fi
171     echo "$1"
172 }
173
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
184         fi
185     fi
186     return 1
187 }
188
189 finddevicedriverinsys () {
190     if is_iscsi $PWD; then
191         handleiscsi "$PWD"
192         return
193     fi
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
200             fi
201             moduledep $MODALIAS
202             unset MODALIAS
203         fi
204
205         cd ..
206     done
207 }
208
209 findstoragedriverinsys () {
210     local sysfs=$(freadlink "$1")
211
212     # if its a partition look at the device holding the partition
213     if [ -f "$sysfs/start" ]; then
214         sysfs=$(freadlink ${sysfs%/*})
215     fi
216
217     if [[ ! "$sysfs" =~ ^/sys/.*block/.*$ ]]; then
218         #error "WARNING: $sysfs is a not a block sysfs path, skipping"
219         return
220     fi
221
222     case " $handleddevices " in
223         *" $sysfs "*)
224             return ;;
225         *) handleddevices="$handleddevices $sysfs" ;;
226     esac
227
228     if [[ "$sysfs" =~ ^/sys/.*block/md[0-9]+$ ]]; then
229         local raid=${sysfs##*/}
230         vecho "Found MDRAID component $raid"
231         handleraid $raid
232     fi
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)
236     fi
237
238     for slave in $(ls -d "$sysfs"/slaves/* 2>/dev/null) ; do
239         findstoragedriverinsys "$slave"
240     done
241
242     if [ -L "$sysfs/device" ]; then
243         qpushd $(freadlink "$sysfs/device")
244         finddevicedriverinsys
245         qpopd
246     fi
247 }
248
249 findstoragedriver () {
250     local device="$1"
251
252     if [ ! -b "$device" ]; then
253         #error "WARNING: $device is a not a block device, skipping"
254         return
255     fi
256
257     local majmin=$(get_numeric_dev dec "$device")
258     local sysfs=$(finddevnoinsys "$majmin")
259
260     if [ -z "$sysfs" ]; then
261         #error "WARNING: $device major:minor $majmin not found, skipping"
262         return
263     fi
264
265     vecho "Looking for driver for $device in $sysfs"
266     findstoragedriverinsys "$sysfs"
267 }
268
269 iscsi_get_rec_val() {
270
271     # The open-iscsi 742 release changed to using flat files in
272     # /var/lib/iscsi.
273
274     result=$(grep "^${2} = " "$1" |  sed -e s'/.* = //')
275 }
276
277 iscsi_set_parameters() {
278     path=$1
279     vecho setting iscsi parameters
280
281     tmpfile=$(mktemp)
282
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
289     fi
290
291     nit_name=$(grep "^InitiatorName=" /etc/iscsi/initiatorname.iscsi | \
292         sed -e "s/^InitiatorName=//")
293
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}
303
304     # Note: we get chap secrets (passwords) in plaintext, and also store
305     # them in the initrd.
306
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=""
315     fi
316
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=""
325     fi
326
327     rm $tmpfile
328 }
329
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
339     fi
340 }
341
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
348     fi
349 }
350
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
374                         fi
375                     done
376                 fi
377
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++
391                 fi
392
393                 let ncryptodevs++
394                 findstoragedriver "/dev/$slavedev"
395                 ;;
396         esac
397     done << EOF
398         $(dmsetup table -j $major -m $minor 2>/dev/null)
399 EOF
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
409                     ;;
410             esac
411         fi
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
418                         ;;
419                 esac
420                 break
421             fi
422         done
423 }
424
425 handleiscsi() {
426     vecho "Found iscsi component $1"
427
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
436 }
437
438 handleraid() {
439     local start=0
440
441     if [ -n "$noraid" -o ! -f /proc/mdstat ]; then
442         return 0
443     fi
444
445     levels=$(awk "/^$1[  ]*:/ { print\$4 }" /proc/mdstat)
446
447     for level in $levels ; do
448         case $level in
449             linear)
450                 start=1
451                 ;;
452             multipath)
453                 start=1
454                 ;;
455             raid[01] | raid10)
456                 start=1
457                 ;;
458             raid[456])
459                 start=1
460                 ;;
461             *)
462                 error "raid level $level (in /proc/mdstat) not recognized"
463                 ;;
464         esac
465     done
466     if [ "$start" = 1 ]; then
467         raiddevices="$raiddevices $1"
468     fi
469     return $start
470 }
471
472 lvshow() {
473     lvm lvs --ignorelockingfailure --noheadings -o vg_name \
474         $1 2>/dev/null | egrep -v '^ *(WARNING:|Volume Groups with)'
475 }
476
477 vgdisplay() {
478     lvm vgdisplay --ignorelockingfailure -v $1 2>/dev/null |
479     sed -n 's/PV Name//p'
480 }
481
482 dmmods_found="n"
483 find_base_dm_mods()
484 {
485     [ "$dmmods_found" == "n" ] || return
486     dmmods_found="y"
487 }
488
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
498             fi
499             ;;
500
501
502         -v|--verbose)
503             set_verbose true
504             ;;
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
511             fi
512             ;;
513         --rootdev*)
514             if [ "$1" != "${1##--rootdev=}" ]; then
515                 rootdev="${1##--rootdev=}"
516             else
517                 rootdev="$2"
518                 shift
519             fi
520             ;;
521         --thawdev*)
522             if [ "$1" != "${1##--thawdev=}" ]; then
523                 thawdev="${1##--thawdev=}"
524             else
525                 thawdev="$2"
526                 shift
527             fi
528             ;;
529         --rootfs*)
530             if [ "$1" != "${1##--rootfs=}" ]; then
531                 rootfs="${1##--rootfs=}"
532             else
533                 rootfs="$2"
534                 shift
535             fi
536             ;;
537         --rootopts*)
538             if [ "$1" != "${1##--rootopts=}" ]; then
539                 rootopts="${1##--rootopts=}"
540             else
541                 rootopts="$2"
542                 shift
543             fi
544             ;;
545         --root*)
546             if [ "$1" != "${1##--root=}" ]; then
547                 root="${1##--root=}"
548             else
549                 root="$2"
550                 shift
551             fi
552             ;;
553         --loopdev*)
554             if [ "$1" != "${1##--loopdev=}" ]; then
555                 loopdev="${1##--loopdev=}"
556             else
557                 loopdev="$2"
558                 shift
559             fi
560             ;;
561         --loopfs*)
562             if [ "$1" != "${1##--loopfs=}" ]; then
563                 loopfs="${1##--loopfs=}"
564             else
565                 loopfs="$2"
566                 shift
567             fi
568             ;;
569         --loopopts*)
570             if [ "$1" != "${1##--loopopts=}" ]; then
571                 loopopts="${1##--loopopts=}"
572             else
573                 loopopts="$2"
574                 shift
575             fi
576             ;;
577         --looppath*)
578             if [ "$1" != "${1##--looppath=}" ]; then
579                 looppath="${1##--looppath=}"
580             else
581                 looppath="$2"
582                 shift
583             fi
584             ;;
585         --help)
586             usage -n
587             ;;
588         *)
589             if [ -z "$target" ]; then
590                 target=$1
591             elif [ -z "$kernel" ]; then
592                 kernel=$1
593             else
594                 usage
595             fi
596             ;;
597     esac
598
599     shift
600 done
601
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"
605
606
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
613     fi
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"
620 fi
621
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"
628 fi
629
630
631 cemit()
632 {
633     cat
634 }
635
636 emit()
637 {
638     NONL=""
639     if [ "$1" == "-n" ]; then
640         NONL="-n"
641         shift
642     fi
643     echo $NONL "$@"
644 }
645
646 emitdmraids()
647 {
648     if [ -z "$nodmraid" -a -n "$DMRAIDS" ]; then
649         for raid in $DMRAIDS; do
650             echo -n "rd_DM_UUID=$raid "
651         done
652     fi
653 }
654
655
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
660
661 emitcrypto()
662 {
663     local luksuuid=$(grep "^$2 " /etc/crypttab 2>/dev/null| awk '{ print $2 }')
664     if [ -z "$luksuuid" ]; then
665         luksuuid="$2"
666     fi
667     luksuuid=${luksuuid##UUID=}
668     echo -n "rd_LUKS_UUID=$luksuuid "
669 }
670
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 "
679 fi
680
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 "
687 fi
688
689 cryptdevs="$(echo ${!cryptoraid@} ${!cryptopart@} ${!cryptolv@})"
690
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
697 fi
698
699 # output local keyboard/18n settings
700 [ -e /etc/sysconfig/keyboard ] && . /etc/sysconfig/keyboard
701 [ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n
702
703 for i in KEYTABLE SYSFONT SYSFONTACM UNIMAP LANG; do
704     val=$(eval echo \$$i)
705     [[ $val ]] && echo -n "$i=$val "
706 done
707
708 if [ -n "$KEYBOARDTYPE" -a "$KEYBOARDTYPE" != "pc" ]; then
709     echo -n "KEYBOARDTYPE=$KEYBOARDTYPE "
710 fi
711
712 if [ -n "$rootdev" ]; then
713     echo -n "root=$rootdev "
714 fi
715
716 echo