From 1b827040f8b3e1e4fec19de76526fe0620654502 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Mon, 7 Oct 2013 14:24:36 +0200 Subject: [PATCH] fcoe: add FCoE UEFI boot device support --- modules.d/95fcoe/module-setup.sh | 1 + modules.d/95fcoe/parse-uefifcoe.sh | 35 +++++++ modules.d/99base/module-setup.sh | 1 + modules.d/99base/uefi-lib.sh | 155 +++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100755 modules.d/95fcoe/parse-uefifcoe.sh create mode 100755 modules.d/99base/uefi-lib.sh diff --git a/modules.d/95fcoe/module-setup.sh b/modules.d/95fcoe/module-setup.sh index d3c58cc6..08ba4eac 100755 --- a/modules.d/95fcoe/module-setup.sh +++ b/modules.d/95fcoe/module-setup.sh @@ -32,6 +32,7 @@ install() { inst "$moddir/fcoe-up.sh" "/sbin/fcoe-up" inst "$moddir/fcoe-edd.sh" "/sbin/fcoe-edd" inst "$moddir/fcoe-genrules.sh" "/sbin/fcoe-genrules.sh" + inst_hook cmdline 20 "$moddir/parse-uefifcoe.sh" inst_hook cmdline 99 "$moddir/parse-fcoe.sh" dracut_need_initqueue } diff --git a/modules.d/95fcoe/parse-uefifcoe.sh b/modules.d/95fcoe/parse-uefifcoe.sh new file mode 100755 index 00000000..e03bcb39 --- /dev/null +++ b/modules.d/95fcoe/parse-uefifcoe.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +command -v getarg >/dev/null || . /lib/dracut-lib.sh +command -v get_fcoe_boot_mac >/dev/null || . /lib/uefi-lib.sh +command -v set_ifname >/dev/null || . /lib/net-lib.sh + +print_fcoe_uefi_conf() +{ + local mac dev vlan + mac=$(get_fcoe_boot_mac) + [ -z "$mac" ] && continue + dev=$(set_ifname fcoe $mac) + vlan=$(get_fcoe_boot_vlan) + if [ "$vlan" -ne "0" ]; then + case "$vlan" in + [0-9]*) + printf "%s\n" "vlan=$dev.$vlan:$dev" + dev="$dev.$vlan" + ;; + *) + printf "%s\n" "vlan=$vlan:$dev" + dev="$vlan" + ;; + esac + fi + # fcoe=eth0:nodcb + printf "%s\n" "$dev:nodcb" +} + + +if [ -e /sys/firmware/efi/vars/FcoeBootDevice-a0ebca23-5f9c-447a-a268-22b6c158c2ac/data ]; then + print_fcoe_uefi_conf > /etc/cmdline.d/40-fcoe-uefi.conf +fi diff --git a/modules.d/99base/module-setup.sh b/modules.d/99base/module-setup.sh index 52ce4004..d33a0fb4 100755 --- a/modules.d/99base/module-setup.sh +++ b/modules.d/99base/module-setup.sh @@ -42,6 +42,7 @@ install() { mkdir -p ${initdir}/tmp inst_simple "$moddir/dracut-lib.sh" "/lib/dracut-lib.sh" + inst_simple "$moddir/uefi-lib.sh" "/lib/uefi-lib.sh" if ! dracut_module_included "systemd"; then inst_multiple switch_root || dfatal "Failed to install switch_root" diff --git a/modules.d/99base/uefi-lib.sh b/modules.d/99base/uefi-lib.sh new file mode 100755 index 00000000..faedbac5 --- /dev/null +++ b/modules.d/99base/uefi-lib.sh @@ -0,0 +1,155 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +# +# Copyright 2013 Red Hat, Inc. All rights reserved. +# Copyright 2013 Harald Hoyer +# +# 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 +# along with this program. If not, see . +# + +getbyte () { + local IFS= LC_CTYPE=C res c + read -r -n 1 -d '' c + res=$? + # the single quote in the argument of the printf + # yields the numeric value of $c (ASCII since LC_CTYPE=C) + [[ -n $c ]] && c=$(printf '%u' "'$c") || c=0 + printf "$c" + return $res +} + +getword () { + local b1 b2 val + b1=$(getbyte) || return 1 + b2=$(getbyte) || return 1 + (( val = b2 * 256 + b1 )) + echo $val + return 0 +} + +# Acpi(PNP0A08,0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)/MAC(90E2BA265ED4,0x0)/Vlan(172)/Fibre(0x4EA06104A0CC0050,0x0) +uefi_device_path() +{ + local IFS= LC_CTYPE=C res tt len type hextype first + first=1 + + while :; do + type=$(getbyte) || return 1 + subtype=$(getbyte) || return 1 + len=$(getword) || return 1 + hextype=$(printf "%02x%02x" "$type" "$subtype") + if [[ $first == 1 ]]; then + first=0 + elif [[ $hextype != "7fff" ]]; then + printf "/" + fi + case $hextype in + 0101) + # PCI + tt=$(getword) + printf "PCI(0x%x,0x%x)" $(($tt / 256)) $(($tt & 255)) + ;; + 0201) + # ACPI + printf "Acpi(0x%x,0x%x)" $(($(getword) + $(getword) * 65536)) $(($(getword) + $(getword) * 65536)) + ;; + 0303) + # FIBRE + getword &>/dev/null + getword &>/dev/null + printf "Fibre(0x%x%x%x%x%x%x%x%x,0x%x)" \ + $(getbyte) $(getbyte) $(getbyte) $(getbyte) \ + $(getbyte) $(getbyte) $(getbyte) $(getbyte) \ + $(( $(getword) + $(getword) * 65536 + 4294967296 * ( $(getword) + $(getword) * 65536 ) )) + ;; + 030b) + # MAC + printf "MAC(%02x%02x%02x%02x%02x%02x," $(getbyte) $(getbyte) $(getbyte) $(getbyte) $(getbyte) $(getbyte) + read -r -N 26 tt || return 1 + printf "0x%x)" $(getbyte) + ;; + 0314) + # VLAN + printf "VLAN(%d)" $(getword) + ;; + 7fff) + # END + printf "\n" + return 0 + ;; + *) + printf "Unknown(Type:%d SubType:%d len=%d)" "$type" "$subtype" "$len" + read -r -N $(($len-4)) tt || return 1 + ;; + esac + done +} + +get_fcoe_boot_mac() +{ + data=${1:-/sys/firmware/efi/vars/FcoeBootDevice-a0ebca23-5f9c-447a-a268-22b6c158c2ac/data} + [ -f $data ] || return 1 + local IFS= LC_CTYPE=C tt len type hextype + first=1 + + while :; do + type=$(getbyte) || return 1 + subtype=$(getbyte) || return 1 + len=$(getword) || return 1 + hextype=$(printf "%02x%02x" "$type" "$subtype") + case $hextype in + 030b) + # MAC + printf "%02x:%02x:%02x:%02x:%02x:%02x" $(getbyte) $(getbyte) $(getbyte) $(getbyte) $(getbyte) $(getbyte) + read -r -N 27 tt || return 1 + ;; + 7fff) + # END + return 0 + ;; + *) + read -r -N $(($len-4)) tt || return 1 + ;; + esac + done < $data +} + +get_fcoe_boot_vlan() +{ + data=${1:-/sys/firmware/efi/vars/FcoeBootDevice-a0ebca23-5f9c-447a-a268-22b6c158c2ac/data} + [ -f $data ] || return 1 + local IFS= LC_CTYPE=C tt len type hextype + first=1 + + while :; do + type=$(getbyte) || return 1 + subtype=$(getbyte) || return 1 + len=$(getword) || return 1 + hextype=$(printf "%02x%02x" "$type" "$subtype") + case $hextype in + 0314) + # VLAN + printf "%d" $(getword) + ;; + 7fff) + # END + return 0 + ;; + *) + read -r -N $(($len-4)) tt || return 1 + ;; + esac + done < $data +}