4 Copyright (C) 2021, Red Hat, Inc.
5 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
6 Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/BaseLib.h> // CpuDeadLoop()
13 #include <Library/DebugLib.h> // DEBUG()
14 #include <Library/XenPlatformLib.h> // XenGetInfoHOB()
16 #include "AcpiPlatform.h"
18 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
19 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
21 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*XenAcpiRsdpStructurePtr
= NULL
;
24 Get the address of Xen ACPI Root System Description Pointer (RSDP)
27 @param RsdpStructurePtr Return pointer to RSDP structure
29 @return EFI_SUCCESS Find Xen RSDP structure successfully.
30 @return EFI_NOT_FOUND Don't find Xen RSDP structure.
31 @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
37 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
**RsdpPtr
40 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*RsdpStructurePtr
;
43 EFI_XEN_INFO
*XenInfo
;
46 // Detect the RSDP structure
50 // First look for PVH one
52 XenInfo
= XenGetInfoHOB ();
53 ASSERT (XenInfo
!= NULL
);
54 if (XenInfo
->RsdpPvh
!= NULL
) {
55 DEBUG ((DEBUG_INFO
, "%a: Use ACPI RSDP table at 0x%p\n",
56 gEfiCallerBaseName
, XenInfo
->RsdpPvh
));
57 *RsdpPtr
= XenInfo
->RsdpPvh
;
62 // Otherwise, look for the HVM one
64 for (XenAcpiPtr
= (UINT8
*)(UINTN
) XEN_ACPI_PHYSICAL_ADDRESS
;
65 XenAcpiPtr
< (UINT8
*)(UINTN
) XEN_BIOS_PHYSICAL_END
;
68 RsdpStructurePtr
= (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)
71 if (!AsciiStrnCmp ((CHAR8
*) &RsdpStructurePtr
->Signature
, "RSD PTR ", 8)) {
73 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
74 // This is only the first 20 bytes of the structure
77 (CONST UINT8
*)RsdpStructurePtr
,
78 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
84 if (RsdpStructurePtr
->Revision
>= 2) {
86 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
89 (CONST UINT8
*)RsdpStructurePtr
,
90 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
96 *RsdpPtr
= RsdpStructurePtr
;
101 return EFI_NOT_FOUND
;
105 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
106 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
107 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
109 @param AcpiProtocol Protocol instance pointer.
111 @return EFI_SUCCESS The table was successfully inserted.
112 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
113 NULL, or AcpiTableBufferSize and the size
114 field embedded in the ACPI table pointed to
115 by AcpiTableBuffer are not in sync.
116 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
122 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
128 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
129 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
130 VOID
*CurrentTableEntry
;
131 UINTN CurrentTablePointer
;
132 EFI_ACPI_DESCRIPTION_HEADER
*CurrentTable
;
134 UINTN NumberOfTableEntries
;
135 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt2Table
;
136 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt1Table
;
137 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs2Table
;
138 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs1Table
;
139 EFI_ACPI_DESCRIPTION_HEADER
*DsdtTable
;
147 NumberOfTableEntries
= 0;
150 // Try to find Xen ACPI tables
152 Status
= GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr
);
153 if (EFI_ERROR (Status
)) {
158 // If XSDT table is find, just install its tables.
159 // Otherwise, try to find and install the RSDT tables.
161 if (XenAcpiRsdpStructurePtr
->XsdtAddress
) {
163 // Retrieve the addresses of XSDT and
164 // calculate the number of its table entries.
166 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
167 XenAcpiRsdpStructurePtr
->XsdtAddress
;
168 NumberOfTableEntries
= (Xsdt
->Length
-
169 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
173 // Install ACPI tables found in XSDT.
175 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
177 // Get the table entry from XSDT
179 CurrentTableEntry
= (VOID
*) ((UINT8
*) Xsdt
+
180 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
181 Index
* sizeof (UINT64
));
182 CurrentTablePointer
= (UINTN
) *(UINT64
*)CurrentTableEntry
;
183 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
186 // Install the XSDT tables
188 Status
= InstallAcpiTable (
191 CurrentTable
->Length
,
195 if (EFI_ERROR (Status
)) {
200 // Get the FACS and DSDT table address from the table FADT
202 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
203 Fadt2Table
= (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
204 (UINTN
) CurrentTablePointer
;
205 Facs2Table
= (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
206 (UINTN
) Fadt2Table
->FirmwareCtrl
;
207 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt2Table
->Dsdt
;
211 else if (XenAcpiRsdpStructurePtr
->RsdtAddress
) {
213 // Retrieve the addresses of RSDT and
214 // calculate the number of its table entries.
216 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
217 XenAcpiRsdpStructurePtr
->RsdtAddress
;
218 NumberOfTableEntries
= (Rsdt
->Length
-
219 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
223 // Install ACPI tables found in XSDT.
225 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
227 // Get the table entry from RSDT
229 CurrentTableEntry
= (UINT32
*) ((UINT8
*) Rsdt
+
230 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
231 Index
* sizeof (UINT32
));
232 CurrentTablePointer
= *(UINT32
*)CurrentTableEntry
;
233 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
236 // Install the RSDT tables
238 Status
= InstallAcpiTable (
241 CurrentTable
->Length
,
245 if (EFI_ERROR (Status
)) {
250 // Get the FACS and DSDT table address from the table FADT
252 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
253 Fadt1Table
= (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
254 (UINTN
) CurrentTablePointer
;
255 Facs1Table
= (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
256 (UINTN
) Fadt1Table
->FirmwareCtrl
;
257 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt1Table
->Dsdt
;
263 // Install the FACS table.
269 Status
= InstallAcpiTable (
275 if (EFI_ERROR (Status
)) {
279 else if (Fadt1Table
) {
283 Status
= InstallAcpiTable (
289 if (EFI_ERROR (Status
)) {
295 // Install DSDT table. If we reached this point without finding the DSDT,
296 // then we're out of sync with the hypervisor, and cannot continue.
298 if (DsdtTable
== NULL
) {
299 DEBUG ((DEBUG_ERROR
, "%a: no DSDT found\n", __FUNCTION__
));
304 Status
= InstallAcpiTable (
310 if (EFI_ERROR (Status
)) {