4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/BaseLib.h>
13 #include "AcpiPlatform.h"
15 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
16 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
18 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*XenAcpiRsdpStructurePtr
= NULL
;
21 Get the address of Xen ACPI Root System Description Pointer (RSDP)
24 @param RsdpStructurePtr Return pointer to RSDP structure
26 @return EFI_SUCCESS Find Xen RSDP structure successfully.
27 @return EFI_NOT_FOUND Don't find Xen RSDP structure.
28 @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
34 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
**RsdpPtr
37 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*RsdpStructurePtr
;
40 EFI_XEN_INFO
*XenInfo
;
43 // Detect the RSDP structure
47 // First look for PVH one
49 XenInfo
= XenGetInfoHOB ();
50 ASSERT (XenInfo
!= NULL
);
51 if (XenInfo
->RsdpPvh
!= NULL
) {
52 DEBUG ((DEBUG_INFO
, "%a: Use ACPI RSDP table at 0x%p\n",
53 gEfiCallerBaseName
, XenInfo
->RsdpPvh
));
54 *RsdpPtr
= XenInfo
->RsdpPvh
;
59 // Otherwise, look for the HVM one
61 for (XenAcpiPtr
= (UINT8
*)(UINTN
) XEN_ACPI_PHYSICAL_ADDRESS
;
62 XenAcpiPtr
< (UINT8
*)(UINTN
) XEN_BIOS_PHYSICAL_END
;
65 RsdpStructurePtr
= (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)
68 if (!AsciiStrnCmp ((CHAR8
*) &RsdpStructurePtr
->Signature
, "RSD PTR ", 8)) {
70 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
71 // This is only the first 20 bytes of the structure
74 (CONST UINT8
*)RsdpStructurePtr
,
75 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
81 if (RsdpStructurePtr
->Revision
>= 2) {
83 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
86 (CONST UINT8
*)RsdpStructurePtr
,
87 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
93 *RsdpPtr
= RsdpStructurePtr
;
102 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
103 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
104 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
106 @param AcpiProtocol Protocol instance pointer.
108 @return EFI_SUCCESS The table was successfully inserted.
109 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
110 NULL, or AcpiTableBufferSize and the size
111 field embedded in the ACPI table pointed to
112 by AcpiTableBuffer are not in sync.
113 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
119 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
125 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
126 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
127 VOID
*CurrentTableEntry
;
128 UINTN CurrentTablePointer
;
129 EFI_ACPI_DESCRIPTION_HEADER
*CurrentTable
;
131 UINTN NumberOfTableEntries
;
132 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt2Table
;
133 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt1Table
;
134 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs2Table
;
135 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs1Table
;
136 EFI_ACPI_DESCRIPTION_HEADER
*DsdtTable
;
144 NumberOfTableEntries
= 0;
147 // Try to find Xen ACPI tables
149 Status
= GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr
);
150 if (EFI_ERROR (Status
)) {
155 // If XSDT table is find, just install its tables.
156 // Otherwise, try to find and install the RSDT tables.
158 if (XenAcpiRsdpStructurePtr
->XsdtAddress
) {
160 // Retrieve the addresses of XSDT and
161 // calculate the number of its table entries.
163 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
164 XenAcpiRsdpStructurePtr
->XsdtAddress
;
165 NumberOfTableEntries
= (Xsdt
->Length
-
166 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
170 // Install ACPI tables found in XSDT.
172 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
174 // Get the table entry from XSDT
176 CurrentTableEntry
= (VOID
*) ((UINT8
*) Xsdt
+
177 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
178 Index
* sizeof (UINT64
));
179 CurrentTablePointer
= (UINTN
) *(UINT64
*)CurrentTableEntry
;
180 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
183 // Install the XSDT tables
185 Status
= InstallAcpiTable (
188 CurrentTable
->Length
,
192 if (EFI_ERROR (Status
)) {
197 // Get the FACS and DSDT table address from the table FADT
199 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
200 Fadt2Table
= (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
201 (UINTN
) CurrentTablePointer
;
202 Facs2Table
= (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
203 (UINTN
) Fadt2Table
->FirmwareCtrl
;
204 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt2Table
->Dsdt
;
208 else if (XenAcpiRsdpStructurePtr
->RsdtAddress
) {
210 // Retrieve the addresses of RSDT and
211 // calculate the number of its table entries.
213 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
214 XenAcpiRsdpStructurePtr
->RsdtAddress
;
215 NumberOfTableEntries
= (Rsdt
->Length
-
216 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
220 // Install ACPI tables found in XSDT.
222 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
224 // Get the table entry from RSDT
226 CurrentTableEntry
= (UINT32
*) ((UINT8
*) Rsdt
+
227 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
228 Index
* sizeof (UINT32
));
229 CurrentTablePointer
= *(UINT32
*)CurrentTableEntry
;
230 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
233 // Install the RSDT tables
235 Status
= InstallAcpiTable (
238 CurrentTable
->Length
,
242 if (EFI_ERROR (Status
)) {
247 // Get the FACS and DSDT table address from the table FADT
249 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
250 Fadt1Table
= (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
251 (UINTN
) CurrentTablePointer
;
252 Facs1Table
= (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
253 (UINTN
) Fadt1Table
->FirmwareCtrl
;
254 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt1Table
->Dsdt
;
260 // Install the FACS table.
266 Status
= InstallAcpiTable (
272 if (EFI_ERROR (Status
)) {
276 else if (Fadt1Table
) {
280 Status
= InstallAcpiTable (
286 if (EFI_ERROR (Status
)) {
292 // Install DSDT table. If we reached this point without finding the DSDT,
293 // then we're out of sync with the hypervisor, and cannot continue.
295 if (DsdtTable
== NULL
) {
296 DEBUG ((DEBUG_ERROR
, "%a: no DSDT found\n", __FUNCTION__
));
301 Status
= InstallAcpiTable (
307 if (EFI_ERROR (Status
)) {