summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/Library
diff options
context:
space:
mode:
authorCorvin Köhne <corvink@freebsd.org>2023-06-21 09:31:13 +0200
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-06-23 17:26:37 +0000
commitea88df6b26e93bfe12cea6804631d84e871be77c (patch)
treeadc570473574a81a4486e754e80e7a57eee6f136 /OvmfPkg/Library
parentf5d851673d4d646c129dca4018258f184ab70cbc (diff)
downloadedk2-ea88df6b26e93bfe12cea6804631d84e871be77c.tar.gz
edk2-ea88df6b26e93bfe12cea6804631d84e871be77c.tar.bz2
edk2-ea88df6b26e93bfe12cea6804631d84e871be77c.zip
OvmfPkg: move PciEncoding into AcpiPlatformLib
Bhyve supports providing ACPI tables by FwCfg. Therefore, InstallQemuFwCfgTables should be moved to AcpiPlatformLib to reuse the code. As first step, move PciEncoding into AcpiPlatformLib. Signed-off-by: Corvin Köhne <corvink@FreeBSD.org> Acked-by: Peter Grehan <grehan@freebsd.org>
Diffstat (limited to 'OvmfPkg/Library')
-rw-r--r--OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf7
-rw-r--r--OvmfPkg/Library/AcpiPlatformLib/PciDecoding.c233
2 files changed, 240 insertions, 0 deletions
diff --git a/OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf b/OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf
index dfe0e5623d..4be501bb2c 100644
--- a/OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf
+++ b/OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf
@@ -16,11 +16,18 @@
[Sources]
DxeAcpiPlatformLib.c
+ PciDecoding.c
[Packages]
+ MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
BaseLib
DebugLib
+ PcdLib
+ UefiBootServicesTableLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
diff --git a/OvmfPkg/Library/AcpiPlatformLib/PciDecoding.c b/OvmfPkg/Library/AcpiPlatformLib/PciDecoding.c
new file mode 100644
index 0000000000..58fbfeefda
--- /dev/null
+++ b/OvmfPkg/Library/AcpiPlatformLib/PciDecoding.c
@@ -0,0 +1,233 @@
+/** @file
+ Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
+ regenerates the ACPI tables.
+
+ Copyright (C) 2016, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/AcpiPlatformLib.h>
+#include <Library/DebugLib.h> // DEBUG()
+#include <Library/MemoryAllocationLib.h> // AllocatePool()
+#include <Library/UefiBootServicesTableLib.h> // gBS
+
+/**
+ Collect all PciIo protocol instances in the system. Save their original
+ attributes, and enable IO and MMIO decoding for each.
+
+ This is a best effort function; it doesn't return status codes. Its
+ caller is supposed to proceed even if this function fails.
+
+ @param[out] OriginalAttributes On output, a dynamically allocated array of
+ ORIGINAL_ATTRIBUTES elements. The array lists
+ the PciIo protocol instances found in the
+ system at the time of the call, plus the
+ original PCI attributes for each.
+
+ Before returning, the function enables IO and
+ MMIO decoding for each PciIo instance it
+ finds.
+
+ On error, or when no such instances are
+ found, OriginalAttributes is set to NULL.
+
+ @param[out] Count On output, the number of elements in
+ OriginalAttributes. On error it is set to
+ zero.
+**/
+VOID
+EnablePciDecoding (
+ OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+ OUT UINTN *Count
+ )
+{
+ EFI_STATUS Status;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ ORIGINAL_ATTRIBUTES *OrigAttrs;
+ UINTN Idx;
+
+ *OriginalAttributes = NULL;
+ *Count = 0;
+
+ if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+ //
+ // The platform downloads ACPI tables from QEMU in general, but there are
+ // no root bridges in this execution. We're done.
+ //
+ return;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL /* SearchKey */,
+ &NoHandles,
+ &Handles
+ );
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // No PCI devices were found on either of the root bridges. We're done.
+ //
+ return;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: LocateHandleBuffer(): %r\n",
+ __func__,
+ Status
+ ));
+ return;
+ }
+
+ OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
+ if (OrigAttrs == NULL) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: AllocatePool(): out of resources\n",
+ __func__
+ ));
+ goto FreeHandles;
+ }
+
+ for (Idx = 0; Idx < NoHandles; ++Idx) {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Attributes;
+
+ //
+ // Look up PciIo on the handle and stash it
+ //
+ Status = gBS->HandleProtocol (
+ Handles[Idx],
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+ ASSERT_EFI_ERROR (Status);
+ OrigAttrs[Idx].PciIo = PciIo;
+
+ //
+ // Stash the current attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &OrigAttrs[Idx].PciAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: EfiPciIoAttributeOperationGet: %r\n",
+ __func__,
+ Status
+ ));
+ goto RestoreAttributes;
+ }
+
+ //
+ // Retrieve supported attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Attributes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: EfiPciIoAttributeOperationSupported: %r\n",
+ __func__,
+ Status
+ ));
+ goto RestoreAttributes;
+ }
+
+ //
+ // Enable IO and MMIO decoding
+ //
+ Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Attributes,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: EfiPciIoAttributeOperationEnable: %r\n",
+ __func__,
+ Status
+ ));
+ goto RestoreAttributes;
+ }
+ }
+
+ //
+ // Success
+ //
+ FreePool (Handles);
+ *OriginalAttributes = OrigAttrs;
+ *Count = NoHandles;
+ return;
+
+RestoreAttributes:
+ while (Idx > 0) {
+ --Idx;
+ OrigAttrs[Idx].PciIo->Attributes (
+ OrigAttrs[Idx].PciIo,
+ EfiPciIoAttributeOperationSet,
+ OrigAttrs[Idx].PciAttributes,
+ NULL
+ );
+ }
+
+ FreePool (OrigAttrs);
+
+FreeHandles:
+ FreePool (Handles);
+}
+
+/**
+ Restore the original PCI attributes saved with EnablePciDecoding().
+
+ @param[in] OriginalAttributes The array allocated and populated by
+ EnablePciDecoding(). This parameter may be
+ NULL. If OriginalAttributes is NULL, then the
+ function is a no-op; otherwise the PciIo
+ attributes will be restored, and the
+ OriginalAttributes array will be freed.
+
+ @param[in] Count The Count value stored by EnablePciDecoding(),
+ the number of elements in OriginalAttributes.
+ Count may be zero if and only if
+ OriginalAttributes is NULL.
+**/
+VOID
+RestorePciDecoding (
+ IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+ IN UINTN Count
+ )
+{
+ UINTN Idx;
+
+ ASSERT ((OriginalAttributes == NULL) == (Count == 0));
+ if (OriginalAttributes == NULL) {
+ return;
+ }
+
+ for (Idx = 0; Idx < Count; ++Idx) {
+ OriginalAttributes[Idx].PciIo->Attributes (
+ OriginalAttributes[Idx].PciIo,
+ EfiPciIoAttributeOperationSet,
+ OriginalAttributes[Idx].PciAttributes,
+ NULL
+ );
+ }
+
+ FreePool (OriginalAttributes);
+}