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