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