Add BhyvePkg, to support the bhyve hypervisor
BhyvePkg supports the bhyve hypervisor, which is a hypervisor/virtual machine manager available on FreeBSD, macOS and Illumos. Signed-off-by: Rebecca Cran <rebecca@bsdio.com> Message-Id: <20200713054131.479627-2-rebecca@bsdio.com> Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
137c2c6eff
commit
656419f922
251
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
Normal file
251
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
Normal file
@@ -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;
|
||||
}
|
||||
|
77
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
Normal file
77
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
Normal file
@@ -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
|
||||
|
65
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
Normal file
65
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
Normal file
@@ -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
|
||||
OvmfPkg/Bhyve/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
|
132
OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
Normal file
132
OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
Normal file
@@ -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
|
||||
);
|
||||
}
|
90
OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c
Normal file
90
OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c
Normal file
@@ -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;
|
||||
}
|
192
OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c
Normal file
192
OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c
Normal file
@@ -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);
|
||||
}
|
Reference in New Issue
Block a user