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 "AcpiPlatform.h"
12 #include <Library/HobLib.h>
13 #include <Guid/XenInfo.h>
14 #include <Library/BaseLib.h>
16 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
17 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
19 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*XenAcpiRsdpStructurePtr
= NULL
;
22 This function detects if OVMF is running on Xen.
30 EFI_HOB_GUID_TYPE
*GuidHob
;
33 // See if a XenInfo HOB is available
35 GuidHob
= GetFirstGuidHob (&gEfiXenInfoGuid
);
36 if (GuidHob
== NULL
) {
44 Get the address of Xen ACPI Root System Description Pointer (RSDP)
47 @param RsdpStructurePtr Return pointer to RSDP structure
49 @return EFI_SUCCESS Find Xen RSDP structure successfully.
50 @return EFI_NOT_FOUND Don't find Xen RSDP structure.
51 @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
57 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
**RsdpPtr
60 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*RsdpStructurePtr
;
65 // Detect the RSDP structure
67 for (XenAcpiPtr
= (UINT8
*)(UINTN
) XEN_ACPI_PHYSICAL_ADDRESS
;
68 XenAcpiPtr
< (UINT8
*)(UINTN
) XEN_BIOS_PHYSICAL_END
;
71 RsdpStructurePtr
= (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)
74 if (!AsciiStrnCmp ((CHAR8
*) &RsdpStructurePtr
->Signature
, "RSD PTR ", 8)) {
76 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
77 // This is only the first 20 bytes of the structure
80 (CONST UINT8
*)RsdpStructurePtr
,
81 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
87 if (RsdpStructurePtr
->Revision
>= 2) {
89 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
92 (CONST UINT8
*)RsdpStructurePtr
,
93 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
)
99 *RsdpPtr
= RsdpStructurePtr
;
104 return EFI_NOT_FOUND
;
108 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
109 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
110 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
112 @param AcpiProtocol Protocol instance pointer.
114 @return EFI_SUCCESS The table was successfully inserted.
115 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
116 NULL, or AcpiTableBufferSize and the size
117 field embedded in the ACPI table pointed to
118 by AcpiTableBuffer are not in sync.
119 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
125 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
131 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
132 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
133 VOID
*CurrentTableEntry
;
134 UINTN CurrentTablePointer
;
135 EFI_ACPI_DESCRIPTION_HEADER
*CurrentTable
;
137 UINTN NumberOfTableEntries
;
138 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt2Table
;
139 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt1Table
;
140 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs2Table
;
141 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs1Table
;
142 EFI_ACPI_DESCRIPTION_HEADER
*DsdtTable
;
150 NumberOfTableEntries
= 0;
153 // Try to find Xen ACPI tables
155 Status
= GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr
);
156 if (EFI_ERROR (Status
)) {
161 // If XSDT table is find, just install its tables.
162 // Otherwise, try to find and install the RSDT tables.
164 if (XenAcpiRsdpStructurePtr
->XsdtAddress
) {
166 // Retrieve the addresses of XSDT and
167 // calculate the number of its table entries.
169 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
170 XenAcpiRsdpStructurePtr
->XsdtAddress
;
171 NumberOfTableEntries
= (Xsdt
->Length
-
172 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
176 // Install ACPI tables found in XSDT.
178 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
180 // Get the table entry from XSDT
182 CurrentTableEntry
= (VOID
*) ((UINT8
*) Xsdt
+
183 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
184 Index
* sizeof (UINT64
));
185 CurrentTablePointer
= (UINTN
) *(UINT64
*)CurrentTableEntry
;
186 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
189 // Install the XSDT tables
191 Status
= InstallAcpiTable (
194 CurrentTable
->Length
,
198 if (EFI_ERROR (Status
)) {
203 // Get the FACS and DSDT table address from the table FADT
205 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
206 Fadt2Table
= (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
207 (UINTN
) CurrentTablePointer
;
208 Facs2Table
= (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
209 (UINTN
) Fadt2Table
->FirmwareCtrl
;
210 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt2Table
->Dsdt
;
214 else if (XenAcpiRsdpStructurePtr
->RsdtAddress
) {
216 // Retrieve the addresses of RSDT and
217 // calculate the number of its table entries.
219 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
)
220 XenAcpiRsdpStructurePtr
->RsdtAddress
;
221 NumberOfTableEntries
= (Rsdt
->Length
-
222 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)) /
226 // Install ACPI tables found in XSDT.
228 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
230 // Get the table entry from RSDT
232 CurrentTableEntry
= (UINT32
*) ((UINT8
*) Rsdt
+
233 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
234 Index
* sizeof (UINT32
));
235 CurrentTablePointer
= *(UINT32
*)CurrentTableEntry
;
236 CurrentTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTablePointer
;
239 // Install the RSDT tables
241 Status
= InstallAcpiTable (
244 CurrentTable
->Length
,
248 if (EFI_ERROR (Status
)) {
253 // Get the FACS and DSDT table address from the table FADT
255 if (!AsciiStrnCmp ((CHAR8
*) &CurrentTable
->Signature
, "FACP", 4)) {
256 Fadt1Table
= (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*)
257 (UINTN
) CurrentTablePointer
;
258 Facs1Table
= (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)
259 (UINTN
) Fadt1Table
->FirmwareCtrl
;
260 DsdtTable
= (EFI_ACPI_DESCRIPTION_HEADER
*) (UINTN
) Fadt1Table
->Dsdt
;
266 // Install the FACS table.
272 Status
= InstallAcpiTable (
278 if (EFI_ERROR (Status
)) {
282 else if (Fadt1Table
) {
286 Status
= 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
= InstallAcpiTable (
313 if (EFI_ERROR (Status
)) {