From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out02.mta.xmission.com (out02.mta.xmission.com [166.70.13.232]) by mx.groups.io with SMTP id smtpd.web11.1500.1587434702062472609 for ; Mon, 20 Apr 2020 19:05:02 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: bsdio.com, ip: 166.70.13.232, mailfrom: rebecca@bsdio.com) Received: from in01.mta.xmission.com ([166.70.13.51]) by out02.mta.xmission.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jQiHU-0004E0-Vn; Mon, 20 Apr 2020 20:05:01 -0600 Received: from mta4.zcs.xmission.com ([166.70.13.68]) by in01.mta.xmission.com with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.87) (envelope-from ) id 1jQiHS-0008Mx-Ki; Mon, 20 Apr 2020 20:05:00 -0600 Received: from localhost (localhost [127.0.0.1]) by mta4.zcs.xmission.com (Postfix) with ESMTP id 6AAFD5003C6; Mon, 20 Apr 2020 20:04:58 -0600 (MDT) X-Amavis-Modified: Mail body modified (using disclaimer) - mta4.zcs.xmission.com Received: from mta4.zcs.xmission.com ([127.0.0.1]) by localhost (mta4.zcs.xmission.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id tDKQSC4YCGd8; Mon, 20 Apr 2020 20:04:58 -0600 (MDT) Received: from photon.int.bluestop.org (muon.bluestop.org [65.103.231.193]) by mta4.zcs.xmission.com (Postfix) with ESMTPSA id C1B80500324; Mon, 20 Apr 2020 20:04:57 -0600 (MDT) From: "Rebecca Cran" To: devel@edk2.groups.io Cc: Jordan Justen , Laszlo Ersek , Ard Biesheuvel , Leif Lindholm , Michael Kinney , Andrew Fish , Rebecca Cran Date: Mon, 20 Apr 2020 20:04:40 -0600 Message-Id: <20200421020441.34175-8-rebecca@bsdio.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200421020441.34175-1-rebecca@bsdio.com> References: <20200421020441.34175-1-rebecca@bsdio.com> MIME-Version: 1.0 X-XM-SPF: eid=1jQiHS-0008Mx-Ki;;;mid=<20200421020441.34175-8-rebecca@bsdio.com>;;;hst=in01.mta.xmission.com;;;ip=166.70.13.68;;;frm=rebecca@bsdio.com;;;spf=pass X-SA-Exim-Connect-IP: 166.70.13.68 X-SA-Exim-Mail-From: rebecca@bsdio.com X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on sa06.xmission.com X-Spam-Level: * X-Spam-Status: No, score=1.4 required=8.0 tests=ALL_TRUSTED,BAYES_50, DCC_CHECK_NEGATIVE,FVGT_m_MULTI_ODD,LotsOfNums_01 autolearn=disabled version=3.4.2 X-Spam-Report: * -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP * 0.8 BAYES_50 BODY: Bayes spam probability is 40 to 60% * [score: 0.5000] * 1.2 LotsOfNums_01 BODY: Lots of long strings of numbers * -0.0 DCC_CHECK_NEGATIVE Not listed in DCC * [sa06 1397; IP=ok Body=1 Fuz1=1] [Fuz2=1] * 0.4 FVGT_m_MULTI_ODD Contains multiple odd letter combinations X-Spam-DCC: XMission; sa06 1397; IP=ok Body=1 Fuz1=1 Fuz2=1 X-Spam-Combo: *;devel@edk2.groups.io X-Spam-Relay-Country: X-Spam-Timing: total 1615 ms - load_scoreonly_sql: 0.06 (0.0%), signal_user_changed: 12 (0.7%), b_tie_ro: 10 (0.6%), parse: 3.6 (0.2%), extract_message_metadata: 28 (1.7%), get_uri_detail_list: 13 (0.8%), tests_pri_-1000: 23 (1.4%), tests_pri_-950: 1.23 (0.1%), tests_pri_-900: 1.03 (0.1%), tests_pri_-90: 152 (9.4%), check_bayes: 150 (9.3%), b_tokenize: 58 (3.6%), b_tok_get_all: 24 (1.5%), b_comp_prob: 8 (0.5%), b_tok_touch_all: 54 (3.4%), b_finish: 1.55 (0.1%), tests_pri_0: 1372 (85.0%), check_dkim_signature: 1.65 (0.1%), check_dkim_adsp: 3.4 (0.2%), poll_dns_idle: 0.59 (0.0%), tests_pri_10: 2.2 (0.1%), tests_pri_500: 13 (0.8%), rewrite_mail: 0.00 (0.0%) Subject: [PATCH v2 7/8] BhyvePkg: Add AcpiPlatformDxe X-Spam-Flag: No X-SA-Exim-Version: 4.2.1 (built Thu, 05 May 2016 13:38:54 -0600) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Content-Transfer-Encoding: 8bit Make a copy of OvmfPkg/AcpiPlatformDxe under BhyvePkg, with the changes needed to support the bhyve hypervisor. Signed-off-by: Rebecca Cran --- BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c | 250 +++++++++++++++++++ BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h | 76 ++++++ BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 64 +++++ BhyvePkg/AcpiPlatformDxe/Bhyve.c | 138 ++++++++++ BhyvePkg/AcpiPlatformDxe/EntryPoint.c | 90 +++++++ BhyvePkg/AcpiPlatformDxe/PciDecoding.c | 192 ++++++++++++++ OvmfPkg/AcpiPlatformDxe/AcpiPlatform.c | 8 +- OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h | 9 + OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 3 + OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/OvmfXen.dsc | 1 + 13 files changed, 831 insertions(+), 3 deletions(-) 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 000000000000..4814a9f1e6cf --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c @@ -0,0 +1,250 @@ +/** @file + OVMF ACPI Platform Driver + + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ 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 000000000000..157ff42c07cf --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h @@ -0,0 +1,76 @@ +/** @file + Sample ACPI Platform Driver + + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ACPI_PLATFORM_H_INCLUDED_ +#define _ACPI_PLATFORM_H_INCLUDED_ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +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 000000000000..6e931d85c058 --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -0,0 +1,64 @@ +## @file +# OVMF ACPI Platform Driver +# +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause +## + +[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 000000000000..7f1a5fd66492 --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/Bhyve.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ * Copyright (C) 2012, Red Hat, Inc. + * Copyright (c) 2014, Pluribus Networks, Inc. + * + * This program and the accompanying materials are licensed and made + * available under the terms and conditions of the BSD License which + * accompanies this distribution. The full text of the license may be + * found at http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" + * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER + * EXPRESS OR IMPLIED. + */ +#include "AcpiPlatform.h" + +#include +#include +#include + +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 000000000000..f66f89291157 --- /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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#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 000000000000..73894106c9ec --- /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 + +#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); +} diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.c index f872d91aea72..5f501c38bf8e 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.c +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.c @@ -157,8 +157,10 @@ InstallOvmfFvTables ( if (QemuDetected ()) { TableInstallFunction = QemuInstallAcpiTable; - } else { + } else if (XenDetected()) { TableInstallFunction = InstallAcpiTable; + } else { + TableInstallFunction = BhyveInstallAcpiTable; } // @@ -245,11 +247,11 @@ InstallAcpiTables ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable ) { - EFI_STATUS Status; + EFI_STATUS Status = EFI_UNSUPPORTED; if (XenDetected ()) { Status = InstallXenTables (AcpiTable); - } else { + } else if (QemuDetected()) { Status = InstallQemuFwCfgTables (AcpiTable); } diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h index 9597e028e4a7..160a541aeed8 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatform.h @@ -53,6 +53,15 @@ QemuInstallAcpiTable ( 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 ( diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf index e486b8afa56d..f3b5ab413be7 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -30,11 +30,13 @@ [Sources] QemuFwCfgAcpi.c QemuLoader.h Xen.c + Bhyve.c [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec OvmfPkg/OvmfPkg.dec + BhyvePkg/BhyvePkg.dec UefiCpuPkg/UefiCpuPkg.dec [LibraryClasses] @@ -46,6 +48,7 @@ [LibraryClasses] UefiDriverEntryPoint QemuFwCfgLib QemuFwCfgS3Lib + BhyveFwCtlLib MemoryAllocationLib BaseLib DxeServicesTableLib diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index cbc5f0e583bc..3dd41e4f1c4a 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -159,6 +159,7 @@ [LibraryClasses] UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + BhyveFwCtlLib|BhyvePkg/Library/BhyveFwCtlLibNull/BhyveFwCtlLibNull.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 6d69cc6cb56f..d246a96a1b2e 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -163,6 +163,7 @@ [LibraryClasses] UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + BhyveFwCtlLib|BhyvePkg/Library/BhyveFwCtlLibNull/BhyveFwCtlLibNull.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 5ad4f461ce52..ff030ee502b5 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -163,6 +163,7 @@ [LibraryClasses] UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + BhyveFwCtlLib|BhyvePkg/Library/BhyveFwCtlLibNull/BhyveFwCtlLibNull.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc index 47ee8db8b884..b12abaeb0d51 100644 --- a/OvmfPkg/OvmfXen.dsc +++ b/OvmfPkg/OvmfXen.dsc @@ -155,6 +155,7 @@ [LibraryClasses] UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + BhyveFwCtlLib|BhyvePkg/Library/BhyveFwCtlLibNull/BhyveFwCtlLibNull.inf QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf -- 2.20.1