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