public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 1/1] OvmfPkg/BhyveBhf: install bhyve's ACPI tables
@ 2023-04-17 12:11 Corvin Köhne
  2023-05-03  2:32 ` [edk2-devel] " Rebecca Cran
  0 siblings, 1 reply; 2+ messages in thread
From: Corvin Köhne @ 2023-04-17 12:11 UTC (permalink / raw)
  To: devel
  Cc: Corvin Köhne, Michael D Kinney, Liming Gao, Zhiguang Liu,
	Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
	Rebecca Cran, Peter Grehan

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.

Ideally, we use the qemu fwcfg interface to pass the ACPI tables from
bhyve to OVMF. bhyve will support this in the future. However, current
bhyve executables don't support passing ACPI tables by the qemu fwcfg
interface. They just copy the ACPI into main memory. For that reason,
pick up the ACPI tables from main memory.

Implementation is similar to OvmfPkg/XenAcpiPlatformDxe/Xen.c.

Signed-off-by: Corvin Köhne <corvink@FreeBSD.org>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rebecca Cran <rebecca@bsdio.com>
Cc: Peter Grehan <grehan@freebsd.org>
---
 MdePkg/Include/Uefi/UefiBaseType.h           |   2 +
 OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h |   6 +
 OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c |  17 ++
 OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c        | 258 +++++++++++++++++++
 4 files changed, 283 insertions(+)

diff --git a/MdePkg/Include/Uefi/UefiBaseType.h b/MdePkg/Include/Uefi/UefiBaseType.h
index 83975a08eb4c..b18a0760ee61 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.h b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
index 54d1af073eab..b2724135d09f 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/AcpiPlatform.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
index 999e9f151ebb..6077d4d313a3 100644
--- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
@@ -243,6 +243,23 @@ InstallAcpiTables (
 {
   EFI_STATUS  Status;
 
+  Status = InstallBhyveTables (AcpiTable);
+  if (!EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  if (Status != EFI_NOT_FOUND) {
+    DEBUG (
+      (
+       DEBUG_WARN,
+       "%a: unable to install bhyve's ACPI tables (%r)\n",
+       __func__,
+       Status
+      )
+      );
+    return Status;
+  }
+
   Status = InstallOvmfFvTables (AcpiTable);
 
   return Status;
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
index e216a21bfaed..fa5e79bfe3b4 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,249 @@ BhyveInstallAcpiTable (
            TableKey
            );
 }
+
+/**
+  Get the address of bhyve's ACPI Root System Description Pointer (RSDP).
+
+  @param  RsdpPtr             Return pointer to RSDP.
+
+  @retval EFI_SUCCESS         Bhyve's RSDP successfully found.
+  @retval EFI_NOT_FOUND       Couldn't find bhyve's RSDP.
+  @retval EFI_UNSUPPORTED     Revision is lower than 2.
+  @retval 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;
+  UINT8                                         Sum;
+
+  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_WARN, "%a: unsupported RSDP found\n", __func__));
+      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.
+    //
+    Sum = CalculateCheckSum8 (
+            (CONST UINT8 *)Rsdp,
+            sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
+            );
+    if (Sum != 0) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: RSDP header checksum not valid: 0x%02x\n",
+        __func__,
+        Sum
+        ));
+      return EFI_PROTOCOL_ERROR;
+    }
+
+    Sum = CalculateCheckSum8 (
+            (CONST UINT8 *)Rsdp,
+            sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
+            );
+    if (Sum != 0) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: RSDP table checksum not valid: 0x%02x\n",
+        __func__,
+        Sum
+        ));
+      return EFI_PROTOCOL_ERROR;
+    }
+
+    //
+    // RSDP was found and is valid
+    //
+    *RsdpPtr = Rsdp;
+
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_WARN, "%a: RSDP not found\n", __func__));
+  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.
+
+  @retval EFI_SUCCESS         All tables were successfully inserted.
+  @retval EFI_UNSUPPORTED     Bhyve's ACPI tables doesn't include a XSDT.
+  @retval EFI_PROTOCOL_ERROR  Invalid XSDT found.
+
+  @retval                     Error codes propagated from underlying functions.
+**/
+EFI_STATUS
+EFIAPI
+InstallBhyveTables (
+  IN   EFI_ACPI_TABLE_PROTOCOL  *AcpiProtocol
+  )
+{
+  EFI_STATUS                                      Status;
+  UINTN                                           TableHandle;
+  UINTN                                           NumberOfTableEntries;
+  EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE  *Xsdt;
+  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER    *Rsdp;
+  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE       *Fadt;
+  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE    *Facs;
+  EFI_ACPI_DESCRIPTION_HEADER                     *Dsdt;
+  EFI_ACPI_DESCRIPTION_HEADER                     *CurrentTable;
+
+  Rsdp = NULL;
+  Facs = NULL;
+  Dsdt = NULL;
+
+  //
+  // Try to find bhyve ACPI tables
+  //
+  Status = BhyveGetAcpiRsdp (&Rsdp);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "%a: can't get RSDP (%r)\n", __func__, Status));
+    return Status;
+  }
+
+  //
+  // Bhyve should always provide a XSDT
+  //
+  Xsdt = NUMERIC_VALUE_AS_POINTER (
+           EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE,
+           Rsdp->XsdtAddress
+           );
+
+  if (Xsdt == NULL) {
+    DEBUG ((DEBUG_WARN, "%a: XSDT not found\n", __func__));
+    return EFI_UNSUPPORTED;
+  }
+
+  if (Xsdt->Header.Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
+    DEBUG ((DEBUG_ERROR, "%a: invalid XSDT length\n", __func__));
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  //
+  // Install ACPI tables
+  //
+  NumberOfTableEntries = (Xsdt->Header.Length - sizeof (Xsdt->Header)) / sizeof (UINT64);
+
+  for (UINTN Index = 0; Index < NumberOfTableEntries; Index++) {
+    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_ERROR,
+        "%a: failed to install ACPI table %c%c%c%c (%r)\n",
+        __func__,
+        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) {
+      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_ERROR, "%a: failed to install FACS (%r)\n", __func__, 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", __func__));
+    CpuDeadLoop ();
+  }
+
+  Status = AcpiProtocol->InstallAcpiTable (
+                           AcpiProtocol,
+                           Dsdt,
+                           Dsdt->Length,
+                           &TableHandle
+                           );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: failed to install DSDT (%r)\n", __func__, Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [edk2-devel] [PATCH v2 1/1] OvmfPkg/BhyveBhf: install bhyve's ACPI tables
  2023-04-17 12:11 [PATCH v2 1/1] OvmfPkg/BhyveBhf: install bhyve's ACPI tables Corvin Köhne
@ 2023-05-03  2:32 ` Rebecca Cran
  0 siblings, 0 replies; 2+ messages in thread
