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> // CpuDeadLoop()
12 #include <Library/DebugLib.h> // DEBUG()
13 #include <Library/XenPlatformLib.h> // XenGetInfoHOB()
15 #include "AcpiPlatform.h"
17 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
18 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
20 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*XenAcpiRsdpStructurePtr
= NULL
;
23 Get the address of Xen ACPI Root System Description Pointer (RSDP)
26 @param RsdpStructurePtr Return pointer to RSDP structure
28 @return EFI_SUCCESS Find Xen RSDP structure successfully.
29 @return EFI_NOT_FOUND Don't find Xen RSDP structure.
30 @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
36 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
**RsdpPtr
39 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*RsdpStructurePtr
;
42 EFI_XEN_INFO
*XenInfo
;
45 // Detect the RSDP structure
49 // First look for PVH one
51 XenInfo
= XenGetInfoHOB ();
52 ASSERT (XenInfo
!= NULL
);
53 if (XenInfo
->RsdpPvh
!= NULL
) {
54 DEBUG ((DEBUG_INFO
, "%a: Use ACPI RSDP table at 0x%p\n",
55 gEfiCallerBaseName
, XenInfo
->RsdpPvh
));
56 *RsdpPtr
= XenInfo
->RsdpPvh
;
61 // Otherwise, look for the HVM one
63 for (XenAcpiPtr
= (UINT8
*)(UINTN
) XEN_ACPI_PHYSICAL_ADDRESS
;
64 XenAcpiPtr
< (UINT8
*)(UINTN
) XEN_BIOS_PHYSICAL_END
;
67 RsdpStructurePtr
= (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)
70 if (!AsciiStrnCmp ((CHAR8
*) &RsdpStructurePtr
->Signature
, "RSD PTR ", 8)) {
72 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
73 // This is only the first 20 bytes of the structure
76 (CONST UINT8
*)RsdpStructurePtr
,
77 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
83 if (RsdpStructurePtr
->Revision
>= 2) {
85 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
88 (CONST UINT8
*)RsdpStructurePtr
,
89 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
95 *RsdpPtr
= RsdpStructurePtr
;
100 return EFI_NOT_FOUND
;
104 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
105 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
106 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
108 @param AcpiProtocol Protocol instance pointer.
110 @return EFI_SUCCESS The table was successfully inserted.
111 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
112 NULL, or AcpiTableBufferSize and the size
113 field embedded in the ACPI table pointed to
114 by AcpiTableBuffer are not in sync.
115 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
121 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
127 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
128 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
129 VOID
*CurrentTableEntry
;
130 UINTN CurrentTablePointer
;
131 EFI_ACPI_DESCRIPTION_HEADER
*CurrentTable
;
133 UINTN NumberOfTableEntries
;
134 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt2Table
;
135 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt1Table
;
136 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs2Table
;
137 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs1Table
;
138 EFI_ACPI_DESCRIPTION_HEADER
*DsdtTable
;
146 NumberOfTableEntries
= 0;
149 // Try to find Xen ACPI tables
151 Status
= GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr
);
152 if (EFI_ERROR (Status
)) {
157 // If XSDT table is find, just install its tables.
158 // Otherwise, try to find and install the RSDT tables.
160 if (XenAcpiRsdpStructurePtr
->XsdtAddress
) {
162 // Retrieve the addresses of XSDT and
163 // calculate the number of its table entries.
165 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
166 XenAcpiRsdpStructurePtr
->XsdtAddress
;
167 NumberOfTableEntries
= (Xsdt
->Length
-
168 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
172 // Install ACPI tables found in XSDT.
174 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
176 // Get the table entry from XSDT
178 CurrentTableEntry
= (VOID
*) ((UINT8
*) Xsdt
+
179 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
180 Index
* sizeof (UINT64
));
181 CurrentTablePointer
= (UINTN
) *(UINT64
*)CurrentTableEntry
;
182 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
185 // Install the XSDT tables
187 Status
= InstallAcpiTable (
190 CurrentTable
->Length
,
194 if (EFI_ERROR (Status
)) {
199 // Get the FACS and DSDT table address from the table FADT
201 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
202 Fadt2Table
= (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
203 (UINTN
) CurrentTablePointer
;
204 Facs2Table
= (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
205 (UINTN
) Fadt2Table
->FirmwareCtrl
;
206 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt2Table
->Dsdt
;
210 else if (XenAcpiRsdpStructurePtr
->RsdtAddress
) {
212 // Retrieve the addresses of RSDT and
213 // calculate the number of its table entries.
215 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
216 XenAcpiRsdpStructurePtr
->RsdtAddress
;
217 NumberOfTableEntries
= (Rsdt
->Length
-
218 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
222 // Install ACPI tables found in XSDT.
224 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
226 // Get the table entry from RSDT
228 CurrentTableEntry
= (UINT32
*) ((UINT8
*) Rsdt
+
229 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
230 Index
* sizeof (UINT32
));
231 CurrentTablePointer
= *(UINT32
*)CurrentTableEntry
;
232 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
235 // Install the RSDT tables
237 Status
= InstallAcpiTable (
240 CurrentTable
->Length
,
244 if (EFI_ERROR (Status
)) {
249 // Get the FACS and DSDT table address from the table FADT
251 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
252 Fadt1Table
= (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
253 (UINTN
) CurrentTablePointer
;
254 Facs1Table
= (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
255 (UINTN
) Fadt1Table
->FirmwareCtrl
;
256 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt1Table
->Dsdt
;
262 // Install the FACS table.
268 Status
= InstallAcpiTable (
274 if (EFI_ERROR (Status
)) {
278 else if (Fadt1Table
) {
282 Status
= InstallAcpiTable (
288 if (EFI_ERROR (Status
)) {
294 // Install DSDT table. If we reached this point without finding the DSDT,
295 // then we're out of sync with the hypervisor, and cannot continue.
297 if (DsdtTable
== NULL
) {
298 DEBUG ((DEBUG_ERROR
, "%a: no DSDT found\n", __FUNCTION__
));
303 Status
= InstallAcpiTable (
309 if (EFI_ERROR (Status
)) {