OvmfPkg: QemuBootOrderLib: OFW-to-UEFI translation for virtio-mmio

The TranslateMmioOfwNodes() function recognizes the following OpenFirmware
device paths:

  virtio-blk:       /virtio-mmio@000000000a003c00/disk@0,0
  virtio-scsi disk: /virtio-mmio@000000000a003a00/channel@0/disk@2,3
  virtio-net NIC:   /virtio-mmio@000000000a003e00/ethernet-phy@0

The new translation can be enabled with the
"PcdQemuBootOrderMmioTranslation" Feature PCD. This PCD also controls if
the "survival policy" covers unselected boot options that start with the
virtio-mmio VenHw() node.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16575 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Laszlo Ersek 2015-01-02 12:08:19 +00:00 committed by lersek
parent ca0d7c98f2
commit 4333691690
3 changed files with 201 additions and 1 deletions

View File

@ -23,7 +23,9 @@
#include <Library/PrintLib.h> #include <Library/PrintLib.h>
#include <Library/DevicePathLib.h> #include <Library/DevicePathLib.h>
#include <Library/QemuBootOrderLib.h> #include <Library/QemuBootOrderLib.h>
#include <Library/BaseMemoryLib.h>
#include <Guid/GlobalVariable.h> #include <Guid/GlobalVariable.h>
#include <Guid/VirtioMmioTransport.h>
/** /**
@ -36,6 +38,7 @@
Numbers of nodes in OpenFirmware device paths that are required and examined. Numbers of nodes in OpenFirmware device paths that are required and examined.
**/ **/
#define REQUIRED_PCI_OFW_NODES 2 #define REQUIRED_PCI_OFW_NODES 2
#define REQUIRED_MMIO_OFW_NODES 1
#define EXAMINED_OFW_NODES 4 #define EXAMINED_OFW_NODES 4
@ -801,6 +804,182 @@ TranslatePciOfwNodes (
} }
//
// A type providing easy raw access to the base address of a virtio-mmio
// transport.
//
typedef union {
UINT64 Uint64;
UINT8 Raw[8];
} VIRTIO_MMIO_BASE_ADDRESS;
/**
Translate an MMIO-like array of OpenFirmware device nodes to a UEFI device
path fragment.
@param[in] OfwNode Array of OpenFirmware device nodes to
translate, constituting the beginning of an
OpenFirmware device path.
@param[in] NumNodes Number of elements in OfwNode.
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
contents is indeterminate.
@param[in out] TranslatedSize On input, the number of CHAR16's in
Translated. On RETURN_SUCCESS this parameter
is assigned the number of non-NUL CHAR16's
written to Translated. In case of other return
values, TranslatedSize is indeterminate.
@retval RETURN_SUCCESS Translation successful.
@retval RETURN_BUFFER_TOO_SMALL The translation does not fit into the number
of bytes provided.
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.
**/
STATIC
RETURN_STATUS
TranslateMmioOfwNodes (
IN CONST OFW_NODE *OfwNode,
IN UINTN NumNodes,
OUT CHAR16 *Translated,
IN OUT UINTN *TranslatedSize
)
{
VIRTIO_MMIO_BASE_ADDRESS VirtioMmioBase;
CHAR16 VenHwString[60 + 1];
UINTN NumEntries;
UINTN Written;
//
// Get the base address of the virtio-mmio transport.
//
if (NumNodes < REQUIRED_MMIO_OFW_NODES ||
!SubstringEq (OfwNode[0].DriverName, "virtio-mmio")
) {
return RETURN_UNSUPPORTED;
}
NumEntries = 1;
if (ParseUnitAddressHexList (
OfwNode[0].UnitAddress,
&VirtioMmioBase.Uint64,
&NumEntries
) != RETURN_SUCCESS
) {
return RETURN_UNSUPPORTED;
}
UnicodeSPrintAsciiFormat (VenHwString, sizeof VenHwString,
"VenHw(%g,%02X%02X%02X%02X%02X%02X%02X%02X)", &gVirtioMmioTransportGuid,
VirtioMmioBase.Raw[0], VirtioMmioBase.Raw[1], VirtioMmioBase.Raw[2],
VirtioMmioBase.Raw[3], VirtioMmioBase.Raw[4], VirtioMmioBase.Raw[5],
VirtioMmioBase.Raw[6], VirtioMmioBase.Raw[7]);
if (NumNodes >= 2 &&
SubstringEq (OfwNode[1].DriverName, "disk")) {
//
// OpenFirmware device path (virtio-blk disk):
//
// /virtio-mmio@000000000a003c00/disk@0,0
// ^ ^ ^
// | fixed
// base address of virtio-mmio register block
//
// UEFI device path prefix:
//
// <VenHwString>/HD(
//
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
"%s/HD(",
VenHwString
);
} else if (NumNodes >= 3 &&
SubstringEq (OfwNode[1].DriverName, "channel") &&
SubstringEq (OfwNode[2].DriverName, "disk")) {
//
// OpenFirmware device path (virtio-scsi disk):
//
// /virtio-mmio@000000000a003a00/channel@0/disk@2,3
// ^ ^ ^ ^
// | | | LUN
// | | target
// | channel (unused, fixed 0)
// base address of virtio-mmio register block
//
// UEFI device path prefix:
//
// <VenHwString>/Scsi(0x2,0x3)
//
UINT64 TargetLun[2];
TargetLun[1] = 0;
NumEntries = sizeof (TargetLun) / sizeof (TargetLun[0]);
if (ParseUnitAddressHexList (
OfwNode[2].UnitAddress,
TargetLun,
&NumEntries
) != RETURN_SUCCESS
) {
return RETURN_UNSUPPORTED;
}
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
"%s/Scsi(0x%Lx,0x%Lx)",
VenHwString,
TargetLun[0],
TargetLun[1]
);
} else if (NumNodes >= 2 &&
SubstringEq (OfwNode[1].DriverName, "ethernet-phy")) {
//
// OpenFirmware device path (virtio-net NIC):
//
// /virtio-mmio@000000000a003e00/ethernet-phy@0
// ^ ^
// | fixed
// base address of virtio-mmio register block
//
// UEFI device path prefix (dependent on presence of nonzero PCI function):
//
// <VenHwString>/MAC(
//
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
"%s/MAC(",
VenHwString
);
} else {
return RETURN_UNSUPPORTED;
}
//
// There's no way to differentiate between "completely used up without
// truncation" and "truncated", so treat the former as the latter, and return
// success only for "some room left unused".
//
if (Written + 1 < *TranslatedSize) {
*TranslatedSize = Written;
return RETURN_SUCCESS;
}
return RETURN_BUFFER_TOO_SMALL;
}
/** /**
Translate an array of OpenFirmware device nodes to a UEFI device path Translate an array of OpenFirmware device nodes to a UEFI device path
@ -850,6 +1029,11 @@ TranslateOfwNodes (
Status = TranslatePciOfwNodes (OfwNode, NumNodes, Translated, Status = TranslatePciOfwNodes (OfwNode, NumNodes, Translated,
TranslatedSize); TranslatedSize);
} }
if (Status == RETURN_UNSUPPORTED &&
FeaturePcdGet (PcdQemuBootOrderMmioTranslation)) {
Status = TranslateMmioOfwNodes (OfwNode, NumNodes, Translated,
TranslatedSize);
}
return Status; return Status;
} }
@ -1069,7 +1253,7 @@ Exit:
This function should accommodate any further policy changes in "boot option This function should accommodate any further policy changes in "boot option
survival". Currently we're adding back everything that starts with neither survival". Currently we're adding back everything that starts with neither
PciRoot() nor HD(). PciRoot() nor HD() nor a virtio-mmio VenHw() node.
@param[in,out] BootOrder The structure holding the boot order to @param[in,out] BootOrder The structure holding the boot order to
complete. The caller is responsible for complete. The caller is responsible for
@ -1141,6 +1325,18 @@ BootOrderComplete (
// //
Keep = !FeaturePcdGet (PcdQemuBootOrderPciTranslation); Keep = !FeaturePcdGet (PcdQemuBootOrderPciTranslation);
} }
} else if (DevicePathType(FirstNode) == HARDWARE_DEVICE_PATH &&
DevicePathSubType(FirstNode) == HW_VENDOR_DP) {
VENDOR_DEVICE_PATH *VenHw;
VenHw = (VENDOR_DEVICE_PATH *)FirstNode;
if (CompareGuid (&VenHw->Guid, &gVirtioMmioTransportGuid)) {
//
// drop virtio-mmio if we enabled the user to select boot options
// referencing such device paths
//
Keep = !FeaturePcdGet (PcdQemuBootOrderMmioTranslation);
}
} }
if (Keep) { if (Keep) {

View File

@ -48,9 +48,12 @@
BaseLib BaseLib
PrintLib PrintLib
DevicePathLib DevicePathLib
BaseMemoryLib
[Guids] [Guids]
gEfiGlobalVariableGuid gEfiGlobalVariableGuid
gVirtioMmioTransportGuid
[FeaturePcd] [FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation

View File

@ -105,3 +105,4 @@
[PcdsFeatureFlag] [PcdsFeatureFlag]
gUefiOvmfPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|3 gUefiOvmfPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|3
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d