]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenAcpiPlatformDxe/Xen.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / XenAcpiPlatformDxe / Xen.c
1 /** @file
2 OVMF ACPI Xen support
3
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>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <Library/BaseLib.h> // CpuDeadLoop()
13 #include <Library/DebugLib.h> // DEBUG()
14 #include <Library/XenPlatformLib.h> // XenGetInfoHOB()
15
16 #include "AcpiPlatform.h"
17
18 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
19 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
20
21 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;
22
23 /**
24 Get the address of Xen ACPI Root System Description Pointer (RSDP)
25 structure.
26
27 @param RsdpStructurePtr Return pointer to RSDP structure
28
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.
32
33 **/
34 EFI_STATUS
35 EFIAPI
36 GetXenAcpiRsdp (
37 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
38 )
39 {
40 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
41 UINT8 *XenAcpiPtr;
42 UINT8 Sum;
43 EFI_XEN_INFO *XenInfo;
44
45 //
46 // Detect the RSDP structure
47 //
48
49 //
50 // First look for PVH one
51 //
52 XenInfo = XenGetInfoHOB ();
53 ASSERT (XenInfo != NULL);
54 if (XenInfo->RsdpPvh != NULL) {
55 DEBUG ((
56 DEBUG_INFO,
57 "%a: Use ACPI RSDP table at 0x%p\n",
58 gEfiCallerBaseName,
59 XenInfo->RsdpPvh
60 ));
61 *RsdpPtr = XenInfo->RsdpPvh;
62 return EFI_SUCCESS;
63 }
64
65 //
66 // Otherwise, look for the HVM one
67 //
68 for (XenAcpiPtr = (UINT8 *)(UINTN)XEN_ACPI_PHYSICAL_ADDRESS;
69 XenAcpiPtr < (UINT8 *)(UINTN)XEN_BIOS_PHYSICAL_END;
70 XenAcpiPtr += 0x10)
71 {
72 RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
73 (UINTN)XenAcpiPtr;
74
75 if (!AsciiStrnCmp ((CHAR8 *)&RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
76 //
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
79 //
80 Sum = CalculateSum8 (
81 (CONST UINT8 *)RsdpStructurePtr,
82 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
83 );
84 if (Sum != 0) {
85 return EFI_ABORTED;
86 }
87
88 if (RsdpStructurePtr->Revision >= 2) {
89 //
90 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
91 //
92 Sum = CalculateSum8 (
93 (CONST UINT8 *)RsdpStructurePtr,
94 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
95 );
96 if (Sum != 0) {
97 return EFI_ABORTED;
98 }
99 }
100
101 *RsdpPtr = RsdpStructurePtr;
102 return EFI_SUCCESS;
103 }
104 }
105
106 return EFI_NOT_FOUND;
107 }
108
109 /**
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.
113
114 @param AcpiProtocol Protocol instance pointer.
115
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.
122
123 **/
124 EFI_STATUS
125 EFIAPI
126 InstallXenTables (
127 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
128 )
129 {
130 EFI_STATUS Status;
131 UINTN TableHandle;
132
133 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
134 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
135 VOID *CurrentTableEntry;
136 UINTN CurrentTablePointer;
137 EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
138 UINTN Index;
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;
145
146 Fadt2Table = NULL;
147 Fadt1Table = NULL;
148 Facs2Table = NULL;
149 Facs1Table = NULL;
150 DsdtTable = NULL;
151 TableHandle = 0;
152 NumberOfTableEntries = 0;
153
154 //
155 // Try to find Xen ACPI tables
156 //
157 Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);
158 if (EFI_ERROR (Status)) {
159 return Status;
160 }
161
162 //
163 // If XSDT table is find, just install its tables.
164 // Otherwise, try to find and install the RSDT tables.
165 //
166 if (XenAcpiRsdpStructurePtr->XsdtAddress) {
167 //
168 // Retrieve the addresses of XSDT and
169 // calculate the number of its table entries.
170 //
171 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
172 XenAcpiRsdpStructurePtr->XsdtAddress;
173 NumberOfTableEntries = (Xsdt->Length -
174 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
175 sizeof (UINT64);
176
177 //
178 // Install ACPI tables found in XSDT.
179 //
180 for (Index = 0; Index < NumberOfTableEntries; Index++) {
181 //
182 // Get the table entry from XSDT
183 //
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;
189
190 //
191 // Install the XSDT tables
192 //
193 Status = AcpiProtocol->InstallAcpiTable (
194 AcpiProtocol,
195 CurrentTable,
196 CurrentTable->Length,
197 &TableHandle
198 );
199
200 if (EFI_ERROR (Status)) {
201 return Status;
202 }
203
204 //
205 // Get the FACS and DSDT table address from the table FADT
206 //
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;
213 }
214 }
215 } else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
216 //
217 // Retrieve the addresses of RSDT and
218 // calculate the number of its table entries.
219 //
220 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
221 XenAcpiRsdpStructurePtr->RsdtAddress;
222 NumberOfTableEntries = (Rsdt->Length -
223 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
224 sizeof (UINT32);
225
226 //
227 // Install ACPI tables found in XSDT.
228 //
229 for (Index = 0; Index < NumberOfTableEntries; Index++) {
230 //
231 // Get the table entry from RSDT
232 //
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;
238
239 //
240 // Install the RSDT tables
241 //
242 Status = AcpiProtocol->InstallAcpiTable (
243 AcpiProtocol,
244 CurrentTable,
245 CurrentTable->Length,
246 &TableHandle
247 );
248
249 if (EFI_ERROR (Status)) {
250 return Status;
251 }
252
253 //
254 // Get the FACS and DSDT table address from the table FADT
255 //
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;
262 }
263 }
264 }
265
266 //
267 // Install the FACS table.
268 //
269 if (Fadt2Table) {
270 //
271 // FACS 2.0
272 //
273 Status = AcpiProtocol->InstallAcpiTable (
274 AcpiProtocol,
275 Facs2Table,
276 Facs2Table->Length,
277 &TableHandle
278 );
279 if (EFI_ERROR (Status)) {
280 return Status;
281 }
282 } else if (Fadt1Table) {
283 //
284 // FACS 1.0
285 //
286 Status = AcpiProtocol->InstallAcpiTable (
287 AcpiProtocol,
288 Facs1Table,
289 Facs1Table->Length,
290 &TableHandle
291 );
292 if (EFI_ERROR (Status)) {
293 return Status;
294 }
295 }
296
297 //
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.
300 //
301 if (DsdtTable == NULL) {
302 DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));
303 ASSERT (FALSE);
304 CpuDeadLoop ();
305 }
306
307 Status = AcpiProtocol->InstallAcpiTable (
308 AcpiProtocol,
309 DsdtTable,
310 DsdtTable->Length,
311 &TableHandle
312 );
313 if (EFI_ERROR (Status)) {
314 return Status;
315 }
316
317 return EFI_SUCCESS;
318 }