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
) {
57 "%a: Use ACPI RSDP table at 0x%p\n",
61 *RsdpPtr
= XenInfo
->RsdpPvh
;
66 // Otherwise, look for the HVM one
68 for (XenAcpiPtr
= (UINT8
*)(UINTN
)XEN_ACPI_PHYSICAL_ADDRESS
;
69 XenAcpiPtr
< (UINT8
*)(UINTN
)XEN_BIOS_PHYSICAL_END
;
72 RsdpStructurePtr
= (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)
75 if (!AsciiStrnCmp ((CHAR8
*)&RsdpStructurePtr
->Signature
, "RSD PTR ", 8)) {
77 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
78 // This is only the first 20 bytes of the structure
81 (CONST UINT8
*)RsdpStructurePtr
,
82 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
88 if (RsdpStructurePtr
->Revision
>= 2) {
90 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
93 (CONST UINT8
*)RsdpStructurePtr
,
94 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
101 *RsdpPtr
= RsdpStructurePtr
;
106 return EFI_NOT_FOUND
;
110 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
111 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
112 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
114 @param AcpiProtocol Protocol instance pointer.
116 @return EFI_SUCCESS The table was successfully inserted.
117 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
118 NULL, or AcpiTableBufferSize and the size
119 field embedded in the ACPI table pointed to
120 by AcpiTableBuffer are not in sync.
121 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
127 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
133 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
134 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
135 VOID
*CurrentTableEntry
;
136 UINTN CurrentTablePointer
;
137 EFI_ACPI_DESCRIPTION_HEADER
*CurrentTable
;
139 UINTN NumberOfTableEntries
;
140 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt2Table
;
141 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt1Table
;
142 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs2Table
;
143 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs1Table
;
144 EFI_ACPI_DESCRIPTION_HEADER
*DsdtTable
;
152 NumberOfTableEntries
= 0;
155 // Try to find Xen ACPI tables
157 Status
= GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr
);
158 if (EFI_ERROR (Status
)) {
163 // If XSDT table is find, just install its tables.
164 // Otherwise, try to find and install the RSDT tables.
166 if (XenAcpiRsdpStructurePtr
->XsdtAddress
) {
168 // Retrieve the addresses of XSDT and
169 // calculate the number of its table entries.
171 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)
172 XenAcpiRsdpStructurePtr
->XsdtAddress
;
173 NumberOfTableEntries
= (Xsdt
->Length
-
174 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
178 // Install ACPI tables found in XSDT.
180 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
182 // Get the table entry from XSDT
184 CurrentTableEntry
= (VOID
*)((UINT8
*)Xsdt
+
185 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
186 Index
* sizeof (UINT64
));
187 CurrentTablePointer
= (UINTN
)*(UINT64
*)CurrentTableEntry
;
188 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*)CurrentTablePointer
;
191 // Install the XSDT tables
193 Status
= AcpiProtocol
->InstallAcpiTable (
196 CurrentTable
->Length
,
200 if (EFI_ERROR (Status
)) {
205 // Get the FACS and DSDT table address from the table FADT
207 if (!AsciiStrnCmp ((CHAR8
*)&CurrentTable
->Signature
, "FACP", 4)) {
208 Fadt2Table
= (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
209 (UINTN
)CurrentTablePointer
;
210 Facs2Table
= (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
211 (UINTN
)Fadt2Table
->FirmwareCtrl
;
212 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)Fadt2Table
->Dsdt
;
215 } else if (XenAcpiRsdpStructurePtr
->RsdtAddress
) {
217 // Retrieve the addresses of RSDT and
218 // calculate the number of its table entries.
220 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)
221 XenAcpiRsdpStructurePtr
->RsdtAddress
;
222 NumberOfTableEntries
= (Rsdt
->Length
-
223 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
227 // Install ACPI tables found in XSDT.
229 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
231 // Get the table entry from RSDT
233 CurrentTableEntry
= (UINT32
*)((UINT8
*)Rsdt
+
234 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
235 Index
* sizeof (UINT32
));
236 CurrentTablePointer
= *(UINT32
*)CurrentTableEntry
;
237 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*)CurrentTablePointer
;
240 // Install the RSDT tables
242 Status
= AcpiProtocol
->InstallAcpiTable (
245 CurrentTable
->Length
,
249 if (EFI_ERROR (Status
)) {
254 // Get the FACS and DSDT table address from the table FADT
256 if (!AsciiStrnCmp ((CHAR8
*)&CurrentTable
->Signature
, "FACP", 4)) {
257 Fadt1Table
= (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
258 (UINTN
)CurrentTablePointer
;
259 Facs1Table
= (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
260 (UINTN
)Fadt1Table
->FirmwareCtrl
;
261 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)Fadt1Table
->Dsdt
;
267 // Install the FACS table.
273 Status
= AcpiProtocol
->InstallAcpiTable (
279 if (EFI_ERROR (Status
)) {
282 } else if (Fadt1Table
) {
286 Status
= AcpiProtocol
->InstallAcpiTable (
292 if (EFI_ERROR (Status
)) {
298 // Install DSDT table. If we reached this point without finding the DSDT,
299 // then we're out of sync with the hypervisor, and cannot continue.
301 if (DsdtTable
== NULL
) {
302 DEBUG ((DEBUG_ERROR
, "%a: no DSDT found\n", __FUNCTION__
));
307 Status
= AcpiProtocol
->InstallAcpiTable (
313 if (EFI_ERROR (Status
)) {