#
# geninitrd functions
-# Find root device from fstab.
-#
-# @param string $fstab location of /etc/fstab
+# Get device name from UUID/LABEL
+# @param string device path or UUID/LABEL name
# @return false on failure
-#
-# Sets global variables:
-# - $rootdev
-# - $rootdev_add
-# - $rootFS
#
-find_root() {
- local fstab="$1"
- local function="${PROGRAM:+$PROGRAM: }find_root"
- local rootopt
-
- eval $(awk '!/^[\t ]*#/ && $2 == "/" {printf("rootdev=\"%s\"\nrootFs=\"%s\"\nrootopt=\"%s\"\n", $1, $3, $4)}' $fstab)
- if [ -z "$rootdev" ]; then
- echo >&2 "$function: can't find fstab entry for root mountpoint"
- return 1
- fi
-
- # additional devices needed (xfs logdev)
- rootdev_add=$(echo "$rootopt" | awk -F',' '{ for (i=1; i<=NF; i++) { if ($i ~ /^logdev=/) { gsub(/^logdev=/, NIL, $i); print $i; } } }')
+find_devname() {
+ local outname name="$1"
+ local function="${PROGRAM:+$PROGRAM: }find_devname"
- case $rootdev in
+ outname="$name"
+ case $name in
LABEL=*)
if [ ! -x /sbin/blkid ]; then
echo >&2 "$function: /sbin/blkid is missing"
return 2
fi
- local label=${rootdev#"LABEL="}
+ local label=${name#"LABEL="}
local dev=$(/sbin/blkid -l -t LABEL="$label" -o device)
if [ "$dev" ]; then
if [ ! -r "$dev" ]; then
echo >&2 "$function: blkid returned device $dev which doesn't exist"
return 2
fi
- rootdev=$dev
+ outname=$dev
fi
;;
return 2
fi
- local uuid=${rootdev#"UUID="}
+ local uuid=${name#"UUID="}
local dev=$(/sbin/blkid -l -t UUID="$uuid" -o device)
if [ "$dev" ]; then
echo >&2 "$function: blkid returned device $dev which doesn't exist"
return 2
fi
- rootdev=$dev
+ outname=$dev
fi
;;
esac
+ echo $outname
+}
+
+# Find root device from fstab.
+#
+# @param string $fstab location of /etc/fstab
+# @return false on failure
+#
+# Sets global variables:
+# - $rootdev
+# - $rootdev_add
+# - $rootFS
+#
+find_root() {
+ local fstab="$1"
+ local function="${PROGRAM:+$PROGRAM: }find_root"
+ local rootopt
+
+ eval $(awk '!/^[\t ]*#/ && $2 == "/" {printf("rootdev=\"%s\"\nrootFs=\"%s\"\nrootopt=\"%s\"\n", $1, $3, $4)}' $fstab)
+ if [ -z "$rootdev" ]; then
+ echo >&2 "$function: can't find fstab entry for root mountpoint"
+ return 1
+ fi
+
+ # additional devices needed (xfs logdev)
+ rootdev_add=$(echo "$rootopt" | awk -F',' '{ for (i=1; i<=NF; i++) { if ($i ~ /^logdev=/) { gsub(/^logdev=/, NIL, $i); print $i; } } }')
+ rootdev=$(find_devname "$rootdev")
case $rootdev in
/dev/dm-*)
local node
fi
if [ ! -r "$rootdev" ]; then
- echo >&2 "$function: can't find real device for $rootdev"
+ echo >&2 "$function: rootfs device file $rootdev doesn't exist"
return 1
fi
# which they got from blkid program fs was specifed as UUID= in fstab
dm_lvm2_name() {
local node="$1"
- local dm_minor
+ local dm_minor stat
if [ ! -b "$node" ]; then
echo >&2 "dm_lvm2_name: $node is not a block device"
dm_minor=${node#/dev/dm-}
;;
/dev/mapper/*)
- dm_minor=$(ls -l $node | awk '{print $6}')
+ stat=$(stat -L -c %T "$node") || die "stat failed: $node"
+ dm_minor=$((0x$stat))
;;
esac
# @return DM name
dm_name() {
local node="$1"
- dmsetup info -c --noheadings $node | awk -F: '{print $1}'
+ dmsetup info -c --noheadings -o name $node
}
# get subsystem name for DM node
# node can be /dev/dm-0, /dev/mapper/name
# @return subsystem name
dm_subsystem() {
- local node="$1"
- dmsetup info -c --noheadings -o subsystem $node
+ local node="$1" out
+ out=$(dmsetup info -c --noheadings -o subsystem $node)
+ if [ $? -eq 0 -a -n "$out" ]; then
+ echo "$out"
+ return
+ fi
+
+ # for very old kernels (2.6.16), subsystem is empty, assume LVM
+ # TODO: fix this if needed to have crypt as well
+ echo "LVM"
}
# resolve any dm node to it's full path in /dev/mapper
local node="$1"
printf "/dev/mapper/%s" $(dm_name "$node")
}
+
+# find modules by class
+# find_modules_by_class 0106 - finds modules for SATA devices in the system
+# find_modules_by_class 0c03 - finds modules for USB controllers
+find_modules_by_class() {
+ if modprobe --version | grep -q "^kmod"; then
+ find_modules_by_class_kmod $@
+ else
+ find_modules_by_class_mit $@
+ fi
+}
+
+# find modules by class (kmod version)
+# find_modules_by_class 0106 - finds modules for SATA devices in the system
+# find_modules_by_class 0c03 - finds modules for USB controllers
+find_modules_by_class_kmod() {
+ local req_class="$1" i j modaliases
+
+ if [ ! -d "/sys/devices" ]; then
+ warn "No /sys/devices/ found. Is /sys mounted?"
+ return
+ fi
+
+ for i in $(grep -li "^0x${req_class}" /sys/devices/pci*/*/class); do
+ j=$(dirname $i)
+ modaliases="$modaliases $(cat $j/modalias)"
+ done
+
+ if [ -z "$modaliases" ]; then
+ return
+ fi
+
+ echo $modaliases | xargs modprobe --set-version $kernel -aRn | awk '
+ BEGIN { skip_modules[notexisting_module]=""; modules[1]=""; xhci=""; ehci_pci=""; ehci_hcd=""; ehci_platform=""; ohci=""; uhci="" }
+ {
+ module=$1
+ if (module == "xhci_hcd") {
+ xhci="xhci_hcd"
+ } else if (module == "ehci_hcd") {
+ ehci_hcd="ehci_hcd"
+ } else if (module == "ehci_pci") {
+ ehci_pci="ehci_pci"
+ } else if (module == "ehci_platform") {
+ ehci_platform="ehci_platform"
+ } else if (module == "ohci_hcd") {
+ ohci="ohci_hcd"
+ } else if (module == "uhci_hcd") {
+ uhci="uhci_hcd"
+ } else if (!(module in skip_modules)) {
+ modules[cnt]=module
+ }
+ skip_modules[module]=1;
+ }
+ END {
+ # ehci/ohci/uhci/xhci hack to preserve such order
+ printf "%s %s %s %s %s %s ", ehci_hcd, ehci_pci, ehci_platform, ohci, uhci, xhci;
+ for (i in modules) { printf "%s ", modules[i]; };
+ }
+ '
+}
+
+# find modules by class (module-init-tools version)
+# find_modules_by_class 0106 - finds modules for SATA devices in the system
+# find_modules_by_class 0c03 - finds modules for USB controllers
+find_modules_by_class_mit() {
+ local req_class="$1" pcimap lspci
+
+ pcimap="/lib/modules/$kernel/modules.pcimap"
+
+ lspci=$(find_tool /sbin/lspci)
+ if [ ! -x "$lspci" ]; then
+ warn "Failed to execute lspci. Is pciutils package installed?"
+ fi
+
+ # no pcimap, nothing to lookup from
+ if [ ! -f "$pcimap" ]; then
+ warn "No $pcimap file. Cannot find modules for desired class!"
+ return
+ fi
+
+ if [ -z "$lspci" ]; then
+ return
+ fi
+
+ LC_ALL=C lspci -p "$pcimap" -kvmmn | awk -vreq_class="${req_class}" '
+ BEGIN { skip_modules[notexisting_module]=""; modules[1]=""; xhci=""; ehci_pci=""; ehci_hcd=""; ehci_platform=""; ohci=""; uhci="" }
+ /^Slot:/ { found=0 }
+ /^Class:/ { if (req_class == $2) { found = 1 } }
+ /^Driver:/ { if (found) {
+ module = $2;
+ if (module == "xhci_hcd") {
+ xhci = "xhci_hcd"
+ } else if (module == "ehci_hcd") {
+ ehci_hcd = "ehci_hcd"
+ } else if (module == "ehci_pci") {
+ ehci_pci="ehci_pci"
+ } else if (module == "ehci_platform") {
+ ehci_platform="ehci_platform"
+ } else if (module == "ohci_hcd") {
+ ohci = "ohci_hcd"
+ } else if (module == "uhci_hcd") {
+ uhci = "uhci_hcd"
+ } else if (!(module in skip_modules)) {
+ modules[cnt] = module
+ }
+ skip_modules[module] = 1;
+ }
+ found=0
+ }
+ END {
+ # ehci/ohci/uhci/xhci hack to preserve such order
+ printf "%s %s %s %s %s %s ", ehci_hcd, ehci_pci, ehci_platform, ohci, uhci, xhci;
+ for (i in modules) { printf "%s ", modules[i]; }
+ }
+ '
+}
+
+# get possible paths for specifed patter containing LIBDIR
+get_libdir() {
+ for dir in lib lib64 libx32; do
+ echo -n "${1/LIBDIR/$dir} "
+ done
+}