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