]>
Commit | Line | Data |
---|---|---|
04b56f3a JK |
1 | #!/bin/bash |
2 | # | |
33ee031c | 3 | # functions used by dracut and other tools. |
04b56f3a | 4 | # |
33ee031c | 5 | # Copyright 2005-2009 Red Hat, Inc. All rights reserved. |
04b56f3a JK |
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 | |
0f9c78c1 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
04b56f3a | 19 | # |
04b56f3a JK |
20 | |
21 | IF_RTLD="" | |
22 | IF_dynamic="" | |
36b24d7c | 23 | |
3198f171 | 24 | # Generic substring function. If $2 is in $1, return 0. |
f76ef3aa | 25 | strstr() { [[ $1 =~ $2 ]]; } |
f04dc5f3 | 26 | |
87122afc AŻ |
27 | # Create all subdirectories for given path without creating the last element. |
28 | # $1 = path | |
29 | mksubdirs() { mkdir -p ${1%/*}; } | |
30 | ||
22ecea45 AŻ |
31 | # Version comparision function. Assumes Linux style version scheme. |
32 | # $1 = version a | |
33 | # $2 = comparision op (gt, ge, eq, le, lt, ne) | |
34 | # $3 = version b | |
ecf42850 | 35 | vercmp() { |
22ecea45 | 36 | local n1=(${1//./ }) op=$2 n2=(${3//./ }) i res |
ecf42850 | 37 | |
2c24ee9a | 38 | for ((i=0; ; i++)) |
22ecea45 AŻ |
39 | do |
40 | if [[ ! ${n1[i]}${n2[i]} ]]; then res=0 | |
41 | elif ((${n1[i]:-0} > ${n2[i]:-0})); then res=1 | |
42 | elif ((${n1[i]:-0} < ${n2[i]:-0})); then res=2 | |
43 | else continue | |
44 | fi | |
45 | break | |
ecf42850 | 46 | done |
ecf42850 | 47 | |
22ecea45 AŻ |
48 | case $op in |
49 | gt) ((res == 1));; | |
50 | ge) ((res != 2));; | |
51 | eq) ((res == 0));; | |
52 | le) ((res != 1));; | |
53 | lt) ((res == 2));; | |
54 | ne) ((res != 0));; | |
55 | esac | |
ecf42850 AŻ |
56 | } |
57 | ||
4cf26268 | 58 | # Log initrd creation. |
1a918b40 | 59 | if ! [[ $dracutlogfile ]]; then |
5d791c0e | 60 | [[ $dracutbasedir = /usr/share/dracut ]] && \ |
e0dca0e4 VL |
61 | dracutlogfile=/var/log/dracut.log || \ |
62 | dracutlogfile=/tmp/dracut.log | |
59580f28 HH |
63 | # [[ -w $dracutlogfile ]] || dracutlogfile=/tmp/dracut.log |
64 | if [[ -w $dracutlogfile ]]; then | |
65 | >"$dracutlogfile" | |
66 | fi | |
e0dca0e4 | 67 | fi |
1a918b40 | 68 | |
6fac4691 HH |
69 | dwarning() { |
70 | echo "W: $@" >&2 | |
161efa1f | 71 | [[ -w $dracutlogfile ]] && echo "W: $@" >>"$dracutlogfile" |
6fac4691 HH |
72 | } |
73 | ||
74 | dinfo() { | |
84ffb877 | 75 | [[ $beverbose ]] && echo "I: $@" >&2 |
161efa1f | 76 | [[ -w $dracutlogfile ]] && echo "I: $@" >>"$dracutlogfile" |
6fac4691 HH |
77 | } |
78 | ||
79 | derror() { | |
80 | echo "E: $@" >&2 | |
161efa1f | 81 | [[ -w $dracutlogfile ]] && echo "E: $@" >>"$dracutlogfile" |
6fac4691 HH |
82 | } |
83 | ||
87122afc AŻ |
84 | # Function prints global variables in format name=value line by line. |
85 | # $@ = list of global variables' name | |
86 | print_vars() { | |
87 | local var value | |
88 | ||
89 | for var in $@ | |
90 | do | |
91 | value=$(eval echo \$$var) | |
92 | [[ ${value} ]] && echo "${var}=\"${value}\"" | |
93 | done | |
94 | } | |
95 | ||
9ede1929 | 96 | get_fs_env() { |
d8b9844c HH |
97 | eval $(udevadm info --query=env --name=$1|egrep 'ID_FS_(TYPE|UUID)=') |
98 | [[ $ID_FS_TYPE ]] && return | |
99 | ||
59c88f49 | 100 | if [[ -x /lib/udev/vol_id ]]; then |
9ede1929 VL |
101 | eval $(/lib/udev/vol_id --export $1) |
102 | elif find_binary blkid >/dev/null; then | |
103 | eval $(blkid -o udev $1) | |
59c88f49 VL |
104 | else |
105 | return 1 | |
106 | fi | |
9ede1929 VL |
107 | } |
108 | ||
109 | get_fs_type() ( | |
110 | get_fs_env $1 || return | |
111 | echo $ID_FS_TYPE | |
112 | ) | |
113 | ||
114 | get_fs_uuid() ( | |
115 | get_fs_env $1 || return | |
116 | echo $ID_FS_UUID | |
59c88f49 VL |
117 | ) |
118 | ||
17829e94 | 119 | # finds the major:minor of the block device backing the root filesystem. |
f76ef3aa | 120 | find_block_device() { |
17829e94 VL |
121 | local rootdev blkdev fs type opts misc |
122 | while read blkdev fs type opts misc; do | |
123 | [[ $blkdev = rootfs ]] && continue # skip rootfs entry | |
f76ef3aa | 124 | [[ $fs = $1 ]] && { rootdev=$blkdev; break; } # we have a winner! |
17829e94 VL |
125 | done < /proc/mounts |
126 | [[ -b $rootdev ]] || return 1 # oops, not a block device. | |
127 | # get major/minor for the device | |
128 | ls -nLl "$rootdev" | \ | |
129 | (read x x x x maj min x; maj=${maj//,/}; echo $maj:$min) | |
130 | } | |
131 | ||
f76ef3aa VL |
132 | find_root_block_device() { find_block_device /; } |
133 | ||
17829e94 VL |
134 | # Walk all the slave relationships for a given block device. |
135 | # Stop when our helper function returns success | |
136 | # $1 = function to call on every found block device | |
137 | # $2 = block device in major:minor format | |
138 | check_block_and_slaves() { | |
139 | local x | |
140 | [[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry. | |
141 | "$1" $2 && return | |
533d7dc4 | 142 | check_vol_slaves "$@" && return 0 |
a3afcf2a AL |
143 | if [[ -f "/sys/dev/block/$2/../dev" ]]; then |
144 | check_block_and_slaves $1 $(cat "/sys/dev/block/$2/../dev") && return 0 | |
145 | fi | |
17829e94 | 146 | [[ -d /sys/dev/block/$2/slaves ]] || return 1 |
17829e94 | 147 | for x in /sys/dev/block/$2/slaves/*/dev; do |
9defc609 | 148 | [[ -f $x ]] || continue |
17829e94 VL |
149 | check_block_and_slaves $1 $(cat "$x") && return 0 |
150 | done | |
151 | return 1 | |
152 | } | |
153 | ||
533d7dc4 HH |
154 | get_numeric_dev() { |
155 | ls -lH "$1" | { read a b c d maj min rest; printf "%d:%d" ${maj%%,} $min;} | |
156 | } | |
157 | ||
158 | # ugly workaround for the lvm design | |
159 | # There is no volume group device, | |
160 | # so, there are no slave devices for volume groups. | |
161 | # Logical volumes only have the slave devices they really live on, | |
162 | # but you cannot create the logical volume without the volume group. | |
95bde758 | 163 | # And the volume group might be bigger than the devices the LV needs. |
533d7dc4 HH |
164 | check_vol_slaves() { |
165 | for i in /dev/mapper/*; do | |
166 | lv=$(get_numeric_dev $i) | |
167 | if [[ $lv = $2 ]]; then | |
59580f28 | 168 | vg=$(lvm lvs --noheadings -o vg_name $i 2>/dev/null) |
533d7dc4 HH |
169 | # strip space |
170 | vg=$(echo $vg) | |
171 | if [[ $vg ]]; then | |
59580f28 | 172 | for pv in $(lvm vgs --noheadings -o pv_name "$vg" 2>/dev/null); \ |
533d7dc4 HH |
173 | do |
174 | check_block_and_slaves $1 $(get_numeric_dev $pv) \ | |
175 | && return 0 | |
176 | done | |
177 | fi | |
178 | fi | |
179 | done | |
180 | return 1 | |
181 | } | |
182 | ||
19612483 LA |
183 | # Install a directory, keeping symlinks as on the original system. |
184 | # Example: if /lib64 points to /lib on the host, "inst_dir /lib/file" | |
185 | # will create ${initdir}/lib64, ${initdir}/lib64/file, | |
186 | # and a symlink ${initdir}/lib -> lib64. | |
187 | inst_dir() { | |
188 | local dir="$1" | |
189 | [[ -e "${initdir}$dir" ]] && return 0 | |
190 | ||
191 | # iterate over parent directories | |
192 | local file="" | |
193 | local IFS="/" | |
194 | for part in $dir; do | |
195 | [ -z "$part" ] && continue | |
196 | file="$file/$part" | |
197 | [[ -e "${initdir}$file" ]] && continue | |
198 | ||
199 | if [ -L "$file" ]; then | |
200 | # create link as the original | |
201 | local target=$(readlink "$file") | |
202 | ln -sfn "$target" "${initdir}$file" || return 1 | |
203 | # resolve relative path and recursively install destionation | |
204 | [[ "$target" = "${target##*/}" ]] && target="${file%/*}/$target" | |
205 | inst_dir "$target" | |
206 | else | |
207 | # create directory | |
208 | mkdir -p "${initdir}$file" || return 1 | |
209 | fi | |
210 | done | |
211 | } | |
212 | ||
36b24d7c VL |
213 | # $1 = file to copy to ramdisk |
214 | # $2 (optional) Name for the file on the ramdisk | |
215 | # Location of the image dir is assumed to be $initdir | |
3198f171 | 216 | # We never overwrite the target if it exists. |
36b24d7c | 217 | inst_simple() { |
54b44196 VL |
218 | local src target |
219 | [[ -f $1 ]] || return 1 | |
19612483 | 220 | src=$1 target="${2:-$1}" |
3c56f372 HH |
221 | if ! [[ -d ${initdir}$target ]]; then |
222 | [[ -e ${initdir}$target ]] && return 0 | |
223 | inst_dir "${target%/*}" | |
224 | fi | |
6fac4691 | 225 | dinfo "Installing $src" |
f6d1cb89 | 226 | cp -pfL "$src" "${initdir}$target" |
36b24d7c VL |
227 | } |
228 | ||
95bde758 | 229 | # Same as above, but specialized to handle dynamic libraries. |
3198f171 VL |
230 | # It handles making symlinks according to how the original library |
231 | # is referenced. | |
36b24d7c VL |
232 | inst_library() { |
233 | local src=$1 dest=${2:-$1} | |
d46c2e8b | 234 | [[ -e $initdir$dest ]] && return 0 |
36b24d7c | 235 | if [[ -L $src ]]; then |
161efa1f | 236 | reallib=$(readlink -f "$src") |
36b24d7c | 237 | lib=${src##*/} |
9f88fcd9 | 238 | inst_simple "$reallib" "$reallib" |
19612483 | 239 | inst_dir "${dest%/*}" |
36b24d7c VL |
240 | (cd "${initdir}${dest%/*}" && ln -s "$reallib" "$lib") |
241 | else | |
242 | inst_simple "$src" "$dest" | |
243 | fi | |
244 | } | |
3198f171 VL |
245 | |
246 | # find a binary. If we were not passed the full path directly, | |
247 | # search in the usual places to find the binary. | |
6b25d71a VL |
248 | find_binary() { |
249 | local binpath="/bin /sbin /usr/bin /usr/sbin" p | |
0c296f15 | 250 | [[ -z ${1##/*} && -x $1 ]] && { echo $1; return 0; } |
3359c8da | 251 | for p in $binpath; do |
6b25d71a | 252 | [[ -x $p/$1 ]] && { echo "$p/$1"; return 0; } |
3359c8da VL |
253 | done |
254 | return 1 | |
255 | } | |
36b24d7c | 256 | |
3198f171 VL |
257 | # Same as above, but specialized to install binary executables. |
258 | # Install binary executable, and all shared library dependencies, if any. | |
36b24d7c | 259 | inst_binary() { |
54b44196 | 260 | local bin target |
6b25d71a | 261 | bin=$(find_binary "$1") || return 1 |
3198f171 | 262 | target=${2:-$bin} |
d46c2e8b | 263 | inst_symlink $bin $target && return 0 |
36b24d7c | 264 | local LDSO NAME IO FILE ADDR I1 n f TLIBDIR |
d46c2e8b | 265 | [[ -e $initdir$target ]] && return 0 |
8667f2b7 | 266 | # I love bash! |
45b5a4e1 | 267 | LC_ALL=C ldd $bin 2>/dev/null | while read line; do |
f04dc5f3 | 268 | [[ $line = 'not a dynamic executable' ]] && return 1 |
cdad82fd | 269 | if [[ $line =~ not\ found ]]; then |
6fac4691 HH |
270 | derror "Missing a shared library required by $bin." |
271 | derror "Run \"ldd $bin\" to find out what it is." | |
272 | derror "dracut cannot create an initrd." | |
36b24d7c | 273 | exit 1 |
cdad82fd | 274 | fi |
fdb3d52d MP |
275 | so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)' |
276 | [[ $line =~ $so_regex ]] || continue | |
f04dc5f3 | 277 | FILE=${BASH_REMATCH[1]} |
d46c2e8b | 278 | [[ -e ${initdir}$FILE ]] && continue |
8667f2b7 | 279 | # see if we are loading an optimized version of a shared lib. |
fdb3d52d MP |
280 | lib_regex='^(/lib[^/]*).*' |
281 | if [[ $FILE =~ $lib_regex ]]; then | |
8667f2b7 | 282 | TLIBDIR=${BASH_REMATCH[1]} |
161efa1f | 283 | BASE=${FILE##*/} |
8667f2b7 VL |
284 | # prefer nosegneg libs, then unoptimized ones. |
285 | for f in "$TLIBDIR/i686/nosegneg" "$TLIBDIR"; do | |
d46c2e8b | 286 | [[ -e $f/$BASE ]] || continue |
161efa1f | 287 | FILE=$f/$BASE |
8667f2b7 VL |
288 | break |
289 | done | |
36b24d7c | 290 | inst_library "$FILE" "$TLIBDIR/$BASE" |
161efa1f | 291 | IF_dynamic=yes |
36b24d7c | 292 | continue |
cdad82fd | 293 | fi |
36b24d7c | 294 | inst_library "$FILE" |
5c862533 | 295 | done |
3198f171 | 296 | inst_simple "$bin" "$target" |
36b24d7c | 297 | } |
04b56f3a | 298 | |
36b24d7c VL |
299 | # same as above, except for shell scripts. |
300 | # If your shell script does not start with shebang, it is not a shell script. | |
301 | inst_script() { | |
54b44196 | 302 | [[ -f $1 ]] || return 1 |
c7b2624f VL |
303 | local line |
304 | read -r -n 80 line <"$1" | |
00531568 AT |
305 | # If debug is set, clean unprintable chars to prevent messing up the term |
306 | [[ $debug ]] && line=$(echo -n "$line" | tr -c -d '[:print:][:space:]') | |
fdb3d52d MP |
307 | shebang_regex='(#! *)(/[^ ]+).*' |
308 | [[ $line =~ $shebang_regex ]] || return 1 | |
c7b2624f | 309 | inst "${BASH_REMATCH[2]}" && inst_simple "$@" |
04b56f3a JK |
310 | } |
311 | ||
36b24d7c VL |
312 | # same as above, but specialized for symlinks |
313 | inst_symlink() { | |
314 | local src=$1 target=$initdir${2:-$1} realsrc | |
315 | [[ -L $1 ]] || return 1 | |
316 | [[ -L $target ]] && return 0 | |
9f88fcd9 | 317 | realsrc=$(readlink -f "$src") |
161efa1f | 318 | [[ $realsrc = ${realsrc##*/} ]] && realsrc=${src%/*}/$realsrc |
36b24d7c VL |
319 | inst "$realsrc" && ln -s "$realsrc" "$target" |
320 | } | |
321 | ||
95bde758 | 322 | # find a udev rule in the usual places. |
09805e02 | 323 | find_rule() { |
b649f1c2 | 324 | [[ -f $1 ]] && { echo "$1"; return 0; } |
5d791c0e | 325 | for r in . /lib/udev/rules.d /etc/udev/rules.d $dracutbasedir/rules.d; do |
09805e02 VL |
326 | [[ -f $r/$1 ]] && { echo "$r/$1"; return 0; } |
327 | done | |
328 | return 1 | |
329 | } | |
330 | ||
f04dc5f3 VL |
331 | # udev rules always get installed in the same place, so |
332 | # create a function to install them to make life simpler. | |
333 | inst_rules() { | |
161efa1f | 334 | local target=/etc/udev/rules.d |
19612483 LA |
335 | inst_dir "/lib/udev/rules.d" |
336 | inst_dir "$target" | |
f04dc5f3 | 337 | for rule in "$@"; do |
5f70a1bd AŻ |
338 | rule1=$(find_rule "$rule") && \ |
339 | inst_simple "$rule1" "$target/${rule1##*/}" \ | |
340 | || dinfo "Skipping udev rule: $rule" | |
f04dc5f3 VL |
341 | done |
342 | } | |
343 | ||
36b24d7c VL |
344 | # general purpose installation function |
345 | # Same args as above. | |
6b24de99 | 346 | inst() { |
94dcc5b8 HH |
347 | case $# in |
348 | 1) ;; | |
349 | 2) | |
350 | [[ -z $initdir ]] && [[ -d $2 ]] && export initdir=$2 | |
351 | [[ $initdir = $2 ]] && set $1 | |
352 | ;; | |
353 | 3) | |
354 | [[ -z $initdir ]] && export initdir=$2 | |
355 | set $1 $3 | |
356 | ;; | |
357 | *) | |
358 | derror "inst only takes 1 or 2 or 3 arguments" | |
359 | exit 1 | |
360 | ;; | |
361 | esac | |
8c1faa35 | 362 | for x in inst_symlink inst_script inst_binary inst_simple; do |
34fffd88 | 363 | $x "$@" && return 0 |
36b24d7c VL |
364 | done |
365 | return 1 | |
04b56f3a JK |
366 | } |
367 | ||
53f95456 VL |
368 | # install function specialized for hooks |
369 | # $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook | |
370 | # All hooks should be POSIX/SuS compliant, they will be sourced by init. | |
371 | inst_hook() { | |
cdad82fd | 372 | if ! [[ -f $3 ]]; then |
6fac4691 HH |
373 | derror "Cannot install a hook ($3) that does not exist." |
374 | derror "Aborting initrd creation." | |
53f95456 | 375 | exit 1 |
cdad82fd | 376 | elif ! strstr "$hookdirs" "$1"; then |
6fac4691 | 377 | derror "No such hook type $1. Aborting initrd creation." |
53f95456 | 378 | exit 1 |
cdad82fd | 379 | fi |
53f95456 VL |
380 | inst_simple "$3" "/${1}/${2}${3##*/}" |
381 | } | |
382 | ||
f4fff04e | 383 | dracut_install() { |
bd4c4bcb VL |
384 | if [[ $1 = '-o' ]]; then |
385 | local optional=yes | |
386 | shift | |
387 | fi | |
f4fff04e | 388 | while (($# > 0)); do |
bd4c4bcb VL |
389 | if ! inst "$1" ; then |
390 | if [[ $optional = yes ]]; then | |
391 | dwarning "Skipping program $1 as it cannot be found and is flagged to be optional" | |
392 | else | |
393 | derror "Failed to install $1" | |
394 | exit 1 | |
395 | fi | |
396 | fi | |
397 | shift | |
f4fff04e VL |
398 | done |
399 | } | |
400 | ||
87122afc AŻ |
401 | # install function decompressing the target and handling symlinks |
402 | # $@ = list of compressed (gz or bz2) files or symlinks pointing to such files | |
403 | # | |
404 | # Function install targets in the same paths inside overlay but decompressed | |
405 | # and without extensions (.gz, .bz2). | |
406 | inst_decompress() { | |
407 | local src dst realsrc realdst cmd | |
408 | ||
409 | for src in $@ | |
410 | do | |
411 | case ${src} in | |
412 | *.gz) cmd='gzip -d' ;; | |
413 | *.bz2) cmd='bzip2 -d' ;; | |
414 | *) return 1 ;; | |
415 | esac | |
416 | ||
417 | if [[ -L ${src} ]] | |
418 | then | |
419 | realsrc="$(readlink -f ${src})" # symlink target with extension | |
420 | dst="${src%.*}" # symlink without extension | |
421 | realdst="${realsrc%.*}" # symlink target without extension | |
422 | mksubdirs "${initdir}/${src}" | |
423 | # Create symlink without extension to target without extension. | |
424 | ln -s "${realdst}" "${initdir}/${dst}" | |
425 | fi | |
426 | ||
427 | # If the source is symlink we operate on its target. | |
428 | [[ ${realsrc} ]] && src=${realsrc} | |
429 | inst ${src} | |
430 | # Decompress with chosen tool. We assume that tool changes name e.g. | |
431 | # from 'name.gz' to 'name'. | |
432 | ${cmd} "${initdir}${src}" | |
433 | done | |
434 | } | |
435 | ||
436 | # It's similar to above, but if file is not compressed, performs standard | |
437 | # install. | |
438 | # $@ = list of files | |
439 | inst_opt_decompress() { | |
440 | local src | |
441 | ||
442 | for src in $@ | |
443 | do | |
444 | inst_decompress "${src}" || inst "${src}" | |
445 | done | |
446 | } | |
447 | ||
0c2e3d12 | 448 | check_module_deps() { |
4cf26268 VL |
449 | local moddir dep ret |
450 | # if we are already set to be loaded, we do not have to be checked again. | |
bd4c4bcb | 451 | strstr "$mods_to_load" " $1 " && return |
0c2e3d12 | 452 | # turn a module name into a directory, if we can. |
5d791c0e | 453 | moddir=$(echo ${dracutbasedir}/modules.d/??${1}) |
0c2e3d12 VL |
454 | [[ -d $moddir && -x $moddir/install ]] || return 1 |
455 | # if we do not have a check script, we are unconditionally included | |
456 | if [[ -x $moddir/check ]]; then | |
4cf26268 VL |
457 | "$moddir/check" |
458 | ret=$? | |
459 | # a return value of 255 = load module only as a dependency. | |
460 | ((ret==0||ret==255)) || return 1 | |
0c2e3d12 | 461 | for dep in $("$moddir/check" -d); do |
4cf26268 | 462 | check_module_deps "$dep" && continue |
0c2e3d12 VL |
463 | dwarning "Dependency $mod failed." |
464 | return 1 | |
465 | done | |
466 | fi | |
467 | mods_to_load+=" $1 " | |
468 | } | |
469 | ||
470 | should_source_module() { | |
471 | local dep | |
0c1a8ebc | 472 | if [[ $kernel_only = yes ]]; then |
33ee031c HH |
473 | [[ -x $1/installkernel ]] && return 0 |
474 | return 1 | |
475 | fi | |
973c23b0 | 476 | [[ -x $1/install ]] || [[ -x $1/installkernel ]] || return 1 |
0c2e3d12 VL |
477 | [[ -x $1/check ]] || return 0 |
478 | "$1/check" $hostonly || return 1 | |
479 | for dep in $("$1/check" -d); do | |
4cf26268 | 480 | check_module_deps "$dep" && continue |
ed8c7bf5 | 481 | dwarning "Cannot load dracut module \"$mod\", dependencies failed." |
0c2e3d12 VL |
482 | return 1 |
483 | done | |
484 | } | |
485 | ||
486 | check_modules() { | |
70503db4 HH |
487 | local modcheck; |
488 | local mod; | |
5d791c0e | 489 | for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do |
0c2e3d12 | 490 | local mod=${moddir##*/}; mod=${mod#[0-9][0-9]} |
4cf26268 VL |
491 | # If we are already scheduled to be loaded, no need to check again. |
492 | strstr "$mods_to_load" " $mod " && continue | |
493 | # This should never happen, but... | |
0c2e3d12 VL |
494 | [[ -d $moddir ]] || continue |
495 | [[ $dracutmodules != all ]] && ! strstr "$dracutmodules" "$mod" && \ | |
496 | continue | |
497 | strstr "$omit_dracutmodules" "$mod" && continue | |
624b52c4 | 498 | if ! strstr "$add_dracutmodules" "$mod"; then |
970e646b HH |
499 | should_source_module "$moddir" || continue |
500 | fi | |
0c2e3d12 VL |
501 | mods_to_load+=" $mod " |
502 | done | |
70503db4 HH |
503 | |
504 | modcheck=$add_dracutmodules | |
505 | [[ $dracutmodules != all ]] && modcheck="$m $dracutmodules" | |
506 | for mod in $modcheck; do | |
507 | strstr "$mods_to_load" "$mod" && continue | |
508 | strstr "$omit_dracutmodules" "$mod" && continue | |
509 | dwarning "Dracut module \"$mod\" cannot be found." | |
510 | done | |
0c2e3d12 VL |
511 | } |
512 | ||
ddfd1d10 VL |
513 | # Install a single kernel module along with any firmware it may require. |
514 | # $1 = full path to kernel module to install | |
515 | install_kmod_with_fw() { | |
516 | local modname=${1##*/} fwdir found | |
9b37edbf | 517 | modname=${modname%.ko*} |
fb8923f6 VL |
518 | inst_simple "$1" "/lib/modules/$kernel/${1##*/lib/modules/$kernel/}" || \ |
519 | return 0 # no need to go further if the module is already installed | |
ddfd1d10 VL |
520 | for fw in $(modinfo -k $kernel -F firmware $1 2>/dev/null); do |
521 | found='' | |
522 | for fwdir in $fw_dir; do | |
523 | if [[ -d $fwdir && -f $fwdir/$fw ]]; then | |
524 | inst_simple "$fwdir/$fw" "/lib/firmware/$fw" | |
525 | found=yes | |
526 | fi | |
527 | done | |
528 | if [[ $found != yes ]]; then | |
ed8c7bf5 | 529 | dinfo "Possible missing firmware \"${fw}\" for kernel module \"${mod}.ko\"" |
ddfd1d10 VL |
530 | fi |
531 | done | |
532 | } | |
533 | ||
534 | # Do something with all the dependencies of a kernel module. | |
535 | # Note that kernel modules depend on themselves using the technique we use | |
536 | # $1 = function to call for each dependency we find | |
537 | # It will be passed the full path to the found kernel module | |
538 | # $2 = module to get dependencies for | |
539 | # rest of args = arguments to modprobe | |
540 | for_each_kmod_dep() { | |
541 | local func=$1 kmod=$2 cmd modpapth options | |
542 | shift 2 | |
543 | modprobe "$@" --ignore-install --show-depends $kmod 2>/dev/null | \ | |
544 | while read cmd modpath options; do | |
545 | [[ $cmd = insmod ]] || continue | |
546 | $func $modpath | |
547 | done | |
548 | } | |
549 | ||
95bde758 | 550 | # filter kernel modules to install certain modules that meet specific |
240cc7c4 VL |
551 | # requirements. |
552 | # $1 = function to call with module name to filter. | |
553 | # This function will be passed the full path to the module to test. | |
554 | # The behaviour of this function can vary depending on whether $hostonly is set. | |
555 | # If it is, we will only look at modules that are already in memory. | |
556 | # If it is not, we will look at all kernel modules | |
fb8923f6 | 557 | # This function returns the full filenames of modules that match $1 |
240cc7c4 | 558 | filter_kernel_modules () ( |
ba67b923 | 559 | if ! [[ $hostonly ]]; then |
9b37edbf | 560 | filtercmd='find "$srcmods/kernel/drivers" -name "*.ko" -o -name "*.ko.gz"' |
240cc7c4 | 561 | else |
fb8923f6 | 562 | filtercmd='cut -d " " -f 1 </proc/modules|xargs modinfo -F filename -k $kernel' |
240cc7c4 | 563 | fi |
fb8923f6 | 564 | for modname in $(eval $filtercmd); do |
9b37edbf LB |
565 | case $modname in |
566 | *.ko) | |
567 | "$1" "$modname" && echo "$modname" | |
568 | ;; | |
569 | *.ko.gz) | |
570 | gzip -dc "$modname" > $initdir/$$.ko | |
571 | $1 $initdir/$$.ko && echo "$modname" | |
572 | rm -f $initdir/$$.ko | |
573 | ;; | |
574 | esac | |
fb8923f6 | 575 | done |
240cc7c4 VL |
576 | ) |
577 | ||
ddfd1d10 | 578 | # install kernel modules along with all their dependencies. |
6fa0c3d6 | 579 | instmods() { |
0c1a8ebc | 580 | [[ $no_kernel = yes ]] && return |
ecf42850 | 581 | local mod mpargs modpath modname cmd moddirname |
6fa0c3d6 | 582 | while (($# > 0)); do |
9b37edbf | 583 | mod=${1%.ko*} |
6fa0c3d6 | 584 | case $mod in |
992acaa9 | 585 | =*) # This introduces 2 incompatible meanings for =* arguments |
74534e19 | 586 | # to instmods. We need to decide which one to keep. |
0c1a8ebc | 587 | if [[ $mod = =ata && -f $srcmods/modules.block ]] ; then |
c93d9f62 | 588 | instmods $mpargs $(egrep 'ata|ahci' "${srcmods}/modules.block") |
86c9fa48 | 589 | elif [ -f $srcmods/modules.${mod#=} ]; then |
8d385248 | 590 | instmods $mpargs $(cat ${srcmods}/modules.${mod#=} ) |
20122a83 | 591 | else |
8d385248 | 592 | instmods $mpargs $(find "$srcmods" -path "*/${mod#=}/*") |
20122a83 HH |
593 | fi |
594 | ;; | |
6568d86a HH |
595 | --*) |
596 | mod=${mod##*/} | |
597 | mpargs+=" $mod";; | |
71afe645 WT |
598 | i2o_scsi) |
599 | # Must never run this diagnostic-only module | |
600 | shift; continue; | |
601 | ;; | |
6568d86a HH |
602 | *) |
603 | mod=${mod##*/} | |
604 | # if we are already installed, skip this module and go on | |
4cf26268 | 605 | # to the next one. |
3198f171 | 606 | [[ -f $initdir/$1 ]] && { shift; continue; } |
4cf26268 VL |
607 | # If we are building a host-specific initramfs and this |
608 | # module is not already loaded, move on to the next one. | |
74c5dd21 LB |
609 | [[ $hostonly ]] && ! grep -q "${mod//-/_}" /proc/modules && \ |
610 | ! echo $add_drivers | grep -qe "\<${mod}\>" && { | |
4cf26268 VL |
611 | shift; continue; |
612 | } | |
ecf42850 AŻ |
613 | |
614 | # We use '-d' option in modprobe only if modules prefix path | |
615 | # differs from default '/'. This allows us to use Dracut with | |
616 | # old version of modprobe which doesn't have '-d' option. | |
617 | moddirname=${srcmods%%/lib/modules/*} | |
618 | [[ -n ${moddirname} ]] && moddirname="-d ${moddirname}/" | |
619 | ||
0c1a8ebc VL |
620 | # ok, load the module, all its dependencies, and any firmware |
621 | # it may require | |
ddfd1d10 | 622 | for_each_kmod_dep install_kmod_with_fw $mod \ |
ecf42850 | 623 | --set-version $kernel ${moddirname} |
6fa0c3d6 | 624 | ;; |
c93d9f62 | 625 | esac |
6fa0c3d6 | 626 | shift |
04b56f3a | 627 | done |
6fa0c3d6 | 628 | } |
04b56f3a | 629 | |
04b56f3a | 630 | # vim:ts=8:sw=4:sts=4:et |