summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2015-01-02 12:08:19 +0000
committerlersek <lersek@Edk2>2015-01-02 12:08:19 +0000
commit433369169003d4749844615dca4a7239dba8f48b (patch)
treebcb785fd348290039f75553f9b4ede40b0e38911
parentca0d7c98f249ab686b96c72fc88bc9b665aeb4ef (diff)
downloadedk2-platforms-433369169003d4749844615dca4a7239dba8f48b.tar.xz
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
-rw-r--r--OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c198
-rw-r--r--OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf3
-rw-r--r--OvmfPkg/OvmfPkg.dec1
3 files changed, 201 insertions, 1 deletions
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 3599437998..bc2fb56954 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
@@ -23,7 +23,9 @@
#include <Library/PrintLib.h>
#include <Library/DevicePathLib.h>
#include <Library/QemuBootOrderLib.h>
+#include <Library/BaseMemoryLib.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.
**/
#define REQUIRED_PCI_OFW_NODES 2
+#define REQUIRED_MMIO_OFW_NODES 1
#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
@@ -850,6 +1029,11 @@ TranslateOfwNodes (
Status = TranslatePciOfwNodes (OfwNode, NumNodes, Translated,
TranslatedSize);
}
+ if (Status == RETURN_UNSUPPORTED &&
+ FeaturePcdGet (PcdQemuBootOrderMmioTranslation)) {
+ Status = TranslateMmioOfwNodes (OfwNode, NumNodes, Translated,
+ TranslatedSize);
+ }
return Status;
}
@@ -1069,7 +1253,7 @@ Exit:
This function should accommodate any further policy changes in "boot option
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
complete. The caller is responsible for
@@ -1141,6 +1325,18 @@ BootOrderComplete (
//
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) {
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
index 5aa4e6eff0..6289e6abe6 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
@@ -48,9 +48,12 @@
BaseLib
PrintLib
DevicePathLib
+ BaseMemoryLib
[Guids]
gEfiGlobalVariableGuid
+ gVirtioMmioTransportGuid
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index d61cbd69ec..6eb551a8d4 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -105,3 +105,4 @@
[PcdsFeatureFlag]
gUefiOvmfPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|3
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d