From: Rebecca Cran @ 2023-05-03  2:32 UTC (permalink / raw)
  To: devel, corvink
  Cc: Michael D Kinney, Liming Gao, Zhiguang Liu, Ard Biesheuvel,
	Jiewen Yao, Jordan Justen, Gerd Hoffmann, Peter Grehan

Reviewed-by: Rebecca Cran <rebecca@bsdio.com>


On 4/17/23 06:11, Corvin Köhne wrote:
> 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.
>
> Ideally, we use the qemu fwcfg interface to pass the ACPI tables from
> bhyve to OVMF. bhyve will support this in the future. However, current
> bhyve executables don't support passing ACPI tables by the qemu fwcfg
> interface. They just copy the ACPI into main memory. For that reason,
> pick up the ACPI tables from main memory.
>
> Implementation is similar to OvmfPkg/XenAcpiPlatformDxe/Xen.c.
>
> Signed-off-by: Corvin Köhne <corvink@FreeBSD.org>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Rebecca Cran <rebecca@bsdio.com>
> Cc: Peter Grehan <grehan@freebsd.org>
> ---
>   MdePkg/Include/Uefi/UefiBaseType.h           |   2 +
>   OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h |   6 +
>   OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c |  17 ++
>   OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c        | 258 +++++++++++++++++++
>   4 files changed, 283 insertions(+)
>
> diff --git a/MdePkg/Include/Uefi/UefiBaseType.h b/MdePkg/Include/Uefi/UefiBaseType.h
> index 83975a08eb4c..b18a0760ee61 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.h b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
> index 54d1af073eab..b2724135d09f 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/AcpiPlatform.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> index 999e9f151ebb..6077d4d313a3 100644
> --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
> @@ -243,6 +243,23 @@ InstallAcpiTables (
>   {
>     EFI_STATUS  Status;
>   
> +  Status = InstallBhyveTables (AcpiTable);
> +  if (!EFI_ERROR (Status)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (Status != EFI_NOT_FOUND) {
> +    DEBUG (
> +      (
> +       DEBUG_WARN,
> +       "%a: unable to install bhyve's ACPI tables (%r)\n",
> +       __func__,
> +       Status
> +      )
> +      );
> +    return Status;
> +  }
> +
>     Status = InstallOvmfFvTables (AcpiTable);
>   
>     return Status;
> diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
> index e216a21bfaed..fa5e79bfe3b4 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,249 @@ BhyveInstallAcpiTable (
>              TableKey
>              );
>   }
> +
> +/**
> +  Get the address of bhyve's ACPI Root System Description Pointer (RSDP).
> +
> +  @param  RsdpPtr             Return pointer to RSDP.
> +
> +  @retval EFI_SUCCESS         Bhyve's RSDP successfully found.
> +  @retval EFI_NOT_FOUND       Couldn't find bhyve's RSDP.
> +  @retval EFI_UNSUPPORTED     Revision is lower than 2.
> +  @retval 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;
> +  UINT8                                         Sum;
> +
> +  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_WARN, "%a: unsupported RSDP found\n", __func__));
> +      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.
> +    //
> +    Sum = CalculateCheckSum8 (
> +            (CONST UINT8 *)Rsdp,
> +            sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
> +            );
> +    if (Sum != 0) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "%a: RSDP header checksum not valid: 0x%02x\n",
> +        __func__,
> +        Sum
> +        ));
> +      return EFI_PROTOCOL_ERROR;
> +    }
> +
> +    Sum = CalculateCheckSum8 (
> +            (CONST UINT8 *)Rsdp,
> +            sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
> +            );
> +    if (Sum != 0) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "%a: RSDP table checksum not valid: 0x%02x\n",
> +        __func__,
> +        Sum
> +        ));
> +      return EFI_PROTOCOL_ERROR;
> +    }
> +
> +    //
> +    // RSDP was found and is valid
> +    //
> +    *RsdpPtr = Rsdp;
> +
> +    return EFI_SUCCESS;
> +  }
> +
> +  DEBUG ((DEBUG_WARN, "%a: RSDP not found\n", __func__));
> +  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.
> +
> +  @retval EFI_SUCCESS         All tables were successfully inserted.
> +  @retval EFI_UNSUPPORTED     Bhyve's ACPI tables doesn't include a XSDT.
> +  @retval EFI_PROTOCOL_ERROR  Invalid XSDT found.
> +
> +  @retval                     Error codes propagated from underlying functions.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallBhyveTables (
> +  IN   EFI_ACPI_TABLE_PROTOCOL  *AcpiProtocol
> +  )
> +{
> +  EFI_STATUS                                      Status;
> +  UINTN                                           TableHandle;
> +  UINTN                                           NumberOfTableEntries;
> +  EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE  *Xsdt;
> +  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER    *Rsdp;
> +  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE       *Fadt;
> +  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE    *Facs;
> +  EFI_ACPI_DESCRIPTION_HEADER                     *Dsdt;
> +  EFI_ACPI_DESCRIPTION_HEADER                     *CurrentTable;
> +
> +  Rsdp = NULL;
> +  Facs = NULL;
> +  Dsdt = NULL;
> +
> +  //
> +  // Try to find bhyve ACPI tables
> +  //
> +  Status = BhyveGetAcpiRsdp (&Rsdp);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_WARN, "%a: can't get RSDP (%r)\n", __func__, Status));
> +    return Status;
> +  }
> +
> +  //
> +  // Bhyve should always provide a XSDT
> +  //
> +  Xsdt = NUMERIC_VALUE_AS_POINTER (
> +           EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE,
> +           Rsdp->XsdtAddress
> +           );
> +
> +  if (Xsdt == NULL) {
> +    DEBUG ((DEBUG_WARN, "%a: XSDT not found\n", __func__));
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (Xsdt->Header.Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
> +    DEBUG ((DEBUG_ERROR, "%a: invalid XSDT length\n", __func__));
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +
> +  //
> +  // Install ACPI tables
> +  //
> +  NumberOfTableEntries = (Xsdt->Header.Length - sizeof (Xsdt->Header)) / sizeof (UINT64);
> +
> +  for (UINTN Index = 0; Index < NumberOfTableEntries; Index++) {
> +    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_ERROR,
> +        "%a: failed to install ACPI table %c%c%c%c (%r)\n",
> +        __func__,
> +        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) {
> +      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_ERROR, "%a: failed to install FACS (%r)\n", __func__, 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", __func__));
> +    CpuDeadLoop ();
> +  }
> +
> +  Status = AcpiProtocol->InstallAcpiTable (
> +                           AcpiProtocol,
> +                           Dsdt,
> +                           Dsdt->Length,
> +                           &TableHandle
> +                           );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: failed to install DSDT (%r)\n", __func__, Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-05-03  2:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-17 12:11 [PATCH v2 1/1] OvmfPkg/BhyveBhf: install bhyve's ACPI tables Corvin Köhne
2023-05-03  2:32 ` [edk2-devel] " Rebecca Cran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox