]> git.ipfire.org Git - thirdparty/dracut.git/blob - dracut-functions.sh
omit drivers fix
[thirdparty/dracut.git] / dracut-functions.sh
1 #!/bin/bash
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 # functions used by dracut and other tools.
6 #
7 # Copyright 2005-2009 Red Hat, Inc. All rights reserved.
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #
22 export LC_MESSAGES=C
23
24 if [[ $DRACUT_KERNEL_LAZY ]] && ! [[ $DRACUT_KERNEL_LAZY_HASHDIR ]]; then
25 if ! [[ -d "$initdir/.kernelmodseen" ]]; then
26 mkdir -p "$initdir/.kernelmodseen"
27 fi
28 DRACUT_KERNEL_LAZY_HASHDIR="$initdir/.kernelmodseen"
29 fi
30
31 if [[ $initdir ]] && ! [[ -d $initdir ]]; then
32 mkdir -p "$initdir"
33 fi
34
35 # Generic substring function. If $2 is in $1, return 0.
36 strstr() { [[ $1 = *$2* ]]; }
37
38 # find a binary. If we were not passed the full path directly,
39 # search in the usual places to find the binary.
40 find_binary() {
41 if [[ -z ${1##/*} ]]; then
42 if [[ -x $1 ]] || { [[ "$1" == *.so* ]] && ldd "$1" &>/dev/null; }; then
43 printf "%s\n" "$1"
44 return 0
45 fi
46 fi
47
48 type -P "${1##*/}"
49 }
50
51 if ! [[ $dracutbasedir ]]; then
52 dracutbasedir=${BASH_SOURCE[0]%/*}
53 [[ $dracutbasedir = "dracut-functions" ]] && dracutbasedir="."
54 [[ $dracutbasedir ]] || dracutbasedir="."
55 dracutbasedir="$(readlink -f $dracutbasedir)"
56 fi
57
58 # Detect lib paths
59 if ! [[ $libdirs ]] ; then
60 if [[ "$(ldd /bin/sh)" == */lib64/* ]] &>/dev/null \
61 && [[ -d /lib64 ]]; then
62 libdirs+=" /lib64"
63 [[ -d /usr/lib64 ]] && libdirs+=" /usr/lib64"
64 else
65 libdirs+=" /lib"
66 [[ -d /usr/lib ]] && libdirs+=" /usr/lib"
67 fi
68 export libdirs
69 fi
70
71 if ! [[ $kernel ]]; then
72 kernel=$(uname -r)
73 export kernel
74 fi
75
76 srcmods="/lib/modules/$kernel/"
77 [[ $drivers_dir ]] && {
78 if vercmp "$(modprobe --version | cut -d' ' -f3)" lt 3.7; then
79 dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
80 exit 1
81 fi
82 srcmods="$drivers_dir"
83 }
84 export srcmods
85
86 if ! type dinfo >/dev/null 2>&1; then
87 . "$dracutbasedir/dracut-logger.sh"
88 dlog_init
89 fi
90
91 if ! [[ $initdir ]]; then
92 dfatal "initdir not set"
93 exit 1
94 fi
95
96 # export standard hookdirs
97 [[ $hookdirs ]] || {
98 hookdirs="cmdline pre-udev pre-trigger netroot "
99 hookdirs+="initqueue initqueue/settled initqueue/online initqueue/finished initqueue/timeout "
100 hookdirs+="pre-mount pre-pivot cleanup mount "
101 hookdirs+="emergency shutdown-emergency pre-shutdown shutdown "
102 export hookdirs
103 }
104
105 dracut_need_initqueue() {
106 >"$initdir/lib/dracut/need-initqueue"
107 }
108
109 dracut_module_included() {
110 [[ "$mods_to_load $modules_loaded" == *$@* ]]
111 }
112
113 # Create all subdirectories for given path without creating the last element.
114 # $1 = path
115 mksubdirs() {
116 [[ -e ${1%/*} ]] || mkdir -m 0755 -p -- "${1%/*}"
117 }
118
119 # Version comparision function. Assumes Linux style version scheme.
120 # $1 = version a
121 # $2 = comparision op (gt, ge, eq, le, lt, ne)
122 # $3 = version b
123 vercmp() {
124 local _n1=${1//./ } _op=$2 _n2=${3//./ } _i _res
125
126 for ((_i=0; ; _i++))
127 do
128 if [[ ! ${_n1[_i]}${_n2[_i]} ]]; then _res=0
129 elif ((${_n1[_i]:-0} > ${_n2[_i]:-0})); then _res=1
130 elif ((${_n1[_i]:-0} < ${_n2[_i]:-0})); then _res=2
131 else continue
132 fi
133 break
134 done
135
136 case $_op in
137 gt) ((_res == 1));;
138 ge) ((_res != 2));;
139 eq) ((_res == 0));;
140 le) ((_res != 1));;
141 lt) ((_res == 2));;
142 ne) ((_res != 0));;
143 esac
144 }
145
146 # is_func <command>
147 # Check whether $1 is a function.
148 is_func() {
149 [[ "$(type -t "$1")" = "function" ]]
150 }
151
152 # Function prints global variables in format name=value line by line.
153 # $@ = list of global variables' name
154 print_vars() {
155 local _var _value
156
157 for _var in "$@"
158 do
159 eval printf -v _value "%s" "\$$_var"
160 [[ ${_value} ]] && printf '%s="%s"\n' "$_var" "$_value"
161 done
162 }
163
164 # normalize_path <path>
165 # Prints the normalized path, where it removes any duplicated
166 # and trailing slashes.
167 # Example:
168 # $ normalize_path ///test/test//
169 # /test/test
170 normalize_path() {
171 shopt -q -s extglob
172 set -- "${1//+(\/)//}"
173 shopt -q -u extglob
174 echo "${1%/}"
175 }
176
177 # convert_abs_rel <from> <to>
178 # Prints the relative path, when creating a symlink to <to> from <from>.
179 # Example:
180 # $ convert_abs_rel /usr/bin/test /bin/test-2
181 # ../../bin/test-2
182 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
183 convert_abs_rel() {
184 local __current __absolute __abssize __cursize __newpath
185 local -i __i __level
186
187 set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
188
189 # corner case #1 - self looping link
190 [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
191
192 # corner case #2 - own dir link
193 [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
194
195 IFS="/" __current=($1)
196 IFS="/" __absolute=($2)
197
198 __abssize=${#__absolute[@]}
199 __cursize=${#__current[@]}
200
201 while [[ "${__absolute[__level]}" == "${__current[__level]}" ]]
202 do
203 (( __level++ ))
204 if (( __level > __abssize || __level > __cursize ))
205 then
206 break
207 fi
208 done
209
210 for ((__i = __level; __i < __cursize-1; __i++))
211 do
212 if ((__i > __level))
213 then
214 __newpath=$__newpath"/"
215 fi
216 __newpath=$__newpath".."
217 done
218
219 for ((__i = __level; __i < __abssize; __i++))
220 do
221 if [[ -n $__newpath ]]
222 then
223 __newpath=$__newpath"/"
224 fi
225 __newpath=$__newpath${__absolute[__i]}
226 done
227
228 echo "$__newpath"
229 }
230
231 if [[ "$(ln --help)" == *--relative* ]]; then
232 ln_r() {
233 ln -sfnr "${initdir}/$1" "${initdir}/$2"
234 }
235 else
236 ln_r() {
237 local _source=$1
238 local _dest=$2
239 [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
240 ln -sfn -- "$(convert_abs_rel "${_dest}" "${_source}")" "${initdir}/${_dest}"
241 }
242 fi
243
244 get_persistent_dev() {
245 local i _tmp _dev
246
247 _dev=$(udevadm info --query=name --name="$1" 2>/dev/null)
248 [ -z "$_dev" ] && return
249
250 for i in /dev/mapper/* /dev/disk/by-uuid/* /dev/disk/by-id/*; do
251 [[ $i == /dev/mapper/mpath* ]] && continue
252 _tmp=$(udevadm info --query=name --name="$i" 2>/dev/null)
253 if [ "$_tmp" = "$_dev" ]; then
254 printf -- "%s" "$i"
255 return
256 fi
257 done
258 }
259
260 # get_fs_env <device>
261 # Get and set the ID_FS_TYPE variable from udev for a device.
262 # Example:
263 # $ get_fs_env /dev/sda2; echo $ID_FS_TYPE
264 # ext4
265 get_fs_env() {
266 local evalstr
267 local found
268
269 [[ $1 ]] || return
270 unset ID_FS_TYPE
271 if ID_FS_TYPE=$(udevadm info --query=env --name="$1" \
272 | { while read line; do
273 [[ "$line" == DEVPATH\=* ]] && found=1;
274 if [[ "$line" == ID_FS_TYPE\=* ]]; then
275 printf "%s" "${line#ID_FS_TYPE=}";
276 exit 0;
277 fi
278 done; [[ $found ]] && exit 0; exit 1; }) ; then
279 if [[ $ID_FS_TYPE ]]; then
280 printf "%s" "$ID_FS_TYPE"
281 return 0
282 fi
283 fi
284
285 # Fallback, if we don't have udev information
286 if find_binary blkid >/dev/null; then
287 ID_FS_TYPE=$(blkid -u filesystem -o export -- "$1" \
288 | while read line; do
289 if [[ "$line" == TYPE\=* ]]; then
290 printf "%s" "${line#TYPE=}";
291 exit 0;
292 fi
293 done)
294 if [[ $ID_FS_TYPE ]]; then
295 printf "%s" "$ID_FS_TYPE"
296 return 0
297 fi
298 fi
299 return 1
300 }
301
302 # get_maj_min <device>
303 # Prints the major and minor of a device node.
304 # Example:
305 # $ get_maj_min /dev/sda2
306 # 8:2
307 get_maj_min() {
308 local _maj _min _majmin
309 _majmin="$(stat -L -c '%t:%T' "$1" 2>/dev/null)"
310 printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))"
311 }
312
313 # find_block_device <mountpoint>
314 # Prints the major and minor number of the block device
315 # for a given mountpoint.
316 # Unless $use_fstab is set to "yes" the functions
317 # uses /proc/self/mountinfo as the primary source of the
318 # information and only falls back to /etc/fstab, if the mountpoint
319 # is not found there.
320 # Example:
321 # $ find_block_device /usr
322 # 8:4
323 find_block_device() {
324 local _majmin _dev _majmin _find_mpt
325 _find_mpt="$1"
326 if [[ $use_fstab != yes ]]; then
327 [[ -d $_find_mpt/. ]]
328 findmnt -e -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \
329 while read _majmin _dev; do
330 if [[ -b $_dev ]]; then
331 if ! [[ $_majmin ]] || [[ $_majmin == 0:* ]]; then
332 _majmin=$(get_maj_min $_dev)
333 fi
334 if [[ $_majmin ]]; then
335 echo $_majmin
336 else
337 echo $_dev
338 fi
339 return 0
340 fi
341 if [[ $_dev = *:* ]]; then
342 echo $_dev
343 return 0
344 fi
345 done; return 1; } && return 0
346 fi
347 # fall back to /etc/fstab
348
349 findmnt -e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \
350 while read _majmin _dev; do
351 if ! [[ $_dev ]]; then
352 _dev="$_majmin"
353 unset _majmin
354 fi
355 if [[ -b $_dev ]]; then
356 [[ $_majmin ]] || _majmin=$(get_maj_min $_dev)
357 if [[ $_majmin ]]; then
358 echo $_majmin
359 else
360 echo $_dev
361 fi
362 return 0
363 fi
364 if [[ $_dev = *:* ]]; then
365 echo $_dev
366 return 0
367 fi
368 done; return 1; } && return 0
369
370 return 1
371 }
372
373 # find_mp_fstype <mountpoint>
374 # Echo the filesystem type for a given mountpoint.
375 # /proc/self/mountinfo is taken as the primary source of information
376 # and /etc/fstab is used as a fallback.
377 # No newline is appended!
378 # Example:
379 # $ find_mp_fstype /;echo
380 # ext4
381 find_mp_fstype() {
382 local _fs
383
384 if [[ $use_fstab != yes ]]; then
385 findmnt -e -v -n -o 'FSTYPE' --target "$1" | { \
386 while read _fs; do
387 [[ $_fs ]] || continue
388 [[ $_fs = "autofs" ]] && continue
389 echo -n $_fs
390 return 0
391 done; return 1; } && return 0
392 fi
393
394 findmnt --fstab -e -v -n -o 'FSTYPE' --target "$1" | { \
395 while read _fs; do
396 [[ $_fs ]] || continue
397 [[ $_fs = "autofs" ]] && continue
398 echo -n $_fs
399 return 0
400 done; return 1; } && return 0
401
402 return 1
403 }
404
405 # find_dev_fstype <device>
406 # Echo the filesystem type for a given device.
407 # /proc/self/mountinfo is taken as the primary source of information
408 # and /etc/fstab is used as a fallback.
409 # No newline is appended!
410 # Example:
411 # $ find_dev_fstype /dev/sda2;echo
412 # ext4
413 find_dev_fstype() {
414 local _find_dev _fs
415 _find_dev="$1"
416 if ! [[ "$_find_dev" = /dev* ]]; then
417 [[ -b "/dev/block/$_find_dev" ]] && _find_dev="/dev/block/$_find_dev"
418 fi
419
420 if [[ $use_fstab != yes ]]; then
421 findmnt -e -v -n -o 'FSTYPE' --source "$_find_dev" | { \
422 while read _fs; do
423 [[ $_fs ]] || continue
424 [[ $_fs = "autofs" ]] && continue
425 echo -n $_fs
426 return 0
427 done; return 1; } && return 0
428 fi
429
430 findmnt --fstab -e -v -n -o 'FSTYPE' --source "$_find_dev" | { \
431 while read _fs; do
432 [[ $_fs ]] || continue
433 [[ $_fs = "autofs" ]] && continue
434 echo -n $_fs
435 return 0
436 done; return 1; } && return 0
437
438 return 1
439
440 }
441
442 # finds the major:minor of the block device backing the root filesystem.
443 find_root_block_device() { find_block_device /; }
444
445 # for_each_host_dev_fs <func>
446 # Execute "<func> <dev> <filesystem>" for every "<dev> <fs>" pair found
447 # in ${host_fs_types[@]}
448 for_each_host_dev_fs()
449 {
450 local _func="$1"
451 local _dev
452 local _ret=1
453
454 [[ "${!host_fs_types[@]}" ]] || return 0
455
456 for _dev in "${!host_fs_types[@]}"; do
457 $_func "$_dev" "${host_fs_types[$_dev]}" && _ret=0
458 done
459 return $_ret
460 }
461
462 host_fs_all()
463 {
464 echo "${host_fs_types[@]}"
465 }
466
467 # Walk all the slave relationships for a given block device.
468 # Stop when our helper function returns success
469 # $1 = function to call on every found block device
470 # $2 = block device in major:minor format
471 check_block_and_slaves() {
472 local _x
473 [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
474 "$1" $2 && return
475 check_vol_slaves "$@" && return 0
476 if [[ -f /sys/dev/block/$2/../dev ]]; then
477 check_block_and_slaves $1 $(<"/sys/dev/block/$2/../dev") && return 0
478 fi
479 [[ -d /sys/dev/block/$2/slaves ]] || return 1
480 for _x in /sys/dev/block/$2/slaves/*/dev; do
481 [[ -f $_x ]] || continue
482 check_block_and_slaves $1 $(<"$_x") && return 0
483 done
484 return 1
485 }
486
487 check_block_and_slaves_all() {
488 local _x _ret=1
489 [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
490 if "$1" $2; then
491 _ret=0
492 fi
493 check_vol_slaves "$@" && return 0
494 if [[ -f /sys/dev/block/$2/../dev ]]; then
495 check_block_and_slaves_all $1 $(<"/sys/dev/block/$2/../dev") && _ret=0
496 fi
497 [[ -d /sys/dev/block/$2/slaves ]] || return 1
498 for _x in /sys/dev/block/$2/slaves/*/dev; do
499 [[ -f $_x ]] || continue
500 check_block_and_slaves_all $1 $(<"$_x") && _ret=0
501 done
502 return $_ret
503 }
504 # for_each_host_dev_and_slaves <func>
505 # Execute "<func> <dev>" for every "<dev>" found
506 # in ${host_devs[@]} and their slaves
507 for_each_host_dev_and_slaves_all()
508 {
509 local _func="$1"
510 local _dev
511 local _ret=1
512
513 [[ "${host_devs[@]}" ]] || return 0
514
515 for _dev in ${host_devs[@]}; do
516 [[ -b "$_dev" ]] || continue
517 if check_block_and_slaves_all $_func $(get_maj_min $_dev); then
518 _ret=0
519 fi
520 done
521 return $_ret
522 }
523
524 for_each_host_dev_and_slaves()
525 {
526 local _func="$1"
527 local _dev
528
529 [[ "${host_devs[@]}" ]] || return 0
530
531 for _dev in ${host_devs[@]}; do
532 [[ -b "$_dev" ]] || continue
533 check_block_and_slaves $_func $(get_maj_min $_dev) && return 0
534 done
535 return 1
536 }
537
538 # ugly workaround for the lvm design
539 # There is no volume group device,
540 # so, there are no slave devices for volume groups.
541 # Logical volumes only have the slave devices they really live on,
542 # but you cannot create the logical volume without the volume group.
543 # And the volume group might be bigger than the devices the LV needs.
544 check_vol_slaves() {
545 local _lv _vg _pv
546 for i in /dev/mapper/*; do
547 _lv=$(get_maj_min $i)
548 if [[ $_lv = $2 ]]; then
549 _vg=$(lvm lvs --noheadings -o vg_name $i 2>/dev/null)
550 # strip space
551 _vg=$(echo $_vg)
552 if [[ $_vg ]]; then
553 for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null)
554 do
555 check_block_and_slaves $1 $(get_maj_min $_pv) && return 0
556 done
557 fi
558 fi
559 done
560 return 1
561 }
562
563 # fs_get_option <filesystem options> <search for option>
564 # search for a specific option in a bunch of filesystem options
565 # and return the value
566 fs_get_option() {
567 local _fsopts=$1
568 local _option=$2
569 local OLDIFS="$IFS"
570 IFS=,
571 set -- $_fsopts
572 IFS="$OLDIFS"
573 while [ $# -gt 0 ]; do
574 case $1 in
575 $_option=*)
576 echo ${1#${_option}=}
577 break
578 esac
579 shift
580 done
581 }
582
583
584 if ! [[ $DRACUT_INSTALL ]]; then
585 DRACUT_INSTALL=$(find_binary dracut-install)
586 fi
587
588 if ! [[ $DRACUT_INSTALL ]] && [[ -x $dracutbasedir/dracut-install ]]; then
589 DRACUT_INSTALL=$dracutbasedir/dracut-install
590 fi
591
592 if ! [[ -x $DRACUT_INSTALL ]]; then
593 dfatal "dracut-install not found!"
594 exit 10
595 fi
596
597 [[ $DRACUT_RESOLVE_LAZY ]] || export DRACUT_RESOLVE_DEPS=1
598 inst_dir() {
599 [[ -e ${initdir}/"$1" ]] && return 0 # already there
600 $DRACUT_INSTALL ${initdir+-D "$initdir"} -d "$@"
601 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} -d "$@" || :
602 }
603
604 inst() {
605 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
606 #dinfo "$DRACUT_INSTALL -l $@"
607 $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
608 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
609 }
610
611 inst_simple() {
612 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
613 [[ -e $1 ]] || return 1 # no source
614 $DRACUT_INSTALL ${initdir+-D "$initdir"} "$@"
615 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} "$@" || :
616 }
617
618 inst_symlink() {
619 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
620 [[ -L $1 ]] || return 1
621 $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
622 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
623 }
624
625 inst_multiple() {
626 local ret
627 #dinfo "initdir=$initdir $DRACUT_INSTALL -l $@"
628 $DRACUT_INSTALL ${initdir+-D "$initdir"} -a ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
629 ret=$?
630 (($ret != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} -a ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
631 return $ret
632 }
633
634 dracut_install() {
635 inst_multiple "$@"
636 }
637
638 inst_library() {
639 [[ -e ${initdir}/"${2:-$1}" ]] && return 0 # already there
640 [[ -e $1 ]] || return 1 # no source
641 $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
642 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
643 }
644
645 inst_binary() {
646 $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
647 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
648 }
649
650 inst_script() {
651 $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@"
652 (($? != 0)) && derror $DRACUT_INSTALL ${initdir+-D "$initdir"} ${DRACUT_RESOLVE_DEPS+-l} ${DRACUT_FIPS_MODE+-H} "$@" || :
653 }
654
655 # find symlinks linked to given library file
656 # $1 = library file
657 # Function searches for symlinks by stripping version numbers appended to
658 # library filename, checks if it points to the same target and finally
659 # prints the list of symlinks to stdout.
660 #
661 # Example:
662 # rev_lib_symlinks libfoo.so.8.1
663 # output: libfoo.so.8 libfoo.so
664 # (Only if libfoo.so.8 and libfoo.so exists on host system.)
665 rev_lib_symlinks() {
666 [[ ! $1 ]] && return 0
667
668 local fn="$1" orig="$(readlink -f "$1")" links=''
669
670 [[ ${fn} == *.so.* ]] || return 1
671
672 until [[ ${fn##*.} == so ]]; do
673 fn="${fn%.*}"
674 [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
675 done
676
677 echo "${links}"
678 }
679
680 # attempt to install any programs specified in a udev rule
681 inst_rule_programs() {
682 local _prog _bin
683
684 if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
685 for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
686 _bin=""
687 if [ -x ${udevdir}/$_prog ]; then
688 _bin=${udevdir}/$_prog
689 elif [[ "${_prog/\$env\{/}" == "$_prog" ]]; then
690 _bin=$(find_binary "$_prog") || {
691 dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found"
692 continue;
693 }
694 fi
695
696 [[ $_bin ]] && inst_binary "$_bin"
697 done
698 fi
699 if grep -qE 'RUN[+=]=?"[^ "]+' "$1"; then
700 for _prog in $(grep -E 'RUN[+=]=?"[^ "]+' "$1" | sed -r 's/.*RUN[+=]=?"([^ "]+).*/\1/'); do
701 _bin=""
702 if [ -x ${udevdir}/$_prog ]; then
703 _bin=${udevdir}/$_prog
704 elif [[ "${_prog/\$env\{/}" == "$_prog" ]] && [[ "${_prog}" != "/sbin/initqueue" ]]; then
705 _bin=$(find_binary "$_prog") || {
706 dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found"
707 continue;
708 }
709 fi
710
711 [[ $_bin ]] && inst_binary "$_bin"
712 done
713 fi
714 if grep -qE 'IMPORT\{program\}==?"[^ "]+' "$1"; then
715 for _prog in $(grep -E 'IMPORT\{program\}==?"[^ "]+' "$1" | sed -r 's/.*IMPORT\{program\}==?"([^ "]+).*/\1/'); do
716 _bin=""
717 if [ -x ${udevdir}/$_prog ]; then
718 _bin=${udevdir}/$_prog
719 elif [[ "${_prog/\$env\{/}" == "$_prog" ]]; then
720 _bin=$(find_binary "$_prog") || {
721 dinfo "Skipping program $_prog using in udev rule ${1##*/} as it cannot be found"
722 continue;
723 }
724 fi
725
726 [[ $_bin ]] && dracut_install "$_bin"
727 done
728 fi
729 }
730
731 # attempt to install any programs specified in a udev rule
732 inst_rule_group_owner() {
733 local i
734
735 if grep -qE 'OWNER=?"[^ "]+' "$1"; then
736 for i in $(grep -E 'OWNER=?"[^ "]+' "$1" | sed -r 's/.*OWNER=?"([^ "]+).*/\1/'); do
737 if ! egrep -q "^$i:" "$initdir/etc/passwd" 2>/dev/null; then
738 egrep "^$i:" /etc/passwd 2>/dev/null >> "$initdir/etc/passwd"
739 fi
740 done
741 fi
742 if grep -qE 'GROUP=?"[^ "]+' "$1"; then
743 for i in $(grep -E 'GROUP=?"[^ "]+' "$1" | sed -r 's/.*GROUP=?"([^ "]+).*/\1/'); do
744 if ! egrep -q "^$i:" "$initdir/etc/group" 2>/dev/null; then
745 egrep "^$i:" /etc/group 2>/dev/null >> "$initdir/etc/group"
746 fi
747 done
748 fi
749 }
750
751 inst_rule_initqueue() {
752 if grep -q -F initqueue "$1"; then
753 dracut_need_initqueue
754 fi
755 }
756
757 # udev rules always get installed in the same place, so
758 # create a function to install them to make life simpler.
759 inst_rules() {
760 local _target=/etc/udev/rules.d _rule _found
761
762 inst_dir "${udevdir}/rules.d"
763 inst_dir "$_target"
764 for _rule in "$@"; do
765 if [ "${_rule#/}" = "$_rule" ]; then
766 for r in ${udevdir}/rules.d /etc/udev/rules.d; do
767 if [[ -f $r/$_rule ]]; then
768 _found="$r/$_rule"
769 inst_rule_programs "$_found"
770 inst_rule_group_owner "$_found"
771 inst_rule_initqueue "$_found"
772 inst_simple "$_found"
773 fi
774 done
775 fi
776 for r in '' ./ $dracutbasedir/rules.d/; do
777 if [[ -f ${r}$_rule ]]; then
778 _found="${r}$_rule"
779 inst_rule_programs "$_found"
780 inst_rule_group_owner "$_found"
781 inst_rule_initqueue "$_found"
782 inst_simple "$_found" "$_target/${_found##*/}"
783 fi
784 done
785 [[ $_found ]] || dinfo "Skipping udev rule: $_rule"
786 done
787 }
788
789 prepare_udev_rules() {
790 [ -z "$UDEVVERSION" ] && export UDEVVERSION=$(udevadm --version)
791
792 for f in "$@"; do
793 f="${initdir}/etc/udev/rules.d/$f"
794 [ -e "$f" ] || continue
795 while read line; do
796 if [ "${line%%IMPORT PATH_ID}" != "$line" ]; then
797 if [ $UDEVVERSION -ge 174 ]; then
798 printf '%sIMPORT{builtin}="path_id"\n' "${line%%IMPORT PATH_ID}"
799 else
800 printf '%sIMPORT{program}="path_id %%p"\n' "${line%%IMPORT PATH_ID}"
801 fi
802 elif [ "${line%%IMPORT BLKID}" != "$line" ]; then
803 if [ $UDEVVERSION -ge 176 ]; then
804 printf '%sIMPORT{builtin}="blkid"\n' "${line%%IMPORT BLKID}"
805 else
806 printf '%sIMPORT{program}="/sbin/blkid -o udev -p $tempnode"\n' "${line%%IMPORT BLKID}"
807 fi
808 else
809 echo "$line"
810 fi
811 done < "${f}" > "${f}.new"
812 mv "${f}.new" "$f"
813 done
814 }
815
816 # install function specialized for hooks
817 # $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook
818 # All hooks should be POSIX/SuS compliant, they will be sourced by init.
819 inst_hook() {
820 if ! [[ -f $3 ]]; then
821 dfatal "Cannot install a hook ($3) that does not exist."
822 dfatal "Aborting initrd creation."
823 exit 1
824 elif ! [[ "$hookdirs" == *$1* ]]; then
825 dfatal "No such hook type $1. Aborting initrd creation."
826 exit 1
827 fi
828 inst_simple "$3" "/lib/dracut/hooks/${1}/${2}-${3##*/}"
829 }
830
831 # install any of listed files
832 #
833 # If first argument is '-d' and second some destination path, first accessible
834 # source is installed into this path, otherwise it will installed in the same
835 # path as source. If none of listed files was installed, function return 1.
836 # On first successful installation it returns with 0 status.
837 #
838 # Example:
839 #
840 # inst_any -d /bin/foo /bin/bar /bin/baz
841 #
842 # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
843 # initramfs.
844 inst_any() {
845 local to f
846
847 [[ $1 = '-d' ]] && to="$2" && shift 2
848
849 for f in "$@"; do
850 if [[ -e $f ]]; then
851 [[ $to ]] && inst "$f" "$to" && return 0
852 inst "$f" && return 0
853 fi
854 done
855
856 return 1
857 }
858
859
860 # inst_libdir_file [-n <pattern>] <file> [<file>...]
861 # Install a <file> located on a lib directory to the initramfs image
862 # -n <pattern> install matching files
863 inst_libdir_file() {
864 local _files
865 if [[ "$1" == "-n" ]]; then
866 local _pattern=$2
867 shift 2
868 for _dir in $libdirs; do
869 for _i in "$@"; do
870 for _f in "$_dir"/$_i; do
871 [[ "$_f" =~ $_pattern ]] || continue
872 [[ -e "$_f" ]] && _files+="$_f "
873 done
874 done
875 done
876 else
877 for _dir in $libdirs; do
878 for _i in "$@"; do
879 for _f in "$_dir"/$_i; do
880 [[ -e "$_f" ]] && _files+="$_f "
881 done
882 done
883 done
884 fi
885 [[ $_files ]] && inst_multiple $_files
886 }
887
888
889 # install function decompressing the target and handling symlinks
890 # $@ = list of compressed (gz or bz2) files or symlinks pointing to such files
891 #
892 # Function install targets in the same paths inside overlay but decompressed
893 # and without extensions (.gz, .bz2).
894 inst_decompress() {
895 local _src _cmd
896
897 for _src in $@
898 do
899 case ${_src} in
900 *.gz) _cmd='gzip -f -d' ;;
901 *.bz2) _cmd='bzip2 -d' ;;
902 *) return 1 ;;
903 esac
904 inst_simple ${_src}
905 # Decompress with chosen tool. We assume that tool changes name e.g.
906 # from 'name.gz' to 'name'.
907 ${_cmd} "${initdir}${_src}"
908 done
909 }
910
911 # It's similar to above, but if file is not compressed, performs standard
912 # install.
913 # $@ = list of files
914 inst_opt_decompress() {
915 local _src
916
917 for _src in $@
918 do
919 inst_decompress "${_src}" || inst "${_src}"
920 done
921 }
922
923 # module_check <dracut module>
924 # execute the check() function of module-setup.sh of <dracut module>
925 # or the "check" script, if module-setup.sh is not found
926 # "check $hostonly" is called
927 module_check() {
928 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
929 local _ret
930 local _forced=0
931 local _hostonly=$hostonly
932 [ $# -eq 2 ] && _forced=$2
933 [[ -d $_moddir ]] || return 1
934 if [[ ! -f $_moddir/module-setup.sh ]]; then
935 # if we do not have a check script, we are unconditionally included
936 [[ -x $_moddir/check ]] || return 0
937 [ $_forced -ne 0 ] && unset hostonly
938 $_moddir/check $hostonly
939 _ret=$?
940 else
941 unset check depends install installkernel
942 check() { true; }
943 . $_moddir/module-setup.sh
944 is_func check || return 0
945 [ $_forced -ne 0 ] && unset hostonly
946 check $hostonly
947 _ret=$?
948 unset check depends install installkernel
949 fi
950 hostonly=$_hostonly
951 return $_ret
952 }
953
954 # module_check_mount <dracut module>
955 # execute the check() function of module-setup.sh of <dracut module>
956 # or the "check" script, if module-setup.sh is not found
957 # "mount_needs=1 check 0" is called
958 module_check_mount() {
959 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
960 local _ret
961 mount_needs=1
962 [[ -d $_moddir ]] || return 1
963 if [[ ! -f $_moddir/module-setup.sh ]]; then
964 # if we do not have a check script, we are unconditionally included
965 [[ -x $_moddir/check ]] || return 0
966 mount_needs=1 $_moddir/check 0
967 _ret=$?
968 else
969 unset check depends install installkernel
970 check() { false; }
971 . $_moddir/module-setup.sh
972 check 0
973 _ret=$?
974 unset check depends install installkernel
975 fi
976 unset mount_needs
977 return $_ret
978 }
979
980 # module_depends <dracut module>
981 # execute the depends() function of module-setup.sh of <dracut module>
982 # or the "depends" script, if module-setup.sh is not found
983 module_depends() {
984 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
985 local _ret
986 [[ -d $_moddir ]] || return 1
987 if [[ ! -f $_moddir/module-setup.sh ]]; then
988 # if we do not have a check script, we have no deps
989 [[ -x $_moddir/check ]] || return 0
990 $_moddir/check -d
991 return $?
992 else
993 unset check depends install installkernel
994 depends() { true; }
995 . $_moddir/module-setup.sh
996 depends
997 _ret=$?
998 unset check depends install installkernel
999 return $_ret
1000 fi
1001 }
1002
1003 # module_install <dracut module>
1004 # execute the install() function of module-setup.sh of <dracut module>
1005 # or the "install" script, if module-setup.sh is not found
1006 module_install() {
1007 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
1008 local _ret
1009 [[ -d $_moddir ]] || return 1
1010 if [[ ! -f $_moddir/module-setup.sh ]]; then
1011 [[ -x $_moddir/install ]] && . "$_moddir/install"
1012 return $?
1013 else
1014 unset check depends install installkernel
1015 install() { true; }
1016 . $_moddir/module-setup.sh
1017 install
1018 _ret=$?
1019 unset check depends install installkernel
1020 return $_ret
1021 fi
1022 }
1023
1024 # module_installkernel <dracut module>
1025 # execute the installkernel() function of module-setup.sh of <dracut module>
1026 # or the "installkernel" script, if module-setup.sh is not found
1027 module_installkernel() {
1028 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
1029 local _ret
1030 [[ -d $_moddir ]] || return 1
1031 if [[ ! -f $_moddir/module-setup.sh ]]; then
1032 [[ -x $_moddir/installkernel ]] && . "$_moddir/installkernel"
1033 return $?
1034 else
1035 unset check depends install installkernel
1036 installkernel() { true; }
1037 . $_moddir/module-setup.sh
1038 installkernel
1039 _ret=$?
1040 unset check depends install installkernel
1041 return $_ret
1042 fi
1043 }
1044
1045 # check_mount <dracut module>
1046 # check_mount checks, if a dracut module is needed for the given
1047 # device and filesystem types in "${host_fs_types[@]}"
1048 check_mount() {
1049 local _mod=$1
1050 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
1051 local _ret
1052 local _moddep
1053
1054 [ "${#host_fs_types[*]}" -le 0 ] && return 1
1055
1056 # If we are already scheduled to be loaded, no need to check again.
1057 [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0
1058 [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1
1059
1060 # This should never happen, but...
1061 [[ -d $_moddir ]] || return 1
1062
1063 [[ $2 ]] || mods_checked_as_dep+=" $_mod "
1064
1065 if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then
1066 return 1
1067 fi
1068
1069 if [[ " $dracutmodules $add_dracutmodules $force_add_dracutmodules" == *\ $_mod\ * ]]; then
1070 module_check_mount $_mod; ret=$?
1071
1072 # explicit module, so also accept ret=255
1073 [[ $ret = 0 || $ret = 255 ]] || return 1
1074 else
1075 # module not in our list
1076 if [[ $dracutmodules = all ]]; then
1077 # check, if we can and should install this module
1078 module_check_mount $_mod || return 1
1079 else
1080 # skip this module
1081 return 1
1082 fi
1083 fi
1084
1085
1086 for _moddep in $(module_depends $_mod); do
1087 # handle deps as if they were manually added
1088 [[ " $add_dracutmodules " == *\ $_moddep\ * ]] || \
1089 add_dracutmodules+=" $_moddep "
1090 [[ " $force_add_dracutmodules " == *\ $_moddep\ * ]] || \
1091 force_add_dracutmodules+=" $_moddep "
1092 # if a module we depend on fail, fail also
1093 if ! check_module $_moddep; then
1094 derror "dracut module '$_mod' depends on '$_moddep', which can't be installed"
1095 return 1
1096 fi
1097 done
1098
1099 [[ " $mods_to_load " == *\ $_mod\ * ]] || \
1100 mods_to_load+=" $_mod "
1101
1102 return 0
1103 }
1104
1105 # check_module <dracut module> [<use_as_dep>]
1106 # check if a dracut module is to be used in the initramfs process
1107 # if <use_as_dep> is set, then the process also keeps track
1108 # that the modules were checked for the dependency tracking process
1109 check_module() {
1110 local _mod=$1
1111 local _moddir=$(echo ${dracutbasedir}/modules.d/??${1})
1112 local _ret
1113 local _moddep
1114 # If we are already scheduled to be loaded, no need to check again.
1115 [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0
1116 [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1
1117
1118 # This should never happen, but...
1119 [[ -d $_moddir ]] || return 1
1120
1121 [[ $2 ]] || mods_checked_as_dep+=" $_mod "
1122
1123 if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then
1124 dinfo "dracut module '$_mod' will not be installed, because it's in the list to be omitted!"
1125 return 1
1126 fi
1127
1128 if [[ " $dracutmodules $add_dracutmodules $force_add_dracutmodules" == *\ $_mod\ * ]]; then
1129 if [[ " $force_add_dracutmodules " == *\ $_mod\ * ]]; then
1130 module_check $_mod 1; ret=$?
1131 else
1132 module_check $_mod 0; ret=$?
1133 fi
1134 # explicit module, so also accept ret=255
1135 [[ $ret = 0 || $ret = 255 ]] || return 1
1136 else
1137 # module not in our list
1138 if [[ $dracutmodules = all ]]; then
1139 # check, if we can and should install this module
1140 module_check $_mod || return 1
1141 else
1142 # skip this module
1143 return 1
1144 fi
1145 fi
1146
1147 for _moddep in $(module_depends $_mod); do
1148 # handle deps as if they were manually added
1149 [[ " $add_dracutmodules " == *\ $_moddep\ * ]] || \
1150 add_dracutmodules+=" $_moddep "
1151 [[ " $force_add_dracutmodules " == *\ $_moddep\ * ]] || \
1152 force_add_dracutmodules+=" $_moddep "
1153 # if a module we depend on fail, fail also
1154 if ! check_module $_moddep; then
1155 derror "dracut module '$_mod' depends on '$_moddep', which can't be installed"
1156 return 1
1157 fi
1158 done
1159
1160 [[ " $mods_to_load " == *\ $_mod\ * ]] || \
1161 mods_to_load+=" $_mod "
1162
1163 return 0
1164 }
1165
1166 # for_each_module_dir <func>
1167 # execute "<func> <dracut module> 1"
1168 for_each_module_dir() {
1169 local _modcheck
1170 local _mod
1171 local _moddir
1172 local _func
1173 _func=$1
1174 for _moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
1175 _mod=${_moddir##*/}; _mod=${_mod#[0-9][0-9]}
1176 $_func $_mod 1
1177 done
1178
1179 # Report any missing dracut modules, the user has specified
1180 _modcheck="$add_dracutmodules $force_add_dracutmodules"
1181 [[ $dracutmodules != all ]] && _modcheck="$m $dracutmodules"
1182 for _mod in $_modcheck; do
1183 [[ " $mods_to_load " == *\ $_mod\ * ]] && continue
1184 [[ " $omit_dracutmodules " == *\ $_mod\ * ]] && continue
1185 derror "dracut module '$_mod' cannot be found or installed."
1186 done
1187 }
1188
1189 # Install a single kernel module along with any firmware it may require.
1190 # $1 = full path to kernel module to install
1191 install_kmod_with_fw() {
1192 # no need to go further if the module is already installed
1193
1194 [[ -e "${initdir}/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" ]] \
1195 && return 0
1196
1197 if [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && [[ -e "$DRACUT_KERNEL_LAZY_HASHDIR/${1##*/}" ]]; then
1198 read ret < "$DRACUT_KERNEL_LAZY_HASHDIR/${1##*/}"
1199 return $ret
1200 fi
1201
1202 if [[ $omit_drivers ]]; then
1203 local _kmod=${1##*/}
1204 _kmod=${_kmod%.ko}
1205 _kmod=${_kmod/-/_}
1206 if [[ "$_kmod" =~ $omit_drivers ]]; then
1207 dinfo "Omitting driver $_kmod"
1208 return 0
1209 fi
1210 if [[ "${1##*/lib/modules/$kernel/}" =~ $omit_drivers ]]; then
1211 dinfo "Omitting driver $_kmod"
1212 return 0
1213 fi
1214 fi
1215
1216 if [[ $silent_omit_drivers ]]; then
1217 local _kmod=${1##*/}
1218 _kmod=${_kmod%.ko}
1219 _kmod=${_kmod/-/_}
1220 [[ "$_kmod" =~ $silent_omit_drivers ]] && return 0
1221 [[ "${1##*/lib/modules/$kernel/}" =~ $silent_omit_drivers ]] && return 0
1222 fi
1223
1224 inst_simple "$1" "/lib/modules/$kernel/${1##*/lib/modules/$kernel/}"
1225 ret=$?
1226 [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && \
1227 [[ -d "$DRACUT_KERNEL_LAZY_HASHDIR" ]] && \
1228 echo $ret > "$DRACUT_KERNEL_LAZY_HASHDIR/${1##*/}"
1229 (($ret != 0)) && return $ret
1230
1231 local _modname=${1##*/} _fwdir _found _fw
1232 _modname=${_modname%.ko*}
1233 for _fw in $(modinfo -k $kernel -F firmware $1 2>/dev/null); do
1234 _found=''
1235 for _fwdir in $fw_dir; do
1236 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1237 inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw"
1238 _found=yes
1239 fi
1240 done
1241 if [[ $_found != yes ]]; then
1242 if ! [[ -d $(echo /sys/module/${_modname//-/_}|{ read a b; echo $a; }) ]]; then
1243 dinfo "Possible missing firmware \"${_fw}\" for kernel module" \
1244 "\"${_modname}.ko\""
1245 else
1246 dwarn "Possible missing firmware \"${_fw}\" for kernel module" \
1247 "\"${_modname}.ko\""
1248 fi
1249 fi
1250 done
1251 return 0
1252 }
1253
1254 # Do something with all the dependencies of a kernel module.
1255 # Note that kernel modules depend on themselves using the technique we use
1256 # $1 = function to call for each dependency we find
1257 # It will be passed the full path to the found kernel module
1258 # $2 = module to get dependencies for
1259 # rest of args = arguments to modprobe
1260 # _fderr specifies FD passed from surrounding scope
1261 for_each_kmod_dep() {
1262 local _func=$1 _kmod=$2 _cmd _modpath _options
1263 shift 2
1264 modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | (
1265 while read _cmd _modpath _options; do
1266 [[ $_cmd = insmod ]] || continue
1267 $_func ${_modpath} || exit $?
1268 done
1269 )
1270 }
1271
1272 dracut_kernel_post() {
1273 local _moddirname=${srcmods%%/lib/modules/*}
1274 local _pid
1275
1276 if [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && [[ -f "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist" ]]; then
1277 xargs -r modprobe -a ${_moddirname+-d ${_moddirname}/} \
1278 --ignore-install --show-depends --set-version $kernel \
1279 < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist" 2>/dev/null \
1280 | sort -u \
1281 | while read _cmd _modpath _options; do
1282 [[ $_cmd = insmod ]] || continue
1283 echo "$_modpath"
1284 done > "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep"
1285
1286 (
1287 if [[ $DRACUT_INSTALL ]] && [[ -z $_moddirname ]]; then
1288 xargs -r $DRACUT_INSTALL ${initdir+-D "$initdir"} -a < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep"
1289 else
1290 while read _modpath; do
1291 local _destpath=$_modpath
1292 [[ $_moddirname ]] && _destpath=${_destpath##$_moddirname/}
1293 _destpath=${_destpath##*/lib/modules/$kernel/}
1294 inst_simple "$_modpath" "/lib/modules/$kernel/${_destpath}" || exit $?
1295 done < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep"
1296 fi
1297 ) &
1298 _pid=$(jobs -p | while read a ; do printf ":$a";done)
1299 _pid=${_pid##*:}
1300
1301 if [[ $DRACUT_INSTALL ]]; then
1302 xargs -r modinfo -k $kernel -F firmware < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep" \
1303 | while read line; do
1304 for _fwdir in $fw_dir; do
1305 echo $_fwdir/$line;
1306 done;
1307 done | xargs -r $DRACUT_INSTALL ${initdir+-D "$initdir"} -a -o
1308 else
1309 for _fw in $(xargs -r modinfo -k $kernel -F firmware < "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist.dep"); do
1310 for _fwdir in $fw_dir; do
1311 if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
1312 inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw"
1313 break
1314 fi
1315 done
1316 done
1317 fi
1318
1319 wait $_pid
1320 fi
1321
1322 for _f in modules.builtin.bin modules.builtin; do
1323 [[ $srcmods/$_f ]] && break
1324 done || {
1325 dfatal "No modules.builtin.bin and modules.builtin found!"
1326 return 1
1327 }
1328
1329 for _f in modules.builtin.bin modules.builtin modules.order; do
1330 [[ $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f"
1331 done
1332
1333 # generate module dependencies for the initrd
1334 if [[ -d $initdir/lib/modules/$kernel ]] && \
1335 ! depmod -a -b "$initdir" $kernel; then
1336 dfatal "\"depmod -a $kernel\" failed."
1337 exit 1
1338 fi
1339
1340 [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && rm -fr -- "$DRACUT_KERNEL_LAZY_HASHDIR"
1341 }
1342
1343 module_is_host_only() {
1344 local _mod=$1
1345 _mod=${_mod##*/}
1346 _mod=${_mod%.ko}
1347
1348 [[ " $add_drivers " == *\ ${_mod}\ * ]] && return 0
1349
1350 # check if module is loaded
1351 for i in /sys/module/${_mod//-/_}; do
1352 [[ -d $i ]] && return 0
1353 done
1354
1355 # check if module is loadable on the current kernel
1356 # this covers the case, where a new module is introduced
1357 # or a module was renamed
1358 # or a module changed from builtin to a module
1359 modinfo -F filename "$_mod" &>/dev/null || return 0
1360
1361 return 1
1362 }
1363
1364 find_kernel_modules_by_path () {
1365 local _OLDIFS
1366
1367 [[ -f "$srcmods/modules.dep" ]] || return 0
1368
1369 _OLDIFS=$IFS
1370 IFS=:
1371 while read a rest; do
1372 [[ $a = */$1/* ]] || continue
1373 printf "%s\n" "$srcmods/$a"
1374 done < "$srcmods/modules.dep"
1375 IFS=$_OLDIFS
1376 return 0
1377 }
1378
1379 find_kernel_modules () {
1380 find_kernel_modules_by_path drivers
1381 }
1382
1383 # instmods [-c [-s]] <kernel module> [<kernel module> ... ]
1384 # instmods [-c [-s]] <kernel subsystem>
1385 # install kernel modules along with all their dependencies.
1386 # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
1387 instmods() {
1388 [[ $no_kernel = yes ]] && return
1389 # called [sub]functions inherit _fderr
1390 local _fderr=9
1391 local _check=no
1392 local _silent=no
1393 if [[ $1 = '-c' ]]; then
1394 _check=yes
1395 shift
1396 fi
1397
1398 if [[ $1 = '-s' ]]; then
1399 _silent=yes
1400 shift
1401 fi
1402
1403 function inst1mod() {
1404 local _ret=0 _mod="$1"
1405 case $_mod in
1406 =*)
1407 ( [[ "$_mpargs" ]] && echo $_mpargs
1408 find_kernel_modules_by_path "${_mod#=}" ) \
1409 | instmods
1410 ((_ret+=$?))
1411 ;;
1412 --*) _mpargs+=" $_mod" ;;
1413 *)
1414 _mod=${_mod##*/}
1415 # if we are already installed, skip this module and go on
1416 # to the next one.
1417 if [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && \
1418 [[ -f "$DRACUT_KERNEL_LAZY_HASHDIR/${_mod%.ko}.ko" ]]; then
1419 read _ret <"$DRACUT_KERNEL_LAZY_HASHDIR/${_mod%.ko}.ko"
1420 return $_ret
1421 fi
1422
1423 _mod=${_mod/-/_}
1424 if [[ $omit_drivers ]] && [[ "$_mod" =~ $omit_drivers ]]; then
1425 dinfo "Omitting driver ${_mod##$srcmods}"
1426 return 0
1427 fi
1428
1429 # If we are building a host-specific initramfs and this
1430 # module is not already loaded, move on to the next one.
1431 [[ $hostonly ]] \
1432 && ! module_is_host_only "$_mod" \
1433 && return 0
1434
1435 if [[ "$_check" = "yes" ]] || ! [[ $DRACUT_KERNEL_LAZY_HASHDIR ]]; then
1436 # We use '-d' option in modprobe only if modules prefix path
1437 # differs from default '/'. This allows us to use dracut with
1438 # old version of modprobe which doesn't have '-d' option.
1439 local _moddirname=${srcmods%%/lib/modules/*}
1440 [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/"
1441
1442 # ok, load the module, all its dependencies, and any firmware
1443 # it may require
1444 for_each_kmod_dep install_kmod_with_fw $_mod \
1445 --set-version $kernel ${_moddirname} $_mpargs
1446 ((_ret+=$?))
1447 else
1448 [[ $DRACUT_KERNEL_LAZY_HASHDIR ]] && \
1449 echo $_mod >> "$DRACUT_KERNEL_LAZY_HASHDIR/lazylist"
1450 fi
1451 ;;
1452 esac
1453 return $_ret
1454 }
1455
1456 function instmods_1() {
1457 local _mod _mpargs
1458 if (($# == 0)); then # filenames from stdin
1459 while read _mod; do
1460 inst1mod "${_mod%.ko*}" || {
1461 if [[ "$_check" == "yes" ]]; then
1462 [[ "$_silent" == "no" ]] && dfatal "Failed to install module $_mod"
1463 return 1
1464 fi
1465 }
1466 done
1467 fi
1468 while (($# > 0)); do # filenames as arguments
1469 inst1mod ${1%.ko*} || {
1470 if [[ "$_check" == "yes" ]]; then
1471 [[ "$_silent" == "no" ]] && dfatal "Failed to install module $1"
1472 return 1
1473 fi
1474 }
1475 shift
1476 done
1477 return 0
1478 }
1479
1480 local _ret _filter_not_found='FATAL: Module .* not found.'
1481 # Capture all stderr from modprobe to _fderr. We could use {var}>...
1482 # redirections, but that would make dracut require bash4 at least.
1483 eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
1484 | while read line; do [[ "$line" =~ $_filter_not_found ]] || echo $line;done | derror
1485 _ret=$?
1486 return $_ret
1487 }
1488 # get_cpu_vendor
1489 # Only two values are returned: AMD or Intel
1490 get_cpu_vendor ()
1491 {
1492 if grep -qE AMD /proc/cpuinfo; then
1493 printf "AMD"
1494 fi
1495 if grep -qE Intel /proc/cpuinfo; then
1496 printf "Intel"
1497 fi
1498 }
1499
1500 # get_host_ucode
1501 # Get the hosts' ucode file based on the /proc/cpuinfo
1502 get_ucode_file ()
1503 {
1504 local family=`grep -E "cpu family" /proc/cpuinfo | head -1 | sed s/.*:\ //`
1505 local model=`grep -E "model" /proc/cpuinfo |grep -v name | head -1 | sed s/.*:\ //`
1506 local stepping=`grep -E "stepping" /proc/cpuinfo | head -1 | sed s/.*:\ //`
1507
1508 if [[ "$(get_cpu_vendor)" == "AMD" ]]; then
1509 # If family greater or equal than 0x15
1510 if [[ $family -ge 21 ]]; then
1511 printf "microcode_amd_fam15h.bin"
1512 else
1513 printf "microcode_amd.bin"
1514 fi
1515 fi
1516 if [[ "$(get_cpu_vendor)" == "Intel" ]]; then
1517 # The /proc/cpuinfo are in decimal.
1518 printf "%02x-%02x-%02x" ${family} ${model} ${stepping}
1519 fi
1520 }