qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: qemu-devel@nongnu.org, edk2-devel@lists.sourceforge.net,
	drjones@redhat.com, ard.biesheuvel@linaro.org,
	peter.maydell@linaro.org, imammedo@redhat.com, mst@redhat.com
Subject: [Qemu-devel] [edk2 PATCH 10/12] OvmfPkg: QemuBootOrderLib: OFW-to-UEFI translation for virtio-mmio
Date: Fri, 28 Nov 2014 00:19:25 +0100	[thread overview]
Message-ID: <1417130367-17777-11-git-send-email-lersek@redhat.com> (raw)
In-Reply-To: <1417130367-17777-1-git-send-email-lersek@redhat.com>

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>
---
 OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf |   3 ++
 OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c   | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 OvmfPkg/OvmfPkg.dec                                   |   1 +
 3 files changed, 201 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
index 5aa4e6e..6289e6a 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/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 3599437..bc2fb56 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/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 41db92d..e3a09cf 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -109,3 +109,4 @@
 [PcdsFeatureFlag]
   gUefiOvmfPkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|3
   gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
+  gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d
-- 
1.8.3.1

  parent reply	other threads:[~2014-11-27 23:20 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-27 23:17 [Qemu-devel] expose QEMU's fw_cfg boot order to ARM guest firmware (Intel BDS) Laszlo Ersek
2014-11-27 23:18 ` [Qemu-devel] [qemu PATCH 0/2] DTB- and MMIO-based fw_cfg for hw/arm/virt Laszlo Ersek
2014-11-27 23:18   ` [Qemu-devel] [qemu PATCH 1/2] fw_cfg: make the FW_CFG_SIZE and FW_CFG_DATA_SIZE macros public Laszlo Ersek
2014-11-27 23:18   ` [Qemu-devel] [qemu PATCH 2/2] arm: add fw_cfg to "virt" board Laszlo Ersek
2014-11-27 23:28     ` Peter Maydell
2014-11-27 23:34       ` Laszlo Ersek
2014-11-27 23:37         ` Peter Maydell
2014-11-28 10:38     ` Andrew Jones
2014-11-28 10:43       ` Laszlo Ersek
2014-11-28 10:49         ` Laszlo Ersek
2014-11-28 11:17           ` Andrew Jones
2014-11-28 10:51         ` Andrew Jones
2014-11-27 23:19 ` [Qemu-devel] [edk2 PATCH 00/12] consume fw_cfg boot order in ArmVirtualizationQemu Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 01/12] ArmVirtualizationPkg: VirtFdtDxe: forward FwCfg addresses from DTB to PCDs Laszlo Ersek
2014-12-05 17:39     ` [Qemu-devel] [edk2] " Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 02/12] ArmVirtualizationPkg: introduce QemuFwCfgLib instance for DXE drivers Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 03/12] ArmVirtualizationPkg: clone PlatformIntelBdsLib from ArmPlatformPkg Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 04/12] ArmVirtualizationPkg: PlatformIntelBdsLib: add basic policy Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 05/12] OvmfPkg: extract QemuBootOrderLib Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 06/12] OvmfPkg: QemuBootOrderLib: featurize PCI-like device path translation Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 07/12] OvmfPkg: introduce VIRTIO_MMIO_TRANSPORT_GUID Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 08/12] ArmVirtualizationPkg: VirtFdtDxe: use dedicated VIRTIO_MMIO_TRANSPORT_GUID Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 09/12] OvmfPkg: QemuBootOrderLib: widen ParseUnitAddressHexList() to UINT64 Laszlo Ersek
2014-11-27 23:19   ` Laszlo Ersek [this message]
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 11/12] ArmVirtualizationPkg: PlatformIntelBdsLib: adhere to QEMU's boot order Laszlo Ersek
2014-11-27 23:19   ` [Qemu-devel] [edk2 PATCH 12/12] ArmVirtualizationPkg: identify "new shell" as builtin shell for Intel BDS Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1417130367-17777-11-git-send-email-lersek@redhat.com \
    --to=lersek@redhat.com \
    --cc=ard.biesheuvel@linaro.org \
    --cc=drjones@redhat.com \
    --cc=edk2-devel@lists.sourceforge.net \
    --cc=imammedo@redhat.com \
    --cc=mst@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).