]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenAcpiPlatformDxe/Xen.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / XenAcpiPlatformDxe / Xen.c
CommitLineData
c9bba52f
LE
1/** @file\r
2 OVMF ACPI Xen support\r
3\r
4 Copyright (C) 2021, Red Hat, Inc.\r
5 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
6 Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12#include <Library/BaseLib.h> // CpuDeadLoop()\r
13#include <Library/DebugLib.h> // DEBUG()\r
14#include <Library/XenPlatformLib.h> // XenGetInfoHOB()\r
15\r
16#include "AcpiPlatform.h"\r
17\r
ac0a286f
MK
18#define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020\r
19#define XEN_BIOS_PHYSICAL_END 0x000FFFFF\r
c9bba52f
LE
20\r
21EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;\r
22\r
23/**\r
24 Get the address of Xen ACPI Root System Description Pointer (RSDP)\r
25 structure.\r
26\r
27 @param RsdpStructurePtr Return pointer to RSDP structure\r
28\r
29 @return EFI_SUCCESS Find Xen RSDP structure successfully.\r
30 @return EFI_NOT_FOUND Don't find Xen RSDP structure.\r
31 @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.\r
32\r
33**/\r
34EFI_STATUS\r
35EFIAPI\r
36GetXenAcpiRsdp (\r
ac0a286f 37 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr\r
c9bba52f
LE
38 )\r
39{\r
ac0a286f
MK
40 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;\r
41 UINT8 *XenAcpiPtr;\r
42 UINT8 Sum;\r
43 EFI_XEN_INFO *XenInfo;\r
c9bba52f
LE
44\r
45 //\r
46 // Detect the RSDP structure\r
47 //\r
48\r
49 //\r
50 // First look for PVH one\r
51 //\r
52 XenInfo = XenGetInfoHOB ();\r
53 ASSERT (XenInfo != NULL);\r
54 if (XenInfo->RsdpPvh != NULL) {\r
ac0a286f
MK
55 DEBUG ((\r
56 DEBUG_INFO,\r
57 "%a: Use ACPI RSDP table at 0x%p\n",\r
58 gEfiCallerBaseName,\r
59 XenInfo->RsdpPvh\r
60 ));\r
c9bba52f
LE
61 *RsdpPtr = XenInfo->RsdpPvh;\r
62 return EFI_SUCCESS;\r
63 }\r
64\r
65 //\r
66 // Otherwise, look for the HVM one\r
67 //\r
ac0a286f
MK
68 for (XenAcpiPtr = (UINT8 *)(UINTN)XEN_ACPI_PHYSICAL_ADDRESS;\r
69 XenAcpiPtr < (UINT8 *)(UINTN)XEN_BIOS_PHYSICAL_END;\r
70 XenAcpiPtr += 0x10)\r
71 {\r
c9bba52f 72 RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)\r
ac0a286f 73 (UINTN)XenAcpiPtr;\r
c9bba52f 74\r
ac0a286f 75 if (!AsciiStrnCmp ((CHAR8 *)&RsdpStructurePtr->Signature, "RSD PTR ", 8)) {\r
c9bba52f
LE
76 //\r
77 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.\r
78 // This is only the first 20 bytes of the structure\r
79 //\r
80 Sum = CalculateSum8 (\r
81 (CONST UINT8 *)RsdpStructurePtr,\r
82 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)\r
83 );\r
84 if (Sum != 0) {\r
85 return EFI_ABORTED;\r
86 }\r
87\r
88 if (RsdpStructurePtr->Revision >= 2) {\r
89 //\r
90 // RSDP ACPI 2.0/3.0 checksum, this is the entire table\r
91 //\r
92 Sum = CalculateSum8 (\r
93 (CONST UINT8 *)RsdpStructurePtr,\r
94 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)\r
95 );\r
96 if (Sum != 0) {\r
97 return EFI_ABORTED;\r
98 }\r
99 }\r
ac0a286f 100\r
c9bba52f
LE
101 *RsdpPtr = RsdpStructurePtr;\r
102 return EFI_SUCCESS;\r
103 }\r
104 }\r
105\r
106 return EFI_NOT_FOUND;\r
107}\r
108\r
109/**\r
110 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables\r
111 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed\r
112 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.\r
113\r
114 @param AcpiProtocol Protocol instance pointer.\r
115\r
116 @return EFI_SUCCESS The table was successfully inserted.\r
117 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is\r
118 NULL, or AcpiTableBufferSize and the size\r
119 field embedded in the ACPI table pointed to\r
120 by AcpiTableBuffer are not in sync.\r
121 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.\r
122\r
123**/\r
124EFI_STATUS\r
125EFIAPI\r
126InstallXenTables (\r
ac0a286f 127 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol\r
c9bba52f
LE
128 )\r
129{\r
ac0a286f
MK
130 EFI_STATUS Status;\r
131 UINTN TableHandle;\r
132\r
133 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
134 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;\r
135 VOID *CurrentTableEntry;\r
136 UINTN CurrentTablePointer;\r
137 EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;\r
138 UINTN Index;\r
139 UINTN NumberOfTableEntries;\r
140 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;\r
141 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;\r
142 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;\r
143 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;\r
144 EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;\r
145\r
146 Fadt2Table = NULL;\r
147 Fadt1Table = NULL;\r
148 Facs2Table = NULL;\r
149 Facs1Table = NULL;\r
150 DsdtTable = NULL;\r
151 TableHandle = 0;\r
c9bba52f
LE
152 NumberOfTableEntries = 0;\r
153\r
154 //\r
155 // Try to find Xen ACPI tables\r
156 //\r
157 Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);\r
158 if (EFI_ERROR (Status)) {\r
159 return Status;\r
160 }\r
161\r
162 //\r
163 // If XSDT table is find, just install its tables.\r
164 // Otherwise, try to find and install the RSDT tables.\r
165 //\r
166 if (XenAcpiRsdpStructurePtr->XsdtAddress) {\r
167 //\r
168 // Retrieve the addresses of XSDT and\r
169 // calculate the number of its table entries.\r
170 //\r
ac0a286f
MK
171 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)\r
172 XenAcpiRsdpStructurePtr->XsdtAddress;\r
c9bba52f 173 NumberOfTableEntries = (Xsdt->Length -\r
ac0a286f
MK
174 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /\r
175 sizeof (UINT64);\r
c9bba52f
LE
176\r
177 //\r
178 // Install ACPI tables found in XSDT.\r
179 //\r
180 for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
181 //\r
182 // Get the table entry from XSDT\r
183 //\r
ac0a286f
MK
184 CurrentTableEntry = (VOID *)((UINT8 *)Xsdt +\r
185 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
186 Index * sizeof (UINT64));\r
187 CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;\r
188 CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;\r
c9bba52f
LE
189\r
190 //\r
191 // Install the XSDT tables\r
192 //\r
3f975ee5
LE
193 Status = AcpiProtocol->InstallAcpiTable (\r
194 AcpiProtocol,\r
195 CurrentTable,\r
196 CurrentTable->Length,\r
197 &TableHandle\r
198 );\r
c9bba52f
LE
199\r
200 if (EFI_ERROR (Status)) {\r
201 return Status;\r
202 }\r
203\r
204 //\r
205 // Get the FACS and DSDT table address from the table FADT\r
206 //\r
ac0a286f 207 if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {\r
c9bba52f 208 Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)\r
ac0a286f 209 (UINTN)CurrentTablePointer;\r
c9bba52f 210 Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)\r
ac0a286f
MK
211 (UINTN)Fadt2Table->FirmwareCtrl;\r
212 DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->Dsdt;\r
c9bba52f
LE
213 }\r
214 }\r
ac0a286f 215 } else if (XenAcpiRsdpStructurePtr->RsdtAddress) {\r
c9bba52f
LE
216 //\r
217 // Retrieve the addresses of RSDT and\r
218 // calculate the number of its table entries.\r
219 //\r
ac0a286f
MK
220 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)\r
221 XenAcpiRsdpStructurePtr->RsdtAddress;\r
c9bba52f 222 NumberOfTableEntries = (Rsdt->Length -\r
ac0a286f
MK
223 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /\r
224 sizeof (UINT32);\r
c9bba52f
LE
225\r
226 //\r
227 // Install ACPI tables found in XSDT.\r
228 //\r
229 for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
230 //\r
231 // Get the table entry from RSDT\r
232 //\r
ac0a286f
MK
233 CurrentTableEntry = (UINT32 *)((UINT8 *)Rsdt +\r
234 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
235 Index * sizeof (UINT32));\r
c9bba52f 236 CurrentTablePointer = *(UINT32 *)CurrentTableEntry;\r
ac0a286f 237 CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;\r
c9bba52f
LE
238\r
239 //\r
240 // Install the RSDT tables\r
241 //\r
3f975ee5
LE
242 Status = AcpiProtocol->InstallAcpiTable (\r
243 AcpiProtocol,\r
244 CurrentTable,\r
245 CurrentTable->Length,\r
246 &TableHandle\r
247 );\r
c9bba52f
LE
248\r
249 if (EFI_ERROR (Status)) {\r
250 return Status;\r
251 }\r
252\r
253 //\r
254 // Get the FACS and DSDT table address from the table FADT\r
255 //\r
ac0a286f 256 if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {\r
c9bba52f 257 Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)\r
ac0a286f 258 (UINTN)CurrentTablePointer;\r
c9bba52f 259 Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)\r
ac0a286f
MK
260 (UINTN)Fadt1Table->FirmwareCtrl;\r
261 DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt1Table->Dsdt;\r
c9bba52f
LE
262 }\r
263 }\r
264 }\r
265\r
266 //\r
267 // Install the FACS table.\r
268 //\r
269 if (Fadt2Table) {\r
270 //\r
271 // FACS 2.0\r
272 //\r
3f975ee5
LE
273 Status = AcpiProtocol->InstallAcpiTable (\r
274 AcpiProtocol,\r
275 Facs2Table,\r
276 Facs2Table->Length,\r
277 &TableHandle\r
278 );\r
c9bba52f
LE
279 if (EFI_ERROR (Status)) {\r
280 return Status;\r
281 }\r
ac0a286f 282 } else if (Fadt1Table) {\r
c9bba52f
LE
283 //\r
284 // FACS 1.0\r
285 //\r
3f975ee5
LE
286 Status = AcpiProtocol->InstallAcpiTable (\r
287 AcpiProtocol,\r
288 Facs1Table,\r
289 Facs1Table->Length,\r
290 &TableHandle\r
291 );\r
c9bba52f
LE
292 if (EFI_ERROR (Status)) {\r
293 return Status;\r
294 }\r
295 }\r
296\r
297 //\r
298 // Install DSDT table. If we reached this point without finding the DSDT,\r
299 // then we're out of sync with the hypervisor, and cannot continue.\r
300 //\r
301 if (DsdtTable == NULL) {\r
302 DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));\r
303 ASSERT (FALSE);\r
304 CpuDeadLoop ();\r
305 }\r
306\r
3f975ee5
LE
307 Status = AcpiProtocol->InstallAcpiTable (\r
308 AcpiProtocol,\r
309 DsdtTable,\r
310 DsdtTable->Length,\r
311 &TableHandle\r
312 );\r
c9bba52f
LE
313 if (EFI_ERROR (Status)) {\r
314 return Status;\r
315 }\r
316\r
317 return EFI_SUCCESS;\r
318}\r