From: "Rebecca Cran" <rebecca@bsdio.com>
To: devel@edk2.groups.io, Jordan Justen <jordan.l.justen@intel.com>,
Laszlo Ersek <lersek@redhat.com>,
Ard Biesheuvel <ard.biesheuvel@arm.com>,
Andrew Fish <afish@apple.com>, Leif Lindholm <leif@nuviainc.com>,
Michael D Kinney <michael.d.kinney@intel.com>
Cc: Rebecca Cran <rebecca@bsdio.com>
Subject: [PATCH v4 6/6] BhyvePkg: Add AcpiPlatformDxe
Date: Fri, 24 Apr 2020 12:29:14 -0600 [thread overview]
Message-ID: <20200424182914.138915-7-rebecca@bsdio.com> (raw)
In-Reply-To: <20200424182914.138915-1-rebecca@bsdio.com>
Make a copy of OvmfPkg/AcpiPlatformDxe under BhyvePkg, with the changes
needed to support the bhyve hypervisor.
Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
---
BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c | 251 +++++++++++++++++++
BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h | 77 ++++++
BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 65 +++++
BhyvePkg/AcpiPlatformDxe/Bhyve.c | 132 ++++++++++
BhyvePkg/AcpiPlatformDxe/EntryPoint.c | 90 +++++++
BhyvePkg/AcpiPlatformDxe/PciDecoding.c | 192 ++++++++++++++
6 files changed, 807 insertions(+)
create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
create mode 100644 BhyvePkg/AcpiPlatformDxe/Bhyve.c
create mode 100644 BhyvePkg/AcpiPlatformDxe/EntryPoint.c
create mode 100644 BhyvePkg/AcpiPlatformDxe/PciDecoding.c
diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..31bbf6c474
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,251 @@
+/** @file
+ OVMF ACPI Platform Driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ return AcpiProtocol->InstallAcpiTable (
+ AcpiProtocol,
+ AcpiTableBuffer,
+ AcpiTableBufferSize,
+ TableKey
+ );
+}
+
+
+/**
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+ @param Instance Return pointer to the first instance of the protocol
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_NOT_FOUND The protocol could not be located.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateFvInstanceWithTables (
+ OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+
+ //
+ // Looking for FV with ACPI storage file
+ //
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID**) &FvInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // See if it has the ACPI storage file
+ //
+ Status = FvInstance->ReadFile (
+ FvInstance,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ //
+ // If we found it, then we are done
+ //
+ if (Status == EFI_SUCCESS) {
+ *Instance = FvInstance;
+ break;
+ }
+ }
+
+ //
+ // Our exit status is determined by the success of the previous operations
+ // If the protocol was found, Instance already points to it.
+ //
+
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
+
+
+/**
+ Find ACPI tables in an FV and install them.
+
+ This is now a fall-back path. Normally, we will search for tables provided
+ by the VMM first.
+
+ If that fails, we use this function to load the ACPI tables from an FV. The
+ sources for the FV based tables is located under OvmfPkg/AcpiTables.
+
+ @param AcpiTable Protocol instance pointer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallOvmfFvTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINTN TableSize;
+ UINTN Size;
+ EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
+
+ Instance = 0;
+ CurrentTable = NULL;
+ TableHandle = 0;
+
+ TableInstallFunction = BhyveInstallAcpiTable;
+
+ //
+ // set FwVol (and use an ASSERT() below) to suppress incorrect
+ // compiler/analyzer warnings
+ //
+ FwVol = NULL;
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateFvInstanceWithTables (&FwVol);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ ASSERT (FwVol != NULL);
+
+ //
+ // Read tables from the storage file.
+ //
+ while (Status == EFI_SUCCESS) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID**) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+
+ TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
+ ASSERT (Size >= TableSize);
+
+ //
+ // Install ACPI table
+ //
+ Status = TableInstallFunction (
+ AcpiTable,
+ CurrentTable,
+ TableSize,
+ &TableHandle
+ );
+
+ //
+ // Free memory allocated by ReadSection
+ //
+ gBS->FreePool (CurrentTable);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Effective entrypoint of Acpi Platform driver.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+InstallAcpiTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = InstallOvmfFvTables (AcpiTable);
+
+ return Status;
+}
+
diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
new file mode 100644
index 0000000000..d30cd11a1d
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
@@ -0,0 +1,77 @@
+/** @file
+ Sample ACPI Platform Driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ACPI_PLATFORM_H_INCLUDED_
+#define _ACPI_PLATFORM_H_INCLUDED_
+
+#include <PiDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/XenPlatformLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+typedef struct {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 PciAttributes;
+} ORIGINAL_ATTRIBUTES;
+
+typedef struct S3_CONTEXT S3_CONTEXT;
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ );
+
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable(
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ );
+
+EFI_STATUS
+EFIAPI
+InstallXenTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
+ );
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
+ );
+
+VOID
+EnablePciDecoding (
+ OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+ OUT UINTN *Count
+ );
+
+VOID
+RestorePciDecoding (
+ IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+ IN UINTN Count
+ );
+
+#endif
+
diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..bc52fa5e2f
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,65 @@
+## @file
+# OVMF ACPI Platform Driver
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = D5F92408-BAB5-44CA-8A60-C212F01D7E9D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ AcpiPlatform.c
+ AcpiPlatform.h
+ EntryPoint.c
+ PciDecoding.c
+ Bhyve.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ PcdLib
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BhyveFwCtlLib
+ MemoryAllocationLib
+ BaseLib
+ DxeServicesTableLib
+ OrderedCollectionLib
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+ gRootBridgesConnectedEventGroupGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
diff --git a/BhyvePkg/AcpiPlatformDxe/Bhyve.c b/BhyvePkg/AcpiPlatformDxe/Bhyve.c
new file mode 100644
index 0000000000..6d42264b65
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/Bhyve.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ * Copyright (C) 2012, Red Hat, Inc.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+#include "AcpiPlatform.h"
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BhyveFwCtlLib.h>
+
+STATIC
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiMadtTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ UINT32 CpuCount;
+ UINTN cSize;
+ UINTN NewBufferSize;
+ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
+ EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
+ EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic;
+ EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso;
+ VOID *Ptr;
+ UINTN Loop;
+ EFI_STATUS Status;
+
+ ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+
+ // Query the host for the number of vCPUs
+ CpuCount = 0;
+ cSize = sizeof(CpuCount);
+ if (BhyveFwCtlGet ("hw.ncpu", &CpuCount, &cSize) == RETURN_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "Retrieved CpuCount %d\n", CpuCount));
+ ASSERT (CpuCount >= 1);
+ } else {
+ DEBUG ((DEBUG_INFO, "CpuCount retrieval error\n"));
+ CpuCount = 1;
+ }
+
+ NewBufferSize = 1 * sizeof (*Madt) +
+ CpuCount * sizeof (*LocalApic) +
+ 1 * sizeof (*IoApic) +
+ 1 * sizeof (*Iso);
+
+ Madt = AllocatePool (NewBufferSize);
+ if (Madt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+ Madt->Header.Length = (UINT32) NewBufferSize;
+ Madt->LocalApicAddress = 0xFEE00000;
+ Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT;
+ Ptr = Madt + 1;
+
+ LocalApic = Ptr;
+ for (Loop = 0; Loop < CpuCount; ++Loop) {
+ LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
+ LocalApic->Length = sizeof (*LocalApic);
+ LocalApic->AcpiProcessorId = (UINT8) Loop;
+ LocalApic->ApicId = (UINT8) Loop;
+ LocalApic->Flags = 1; // enabled
+ ++LocalApic;
+ }
+ Ptr = LocalApic;
+
+ IoApic = Ptr;
+ IoApic->Type = EFI_ACPI_1_0_IO_APIC;
+ IoApic->Length = sizeof (*IoApic);
+ IoApic->IoApicId = (UINT8) CpuCount;
+ IoApic->Reserved = EFI_ACPI_RESERVED_BYTE;
+ IoApic->IoApicAddress = 0xFEC00000;
+ IoApic->SystemVectorBase = 0x00000000;
+ Ptr = IoApic + 1;
+
+ //
+ // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
+ //
+ Iso = Ptr;
+ Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
+ Iso->Length = sizeof (*Iso);
+ Iso->Bus = 0x00; // ISA
+ Iso->Source = 0x00; // IRQ0
+ Iso->GlobalSystemInterruptVector = 0x00000002;
+ Iso->Flags = 0x0000; // Conforms to specs of the bus
+ Ptr = Iso + 1;
+
+ ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize);
+ Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);
+
+ FreePool (Madt);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER *Hdr;
+ EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
+
+ Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;
+ switch (Hdr->Signature) {
+ case EFI_ACPI_1_0_APIC_SIGNATURE:
+ TableInstallFunction = BhyveInstallAcpiMadtTable;
+ break;
+ default:
+ TableInstallFunction = InstallAcpiTable;
+ }
+
+ return TableInstallFunction (
+ AcpiProtocol,
+ AcpiTableBuffer,
+ AcpiTableBufferSize,
+ TableKey
+ );
+}
diff --git a/BhyvePkg/AcpiPlatformDxe/EntryPoint.c b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c
new file mode 100644
index 0000000000..f66f892911
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c
@@ -0,0 +1,90 @@
+/** @file
+ Entry point of OVMF ACPI Platform Driver
+
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include "AcpiPlatform.h"
+
+STATIC
+EFI_ACPI_TABLE_PROTOCOL *
+FindAcpiTableProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID**)&AcpiTable
+ );
+ ASSERT_EFI_ERROR (Status);
+ return AcpiTable;
+}
+
+
+STATIC
+VOID
+EFIAPI
+OnRootBridgesConnected (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO,
+ "%a: root bridges have been connected, installing ACPI tables\n",
+ __FUNCTION__));
+ Status = InstallAcpiTables (FindAcpiTableProtocol ());
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: InstallAcpiTables: %r\n", __FUNCTION__, Status));
+ }
+ gBS->CloseEvent (Event);
+}
+
+
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT RootBridgesConnected;
+
+ //
+ // If the platform doesn't support PCI, or PCI enumeration has been disabled,
+ // install the tables at once, and let the entry point's return code reflect
+ // the full functionality.
+ //
+ if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+ DEBUG ((DEBUG_INFO, "%a: PCI or its enumeration disabled, installing "
+ "ACPI tables\n", __FUNCTION__));
+ return InstallAcpiTables (FindAcpiTableProtocol ());
+ }
+
+ //
+ // Otherwise, delay installing the ACPI tables until root bridges are
+ // connected. The entry point's return status will only reflect the callback
+ // setup. (Note that we're a DXE_DRIVER; our entry point function is invoked
+ // strictly before BDS is entered and can connect the root bridges.)
+ //
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ OnRootBridgesConnected, NULL /* Context */,
+ &gRootBridgesConnectedEventGroupGuid, &RootBridgesConnected);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO,
+ "%a: waiting for root bridges to be connected, registered callback\n",
+ __FUNCTION__));
+ }
+
+ return Status;
+}
diff --git a/BhyvePkg/AcpiPlatformDxe/PciDecoding.c b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c
new file mode 100644
index 0000000000..73894106c9
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c
@@ -0,0 +1,192 @@
+/** @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/MemoryAllocationLib.h>
+
+#include "AcpiPlatform.h"
+
+
+/**
+ 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", __FUNCTION__,
+ Status));
+ return;
+ }
+
+ OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
+ if (OrigAttrs == NULL) {
+ DEBUG ((DEBUG_WARN, "%a: AllocatePool(): out of resources\n",
+ __FUNCTION__));
+ 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",
+ __FUNCTION__, Status));
+ goto RestoreAttributes;
+ }
+
+ //
+ // Retrieve supported attributes
+ //
+ Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0,
+ &Attributes);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n",
+ __FUNCTION__, 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",
+ __FUNCTION__, 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);
+}
--
2.25.1
prev parent reply other threads:[~2020-04-24 18:29 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-24 18:29 [PATCH v4 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
2020-04-24 18:29 ` [PATCH v4 1/6] OvmfPkg: Add bhyve support into AcpiTimerLib Rebecca Cran
2020-04-24 18:29 ` [PATCH v4 2/6] OvmfPkg: Add QemuFwCfgLibNull Rebecca Cran
2020-04-27 9:03 ` [edk2-devel] " Philippe Mathieu-Daudé
2020-04-27 17:33 ` Rebecca Cran
2020-04-28 11:27 ` Philippe Mathieu-Daudé
2020-04-28 16:12 ` Rebecca Cran
2020-04-24 18:29 ` [PATCH v4 3/6] OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h Rebecca Cran
2020-04-24 18:29 ` [PATCH v4 4/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
2020-04-24 18:29 ` [PATCH v4 5/6] BhyvePkg: Add PlatformPei Rebecca Cran
2020-04-24 18:29 ` Rebecca Cran [this message]
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-list 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=20200424182914.138915-7-rebecca@bsdio.com \
--to=devel@edk2.groups.io \
/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