2008-12-18 00:57:43 +03:00
#!/bin/bash
2010-09-10 17:23:06 +04:00
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
2008-12-18 00:57:43 +03:00
#
2009-07-22 14:43:26 +04:00
# functions used by dracut and other tools.
2008-12-18 00:57:43 +03:00
#
2009-07-22 14:43:26 +04:00
# Copyright 2005-2009 Red Hat, Inc. All rights reserved.
2008-12-18 00:57:43 +03:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
2009-03-04 19:29:42 +03:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2008-12-18 00:57:43 +03:00
#
2012-07-19 15:35:50 +04:00
export LC_MESSAGES = C
2012-06-30 11:12:35 +04:00
if [ [ $DRACUT_KERNEL_LAZY ] ] && ! [ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] ; then
if ! [ [ -d " $initdir /.kernelmodseen " ] ] ; then
mkdir -p " $initdir /.kernelmodseen "
fi
DRACUT_KERNEL_LAZY_HASHDIR = " $initdir /.kernelmodseen "
fi
2012-06-27 16:18:21 +04:00
2012-06-30 14:46:55 +04:00
if [ [ $initdir ] ] && ! [ [ -d $initdir ] ] ; then
mkdir -p " $initdir "
fi
2012-06-18 14:52:39 +04:00
# Generic substring function. If $2 is in $1, return 0.
2012-06-22 10:57:20 +04:00
strstr( ) { [ [ $1 = *$2 * ] ] ; }
2012-06-18 14:52:39 +04:00
2012-06-30 11:12:35 +04:00
# find a binary. If we were not passed the full path directly,
# search in the usual places to find the binary.
find_binary( ) {
if [ [ -z ${ 1 ##/* } ] ] ; then
2013-07-04 14:29:59 +04:00
if [ [ -x $1 ] ] || { [ [ " $1 " = = *.so* ] ] && ldd " $1 " & >/dev/null; } ; then
printf "%s\n" " $1 "
2012-06-30 11:12:35 +04:00
return 0
fi
fi
2013-07-04 14:29:59 +04:00
type -P " ${ 1 ##*/ } "
2012-06-30 11:12:35 +04:00
}
2011-03-25 17:40:51 +03:00
if ! [ [ $dracutbasedir ] ] ; then
dracutbasedir = ${ BASH_SOURCE [0]%/* }
[ [ $dracutbasedir = "dracut-functions" ] ] && dracutbasedir = "."
[ [ $dracutbasedir ] ] || dracutbasedir = "."
dracutbasedir = " $( readlink -f $dracutbasedir ) "
fi
2012-06-30 11:12:35 +04:00
if ! [ [ $DRACUT_INSTALL ] ] ; then
DRACUT_INSTALL = $( find_binary dracut-install)
fi
if ! [ [ $DRACUT_INSTALL ] ] && [ [ -x $dracutbasedir /dracut-install ] ] ; then
DRACUT_INSTALL = $dracutbasedir /dracut-install
fi
2012-06-18 14:52:39 +04:00
# Detect lib paths
if ! [ [ $libdirs ] ] ; then
2013-07-04 14:29:59 +04:00
if [ [ " $( ldd /bin/sh) " = = */lib64/* ] ] & >/dev/null \
2012-06-18 14:52:39 +04:00
&& [ [ -d /lib64 ] ] ; then
libdirs += " /lib64"
[ [ -d /usr/lib64 ] ] && libdirs += " /usr/lib64"
else
libdirs += " /lib"
[ [ -d /usr/lib ] ] && libdirs += " /usr/lib"
fi
export libdirs
fi
if ! [ [ $kernel ] ] ; then
kernel = $( uname -r)
export kernel
fi
srcmods = " /lib/modules/ $kernel / "
[ [ $drivers_dir ] ] && {
2013-07-04 14:29:59 +04:00
if vercmp " $( modprobe --version | cut -d' ' -f3) " lt 3.7; then
2012-06-18 14:52:39 +04:00
dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
exit 1
fi
srcmods = " $drivers_dir "
}
export srcmods
2011-03-25 17:38:54 +03:00
if ! type dinfo >/dev/null 2>& 1; then
2012-02-22 13:14:17 +04:00
. " $dracutbasedir /dracut-logger.sh "
2011-03-15 21:37:45 +03:00
dlog_init
fi
2012-07-09 12:02:04 +04:00
if ! [ [ $initdir ] ] ; then
dfatal "initdir not set"
exit 1
fi
2012-02-16 14:49:19 +04:00
# export standard hookdirs
[ [ $hookdirs ] ] || {
2012-03-02 17:46:11 +04:00
hookdirs = "cmdline pre-udev pre-trigger netroot "
2012-03-07 03:25:25 +04:00
hookdirs += "initqueue initqueue/settled initqueue/online initqueue/finished initqueue/timeout "
2012-04-23 13:31:32 +04:00
hookdirs += "pre-mount pre-pivot cleanup mount "
2013-01-18 13:59:39 +04:00
hookdirs += "emergency shutdown-emergency pre-shutdown shutdown "
2012-02-16 14:49:19 +04:00
export hookdirs
}
2013-03-06 19:00:11 +04:00
dracut_need_initqueue( ) {
>" $initdir /lib/dracut/need-initqueue "
}
dracut_module_included( ) {
2013-07-04 14:29:59 +04:00
[ [ " $mods_to_load $modules_loaded " = = *$@ * ] ]
2013-03-06 19:00:11 +04:00
}
2010-07-01 23:17:37 +04:00
# Create all subdirectories for given path without creating the last element.
# $1 = path
2013-07-04 14:29:59 +04:00
mksubdirs( ) {
[ [ -e ${ 1 %/* } ] ] || mkdir -m 0755 -p -- " ${ 1 %/* } "
}
2010-07-01 23:17:37 +04:00
2010-06-11 23:10:34 +04:00
# Version comparision function. Assumes Linux style version scheme.
# $1 = version a
# $2 = comparision op (gt, ge, eq, le, lt, ne)
# $3 = version b
2010-06-09 12:36:05 +04:00
vercmp( ) {
2013-07-04 14:29:59 +04:00
local _n1 = ${ 1 //./ } _op = $2 _n2 = ${ 3 //./ } _i _res
2010-06-09 12:36:05 +04:00
2011-05-12 13:03:30 +04:00
for ( ( _i = 0; ; _i++) )
2010-06-11 23:10:34 +04:00
do
2011-05-12 13:03:30 +04:00
if [ [ ! ${ _n1 [_i] } ${ _n2 [_i] } ] ] ; then _res = 0
elif ( ( ${ _n1 [_i] :- 0 } > ${ _n2 [_i] :- 0 } ) ) ; then _res = 1
elif ( ( ${ _n1 [_i] :- 0 } < ${ _n2 [_i] :- 0 } ) ) ; then _res = 2
2010-06-11 23:10:34 +04:00
else continue
fi
break
2010-06-09 12:36:05 +04:00
done
2011-05-12 13:03:30 +04:00
case $_op in
gt) ( ( _res = = 1) ) ; ;
ge) ( ( _res != 2) ) ; ;
eq) ( ( _res = = 0) ) ; ;
le) ( ( _res != 1) ) ; ;
lt) ( ( _res = = 2) ) ; ;
ne) ( ( _res != 0) ) ; ;
2010-06-11 23:10:34 +04:00
esac
2010-06-09 12:36:05 +04:00
}
2012-02-16 14:49:19 +04:00
# is_func <command>
# Check whether $1 is a function.
2011-02-02 15:34:58 +03:00
is_func( ) {
2013-07-04 14:29:59 +04:00
[ [ " $( type -t " $1 " ) " = "function" ] ]
2011-02-02 15:34:58 +03:00
}
2010-07-01 23:17:37 +04:00
# Function prints global variables in format name=value line by line.
# $@ = list of global variables' name
print_vars( ) {
2011-05-12 13:03:30 +04:00
local _var _value
2010-07-01 23:17:37 +04:00
2013-07-04 14:29:59 +04:00
for _var in " $@ "
2010-07-01 23:17:37 +04:00
do
2013-07-04 14:29:59 +04:00
eval printf -v _value "%s" " \$ $_var "
[ [ ${ _value } ] ] && printf '%s="%s"\n' " $_var " " $_value "
2010-07-01 23:17:37 +04:00
done
}
2012-02-16 14:49:19 +04:00
# normalize_path <path>
# Prints the normalized path, where it removes any duplicated
# and trailing slashes.
# Example:
# $ normalize_path ///test/test//
# /test/test
2011-07-25 16:28:55 +04:00
normalize_path( ) {
2011-10-08 02:20:50 +04:00
shopt -q -s extglob
set -- " ${ 1 //+( \/ )// } "
shopt -q -u extglob
echo " ${ 1 %/ } "
2011-07-25 16:28:55 +04:00
}
2011-07-25 12:25:44 +04:00
2012-02-16 14:49:19 +04:00
# convert_abs_rel <from> <to>
# Prints the relative path, when creating a symlink to <to> from <from>.
# Example:
# $ convert_abs_rel /usr/bin/test /bin/test-2
# ../../bin/test-2
# $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
2011-07-25 12:25:44 +04:00
convert_abs_rel( ) {
2012-02-22 16:04:37 +04:00
local __current __absolute __abssize __cursize __newpath
2011-10-08 02:20:50 +04:00
local -i __i __level
2011-07-25 12:25:44 +04:00
2011-10-08 02:20:50 +04:00
set -- " $( normalize_path " $1 " ) " " $( normalize_path " $2 " ) "
2011-10-08 00:23:49 +04:00
# corner case #1 - self looping link
[ [ " $1 " = = " $2 " ] ] && { echo " ${ 1 ##*/ } " ; return ; }
# corner case #2 - own dir link
[ [ " ${ 1 %/* } " = = " $2 " ] ] && { echo "." ; return ; }
2012-02-22 16:04:37 +04:00
IFS = "/" __current = ( $1 )
IFS = "/" __absolute = ( $2 )
2011-07-25 12:25:44 +04:00
__abssize = ${# __absolute [@] }
__cursize = ${# __current [@] }
2013-07-04 14:29:59 +04:00
while [ [ " ${ __absolute [__level] } " = = " ${ __current [__level] } " ] ]
2011-07-25 12:25:44 +04:00
do
( ( __level++ ) )
if ( ( __level > __abssize || __level > __cursize ) )
then
break
fi
done
for ( ( __i = __level; __i < __cursize-1; __i++) )
do
if ( ( __i > __level) )
then
__newpath = $__newpath "/"
fi
__newpath = $__newpath ".."
done
for ( ( __i = __level; __i < __abssize; __i++) )
do
if [ [ -n $__newpath ] ]
then
__newpath = $__newpath "/"
fi
__newpath = $__newpath ${ __absolute [__i] }
done
echo " $__newpath "
}
2013-07-04 14:29:59 +04:00
if [ [ " $( ln --help) " = = *--relative* ] ] ; then
2012-06-21 03:57:11 +04:00
ln_r( ) {
ln -sfnr " ${ initdir } / $1 " " ${ initdir } / $2 "
}
else
ln_r( ) {
local _source = $1
local _dest = $2
[ [ -d " ${ _dest %/* } " ] ] && _dest = $( readlink -f " ${ _dest %/* } " ) /${ _dest ##*/ }
2013-07-04 14:29:59 +04:00
ln -sfn -- " $( convert_abs_rel " ${ _dest } " " ${ _source } " ) " " ${ initdir } / ${ _dest } "
2012-06-21 03:57:11 +04:00
}
fi
2012-09-10 12:10:46 +04:00
get_persistent_dev( ) {
local i _tmp _dev
_dev = $( udevadm info --query= name --name= " $1 " 2>/dev/null)
[ -z " $_dev " ] && return
2012-09-28 13:13:20 +04:00
for i in /dev/mapper/* /dev/disk/by-uuid/* /dev/disk/by-id/*; do
2013-05-31 09:46:08 +04:00
[ [ $i = = /dev/mapper/mpath* ] ] && continue
2012-09-10 12:10:46 +04:00
_tmp = $( udevadm info --query= name --name= " $i " 2>/dev/null)
if [ " $_tmp " = " $_dev " ] ; then
2013-07-04 14:29:59 +04:00
printf -- "%s" " $i "
2012-09-10 12:10:46 +04:00
return
fi
done
}
2012-02-16 14:49:19 +04:00
# get_fs_env <device>
2013-07-04 14:29:59 +04:00
# Get and set the ID_FS_TYPE variable from udev for a device.
2012-02-16 14:49:19 +04:00
# Example:
2013-07-04 14:29:59 +04:00
# $ get_fs_env /dev/sda2; echo $ID_FS_TYPE
2012-02-16 14:49:19 +04:00
# ext4
2009-08-22 21:04:11 +04:00
get_fs_env( ) {
2012-03-30 12:47:35 +04:00
local evalstr
local found
2010-08-06 15:54:34 +04:00
[ [ $1 ] ] || return
2011-05-12 13:03:30 +04:00
unset ID_FS_TYPE
2013-07-04 14:29:59 +04:00
if ID_FS_TYPE = $( udevadm info --query= env --name= " $1 " \
2012-03-30 12:47:35 +04:00
| { while read line; do
2013-07-04 14:29:59 +04:00
[ [ " $line " = = DEVPATH\= * ] ] && found = 1;
if [ [ " $line " = = ID_FS_TYPE\= * ] ] ; then
printf "%s" " ${ line #ID_FS_TYPE= } " ;
exit 0;
fi
2013-07-31 13:00:29 +04:00
done ; [ [ $found ] ] && exit 0; exit 1; } ) ; then
2013-07-04 14:29:59 +04:00
if [ [ $ID_FS_TYPE ] ] ; then
printf "%s" " $ID_FS_TYPE "
return 0
fi
2012-03-30 12:47:35 +04:00
fi
2010-05-03 13:34:30 +04:00
2012-03-30 12:47:35 +04:00
# Fallback, if we don't have udev information
2012-03-29 16:56:46 +04:00
if find_binary blkid >/dev/null; then
2013-07-04 14:29:59 +04:00
ID_FS_TYPE = $( blkid -u filesystem -o export -- " $1 " \
2012-03-29 16:56:46 +04:00
| while read line; do
2013-07-04 14:29:59 +04:00
if [ [ " $line " = = TYPE\= * ] ] ; then
printf "%s" " ${ line #TYPE= } " ;
exit 0;
fi
2012-03-29 16:56:46 +04:00
done )
2013-07-04 14:29:59 +04:00
if [ [ $ID_FS_TYPE ] ] ; then
printf "%s" " $ID_FS_TYPE "
return 0
fi
2010-08-06 15:54:34 +04:00
fi
2012-03-29 16:56:46 +04:00
return 1
}
2009-08-22 21:04:11 +04:00
2012-02-16 14:49:19 +04:00
# get_maj_min <device>
# Prints the major and minor of a device node.
# Example:
# $ get_maj_min /dev/sda2
# 8:2
2011-12-08 13:43:29 +04:00
get_maj_min( ) {
2013-07-31 13:00:29 +04:00
local _maj _min _majmin
_majmin = " $( stat -L -c '%t:%T' " $1 " 2>/dev/null) "
printf "%s" " $(( 0 x${ _majmin % : * } )) : $(( 0 x${ _majmin #* : } )) "
2011-12-08 13:43:29 +04:00
}
2012-02-16 14:49:19 +04:00
# find_block_device <mountpoint>
# Prints the major and minor number of the block device
# for a given mountpoint.
# Unless $use_fstab is set to "yes" the functions
# uses /proc/self/mountinfo as the primary source of the
# information and only falls back to /etc/fstab, if the mountpoint
# is not found there.
# Example:
# $ find_block_device /usr
# 8:4
2009-08-20 07:20:12 +04:00
find_block_device( ) {
2013-04-09 12:47:39 +04:00
local _majmin _dev _majmin _find_mpt
2013-01-23 17:10:15 +04:00
_find_mpt = " $1 "
2011-03-25 17:56:46 +03:00
if [ [ $use_fstab != yes ] ] ; then
2013-04-09 12:47:39 +04:00
[ [ -d $_find_mpt /. ] ]
2013-07-31 13:00:29 +04:00
findmnt -e -v -n -o 'MAJ:MIN,SOURCE' --target " $_find_mpt " | { \
while read _majmin _dev; do
if [ [ -b $_dev ] ] ; then
if ! [ [ $_majmin ] ] || [ [ $_majmin = = 0:* ] ] ; then
_majmin = $( get_maj_min $_dev )
fi
if [ [ $_majmin ] ] ; then
echo $_majmin
else
echo $_dev
fi
return 0
fi
if [ [ $_dev = *:* ] ] ; then
echo $_dev
return 0
fi
done ; return 1; } && return 0
fi
# fall back to /etc/fstab
findmnt -e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target " $_find_mpt " | { \
2013-04-09 12:47:39 +04:00
while read _majmin _dev; do
2013-07-31 13:00:29 +04:00
if ! [ [ $_dev ] ] ; then
_dev = " $_majmin "
unset _majmin
fi
2013-04-09 12:47:39 +04:00
if [ [ -b $_dev ] ] ; then
2013-07-31 13:00:29 +04:00
[ [ $_majmin ] ] || _majmin = $( get_maj_min $_dev )
2013-04-09 12:47:39 +04:00
if [ [ $_majmin ] ] ; then
echo $_majmin
else
echo $_dev
fi
return 0
fi
if [ [ $_dev = *:* ] ] ; then
echo $_dev
return 0
2010-09-10 17:23:06 +04:00
fi
2013-07-31 13:00:29 +04:00
done ; return 1; } && return 0
2011-03-25 17:56:46 +03:00
return 1
2009-08-16 19:29:21 +04:00
}
2013-04-09 12:47:39 +04:00
# find_mp_fstype <mountpoint>
# Echo the filesystem type for a given mountpoint.
2012-02-16 14:49:19 +04:00
# /proc/self/mountinfo is taken as the primary source of information
# and /etc/fstab is used as a fallback.
# No newline is appended!
# Example:
2013-04-09 12:47:39 +04:00
# $ find_mp_fstype /;echo
2012-02-16 14:49:19 +04:00
# ext4
2013-04-09 12:47:39 +04:00
find_mp_fstype( ) {
local _fs
2011-12-08 13:25:58 +04:00
2013-04-09 12:47:39 +04:00
if [ [ $use_fstab != yes ] ] ; then
2013-07-31 13:00:29 +04:00
findmnt -e -v -n -o 'FSTYPE' --target " $1 " | { \
while read _fs; do
[ [ $_fs ] ] || continue
[ [ $_fs = "autofs" ] ] && continue
echo -n $_fs
return 0
done ; return 1; } && return 0
fi
findmnt --fstab -e -v -n -o 'FSTYPE' --target " $1 " | { \
2013-04-09 12:47:39 +04:00
while read _fs; do
[ [ $_fs ] ] || continue
[ [ $_fs = "autofs" ] ] && continue
echo -n $_fs
return 0
2013-07-31 13:00:29 +04:00
done ; return 1; } && return 0
2011-12-08 13:25:58 +04:00
return 1
}
2013-04-09 12:47:39 +04:00
# find_dev_fstype <device>
# Echo the filesystem type for a given device.
2012-07-26 19:00:07 +04:00
# /proc/self/mountinfo is taken as the primary source of information
# and /etc/fstab is used as a fallback.
# No newline is appended!
# Example:
2013-04-09 12:47:39 +04:00
# $ find_dev_fstype /dev/sda2;echo
2012-07-26 19:00:07 +04:00
# ext4
2013-04-09 12:47:39 +04:00
find_dev_fstype( ) {
2013-06-24 14:47:01 +04:00
local _find_dev _fs
2013-04-09 12:47:39 +04:00
_find_dev = " $1 "
[ [ " $_find_dev " = /dev* ] ] || _find_dev = " /dev/block/ $_find_dev "
2013-06-24 14:47:01 +04:00
if [ [ $use_fstab != yes ] ] ; then
2013-07-31 13:00:29 +04:00
findmnt -e -v -n -o 'FSTYPE' --source " $_find_dev " | { \
while read _fs; do
[ [ $_fs ] ] || continue
[ [ $_fs = "autofs" ] ] && continue
echo -n $_fs
return 0
done ; return 1; } && return 0
fi
findmnt --fstab -e -v -n -o 'FSTYPE' --source " $_find_dev " | { \
2013-06-24 14:47:01 +04:00
while read _fs; do
[ [ $_fs ] ] || continue
[ [ $_fs = "autofs" ] ] && continue
echo -n $_fs
return 0
2013-07-31 13:00:29 +04:00
done ; return 1; } && return 0
2013-06-24 14:47:01 +04:00
return 1
2012-07-26 19:00:07 +04:00
}
2011-12-08 13:25:58 +04:00
# finds the major:minor of the block device backing the root filesystem.
2009-08-20 07:20:12 +04:00
find_root_block_device( ) { find_block_device /; }
2012-02-16 14:49:19 +04:00
# for_each_host_dev_fs <func>
2013-03-11 19:32:16 +04:00
# Execute "<func> <dev> <filesystem>" for every "<dev> <fs>" pair found
2012-02-16 14:49:19 +04:00
# in ${host_fs_types[@]}
2011-12-08 13:43:29 +04:00
for_each_host_dev_fs( )
{
local _func = " $1 "
2011-12-20 10:09:59 +04:00
local _dev
2012-02-22 22:06:00 +04:00
local _ret = 1
2013-03-18 11:43:23 +04:00
[ [ " ${ !host_fs_types[@] } " ] ] || return 0
2013-03-11 19:32:16 +04:00
for _dev in " ${ !host_fs_types[@] } " ; do
$_func " $_dev " " ${ host_fs_types [ $_dev ] } " && _ret = 0
2011-12-08 13:43:29 +04:00
done
2012-02-22 22:06:00 +04:00
return $_ret
2011-12-08 13:43:29 +04:00
}
2013-03-18 11:43:23 +04:00
host_fs_all( )
{
echo " ${ host_fs_types [@] } "
}
2009-08-16 19:29:21 +04:00
# Walk all the slave relationships for a given block device.
# Stop when our helper function returns success
# $1 = function to call on every found block device
# $2 = block device in major:minor format
2011-03-25 17:56:46 +03:00
check_block_and_slaves( ) {
2011-05-12 13:03:30 +04:00
local _x
2009-08-16 19:29:21 +04:00
[ [ -b /dev/block/$2 ] ] || return 1 # Not a block device? So sorry.
" $1 " $2 && return
2009-08-31 16:58:44 +04:00
check_vol_slaves " $@ " && return 0
2010-08-14 23:23:24 +04:00
if [ [ -f /sys/dev/block/$2 /../dev ] ] ; then
2013-07-31 13:00:29 +04:00
check_block_and_slaves $1 $( <" /sys/dev/block/ $2 /../dev " ) && return 0
2010-05-19 10:13:12 +04:00
fi
2009-08-16 19:29:21 +04:00
[ [ -d /sys/dev/block/$2 /slaves ] ] || return 1
2011-05-12 13:03:30 +04:00
for _x in /sys/dev/block/$2 /slaves/*/dev; do
2012-08-01 07:23:42 +04:00
[ [ -f $_x ] ] || continue
2013-07-31 13:00:29 +04:00
check_block_and_slaves $1 $( <" $_x " ) && return 0
2009-08-16 19:29:21 +04:00
done
return 1
}
2012-08-23 07:02:23 +04:00
check_block_and_slaves_all( ) {
local _x _ret = 1
[ [ -b /dev/block/$2 ] ] || return 1 # Not a block device? So sorry.
if " $1 " $2 ; then
2013-07-31 13:00:29 +04:00
_ret = 0
2012-08-23 07:02:23 +04:00
fi
check_vol_slaves " $@ " && return 0
if [ [ -f /sys/dev/block/$2 /../dev ] ] ; then
2013-07-31 13:00:29 +04:00
check_block_and_slaves_all $1 $( <" /sys/dev/block/ $2 /../dev " ) && _ret = 0
2012-08-23 07:02:23 +04:00
fi
[ [ -d /sys/dev/block/$2 /slaves ] ] || return 1
for _x in /sys/dev/block/$2 /slaves/*/dev; do
[ [ -f $_x ] ] || continue
2013-07-31 13:00:29 +04:00
check_block_and_slaves_all $1 $( <" $_x " ) && _ret = 0
2012-08-23 07:02:23 +04:00
done
return $_ret
}
# for_each_host_dev_and_slaves <func>
# Execute "<func> <dev>" for every "<dev>" found
# in ${host_devs[@]} and their slaves
for_each_host_dev_and_slaves_all( )
{
local _func = " $1 "
local _dev
local _ret = 1
2013-03-18 11:43:23 +04:00
[ [ " ${ host_devs [@] } " ] ] || return 0
2012-08-23 07:02:23 +04:00
for _dev in ${ host_devs [@] } ; do
[ [ -b " $_dev " ] ] || continue
if check_block_and_slaves_all $_func $( get_maj_min $_dev ) ; then
2013-07-31 13:00:29 +04:00
_ret = 0
2012-08-23 07:02:23 +04:00
fi
done
return $_ret
}
for_each_host_dev_and_slaves( )
{
local _func = " $1 "
local _dev
2013-03-18 11:43:23 +04:00
[ [ " ${ host_devs [@] } " ] ] || return 0
2012-08-23 07:02:23 +04:00
for _dev in ${ host_devs [@] } ; do
[ [ -b " $_dev " ] ] || continue
2012-08-28 06:05:49 +04:00
check_block_and_slaves $_func $( get_maj_min $_dev ) && return 0
2012-08-23 07:02:23 +04:00
done
return 1
}
2009-08-31 16:58:44 +04:00
# ugly workaround for the lvm design
# There is no volume group device,
# so, there are no slave devices for volume groups.
# Logical volumes only have the slave devices they really live on,
# but you cannot create the logical volume without the volume group.
2009-10-29 12:29:58 +03:00
# And the volume group might be bigger than the devices the LV needs.
2009-08-31 16:58:44 +04:00
check_vol_slaves( ) {
2011-05-12 13:03:30 +04:00
local _lv _vg _pv
2011-03-25 17:56:46 +03:00
for i in /dev/mapper/*; do
2012-02-16 14:48:17 +04:00
_lv = $( get_maj_min $i )
2011-05-12 13:03:30 +04:00
if [ [ $_lv = $2 ] ] ; then
_vg = $( lvm lvs --noheadings -o vg_name $i 2>/dev/null)
2010-09-10 17:23:06 +04:00
# strip space
2011-05-12 13:03:30 +04:00
_vg = $( echo $_vg )
if [ [ $_vg ] ] ; then
for _pv in $( lvm vgs --noheadings -o pv_name " $_vg " 2>/dev/null)
2011-03-25 17:56:46 +03:00
do
2012-02-16 14:48:17 +04:00
check_block_and_slaves $1 $( get_maj_min $_pv ) && return 0
2010-09-10 17:23:06 +04:00
done
fi
fi
2009-08-31 16:58:44 +04:00
done
return 1
}
2012-07-26 19:22:14 +04:00
# fs_get_option <filesystem options> <search for option>
# search for a specific option in a bunch of filesystem options
# and return the value
fs_get_option( ) {
local _fsopts = $1
local _option = $2
local OLDIFS = " $IFS "
IFS = ,
set -- $_fsopts
IFS = " $OLDIFS "
while [ $# -gt 0 ] ; do
case $1 in
$_option = *)
echo ${ 1 # ${ _option } = }
break
esac
shift
done
}
2012-06-30 11:12:35 +04:00
if [ [ $DRACUT_INSTALL ] ] ; then
2012-06-29 14:07:44 +04:00
[ [ $DRACUT_RESOLVE_LAZY ] ] || export DRACUT_RESOLVE_DEPS = 1
inst_dir( ) {
[ [ -e ${ initdir } /" $1 " ] ] && return 0 # already there
2012-06-30 11:12:35 +04:00
$DRACUT_INSTALL ${ initdir +-D " $initdir " } -d " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } -d " $@ " || :
2012-06-29 14:07:44 +04:00
}
2009-09-27 08:33:41 +04:00
2012-06-29 14:07:44 +04:00
inst( ) {
[ [ -e ${ initdir } /" ${ 2 :- $1 } " ] ] && return 0 # already there
2012-06-30 11:12:35 +04:00
#dinfo "$DRACUT_INSTALL -l $@"
$DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ " || :
2012-06-29 14:07:44 +04:00
}
inst_simple( ) {
[ [ -e ${ initdir } /" ${ 2 :- $1 } " ] ] && return 0 # already there
[ [ -e $1 ] ] || return 1 # no source
2012-06-30 11:12:35 +04:00
$DRACUT_INSTALL ${ initdir +-D " $initdir " } " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } " $@ " || :
2012-06-29 14:07:44 +04:00
}
inst_symlink( ) {
[ [ -e ${ initdir } /" ${ 2 :- $1 } " ] ] && return 0 # already there
[ [ -L $1 ] ] || return 1
2012-06-30 11:12:35 +04:00
$DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ " || :
2012-06-29 14:07:44 +04:00
}
dracut_install( ) {
2012-10-08 13:40:08 +04:00
local ret
2012-06-30 11:12:35 +04:00
#dinfo "initdir=$initdir $DRACUT_INSTALL -l $@"
$DRACUT_INSTALL ${ initdir +-D " $initdir " } -a ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ "
2012-10-08 13:40:08 +04:00
ret = $?
( ( $ret != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } -a ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ " || :
return $ret
2012-06-29 14:07:44 +04:00
}
inst_library( ) {
[ [ -e ${ initdir } /" ${ 2 :- $1 } " ] ] && return 0 # already there
[ [ -e $1 ] ] || return 1 # no source
2012-06-30 11:12:35 +04:00
$DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ " || :
2012-06-29 14:07:44 +04:00
}
inst_binary( ) {
2012-06-30 11:12:35 +04:00
$DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ " || :
2012-06-29 14:07:44 +04:00
}
inst_script( ) {
2012-06-30 11:12:35 +04:00
$DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ "
( ( $? != 0) ) && derror $DRACUT_INSTALL ${ initdir +-D " $initdir " } ${ DRACUT_RESOLVE_DEPS +-l } ${ DRACUT_FIPS_MODE +-H } " $@ " || :
2012-06-29 14:07:44 +04:00
}
else
# Install a directory, keeping symlinks as on the original system.
# Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
# will create ${initdir}/lib64, ${initdir}/lib64/file,
# and a symlink ${initdir}/lib -> lib64.
inst_dir( ) {
[ [ -e ${ initdir } /" $1 " ] ] && return 0 # already there
local _dir = " $1 " _part = " ${ 1 %/* } " _file
while [ [ " $_part " != " ${ _part %/* } " ] ] && ! [ [ -e " ${ initdir } / ${ _part } " ] ] ; do
_dir = " $_part $_dir "
_part = ${ _part %/* }
done
# iterate over parent directories
for _file in $_dir ; do
[ [ -e " ${ initdir } / $_file " ] ] && continue
if [ [ -L $_file ] ] ; then
inst_symlink " $_file "
else
2009-09-27 08:33:41 +04:00
# create directory
2012-06-29 14:07:44 +04:00
mkdir -m 0755 -p " ${ initdir } / $_file " || return 1
[ [ -e " $_file " ] ] && chmod --reference= " $_file " " ${ initdir } / $_file "
chmod u+w " ${ initdir } / $_file "
fi
done
}
# $1 = file to copy to ramdisk
# $2 (optional) Name for the file on the ramdisk
# Location of the image dir is assumed to be $initdir
# We never overwrite the target if it exists.
inst_simple( ) {
[ [ -f " $1 " ] ] || return 1
2013-07-04 14:29:59 +04:00
[ [ " $1 " = = */* ] ] || return 1
2012-06-29 14:07:44 +04:00
local _src = $1 _target = " ${ 2 :- $1 } "
[ [ -L $_src ] ] && { inst_symlink $_src $_target ; return $? ; }
if ! [ [ -d ${ initdir } /$_target ] ] ; then
[ [ -e ${ initdir } /$_target ] ] && return 0
[ [ -L ${ initdir } /$_target ] ] && return 0
[ [ -d " ${ initdir } / ${ _target %/* } " ] ] || inst_dir " ${ _target %/* } "
2009-09-27 08:33:41 +04:00
fi
2012-06-29 14:07:44 +04:00
if [ [ $DRACUT_FIPS_MODE ] ] ; then
# install checksum files also
if [ [ -e " ${ _src %/* } /. ${ _src ##*/ } .hmac " ] ] ; then
inst " ${ _src %/* } /. ${ _src ##*/ } .hmac " " ${ _target %/* } /. ${ _target ##*/ } .hmac "
fi
2012-08-24 15:31:57 +04:00
if [ [ -e " /lib/fipscheck/ ${ _src ##*/ } .hmac " ] ] ; then
inst " /lib/fipscheck/ ${ _src ##*/ } .hmac " " /lib/fipscheck/ ${ _target ##*/ } .hmac "
fi
if [ [ -e " /lib64/fipscheck/ ${ _src ##*/ } .hmac " ] ] ; then
inst " /lib64/fipscheck/ ${ _src ##*/ } .hmac " " /lib64/fipscheck/ ${ _target ##*/ } .hmac "
fi
2012-06-29 14:07:44 +04:00
fi
ddebug " Installing $_src "
cp --reflink= auto --sparse= auto -pfL " $_src " " ${ initdir } / $_target "
}
2009-09-27 08:33:41 +04:00
2012-06-29 14:07:44 +04:00
# same as above, but specialized for symlinks
inst_symlink( ) {
local _src = $1 _target = ${ 2 :- $1 } _realsrc
2013-07-04 14:29:59 +04:00
[ [ " $1 " = = */* ] ] || return 1
2012-06-29 14:07:44 +04:00
[ [ -L $1 ] ] || return 1
[ [ -L $initdir /$_target ] ] && return 0
_realsrc = $( readlink -f " $_src " )
if ! [ [ -e $initdir /$_realsrc ] ] ; then
if [ [ -d $_realsrc ] ] ; then
inst_dir " $_realsrc "
else
inst " $_realsrc "
fi
fi
[ [ ! -e $initdir /${ _target %/* } ] ] && inst_dir " ${ _target %/* } "
2011-08-27 00:01:33 +04:00
2012-06-29 14:07:44 +04:00
ln_r " ${ _realsrc } " " ${ _target } "
}
2012-06-22 17:09:07 +04:00
2012-06-29 14:07:44 +04:00
# Same as above, but specialized to handle dynamic libraries.
# It handles making symlinks according to how the original library
# is referenced.
inst_library( ) {
local _src = " $1 " _dest = ${ 2 :- $1 } _lib _reallib _symlink
2013-07-04 14:29:59 +04:00
[ [ " $1 " = = */* ] ] || return 1
2012-06-29 14:07:44 +04:00
[ [ -e $initdir /$_dest ] ] && return 0
if [ [ -L $_src ] ] ; then
if [ [ $DRACUT_FIPS_MODE ] ] ; then
# install checksum files also
if [ [ -e " ${ _src %/* } /. ${ _src ##*/ } .hmac " ] ] ; then
inst " ${ _src %/* } /. ${ _src ##*/ } .hmac " " ${ _dest %/* } /. ${ _dest ##*/ } .hmac "
fi
2012-08-24 15:31:57 +04:00
if [ [ -e " /lib/fipscheck/ ${ _src ##*/ } .hmac " ] ] ; then
inst " /lib/fipscheck/ ${ _src ##*/ } .hmac " " /lib/fipscheck/ ${ _dest ##*/ } .hmac "
fi
if [ [ -e " /lib64/fipscheck/ ${ _src ##*/ } .hmac " ] ] ; then
inst " /lib64/fipscheck/ ${ _src ##*/ } .hmac " " /lib64/fipscheck/ ${ _dest ##*/ } .hmac "
fi
2012-06-29 14:07:44 +04:00
fi
_reallib = $( readlink -f " $_src " )
inst_simple " $_reallib " " $_reallib "
inst_dir " ${ _dest %/* } "
ln_r " ${ _reallib } " " ${ _dest } "
else
inst_simple " $_src " " $_dest "
fi
2012-06-22 17:09:07 +04:00
2012-06-29 14:07:44 +04:00
# Create additional symlinks. See rev_symlinks description.
for _symlink in $( rev_lib_symlinks $_src ) $( rev_lib_symlinks $_reallib ) ; do
[ [ ! -e $initdir /$_symlink ] ] && {
ddebug " Creating extra symlink: $_symlink "
inst_symlink $_symlink
}
done
}
# Same as above, but specialized to install binary executables.
# Install binary executable, and all shared library dependencies, if any.
inst_binary( ) {
local _bin _target
_bin = $( find_binary " $1 " ) || return 1
_target = ${ 2 :- $_bin }
[ [ -e $initdir /$_target ] ] && return 0
local _file _line
local _so_regex = '([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
# I love bash!
LC_ALL = C ldd " $_bin " 2>/dev/null | while read _line; do
[ [ $_line = 'not a dynamic executable' ] ] && break
if [ [ $_line = ~ $_so_regex ] ] ; then
_file = ${ BASH_REMATCH [1] }
[ [ -e ${ initdir } /$_file ] ] && continue
inst_library " $_file "
continue
fi
2013-07-04 14:29:59 +04:00
if [ [ $_line = = *not\ found* ] ] ; then
2012-06-29 14:07:44 +04:00
dfatal " Missing a shared library required by $_bin . "
dfatal " Run \"ldd $_bin \" to find out what it is. "
dfatal " $_line "
dfatal "dracut cannot create an initrd."
exit 1
fi
done
inst_simple " $_bin " " $_target "
}
# same as above, except for shell scripts.
# If your shell script does not start with shebang, it is not a shell script.
inst_script( ) {
local _bin
_bin = $( find_binary " $1 " ) || return 1
shift
local _line _shebang_regex
read -r -n 80 _line <" $_bin "
# If debug is set, clean unprintable chars to prevent messing up the term
[ [ $debug ] ] && _line = $( echo -n " $_line " | tr -c -d '[:print:][:space:]' )
_shebang_regex = '(#! *)(/[^ ]+).*'
[ [ $_line = ~ $_shebang_regex ] ] || return 1
inst " ${ BASH_REMATCH [2] } " && inst_simple " $_bin " " $@ "
}
# general purpose installation function
# Same args as above.
inst( ) {
local _x
case $# in
1) ; ;
2) [ [ ! $initdir && -d $2 ] ] && export initdir = $2
[ [ $initdir = $2 ] ] && set $1 ; ;
3) [ [ -z $initdir ] ] && export initdir = $2
set $1 $3 ; ;
*) dfatal "inst only takes 1 or 2 or 3 arguments"
exit 1; ;
esac
for _x in inst_symlink inst_script inst_binary inst_simple; do
$_x " $@ " && return 0
done
return 1
}
# dracut_install [-o ] <file> [<file> ... ]
# Install <file> to the initramfs image
# -o optionally install the <file> and don't fail, if it is not there
dracut_install( ) {
local _optional = no
if [ [ $1 = '-o' ] ] ; then
_optional = yes
shift
fi
while ( ( $# > 0) ) ; do
if ! inst " $1 " ; then
if [ [ $_optional = yes ] ] ; then
dinfo " Skipping program $1 as it cannot be found and is " \
"flagged to be optional"
else
dfatal " Failed to install $1 "
exit 1
fi
fi
shift
done
}
fi
2009-02-13 15:42:28 +03:00
2010-07-07 18:39:09 +04:00
# find symlinks linked to given library file
# $1 = library file
# Function searches for symlinks by stripping version numbers appended to
# library filename, checks if it points to the same target and finally
# prints the list of symlinks to stdout.
#
# Example:
# rev_lib_symlinks libfoo.so.8.1
# output: libfoo.so.8 libfoo.so
# (Only if libfoo.so.8 and libfoo.so exists on host system.)
rev_lib_symlinks( ) {
[ [ ! $1 ] ] && return 0
local fn = " $1 " orig = " $( readlink -f " $1 " ) " links = ''
2013-07-04 14:29:59 +04:00
[ [ ${ fn } = = *.so.* ] ] || return 1
2010-07-07 18:39:09 +04:00
until [ [ ${ fn ##*. } = = so ] ] ; do
fn = " ${ fn %.* } "
[ [ -L ${ fn } && $( readlink -f " ${ fn } " ) = = ${ orig } ] ] && links += " ${ fn } "
done
2011-03-25 17:56:46 +03:00
echo " ${ links } "
2010-07-07 18:39:09 +04:00
}
2011-12-17 04:35:08 +04:00
# attempt to install any programs specified in a udev rule
inst_rule_programs( ) {
local _prog _bin
if grep -qE 'PROGRAM==?"[^ "]+' " $1 " ; then
for _prog in $( grep -E 'PROGRAM==?"[^ "]+' " $1 " | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/' ) ; do
2012-10-08 17:39:23 +04:00
_bin = ""
2012-06-04 14:58:42 +04:00
if [ -x ${ udevdir } /$_prog ] ; then
_bin = ${ udevdir } /$_prog
2013-03-07 17:27:49 +04:00
elif [ [ " ${ _prog / \$ env \{ / } " = = " $_prog " ] ] ; then
2012-06-04 14:58:42 +04:00
_bin = $( find_binary " $_prog " ) || {
2012-07-26 21:35:12 +04:00
dinfo " Skipping program $_prog using in udev rule ${ 1 ##*/ } as it cannot be found "
2012-06-04 14:58:42 +04:00
continue ;
}
fi
2012-10-08 17:39:23 +04:00
[ [ $_bin ] ] && dracut_install " $_bin "
2012-06-04 14:58:42 +04:00
done
fi
2012-10-04 20:15:36 +04:00
if grep -qE 'RUN[+=]=?"[^ "]+' " $1 " ; then
for _prog in $( grep -E 'RUN[+=]=?"[^ "]+' " $1 " | sed -r 's/.*RUN[+=]=?"([^ "]+).*/\1/' ) ; do
2012-10-08 17:39:23 +04:00
_bin = ""
2012-06-04 14:58:42 +04:00
if [ -x ${ udevdir } /$_prog ] ; then
_bin = ${ udevdir } /$_prog
2013-03-07 17:27:49 +04:00
elif [ [ " ${ _prog / \$ env \{ / } " = = " $_prog " ] ] && [ [ " ${ _prog } " != "/sbin/initqueue" ] ] ; then
2012-06-04 14:58:42 +04:00
_bin = $( find_binary " $_prog " ) || {
2012-07-26 21:35:12 +04:00
dinfo " Skipping program $_prog using in udev rule ${ 1 ##*/ } as it cannot be found "
2012-06-04 14:58:42 +04:00
continue ;
}
fi
2012-10-08 17:39:23 +04:00
[ [ $_bin ] ] && dracut_install " $_bin "
2012-06-04 14:58:42 +04:00
done
fi
2012-07-26 21:12:40 +04:00
if grep -qE 'IMPORT\{program\}==?"[^ "]+' " $1 " ; then
for _prog in $( grep -E 'IMPORT\{program\}==?"[^ "]+' " $1 " | sed -r 's/.*IMPORT\{program\}==?"([^ "]+).*/\1/' ) ; do
2012-10-08 17:39:23 +04:00
_bin = ""
2012-06-04 14:58:42 +04:00
if [ -x ${ udevdir } /$_prog ] ; then
_bin = ${ udevdir } /$_prog
2013-03-07 17:27:49 +04:00
elif [ [ " ${ _prog / \$ env \{ / } " = = " $_prog " ] ] ; then
2011-12-17 04:35:08 +04:00
_bin = $( find_binary " $_prog " ) || {
2012-07-26 21:35:12 +04:00
dinfo " Skipping program $_prog using in udev rule ${ 1 ##*/ } as it cannot be found "
2011-12-17 04:35:08 +04:00
continue ;
}
fi
2012-10-08 17:39:23 +04:00
[ [ $_bin ] ] && dracut_install " $_bin "
2011-12-17 04:35:08 +04:00
done
fi
}
2012-10-04 21:04:36 +04:00
# attempt to install any programs specified in a udev rule
inst_rule_group_owner( ) {
local i
if grep -qE 'OWNER=?"[^ "]+' " $1 " ; then
for i in $( grep -E 'OWNER=?"[^ "]+' " $1 " | sed -r 's/.*OWNER=?"([^ "]+).*/\1/' ) ; do
if ! egrep -q " ^ $i : " " $initdir /etc/passwd " 2>/dev/null; then
egrep " ^ $i : " /etc/passwd 2>/dev/null >> " $initdir /etc/passwd "
fi
done
fi
if grep -qE 'GROUP=?"[^ "]+' " $1 " ; then
for i in $( grep -E 'GROUP=?"[^ "]+' " $1 " | sed -r 's/.*GROUP=?"([^ "]+).*/\1/' ) ; do
if ! egrep -q " ^ $i : " " $initdir /etc/group " 2>/dev/null; then
egrep " ^ $i : " /etc/group 2>/dev/null >> " $initdir /etc/group "
fi
done
fi
}
2013-03-06 19:00:11 +04:00
inst_rule_initqueue( ) {
if grep -q -F initqueue " $1 " ; then
dracut_need_initqueue
fi
}
2009-02-13 15:43:26 +03:00
# udev rules always get installed in the same place, so
# create a function to install them to make life simpler.
2011-03-25 17:56:46 +03:00
inst_rules( ) {
2011-05-12 13:03:30 +04:00
local _target = /etc/udev/rules.d _rule _found
2010-07-05 13:25:21 +04:00
2012-06-04 14:58:42 +04:00
inst_dir " ${ udevdir } /rules.d "
2011-05-12 13:03:30 +04:00
inst_dir " $_target "
for _rule in " $@ " ; do
2013-01-03 12:29:05 +04:00
if [ " ${ _rule #/ } " = " $_rule " ] ; then
2012-06-04 14:58:42 +04:00
for r in ${ udevdir } /rules.d /etc/udev/rules.d; do
2011-09-22 17:43:34 +04:00
if [ [ -f $r /$_rule ] ] ; then
_found = " $r / $_rule "
2011-12-17 04:35:08 +04:00
inst_rule_programs " $_found "
2012-10-04 21:04:36 +04:00
inst_rule_group_owner " $_found "
2013-03-06 19:00:11 +04:00
inst_rule_initqueue " $_found "
2012-06-04 14:58:42 +04:00
inst_simple " $_found "
2011-09-22 17:43:34 +04:00
fi
done
fi
2011-03-25 15:05:05 +03:00
for r in '' ./ $dracutbasedir /rules.d/; do
2011-05-12 13:03:30 +04:00
if [ [ -f ${ r } $_rule ] ] ; then
_found = " ${ r } $_rule "
2011-12-17 04:35:08 +04:00
inst_rule_programs " $_found "
2012-10-04 21:04:36 +04:00
inst_rule_group_owner " $_found "
2013-03-06 19:00:11 +04:00
inst_rule_initqueue " $_found "
2012-06-04 14:58:42 +04:00
inst_simple " $_found " " $_target / ${ _found ##*/ } "
2011-03-25 15:05:05 +03:00
fi
done
2011-05-12 13:03:30 +04:00
[ [ $_found ] ] || dinfo " Skipping udev rule: $_rule "
2009-02-13 15:43:26 +03:00
done
}
2013-03-07 17:49:21 +04:00
prepare_udev_rules( ) {
[ -z " $UDEVVERSION " ] && export UDEVVERSION = $( udevadm --version)
for f in " $@ " ; do
f = " ${ initdir } /etc/udev/rules.d/ $f "
[ -e " $f " ] || continue
while read line; do
if [ " ${ line %%IMPORT PATH_ID } " != " $line " ] ; then
if [ $UDEVVERSION -ge 174 ] ; then
printf '%sIMPORT{builtin}="path_id"\n' " ${ line %%IMPORT PATH_ID } "
else
printf '%sIMPORT{program}="path_id %%p"\n' " ${ line %%IMPORT PATH_ID } "
fi
elif [ " ${ line %%IMPORT BLKID } " != " $line " ] ; then
if [ $UDEVVERSION -ge 176 ] ; then
printf '%sIMPORT{builtin}="blkid"\n' " ${ line %%IMPORT BLKID } "
else
printf '%sIMPORT{program}="/sbin/blkid -o udev -p $tempnode"\n' " ${ line %%IMPORT BLKID } "
fi
else
echo " $line "
fi
done < " ${ f } " > " ${ f } .new "
mv " ${ f } .new " " $f "
done
}
2009-02-13 15:43:29 +03:00
# install function specialized for hooks
# $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook
# All hooks should be POSIX/SuS compliant, they will be sourced by init.
inst_hook( ) {
2009-05-23 06:24:31 +04:00
if ! [ [ -f $3 ] ] ; then
2011-03-25 17:56:47 +03:00
dfatal " Cannot install a hook ( $3 ) that does not exist. "
dfatal "Aborting initrd creation."
2010-09-10 17:23:06 +04:00
exit 1
2013-07-04 14:29:59 +04:00
elif ! [ [ " $hookdirs " = = *$1 * ] ] ; then
2011-05-10 13:39:10 +04:00
dfatal " No such hook type $1 . Aborting initrd creation. "
2010-09-10 17:23:06 +04:00
exit 1
2009-05-23 06:24:31 +04:00
fi
2012-07-30 19:00:27 +04:00
inst_simple " $3 " " /lib/dracut/hooks/ ${ 1 } / ${ 2 } - ${ 3 ##*/ } "
2009-02-13 15:43:29 +03:00
}
2011-08-21 14:47:13 +04:00
# install any of listed files
#
# If first argument is '-d' and second some destination path, first accessible
# source is installed into this path, otherwise it will installed in the same
# path as source. If none of listed files was installed, function return 1.
# On first successful installation it returns with 0 status.
#
# Example:
#
# inst_any -d /bin/foo /bin/bar /bin/baz
#
# Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
# initramfs.
inst_any( ) {
local to f
[ [ $1 = '-d' ] ] && to = " $2 " && shift 2
for f in " $@ " ; do
if [ [ -e $f ] ] ; then
[ [ $to ] ] && inst " $f " " $to " && return 0
inst " $f " && return 0
fi
done
return 1
}
2012-04-10 17:14:38 +04:00
# inst_libdir_file [-n <pattern>] <file> [<file>...]
# Install a <file> located on a lib directory to the initramfs image
2012-06-14 19:42:34 +04:00
# -n <pattern> install matching files
2012-04-10 17:14:38 +04:00
inst_libdir_file( ) {
2012-06-27 11:38:26 +04:00
local _files
2012-04-10 17:14:38 +04:00
if [ [ " $1 " = = "-n" ] ] ; then
2012-06-14 19:42:34 +04:00
local _pattern = $2
2012-04-10 17:14:38 +04:00
shift 2
for _dir in $libdirs ; do
2012-06-15 11:34:00 +04:00
for _i in " $@ " ; do
2012-04-10 17:14:38 +04:00
for _f in " $_dir " /$_i ; do
2012-06-15 11:34:00 +04:00
[ [ " $_f " = ~ $_pattern ] ] || continue
2012-06-27 11:38:26 +04:00
[ [ -e " $_f " ] ] && _files += " $_f "
2012-04-10 17:14:38 +04:00
done
done
done
else
for _dir in $libdirs ; do
2012-06-15 11:34:00 +04:00
for _i in " $@ " ; do
2012-04-10 17:14:38 +04:00
for _f in " $_dir " /$_i ; do
2012-06-27 11:38:26 +04:00
[ [ -e " $_f " ] ] && _files += " $_f "
2012-04-10 17:14:38 +04:00
done
done
done
fi
2012-06-27 11:38:26 +04:00
[ [ $_files ] ] && dracut_install $_files
2012-04-10 17:14:38 +04:00
}
2010-07-01 23:17:37 +04:00
# install function decompressing the target and handling symlinks
# $@ = list of compressed (gz or bz2) files or symlinks pointing to such files
#
# Function install targets in the same paths inside overlay but decompressed
# and without extensions (.gz, .bz2).
inst_decompress( ) {
2012-06-22 17:09:45 +04:00
local _src _cmd
2010-07-01 23:17:37 +04:00
2011-05-12 13:03:30 +04:00
for _src in $@
2010-07-01 23:17:37 +04:00
do
2011-05-12 13:03:30 +04:00
case ${ _src } in
2012-10-16 11:36:28 +04:00
*.gz) _cmd = 'gzip -f -d' ; ;
2011-05-12 13:03:30 +04:00
*.bz2) _cmd = 'bzip2 -d' ; ;
2010-07-01 23:17:37 +04:00
*) return 1 ; ;
esac
2012-06-22 17:09:45 +04:00
inst_simple ${ _src }
2010-07-01 23:17:37 +04:00
# Decompress with chosen tool. We assume that tool changes name e.g.
# from 'name.gz' to 'name'.
2011-05-12 13:03:30 +04:00
${ _cmd } " ${ initdir } ${ _src } "
2010-07-01 23:17:37 +04:00
done
}
# It's similar to above, but if file is not compressed, performs standard
# install.
# $@ = list of files
inst_opt_decompress( ) {
2011-05-12 13:03:30 +04:00
local _src
2010-07-01 23:17:37 +04:00
2011-05-12 13:03:30 +04:00
for _src in $@
2010-07-01 23:17:37 +04:00
do
2011-05-12 13:03:30 +04:00
inst_decompress " ${ _src } " || inst " ${ _src } "
2010-07-01 23:17:37 +04:00
done
}
2012-02-16 14:49:19 +04:00
# module_check <dracut module>
# execute the check() function of module-setup.sh of <dracut module>
# or the "check" script, if module-setup.sh is not found
# "check $hostonly" is called
2011-02-02 15:34:58 +03:00
module_check( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
2011-08-01 06:01:23 +04:00
local _forced = 0
local _hostonly = $hostonly
[ $# -eq 2 ] && _forced = $2
2011-05-12 13:03:30 +04:00
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
2011-02-02 15:34:58 +03:00
# if we do not have a check script, we are unconditionally included
2011-05-12 13:03:30 +04:00
[ [ -x $_moddir /check ] ] || return 0
2011-08-01 06:01:23 +04:00
[ $_forced -ne 0 ] && unset hostonly
2011-05-12 13:03:30 +04:00
$_moddir /check $hostonly
2011-08-01 06:01:23 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
else
unset check depends install installkernel
2013-07-04 14:29:59 +04:00
check( ) { true; }
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
is_func check || return 0
2011-08-01 06:01:23 +04:00
[ $_forced -ne 0 ] && unset hostonly
check $hostonly
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2009-05-24 09:29:44 +04:00
fi
2011-08-01 06:01:23 +04:00
hostonly = $_hostonly
return $_ret
2009-05-24 09:29:44 +04:00
}
2012-02-16 14:49:19 +04:00
# module_check_mount <dracut module>
# execute the check() function of module-setup.sh of <dracut module>
# or the "check" script, if module-setup.sh is not found
# "mount_needs=1 check 0" is called
module_check_mount( ) {
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
mount_needs = 1
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
# if we do not have a check script, we are unconditionally included
[ [ -x $_moddir /check ] ] || return 0
mount_needs = 1 $_moddir /check 0
_ret = $?
else
unset check depends install installkernel
2013-07-04 14:29:59 +04:00
check( ) { false; }
2012-02-16 14:49:19 +04:00
. $_moddir /module-setup.sh
check 0
_ret = $?
unset check depends install installkernel
fi
unset mount_needs
return $_ret
}
# module_depends <dracut module>
# execute the depends() function of module-setup.sh of <dracut module>
# or the "depends" script, if module-setup.sh is not found
2011-02-02 15:34:58 +03:00
module_depends( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
2011-02-02 15:34:58 +03:00
# if we do not have a check script, we have no deps
2011-05-12 13:03:30 +04:00
[ [ -x $_moddir /check ] ] || return 0
$_moddir /check -d
2011-02-02 15:34:58 +03:00
return $?
else
unset check depends install installkernel
2013-07-04 14:29:59 +04:00
depends( ) { true; }
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
depends
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
return $_ret
2009-07-22 14:43:26 +04:00
fi
2009-05-24 09:29:44 +04:00
}
2012-02-16 14:49:19 +04:00
# module_install <dracut module>
# execute the install() function of module-setup.sh of <dracut module>
# or the "install" script, if module-setup.sh is not found
2011-02-02 15:34:58 +03:00
module_install( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
[ [ -x $_moddir /install ] ] && . " $_moddir /install "
2011-02-02 15:34:58 +03:00
return $?
else
unset check depends install installkernel
2013-07-04 14:29:59 +04:00
install( ) { true; }
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
install
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
return $_ret
2011-02-02 15:34:58 +03:00
fi
}
2012-02-16 14:49:19 +04:00
# module_installkernel <dracut module>
# execute the installkernel() function of module-setup.sh of <dracut module>
# or the "installkernel" script, if module-setup.sh is not found
2011-02-02 15:34:58 +03:00
module_installkernel( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
[ [ -x $_moddir /installkernel ] ] && . " $_moddir /installkernel "
2011-02-02 15:34:58 +03:00
return $?
else
unset check depends install installkernel
2013-07-04 14:29:59 +04:00
installkernel( ) { true; }
2013-07-31 13:00:29 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
installkernel
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
return $_ret
2011-02-02 15:34:58 +03:00
fi
}
2012-02-16 14:49:19 +04:00
# check_mount <dracut module>
# check_mount checks, if a dracut module is needed for the given
# device and filesystem types in "${host_fs_types[@]}"
2011-12-20 10:09:57 +04:00
check_mount( ) {
local _mod = $1
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
local _moddep
2012-10-04 00:33:50 +04:00
[ " ${# host_fs_types [*] } " -le 0 ] && return 1
2011-12-20 10:09:57 +04:00
# If we are already scheduled to be loaded, no need to check again.
2013-07-04 14:29:59 +04:00
[ [ " $mods_to_load " = = *\ $_mod \ * ] ] && return 0
[ [ " $mods_checked_as_dep " = = *\ $_mod \ * ] ] && return 1
2011-12-20 10:09:57 +04:00
# This should never happen, but...
[ [ -d $_moddir ] ] || return 1
[ [ $2 ] ] || mods_checked_as_dep += " $_mod "
2013-07-04 14:29:59 +04:00
if [ [ " $omit_dracutmodules " = = *\ $_mod \ * ] ] ; then
2012-07-16 14:21:56 +04:00
return 1
fi
2011-12-20 10:09:57 +04:00
2013-07-04 14:29:59 +04:00
if [ [ " $dracutmodules $add_dracutmodules $force_add_dracutmodules " = = *\ $_mod \ * ] ] ; then
2012-10-04 00:33:50 +04:00
module_check_mount $_mod ; ret = $?
# explicit module, so also accept ret=255
[ [ $ret = 0 || $ret = 255 ] ] || return 1
2011-12-20 10:09:57 +04:00
else
2012-10-04 00:33:50 +04:00
# module not in our list
if [ [ $dracutmodules = all ] ] ; then
# check, if we can and should install this module
module_check_mount $_mod || return 1
else
# skip this module
return 1
fi
2011-12-20 10:09:57 +04:00
fi
2012-10-04 00:33:50 +04:00
2011-12-20 10:09:57 +04:00
for _moddep in $( module_depends $_mod ) ; do
# handle deps as if they were manually added
2013-07-04 14:29:59 +04:00
[ [ " $add_dracutmodules " = = *\ $_moddep \ * ] ] || \
2011-12-20 10:09:57 +04:00
add_dracutmodules += " $_moddep "
2013-07-04 14:29:59 +04:00
[ [ " $force_add_dracutmodules " = = *\ $_moddep \ * ] ] || \
2011-12-20 10:09:57 +04:00
force_add_dracutmodules += " $_moddep "
# if a module we depend on fail, fail also
2012-07-16 14:21:56 +04:00
if ! check_module $_moddep ; then
2012-10-10 16:15:11 +04:00
derror " dracut module ' $_mod ' depends on ' $_moddep ', which can't be installed "
2012-07-16 14:21:56 +04:00
return 1
fi
2011-12-20 10:09:57 +04:00
done
2013-07-04 14:29:59 +04:00
[ [ " $mods_to_load " = = *\ $_mod \ * ] ] || \
2011-12-20 10:09:57 +04:00
mods_to_load += " $_mod "
return 0
}
2012-02-16 14:49:19 +04:00
# check_module <dracut module> [<use_as_dep>]
# check if a dracut module is to be used in the initramfs process
# if <use_as_dep> is set, then the process also keeps track
# that the modules were checked for the dependency tracking process
2011-02-02 15:34:58 +03:00
check_module( ) {
2011-05-12 13:03:30 +04:00
local _mod = $1
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
local _moddep
2011-02-02 15:34:58 +03:00
# If we are already scheduled to be loaded, no need to check again.
2013-07-04 14:29:59 +04:00
[ [ " $mods_to_load " = = *\ $_mod \ * ] ] && return 0
[ [ " $mods_checked_as_dep " = = *\ $_mod \ * ] ] && return 1
2011-02-02 15:34:58 +03:00
# This should never happen, but...
2011-05-12 13:03:30 +04:00
[ [ -d $_moddir ] ] || return 1
2011-02-02 15:34:58 +03:00
2011-05-12 13:03:30 +04:00
[ [ $2 ] ] || mods_checked_as_dep += " $_mod "
2011-02-02 15:34:58 +03:00
2013-07-04 14:29:59 +04:00
if [ [ " $omit_dracutmodules " = = *\ $_mod \ * ] ] ; then
2012-10-10 16:15:11 +04:00
dinfo " dracut module ' $_mod ' will not be installed, because it's in the list to be omitted! "
2012-07-16 14:21:56 +04:00
return 1
fi
2011-02-02 15:34:58 +03:00
2013-07-04 14:29:59 +04:00
if [ [ " $dracutmodules $add_dracutmodules $force_add_dracutmodules " = = *\ $_mod \ * ] ] ; then
if [ [ " $force_add_dracutmodules " = = *\ $_mod \ * ] ] ; then
2011-08-01 06:01:23 +04:00
module_check $_mod 1; ret = $?
else
module_check $_mod 0; ret = $?
fi
2011-02-02 15:34:58 +03:00
# explicit module, so also accept ret=255
[ [ $ret = 0 || $ret = 255 ] ] || return 1
else
# module not in our list
if [ [ $dracutmodules = all ] ] ; then
# check, if we can and should install this module
2011-05-12 13:03:30 +04:00
module_check $_mod || return 1
2010-09-10 17:23:06 +04:00
else
2011-02-02 15:34:58 +03:00
# skip this module
return 1
2009-07-02 13:57:23 +04:00
fi
2011-02-02 15:34:58 +03:00
fi
2010-07-27 13:51:27 +04:00
2011-05-12 13:03:30 +04:00
for _moddep in $( module_depends $_mod ) ; do
2011-02-02 15:34:58 +03:00
# handle deps as if they were manually added
2013-07-04 14:29:59 +04:00
[ [ " $add_dracutmodules " = = *\ $_moddep \ * ] ] || \
2011-05-12 13:03:30 +04:00
add_dracutmodules += " $_moddep "
2013-07-04 14:29:59 +04:00
[ [ " $force_add_dracutmodules " = = *\ $_moddep \ * ] ] || \
2011-08-01 06:01:23 +04:00
force_add_dracutmodules += " $_moddep "
2011-02-02 15:34:58 +03:00
# if a module we depend on fail, fail also
2012-07-16 14:21:56 +04:00
if ! check_module $_moddep ; then
2012-10-10 16:15:11 +04:00
derror " dracut module ' $_mod ' depends on ' $_moddep ', which can't be installed "
2012-07-16 14:21:56 +04:00
return 1
fi
2009-05-24 09:29:44 +04:00
done
2010-05-26 19:42:57 +04:00
2013-07-04 14:29:59 +04:00
[ [ " $mods_to_load " = = *\ $_mod \ * ] ] || \
2011-05-12 13:03:30 +04:00
mods_to_load += " $_mod "
2011-02-02 15:34:58 +03:00
return 0
}
2012-02-16 14:49:19 +04:00
# for_each_module_dir <func>
# execute "<func> <dracut module> 1"
2011-12-20 10:09:57 +04:00
for_each_module_dir( ) {
2011-05-12 13:03:30 +04:00
local _modcheck
local _mod
local _moddir
2011-12-20 10:09:57 +04:00
local _func
_func = $1
2011-05-12 13:03:30 +04:00
for _moddir in " $dracutbasedir /modules.d " /[ 0-9] [ 0-9] *; do
_mod = ${ _moddir ##*/ } ; _mod = ${ _mod #[0-9][0-9] }
2011-12-20 10:09:57 +04:00
$_func $_mod 1
2010-05-26 19:42:57 +04:00
done
2011-03-07 15:08:13 +03:00
# Report any missing dracut modules, the user has specified
2011-08-01 06:01:23 +04:00
_modcheck = " $add_dracutmodules $force_add_dracutmodules "
2011-05-12 13:03:30 +04:00
[ [ $dracutmodules != all ] ] && _modcheck = " $m $dracutmodules "
for _mod in $_modcheck ; do
2013-07-04 14:29:59 +04:00
[ [ " $mods_to_load " = = *\ $_mod \ * ] ] && continue
[ [ " $omit_dracutmodules " = = *\ $_mod \ * ] ] && continue
2012-10-10 16:15:11 +04:00
derror " dracut module ' $_mod ' cannot be found or installed. "
2011-03-07 15:08:13 +03:00
done
2009-05-24 09:29:44 +04:00
}
2009-08-15 23:17:19 +04:00
# Install a single kernel module along with any firmware it may require.
# $1 = full path to kernel module to install
install_kmod_with_fw( ) {
2011-03-07 15:09:25 +03:00
# no need to go further if the module is already installed
2012-02-25 19:11:36 +04:00
2011-03-25 17:56:46 +03:00
[ [ -e " ${ initdir } /lib/modules/ $kernel / ${ 1 ##*/lib/modules/ $kernel / } " ] ] \
&& return 0
2012-02-15 17:53:18 +04:00
2012-06-30 11:12:35 +04:00
if [ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] && [ [ -e " $DRACUT_KERNEL_LAZY_HASHDIR / ${ 1 ##*/ } " ] ] ; then
read ret < " $DRACUT_KERNEL_LAZY_HASHDIR / ${ 1 ##*/ } "
2012-06-27 11:35:39 +04:00
return $ret
fi
2012-02-25 19:11:36 +04:00
2012-02-15 17:53:18 +04:00
if [ [ $omit_drivers ] ] ; then
local _kmod = ${ 1 ##*/ }
_kmod = ${ _kmod %.ko }
_kmod = ${ _kmod /-/_ }
2012-02-22 19:12:10 +04:00
if [ [ " $_kmod " = ~ $omit_drivers ] ] ; then
dinfo " Omitting driver $_kmod "
2012-06-18 14:51:21 +04:00
return 0
2012-02-22 19:12:10 +04:00
fi
if [ [ " ${ 1 ##*/lib/modules/ $kernel / } " = ~ $omit_drivers ] ] ; then
2012-02-15 17:53:18 +04:00
dinfo " Omitting driver $_kmod "
2012-06-18 14:51:21 +04:00
return 0
2012-02-15 17:53:18 +04:00
fi
fi
2013-07-31 15:49:52 +04:00
if [ [ $silent_omit_drivers ] ] ; then
local _kmod = ${ 1 ##*/ }
_kmod = ${ _kmod %.ko }
_kmod = ${ _kmod /-/_ }
[ [ " $_kmod " = ~ $silent_omit_drivers ] ] && return 0
[ [ " ${ 1 ##*/lib/modules/ $kernel / } " = ~ $silent_omit_drivers ] ] && return 0
fi
2012-06-27 11:35:39 +04:00
inst_simple " $1 " " /lib/modules/ $kernel / ${ 1 ##*/lib/modules/ $kernel / } "
ret = $?
2012-06-30 11:12:35 +04:00
[ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] && \
[ [ -d " $DRACUT_KERNEL_LAZY_HASHDIR " ] ] && \
echo $ret > " $DRACUT_KERNEL_LAZY_HASHDIR / ${ 1 ##*/ } "
2012-06-27 11:35:39 +04:00
( ( $ret != 0) ) && return $ret
2011-08-29 00:24:58 +04:00
local _modname = ${ 1 ##*/ } _fwdir _found _fw
_modname = ${ _modname %.ko* }
2011-05-12 13:03:30 +04:00
for _fw in $( modinfo -k $kernel -F firmware $1 2>/dev/null) ; do
_found = ''
for _fwdir in $fw_dir ; do
if [ [ -d $_fwdir && -f $_fwdir /$_fw ] ] ; then
inst_simple " $_fwdir / $_fw " " /lib/firmware/ $_fw "
_found = yes
2010-09-10 17:23:06 +04:00
fi
done
2011-05-12 13:03:30 +04:00
if [ [ $_found != yes ] ] ; then
2012-06-06 20:20:35 +04:00
if ! [ [ -d $( echo /sys/module/${ _modname //-/_ } | { read a b; echo $a ; } ) ] ] ; then
2011-05-12 13:03:30 +04:00
dinfo " Possible missing firmware \" ${ _fw } \" for kernel module " \
" \" ${ _modname } .ko\" "
2011-05-10 13:18:58 +04:00
else
2011-05-12 13:03:30 +04:00
dwarn " Possible missing firmware \" ${ _fw } \" for kernel module " \
" \" ${ _modname } .ko\" "
2011-05-10 13:18:58 +04:00
fi
2010-09-10 17:23:06 +04:00
fi
2009-08-15 23:17:19 +04:00
done
2011-03-07 15:09:25 +03:00
return 0
2009-08-15 23:17:19 +04:00
}
# Do something with all the dependencies of a kernel module.
# Note that kernel modules depend on themselves using the technique we use
2011-03-25 17:56:46 +03:00
# $1 = function to call for each dependency we find
# It will be passed the full path to the found kernel module
2009-08-15 23:17:19 +04:00
# $2 = module to get dependencies for
# rest of args = arguments to modprobe
2011-10-11 01:58:04 +04:00
# _fderr specifies FD passed from surrounding scope
2009-08-15 23:17:19 +04:00
for_each_kmod_dep( ) {
2012-06-18 14:51:21 +04:00
local _func = $1 _kmod = $2 _cmd _modpath _options
2009-08-15 23:17:19 +04:00
shift 2
2011-10-11 01:58:04 +04:00
modprobe " $@ " --ignore-install --show-depends $_kmod 2>& ${ _fderr } | (
2011-05-12 13:03:30 +04:00
while read _cmd _modpath _options; do
[ [ $_cmd = insmod ] ] || continue
$_func ${ _modpath } || exit $?
2011-03-25 17:56:46 +03:00
done
)
2009-08-15 23:17:19 +04:00
}
2012-06-27 19:02:49 +04:00
dracut_kernel_post( ) {
2012-06-27 11:35:39 +04:00
local _moddirname = ${ srcmods %%/lib/modules/* }
2013-07-19 11:34:04 +04:00
local _pid
2012-06-27 11:35:39 +04:00
2012-06-30 11:12:35 +04:00
if [ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] && [ [ -f " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist " ] ] ; then
2012-07-03 00:14:49 +04:00
xargs -r modprobe -a ${ _moddirname +-d ${ _moddirname } / } \
--ignore-install --show-depends --set-version $kernel \
2012-06-30 11:12:35 +04:00
< " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist " 2>/dev/null \
2012-06-29 14:07:44 +04:00
| sort -u \
| while read _cmd _modpath _options; do
[ [ $_cmd = insmod ] ] || continue
echo " $_modpath "
2012-06-30 11:12:35 +04:00
done > " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist.dep "
2012-06-27 11:35:39 +04:00
2012-06-29 14:07:44 +04:00
(
2012-06-30 13:34:13 +04:00
if [ [ $DRACUT_INSTALL ] ] && [ [ -z $_moddirname ] ] ; then
xargs -r $DRACUT_INSTALL ${ initdir +-D " $initdir " } -a < " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist.dep "
2012-06-29 14:07:44 +04:00
else
while read _modpath; do
local _destpath = $_modpath
[ [ $_moddirname ] ] && _destpath = ${ _destpath ## $_moddirname / }
_destpath = ${ _destpath ##*/lib/modules/ $kernel / }
inst_simple " $_modpath " " /lib/modules/ $kernel / ${ _destpath } " || exit $?
2012-06-30 11:12:35 +04:00
done < " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist.dep "
2012-06-29 14:07:44 +04:00
fi
) &
2013-07-31 13:00:29 +04:00
_pid = $( jobs -p | while read a ; do printf " : $a " ; done )
_pid = ${ _pid ##* : }
2012-06-27 11:35:39 +04:00
2012-06-30 13:34:13 +04:00
if [ [ $DRACUT_INSTALL ] ] ; then
xargs -r modinfo -k $kernel -F firmware < " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist.dep " \
2012-06-29 14:07:44 +04:00
| while read line; do
for _fwdir in $fw_dir ; do
echo $_fwdir /$line ;
done ;
2012-06-30 13:34:13 +04:00
done | xargs -r $DRACUT_INSTALL ${ initdir +-D " $initdir " } -a -o
2012-06-29 14:07:44 +04:00
else
2012-06-30 13:34:13 +04:00
for _fw in $( xargs -r modinfo -k $kernel -F firmware < " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist.dep " ) ; do
2012-06-29 14:07:44 +04:00
for _fwdir in $fw_dir ; do
if [ [ -d $_fwdir && -f $_fwdir /$_fw ] ] ; then
inst_simple " $_fwdir / $_fw " " /lib/firmware/ $_fw "
break
fi
done
done
fi
2012-06-27 11:35:39 +04:00
2013-07-19 11:34:04 +04:00
wait $_pid
2012-06-29 14:07:44 +04:00
fi
2012-06-27 19:02:49 +04:00
for _f in modules.builtin.bin modules.builtin; do
[ [ $srcmods /$_f ] ] && break
done || {
dfatal "No modules.builtin.bin and modules.builtin found!"
return 1
}
for _f in modules.builtin.bin modules.builtin modules.order; do
[ [ $srcmods /$_f ] ] && inst_simple " $srcmods / $_f " " /lib/modules/ $kernel / $_f "
done
# generate module dependencies for the initrd
if [ [ -d $initdir /lib/modules/$kernel ] ] && \
! depmod -a -b " $initdir " $kernel ; then
dfatal " \"depmod -a $kernel \" failed. "
exit 1
fi
2013-06-28 12:31:18 +04:00
[ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] && rm -fr -- " $DRACUT_KERNEL_LAZY_HASHDIR "
2012-06-27 11:35:39 +04:00
}
2012-06-06 20:20:35 +04:00
2013-07-31 13:00:29 +04:00
module_is_host_only( ) {
2012-10-04 00:32:07 +04:00
local _mod = $1
_mod = ${ _mod ##*/ }
_mod = ${ _mod %.ko }
2013-07-04 14:29:59 +04:00
[ [ " $add_drivers " = = *\ ${ _mod } \ * ] ] && return 0
2012-10-04 00:32:07 +04:00
# check if module is loaded
2013-07-04 14:29:59 +04:00
for i in /sys/module/${ _mod //-/_ } ; do
[ [ -d $i ] ] && return 0
done
2012-10-04 00:32:07 +04:00
# check if module is loadable on the current kernel
# this covers the case, where a new module is introduced
# or a module was renamed
# or a module changed from builtin to a module
modinfo -F filename " $_mod " & >/dev/null || return 0
return 1
2013-07-04 14:29:59 +04:00
}
2012-10-04 00:32:07 +04:00
2013-07-04 14:29:59 +04:00
find_kernel_modules_by_path ( ) {
2012-06-22 17:10:11 +04:00
local _OLDIFS
2013-02-18 14:57:20 +04:00
2013-07-04 14:29:59 +04:00
[ [ -f " $srcmods /modules.dep " ] ] || return 0
2013-02-18 14:57:20 +04:00
_OLDIFS = $IFS
IFS = :
while read a rest; do
[ [ $a = */$1 /* ] ] || continue
2013-07-04 14:29:59 +04:00
printf "%s\n" " $srcmods / $a "
done < " $srcmods /modules.dep "
2013-02-18 14:57:20 +04:00
IFS = $_OLDIFS
2012-06-22 17:10:11 +04:00
return 0
2013-07-04 14:29:59 +04:00
}
2011-08-12 12:29:00 +04:00
2011-08-30 00:40:21 +04:00
find_kernel_modules ( ) {
find_kernel_modules_by_path drivers
}
2012-07-05 12:42:22 +04:00
# instmods [-c [-s]] <kernel module> [<kernel module> ... ]
# instmods [-c [-s]] <kernel subsystem>
2009-08-15 23:17:19 +04:00
# install kernel modules along with all their dependencies.
2012-02-16 14:49:19 +04:00
# <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
2009-02-13 15:42:25 +03:00
instmods( ) {
2009-08-15 19:56:36 +04:00
[ [ $no_kernel = yes ] ] && return
2011-10-11 01:58:04 +04:00
# called [sub]functions inherit _fderr
local _fderr = 9
2012-05-15 10:19:56 +04:00
local _check = no
2012-07-05 12:42:22 +04:00
local _silent = no
2012-05-15 10:19:56 +04:00
if [ [ $1 = '-c' ] ] ; then
_check = yes
shift
fi
2011-08-30 00:40:21 +04:00
2012-07-05 12:42:22 +04:00
if [ [ $1 = '-s' ] ] ; then
_silent = yes
shift
fi
2011-08-30 00:40:21 +04:00
function inst1mod( ) {
2012-05-15 10:19:56 +04:00
local _ret = 0 _mod = " $1 "
2011-05-12 13:03:30 +04:00
case $_mod in
2011-03-25 17:56:46 +03:00
= *)
2012-06-27 11:35:39 +04:00
( [ [ " $_mpargs " ] ] && echo $_mpargs
find_kernel_modules_by_path " ${ _mod #= } " ) \
| instmods
( ( _ret += $? ) )
2010-09-10 17:23:06 +04:00
; ;
2011-08-30 01:46:25 +04:00
--*) _mpargs += " $_mod " ; ;
2012-02-22 19:12:10 +04:00
*)
2012-02-25 19:11:36 +04:00
_mod = ${ _mod ##*/ }
2009-08-28 15:28:19 +04:00
# if we are already installed, skip this module and go on
2010-09-10 17:23:06 +04:00
# to the next one.
2012-06-30 11:12:35 +04:00
if [ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] && \
[ [ -f " $DRACUT_KERNEL_LAZY_HASHDIR / ${ _mod %.ko } .ko " ] ] ; then
read _ret <" $DRACUT_KERNEL_LAZY_HASHDIR / ${ _mod %.ko } .ko "
2012-06-27 11:35:39 +04:00
return $_ret
fi
2011-08-30 00:40:21 +04:00
2012-02-22 19:12:10 +04:00
if [ [ $omit_drivers ] ] && [ [ " $1 " = ~ $omit_drivers ] ] ; then
dinfo " Omitting driver ${ _mod ## $srcmods } "
2012-06-18 14:51:21 +04:00
return 0
2012-02-22 19:12:10 +04:00
fi
2012-10-04 00:32:07 +04:00
2010-09-10 17:23:06 +04:00
# If we are building a host-specific initramfs and this
# module is not already loaded, move on to the next one.
2012-06-06 20:20:35 +04:00
[ [ $hostonly ] ] \
2012-10-04 00:32:07 +04:00
&& ! module_is_host_only " $_mod " \
2012-06-18 14:51:21 +04:00
&& return 0
2008-12-18 00:57:43 +03:00
2012-06-30 11:12:35 +04:00
if [ [ " $_check " = "yes" ] ] || ! [ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] ; then
2012-06-27 11:35:39 +04:00
# We use '-d' option in modprobe only if modules prefix path
2012-10-10 16:15:11 +04:00
# differs from default '/'. This allows us to use dracut with
2012-06-27 11:35:39 +04:00
# old version of modprobe which doesn't have '-d' option.
local _moddirname = ${ srcmods %%/lib/modules/* }
[ [ -n ${ _moddirname } ] ] && _moddirname = " -d ${ _moddirname } / "
# ok, load the module, all its dependencies, and any firmware
# it may require
for_each_kmod_dep install_kmod_with_fw $_mod \
--set-version $kernel ${ _moddirname } $_mpargs
( ( _ret += $? ) )
else
2012-06-30 11:12:35 +04:00
[ [ $DRACUT_KERNEL_LAZY_HASHDIR ] ] && \
echo $_mod >> " $DRACUT_KERNEL_LAZY_HASHDIR /lazylist "
2012-06-27 11:35:39 +04:00
fi
2010-09-10 17:23:06 +04:00
; ;
2011-03-25 17:56:46 +03:00
esac
2012-05-15 10:19:56 +04:00
return $_ret
2011-08-30 00:40:21 +04:00
}
2011-08-30 03:03:35 +04:00
function instmods_1( ) {
2012-05-15 10:19:56 +04:00
local _mod _mpargs
2011-08-30 03:03:35 +04:00
if ( ( $# = = 0) ) ; then # filenames from stdin
while read _mod; do
2012-05-15 10:19:56 +04:00
inst1mod " ${ _mod %.ko* } " || {
2012-07-05 12:42:22 +04:00
if [ [ " $_check " = = "yes" ] ] ; then
2013-05-28 16:25:49 +04:00
[ [ " $_silent " = = "no" ] ] && dfatal " Failed to install module $_mod "
2012-05-15 10:19:56 +04:00
return 1
fi
}
2011-08-30 03:03:35 +04:00
done
fi
while ( ( $# > 0) ) ; do # filenames as arguments
2012-05-15 10:19:56 +04:00
inst1mod ${ 1 %.ko* } || {
2012-07-05 12:42:22 +04:00
if [ [ " $_check " = = "yes" ] ] ; then
2013-05-28 16:25:49 +04:00
[ [ " $_silent " = = "no" ] ] && dfatal " Failed to install module $1 "
2012-05-15 10:19:56 +04:00
return 1
fi
}
2011-08-30 03:03:35 +04:00
shift
2011-08-30 00:40:21 +04:00
done
2012-05-15 10:19:56 +04:00
return 0
2011-08-30 03:03:35 +04:00
}
2012-05-15 10:19:56 +04:00
local _ret _filter_not_found = 'FATAL: Module .* not found.'
2011-10-11 01:58:04 +04:00
# Capture all stderr from modprobe to _fderr. We could use {var}>...
# redirections, but that would make dracut require bash4 at least.
eval " ( instmods_1 \"\$@\" ) ${ _fderr } >&1 " \
2013-07-31 13:00:29 +04:00
| while read line; do [ [ " $line " = ~ $_filter_not_found ] ] || echo $line ; done | derror
2012-05-15 10:19:56 +04:00
_ret = $?
return $_ret
2011-03-25 17:56:46 +03:00
}
dracut.sh: Support early microcode loading.
On Wed, Jul 10, 2013 at 10:58:15AM -0400, Konrad Rzeszutek Wilk wrote:
> On Wed, Jul 10, 2013 at 09:37:11AM +0200, Harald Hoyer wrote:
> > On 07/10/2013 02:29 AM, Yu, Fenghua wrote:
> > >> From: Konrad Rzeszutek Wilk [mailto:konrad.wilk@oracle.com]
> > >> Sent: Tuesday, July 09, 2013 12:24 PM
> > >> Implement it per Linux kernel Documentation/x86/early-microcode.txt
> > >> (from v3.11-rc0):
> > [...]
> > > This patch works fine with one microcode blob in binary format. There are situations that the microcode is not delivered in one blob in binary format:
> > >
> > > First, each microcode patch is one file instead all microcode patches are in one big blob. Secondly, old delivered microcode file is in ascii format.
> > >
> > > To handle those formats, additional code needs to convert the formats into one big binary microcode blob. I'm not sure if we should consider the code and if we should put the code in dracut.
> > >
> > > Thanks.
> > >
> > > -Fenghua
> > >
> >
> >
> > $ ls /lib/firmware/amd-ucode
> > microcode_amd.bin microcode_amd_fam15h.bin microcode_amd_solaris.bin
>
> Right, so all of those blobs (for AMD) get stuck in AuthenticAMD.bin.
>
> > $ ls /lib/firmware/intel-ucode
> > 06-03-02 06-06-00 06-07-02 06-08-0a 06-0b-04 06-0f-06 06-16-01 06-1c-02
> > 06-25-02 06-2d-07 0f-01-02 0f-02-09 0f-04-03 0f-04-0a
> > 06-05-00 06-06-05 06-07-03 06-09-05 06-0d-06 06-0f-07 06-17-06 06-1c-0a
> > 06-25-05 06-2f-02 0f-02-04 0f-03-02 0f-04-04 0f-06-02
> > 06-05-01 06-06-0a 06-08-01 06-0a-00 06-0e-08 06-0f-0a 06-17-07 06-1d-01
> > 06-26-01 06-3a-09 0f-02-05 0f-03-03 0f-04-07 0f-06-04
> > 06-05-02 06-06-0d 06-08-03 06-0a-01 06-0e-0c 06-0f-0b 06-17-0a 06-1e-04
> > 06-2a-07 0f-00-07 0f-02-06 0f-03-04 0f-04-08 0f-06-05
> > 06-05-03 06-07-01 06-08-06 06-0b-01 06-0f-02 06-0f-0d 06-1a-04 06-1e-05
> > 06-2d-06 0f-00-0a 0f-02-07 0f-04-01 0f-04-09 0f-06-08
>
> And all of those get catted in GenuineIntel.bin.
>
> >
> > Also, for [[ $hostonly ]], we only want to add the current running CPU microcode.
>
> <nods> Will do that. Are you OK with me adding some of this CPU detection logic
> in dracut-functions.sh?
This is still RFC, as I had not done the --no-compress logic (or tested it).
Please see if this is OK:
>From 5f853d2ececd4cadff648e22cb9c9287a01a9783 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Tue, 9 Jul 2013 13:57:01 -0400
Subject: [PATCH] dracut.sh: Support early microcode loading.
Implement it per Linux kernel Documentation/x86/early-microcode.txt
(from v3.11-rc0):
<start>
Early load microcode
====================
By Fenghua Yu <fenghua.yu@intel.com>
Kernel can update microcode in early phase of boot time. Loading microcode early
can fix CPU issues before they are observed during kernel boot time.
Microcode is stored in an initrd file. The microcode is read from the initrd
file and loaded to CPUs during boot time.
The format of the combined initrd image is microcode in cpio format followed by
the initrd image (maybe compressed). Kernel parses the combined initrd image
during boot time. The microcode file in cpio name space is:
on Intel: kernel/x86/microcode/GenuineIntel.bin
on AMD : kernel/x86/microcode/AuthenticAMD.bin
During BSP boot (before SMP starts), if the kernel finds the microcode file in
the initrd file, it parses the microcode and saves matching microcode in memory.
If matching microcode is found, it will be uploaded in BSP and later on in all
APs.
The cached microcode patch is applied when CPUs resume from a sleep state.
There are two legacy user space interfaces to load microcode, either through
/dev/cpu/microcode or through /sys/devices/system/cpu/microcode/reload file
in sysfs.
In addition to these two legacy methods, the early loading method described
here is the third method with which microcode can be uploaded to a system's
CPUs.
The following example script shows how to generate a new combined initrd file in
/boot/initrd-3.5.0.ucode.img with original microcode microcode.bin and
original initrd image /boot/initrd-3.5.0.img.
mkdir initrd
cd initrd
mkdir -p kernel/x86/microcode
cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
find . | cpio -o -H newc >../ucode.cpio
cd ..
cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img
<end>
That is what we do in the patch. Furthermoere there is also
an off-switch: "no-early-microcode" to disable it.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
[v1: Support --host-only parameter]
2013-07-13 01:02:54 +04:00
# get_cpu_vendor
# Only two values are returned: AMD or Intel
get_cpu_vendor ( )
{
if grep -qE AMD /proc/cpuinfo; then
printf "AMD"
fi
if grep -qE Intel /proc/cpuinfo; then
printf "Intel"
fi
}
# get_host_ucode
# Get the hosts' ucode file based on the /proc/cpuinfo
get_ucode_file ( )
{
local family = ` grep -E "cpu family" /proc/cpuinfo | head -1 | sed s/.*:\ //`
local model = ` grep -E "model" /proc/cpuinfo | grep -v name | head -1 | sed s/.*:\ //`
local stepping = ` grep -E "stepping" /proc/cpuinfo | head -1 | sed s/.*:\ //`
if [ [ " $( get_cpu_vendor) " = = "AMD" ] ] ; then
# If family greater or equal than 0x15
if [ [ $family -ge 21 ] ] ; then
printf "microcode_amd_fam15h.bin"
else
printf "microcode_amd.bin"
fi
fi
if [ [ " $( get_cpu_vendor) " = = "Intel" ] ] ; then
# The /proc/cpuinfo are in decimal.
printf "%02x-%02x-%02x" ${ family } ${ model } ${ stepping }
fi
}