Date: Fri, 31 Mar 2023 14:59:33 +0200 From: Mario Marietto <marietto2008@gmail.com> To: =?UTF-8?Q?Corvin_K=C3=B6hne?= <corvink@freebsd.org> Cc: virtualization@freebsd.org Subject: Re: [PATCH] OvmfPkg/BhyveBhf: install bhyve's ACPI tables Message-ID: <CA%2B1FSiggd8Z8VEC=KGhV7wkBiWH1rtJdNTAm8nq71Q-3HgOHsQ@mail.gmail.com> In-Reply-To: <20230331123936.540020-1-corvink@FreeBSD.org>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
Hello Corvin.
I will try your patch very soon if you want to write carefully all the
commands that I should issue. Thanks.
On Fri, Mar 31, 2023 at 2:40 PM Corvin Köhne <corvink@freebsd.org> wrote:
> Hi,
>
> I would like to send the following patch to the EDKII project.
> Therefore, I'd like to get some feedback from the bhyve community before
> sending them to EDKII.
>
> At the moment, UEFI guests are using static ACPI tables. Modifying them
> is not easy because we need to patch them in the EDKII repo.
> Additionally, ACPI tables should be configuration dependent. If one
> assigns a TPM device to one guest, this guest requires different ACPI
> tables than other guests.
>
> Bhyve already builds it own set of ACPI tables. This patch picks them up
> an installs them in the UEFI guest. This will overcome the mentioned
> limitations.
>
> Note that this patch is required to easily implement features like
> qemu's fwcfg or a tpm device emulation.
>
> Here's the patch:
>
> It's much easier to create configuration dependend ACPI tables for bhyve
> than for OVMF. For this reason, don't use the statically created ACPI
> tables provided by OVMF. Instead prefer the dynamically created ACPI
> tables of bhyve. If bhyve provides no ACPI tables or we are unable to
> detect those, fall back to OVMF tables.
>
> Implementation is similar to OvmfPkg/XenAcpiPlatformDxe/Xen.c.
> ---
> MdePkg/Include/Uefi/UefiBaseType.h | 2 +
> OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c | 15 ++
> OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h | 6 +
> OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c | 266 +++++++++++++++++++
> 4 files changed, 289 insertions(+)
>
> diff --git a/MdePkg/Include/Uefi/UefiBaseType.h
> b/MdePkg/Include/Uefi/UefiBaseType.h
> index 83975a08eb..b18a0760ee 100644
> --- a/MdePkg/Include/Uefi/UefiBaseType.h
> +++ b/MdePkg/Include/Uefi/UefiBaseType.h
> @@ -54,6 +54,8 @@ typedef UINT64 EFI_PHYSICAL_ADDRESS;
> ///
> typedef UINT64 EFI_VIRTUAL_ADDRESS;
>
> +#define NUMERIC_VALUE_AS_POINTER(Type, Value) ((Type *) ((UINTN)(Value)))
> +
> ///
> /// EFI Time Abstraction:
> /// Year: 1900 - 9999
> diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> index 999e9f151e..34d9fc80d0 100644
> --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> @@ -243,6 +243,21 @@ InstallAcpiTables (
> {
> EFI_STATUS Status;
>
> + Status = InstallBhyveTables (AcpiTable);
> + if (!EFI_ERROR (Status)) {
> + return EFI_SUCCESS;
> + }
> +
> + if (Status != EFI_NOT_FOUND) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: unable to install bhyve's ACPI tables (%r)\n",
> + __FUNCTION__,
> + Status
> + ));
> + return Status;
> + }
> +
> Status = InstallOvmfFvTables (AcpiTable);
>
> return Status;
> diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
> b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
> index 54d1af073e..b2724135d0 100644
> --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
> +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
> @@ -46,6 +46,12 @@ BhyveInstallAcpiTable (
> OUT UINTN *TableKey
> );
>
> +EFI_STATUS
> +EFIAPI
> +InstallBhyveTables (
> + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
> + );
> +
> EFI_STATUS
> EFIAPI
> InstallXenTables (
> diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
> b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
> index e216a21bfa..5e1b759c01 100644
> --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
> +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
> @@ -13,6 +13,18 @@
> #include <Library/MemoryAllocationLib.h>
> #include <Library/QemuFwCfgLib.h> // QemuFwCfgFindFile()
>
> +#define BHYVE_ACPI_PHYSICAL_ADDRESS ((UINTN)0x000F2400)
> +#define BHYVE_BIOS_PHYSICAL_END ((UINTN)0x00100000)
> +
> +#pragma pack (1)
> +
> +typedef struct {
> + EFI_ACPI_DESCRIPTION_HEADER Header;
> + UINT64 Tables[0];
> +} EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE;
> +
> +#pragma pack ()
> +
> STATIC
> EFI_STATUS
> EFIAPI
> @@ -164,3 +176,257 @@ BhyveInstallAcpiTable (
> TableKey
> );
> }
> +
> +/**
> + Get the address of bhyve's ACPI Root System Description Pointer (RSDP).
> +
> + @param RsdpPtr Return pointer to RSDP.
> +
> + @return EFI_SUCCESS Bhyve's RSDP successfully found.
> + @return EFI_NOT_FOUND Couldn't find bhyve's RSDP.
> + @return EFI_UNSUPPORTED Revision is lower than 2.
> + @return EFI_PROTOCOL_ERROR Invalid RSDP found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +BhyveGetAcpiRsdp (
> + OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
> + )
> +{
> + UINTN RsdpAddress;
> + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
> +
> + if (RsdpPtr == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Detect the RSDP
> + //
> + for (RsdpAddress = BHYVE_ACPI_PHYSICAL_ADDRESS;
> + RsdpAddress < BHYVE_BIOS_PHYSICAL_END;
> + RsdpAddress += 0x10)
> + {
> + Rsdp = NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
> + RsdpAddress
> + );
> + if (Rsdp->Signature !=
> EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
> + continue;
> + }
> +
> + if (Rsdp->Revision < 2) {
> + DEBUG ((DEBUG_INFO, "%a: unsupported RSDP found\n", __FUNCTION__));
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // For ACPI 1.0/2.0/3.0 the checksum of first 20 bytes should be 0.
> + // For ACPI 2.0/3.0 the checksum of the entire table should be 0.
> + //
> + UINT8 Sum = CalculateCheckSum8 (
> + (CONST UINT8 *)Rsdp,
> + sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
> + );
> + if (Sum != 0) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: RSDP header checksum not valid: 0x%02x\n",
> + __FUNCTION__,
> + Sum
> + ));
> + return EFI_PROTOCOL_ERROR;
> + }
> +
> + Sum = CalculateCheckSum8 (
> + (CONST UINT8 *)Rsdp,
> + sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
> + );
> + if (Sum != 0) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: RSDP table checksum not valid: 0x%02x\n",
> + __FUNCTION__,
> + Sum
> + ));
> + return EFI_PROTOCOL_ERROR;
> + }
> +
> + //
> + // RSDP was found and is valid
> + //
> + *RsdpPtr = Rsdp;
> +
> + return EFI_SUCCESS;
> + }
> +
> + DEBUG ((DEBUG_INFO, "%a: RSDP not found\n", __FUNCTION__));
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Get bhyve's ACPI tables from the RSDP. And install bhyve's ACPI tables
> + into the RSDT/XSDT using InstallAcpiTable.
> +
> + @param AcpiProtocol Protocol instance pointer.
> +
> + @return EFI_SUCCESS All tables were successfully inserted.
> + @return EFI_UNSUPPORTED Bhyve's ACPI tables doesn't include a XSDT.
> + @return EFI_PROTOCOL_ERROR Invalid XSDT found.
> +
> + @return Error codes propagated from underlying
> functions.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallBhyveTables (
> + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
> + )
> +{
> + EFI_STATUS Status;
> + UINTN TableHandle;
> + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
> + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
> + EFI_ACPI_DESCRIPTION_HEADER *Dsdt;
> +
> + Rsdp = NULL;
> + Facs = NULL;
> + Dsdt = NULL;
> +
> + //
> + // Try to find bhyve ACPI tables
> + //
> + Status = BhyveGetAcpiRsdp (&Rsdp);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_INFO, "%a: can't get RSDP (%r)\n", __FUNCTION__,
> Status));
> + return Status;
> + }
> +
> + //
> + // Bhyve should always provide a XSDT
> + //
> + EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE *CONST Xsdt =
> + NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE,
> + Rsdp->XsdtAddress
> + );
> +
> + if (Xsdt == NULL) {
> + DEBUG ((DEBUG_INFO, "%a: XSDT not found\n", __FUNCTION__));
> + return EFI_UNSUPPORTED;
> + }
> +
> + if (Xsdt->Header.Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
> + DEBUG ((DEBUG_INFO, "%a: invalid XSDT length\n", __FUNCTION__));
> + return EFI_PROTOCOL_ERROR;
> + }
> +
> + //
> + // Install ACPI tables
> + //
> + CONST UINTN NumberOfTableEntries =
> + (Xsdt->Header.Length - sizeof (Xsdt->Header)) / sizeof (UINT64);
> +
> + for (UINTN Index = 0; Index < NumberOfTableEntries; Index++) {
> + EFI_ACPI_DESCRIPTION_HEADER *CONST CurrentTable =
> + NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_DESCRIPTION_HEADER,
> + Xsdt->Tables[Index]
> + );
> + Status = AcpiProtocol->InstallAcpiTable (
> + AcpiProtocol,
> + CurrentTable,
> + CurrentTable->Length,
> + &TableHandle
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: failed to install ACPI table %c%c%c%c (%r)\n",
> + __FUNCTION__,
> + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[0],
> + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[1],
> + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[2],
> + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[3],
> + Status
> + ));
> + return Status;
> + }
> +
> + if (CurrentTable->Signature ==
> EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
> + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *CONST Fadt =
> + (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *CONST)CurrentTable;
> + if (Fadt->XFirmwareCtrl) {
> + Facs = NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE,
> + Fadt->XFirmwareCtrl
> + );
> + } else {
> + Facs = NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE,
> + Fadt->FirmwareCtrl
> + );
> + }
> +
> + if (Fadt->XDsdt) {
> + Dsdt = NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_DESCRIPTION_HEADER,
> + Fadt->XDsdt
> + );
> + } else {
> + Dsdt = NUMERIC_VALUE_AS_POINTER (
> + EFI_ACPI_DESCRIPTION_HEADER,
> + Fadt->Dsdt
> + );
> + }
> + }
> + }
> +
> + //
> + // Install FACS
> + //
> + if (Facs != NULL) {
> + Status = AcpiProtocol->InstallAcpiTable (
> + AcpiProtocol,
> + Facs,
> + Facs->Length,
> + &TableHandle
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: failed to install FACS (%r)\n",
> + __FUNCTION__,
> + Status
> + ));
> + return Status;
> + }
> + }
> +
> + //
> + // Install DSDT
> + // If it's not found, something bad happened. Don't continue execution.
> + //
> + if (Dsdt == NULL) {
> + DEBUG ((DEBUG_ERROR, "%a: failed to find DSDT\n", __FUNCTION__));
> + CpuDeadLoop ();
> + }
> +
> + Status = AcpiProtocol->InstallAcpiTable (
> + AcpiProtocol,
> + Dsdt,
> + Dsdt->Length,
> + &TableHandle
> + );
> + if (EFI_ERROR (Status)) {
> + DEBUG ((
> + DEBUG_INFO,
> + "%a: failed to install DSDT (%r)\n",
> + __FUNCTION__,
> + Status
> + ));
> + return Status;
> + }
> +
> + return EFI_SUCCESS;
> +}
> --
> 2.40.0
>
>
>
--
Mario.
[-- Attachment #2 --]
<div dir="ltr"><div>Hello Corvin.</div><div><br></div><div>I will try your patch very soon if you want to write carefully all the commands that I should issue. Thanks.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 31, 2023 at 2:40 PM Corvin Köhne <<a href="mailto:corvink@freebsd.org">corvink@freebsd.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
I would like to send the following patch to the EDKII project.<br>
Therefore, I'd like to get some feedback from the bhyve community before<br>
sending them to EDKII.<br>
<br>
At the moment, UEFI guests are using static ACPI tables. Modifying them<br>
is not easy because we need to patch them in the EDKII repo.<br>
Additionally, ACPI tables should be configuration dependent. If one<br>
assigns a TPM device to one guest, this guest requires different ACPI<br>
tables than other guests.<br>
<br>
Bhyve already builds it own set of ACPI tables. This patch picks them up<br>
an installs them in the UEFI guest. This will overcome the mentioned<br>
limitations.<br>
<br>
Note that this patch is required to easily implement features like<br>
qemu's fwcfg or a tpm device emulation.<br>
<br>
Here's the patch:<br>
<br>
It's much easier to create configuration dependend ACPI tables for bhyve<br>
than for OVMF. For this reason, don't use the statically created ACPI<br>
tables provided by OVMF. Instead prefer the dynamically created ACPI<br>
tables of bhyve. If bhyve provides no ACPI tables or we are unable to<br>
detect those, fall back to OVMF tables.<br>
<br>
Implementation is similar to OvmfPkg/XenAcpiPlatformDxe/Xen.c.<br>
---<br>
MdePkg/Include/Uefi/UefiBaseType.h | 2 +<br>
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c | 15 ++<br>
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h | 6 +<br>
OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c | 266 +++++++++++++++++++<br>
4 files changed, 289 insertions(+)<br>
<br>
diff --git a/MdePkg/Include/Uefi/UefiBaseType.h b/MdePkg/Include/Uefi/UefiBaseType.h<br>
index 83975a08eb..b18a0760ee 100644<br>
--- a/MdePkg/Include/Uefi/UefiBaseType.h<br>
+++ b/MdePkg/Include/Uefi/UefiBaseType.h<br>
@@ -54,6 +54,8 @@ typedef UINT64 EFI_PHYSICAL_ADDRESS;<br>
///<br>
typedef UINT64 EFI_VIRTUAL_ADDRESS;<br>
<br>
+#define NUMERIC_VALUE_AS_POINTER(Type, Value) ((Type *) ((UINTN)(Value)))<br>
+<br>
///<br>
/// EFI Time Abstraction:<br>
/// Year: 1900 - 9999<br>
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c<br>
index 999e9f151e..34d9fc80d0 100644<br>
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c<br>
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c<br>
@@ -243,6 +243,21 @@ InstallAcpiTables (<br>
{<br>
EFI_STATUS Status;<br>
<br>
+ Status = InstallBhyveTables (AcpiTable);<br>
+ if (!EFI_ERROR (Status)) {<br>
+ return EFI_SUCCESS;<br>
+ }<br>
+<br>
+ if (Status != EFI_NOT_FOUND) {<br>
+ DEBUG ((<br>
+ DEBUG_INFO,<br>
+ "%a: unable to install bhyve's ACPI tables (%r)\n",<br>
+ __FUNCTION__,<br>
+ Status<br>
+ ));<br>
+ return Status;<br>
+ }<br>
+<br>
Status = InstallOvmfFvTables (AcpiTable);<br>
<br>
return Status;<br>
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h<br>
index 54d1af073e..b2724135d0 100644<br>
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h<br>
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h<br>
@@ -46,6 +46,12 @@ BhyveInstallAcpiTable (<br>
OUT UINTN *TableKey<br>
);<br>
<br>
+EFI_STATUS<br>
+EFIAPI<br>
+InstallBhyveTables (<br>
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol<br>
+ );<br>
+<br>
EFI_STATUS<br>
EFIAPI<br>
InstallXenTables (<br>
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c<br>
index e216a21bfa..5e1b759c01 100644<br>
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c<br>
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c<br>
@@ -13,6 +13,18 @@<br>
#include <Library/MemoryAllocationLib.h><br>
#include <Library/QemuFwCfgLib.h> // QemuFwCfgFindFile()<br>
<br>
+#define BHYVE_ACPI_PHYSICAL_ADDRESS ((UINTN)0x000F2400)<br>
+#define BHYVE_BIOS_PHYSICAL_END ((UINTN)0x00100000)<br>
+<br>
+#pragma pack (1)<br>
+<br>
+typedef struct {<br>
+ EFI_ACPI_DESCRIPTION_HEADER Header;<br>
+ UINT64 Tables[0];<br>
+} EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE;<br>
+<br>
+#pragma pack ()<br>
+<br>
STATIC<br>
EFI_STATUS<br>
EFIAPI<br>
@@ -164,3 +176,257 @@ BhyveInstallAcpiTable (<br>
TableKey<br>
);<br>
}<br>
+<br>
+/**<br>
+ Get the address of bhyve's ACPI Root System Description Pointer (RSDP).<br>
+<br>
+ @param RsdpPtr Return pointer to RSDP.<br>
+<br>
+ @return EFI_SUCCESS Bhyve's RSDP successfully found.<br>
+ @return EFI_NOT_FOUND Couldn't find bhyve's RSDP.<br>
+ @return EFI_UNSUPPORTED Revision is lower than 2.<br>
+ @return EFI_PROTOCOL_ERROR Invalid RSDP found.<br>
+<br>
+**/<br>
+EFI_STATUS<br>
+EFIAPI<br>
+BhyveGetAcpiRsdp (<br>
+ OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr<br>
+ )<br>
+{<br>
+ UINTN RsdpAddress;<br>
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;<br>
+<br>
+ if (RsdpPtr == NULL) {<br>
+ return EFI_INVALID_PARAMETER;<br>
+ }<br>
+<br>
+ //<br>
+ // Detect the RSDP<br>
+ //<br>
+ for (RsdpAddress = BHYVE_ACPI_PHYSICAL_ADDRESS;<br>
+ RsdpAddress < BHYVE_BIOS_PHYSICAL_END;<br>
+ RsdpAddress += 0x10)<br>
+ {<br>
+ Rsdp = NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER,<br>
+ RsdpAddress<br>
+ );<br>
+ if (Rsdp->Signature != EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {<br>
+ continue;<br>
+ }<br>
+<br>
+ if (Rsdp->Revision < 2) {<br>
+ DEBUG ((DEBUG_INFO, "%a: unsupported RSDP found\n", __FUNCTION__));<br>
+ return EFI_UNSUPPORTED;<br>
+ }<br>
+<br>
+ //<br>
+ // For ACPI 1.0/2.0/3.0 the checksum of first 20 bytes should be 0.<br>
+ // For ACPI 2.0/3.0 the checksum of the entire table should be 0.<br>
+ //<br>
+ UINT8 Sum = CalculateCheckSum8 (<br>
+ (CONST UINT8 *)Rsdp,<br>
+ sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)<br>
+ );<br>
+ if (Sum != 0) {<br>
+ DEBUG ((<br>
+ DEBUG_INFO,<br>
+ "%a: RSDP header checksum not valid: 0x%02x\n",<br>
+ __FUNCTION__,<br>
+ Sum<br>
+ ));<br>
+ return EFI_PROTOCOL_ERROR;<br>
+ }<br>
+<br>
+ Sum = CalculateCheckSum8 (<br>
+ (CONST UINT8 *)Rsdp,<br>
+ sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)<br>
+ );<br>
+ if (Sum != 0) {<br>
+ DEBUG ((<br>
+ DEBUG_INFO,<br>
+ "%a: RSDP table checksum not valid: 0x%02x\n",<br>
+ __FUNCTION__,<br>
+ Sum<br>
+ ));<br>
+ return EFI_PROTOCOL_ERROR;<br>
+ }<br>
+<br>
+ //<br>
+ // RSDP was found and is valid<br>
+ //<br>
+ *RsdpPtr = Rsdp;<br>
+<br>
+ return EFI_SUCCESS;<br>
+ }<br>
+<br>
+ DEBUG ((DEBUG_INFO, "%a: RSDP not found\n", __FUNCTION__));<br>
+ return EFI_NOT_FOUND;<br>
+}<br>
+<br>
+/**<br>
+ Get bhyve's ACPI tables from the RSDP. And install bhyve's ACPI tables<br>
+ into the RSDT/XSDT using InstallAcpiTable.<br>
+<br>
+ @param AcpiProtocol Protocol instance pointer.<br>
+<br>
+ @return EFI_SUCCESS All tables were successfully inserted.<br>
+ @return EFI_UNSUPPORTED Bhyve's ACPI tables doesn't include a XSDT.<br>
+ @return EFI_PROTOCOL_ERROR Invalid XSDT found.<br>
+<br>
+ @return Error codes propagated from underlying functions.<br>
+**/<br>
+EFI_STATUS<br>
+EFIAPI<br>
+InstallBhyveTables (<br>
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol<br>
+ )<br>
+{<br>
+ EFI_STATUS Status;<br>
+ UINTN TableHandle;<br>
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;<br>
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;<br>
+ EFI_ACPI_DESCRIPTION_HEADER *Dsdt;<br>
+<br>
+ Rsdp = NULL;<br>
+ Facs = NULL;<br>
+ Dsdt = NULL;<br>
+<br>
+ //<br>
+ // Try to find bhyve ACPI tables<br>
+ //<br>
+ Status = BhyveGetAcpiRsdp (&Rsdp);<br>
+ if (EFI_ERROR (Status)) {<br>
+ DEBUG ((DEBUG_INFO, "%a: can't get RSDP (%r)\n", __FUNCTION__, Status));<br>
+ return Status;<br>
+ }<br>
+<br>
+ //<br>
+ // Bhyve should always provide a XSDT<br>
+ //<br>
+ EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE *CONST Xsdt =<br>
+ NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE,<br>
+ Rsdp->XsdtAddress<br>
+ );<br>
+<br>
+ if (Xsdt == NULL) {<br>
+ DEBUG ((DEBUG_INFO, "%a: XSDT not found\n", __FUNCTION__));<br>
+ return EFI_UNSUPPORTED;<br>
+ }<br>
+<br>
+ if (Xsdt->Header.Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {<br>
+ DEBUG ((DEBUG_INFO, "%a: invalid XSDT length\n", __FUNCTION__));<br>
+ return EFI_PROTOCOL_ERROR;<br>
+ }<br>
+<br>
+ //<br>
+ // Install ACPI tables<br>
+ //<br>
+ CONST UINTN NumberOfTableEntries =<br>
+ (Xsdt->Header.Length - sizeof (Xsdt->Header)) / sizeof (UINT64);<br>
+<br>
+ for (UINTN Index = 0; Index < NumberOfTableEntries; Index++) {<br>
+ EFI_ACPI_DESCRIPTION_HEADER *CONST CurrentTable =<br>
+ NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_DESCRIPTION_HEADER,<br>
+ Xsdt->Tables[Index]<br>
+ );<br>
+ Status = AcpiProtocol->InstallAcpiTable (<br>
+ AcpiProtocol,<br>
+ CurrentTable,<br>
+ CurrentTable->Length,<br>
+ &TableHandle<br>
+ );<br>
+ if (EFI_ERROR (Status)) {<br>
+ DEBUG ((<br>
+ DEBUG_INFO,<br>
+ "%a: failed to install ACPI table %c%c%c%c (%r)\n",<br>
+ __FUNCTION__,<br>
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[0],<br>
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[1],<br>
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[2],<br>
+ NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[3],<br>
+ Status<br>
+ ));<br>
+ return Status;<br>
+ }<br>
+<br>
+ if (CurrentTable->Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {<br>
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *CONST Fadt =<br>
+ (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *CONST)CurrentTable;<br>
+ if (Fadt->XFirmwareCtrl) {<br>
+ Facs = NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE,<br>
+ Fadt->XFirmwareCtrl<br>
+ );<br>
+ } else {<br>
+ Facs = NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE,<br>
+ Fadt->FirmwareCtrl<br>
+ );<br>
+ }<br>
+<br>
+ if (Fadt->XDsdt) {<br>
+ Dsdt = NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_DESCRIPTION_HEADER,<br>
+ Fadt->XDsdt<br>
+ );<br>
+ } else {<br>
+ Dsdt = NUMERIC_VALUE_AS_POINTER (<br>
+ EFI_ACPI_DESCRIPTION_HEADER,<br>
+ Fadt->Dsdt<br>
+ );<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ //<br>
+ // Install FACS<br>
+ //<br>
+ if (Facs != NULL) {<br>
+ Status = AcpiProtocol->InstallAcpiTable (<br>
+ AcpiProtocol,<br>
+ Facs,<br>
+ Facs->Length,<br>
+ &TableHandle<br>
+ );<br>
+ if (EFI_ERROR (Status)) {<br>
+ DEBUG ((<br>
+ DEBUG_INFO,<br>
+ "%a: failed to install FACS (%r)\n",<br>
+ __FUNCTION__,<br>
+ Status<br>
+ ));<br>
+ return Status;<br>
+ }<br>
+ }<br>
+<br>
+ //<br>
+ // Install DSDT<br>
+ // If it's not found, something bad happened. Don't continue execution.<br>
+ //<br>
+ if (Dsdt == NULL) {<br>
+ DEBUG ((DEBUG_ERROR, "%a: failed to find DSDT\n", __FUNCTION__));<br>
+ CpuDeadLoop ();<br>
+ }<br>
+<br>
+ Status = AcpiProtocol->InstallAcpiTable (<br>
+ AcpiProtocol,<br>
+ Dsdt,<br>
+ Dsdt->Length,<br>
+ &TableHandle<br>
+ );<br>
+ if (EFI_ERROR (Status)) {<br>
+ DEBUG ((<br>
+ DEBUG_INFO,<br>
+ "%a: failed to install DSDT (%r)\n",<br>
+ __FUNCTION__,<br>
+ Status<br>
+ ));<br>
+ return Status;<br>
+ }<br>
+<br>
+ return EFI_SUCCESS;<br>
+}<br>
-- <br>
2.40.0<br>
<br>
<br>
</blockquote></div><br clear="all"><br><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature">Mario.<br></div>
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CA%2B1FSiggd8Z8VEC=KGhV7wkBiWH1rtJdNTAm8nq71Q-3HgOHsQ>
