]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AcpiPlatformDxe/Xen.c
IntelFsp2Pkg/SplitFspBin.py: Support rebasing 1.x binary.
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / Xen.c
1 /** @file
2 OVMF ACPI Xen support
3
4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "AcpiPlatform.h"
12 #include <Library/HobLib.h>
13 #include <Guid/XenInfo.h>
14 #include <Library/BaseLib.h>
15
16 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
17 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
18
19 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;
20
21 /**
22 This function detects if OVMF is running on Xen.
23
24 **/
25 BOOLEAN
26 XenDetected (
27 VOID
28 )
29 {
30 EFI_HOB_GUID_TYPE *GuidHob;
31
32 //
33 // See if a XenInfo HOB is available
34 //
35 GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
36 if (GuidHob == NULL) {
37 return FALSE;
38 }
39
40 return TRUE;
41 }
42
43 /**
44 Get the address of Xen ACPI Root System Description Pointer (RSDP)
45 structure.
46
47 @param RsdpStructurePtr Return pointer to RSDP structure
48
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.
52
53 **/
54 EFI_STATUS
55 EFIAPI
56 GetXenAcpiRsdp (
57 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
58 )
59 {
60 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
61 UINT8 *XenAcpiPtr;
62 UINT8 Sum;
63
64 //
65 // Detect the RSDP structure
66 //
67 for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;
68 XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;
69 XenAcpiPtr += 0x10) {
70
71 RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
72 (UINTN) XenAcpiPtr;
73
74 if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
75 //
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
78 //
79 Sum = CalculateSum8 (
80 (CONST UINT8 *)RsdpStructurePtr,
81 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
82 );
83 if (Sum != 0) {
84 return EFI_ABORTED;
85 }
86
87 if (RsdpStructurePtr->Revision >= 2) {
88 //
89 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
90 //
91 Sum = CalculateSum8 (
92 (CONST UINT8 *)RsdpStructurePtr,
93 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
94 );
95 if (Sum != 0) {
96 return EFI_ABORTED;
97 }
98 }
99 *RsdpPtr = RsdpStructurePtr;
100 return EFI_SUCCESS;
101 }
102 }
103
104 return EFI_NOT_FOUND;
105 }
106
107 /**
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.
111
112 @param AcpiProtocol Protocol instance pointer.
113
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.
120
121 **/
122 EFI_STATUS
123 EFIAPI
124 InstallXenTables (
125 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
126 )
127 {
128 EFI_STATUS Status;
129 UINTN TableHandle;
130
131 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
132 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
133 VOID *CurrentTableEntry;
134 UINTN CurrentTablePointer;
135 EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
136 UINTN Index;
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;
143
144 Fadt2Table = NULL;
145 Fadt1Table = NULL;
146 Facs2Table = NULL;
147 Facs1Table = NULL;
148 DsdtTable = NULL;
149 TableHandle = 0;
150 NumberOfTableEntries = 0;
151
152 //
153 // Try to find Xen ACPI tables
154 //
155 Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);
156 if (EFI_ERROR (Status)) {
157 return Status;
158 }
159
160 //
161 // If XSDT table is find, just install its tables.
162 // Otherwise, try to find and install the RSDT tables.
163 //
164 if (XenAcpiRsdpStructurePtr->XsdtAddress) {
165 //
166 // Retrieve the addresses of XSDT and
167 // calculate the number of its table entries.
168 //
169 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
170 XenAcpiRsdpStructurePtr->XsdtAddress;
171 NumberOfTableEntries = (Xsdt->Length -
172 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
173 sizeof (UINT64);
174
175 //
176 // Install ACPI tables found in XSDT.
177 //
178 for (Index = 0; Index < NumberOfTableEntries; Index++) {
179 //
180 // Get the table entry from XSDT
181 //
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;
187
188 //
189 // Install the XSDT tables
190 //
191 Status = InstallAcpiTable (
192 AcpiProtocol,
193 CurrentTable,
194 CurrentTable->Length,
195 &TableHandle
196 );
197
198 if (EFI_ERROR (Status)) {
199 return Status;
200 }
201
202 //
203 // Get the FACS and DSDT table address from the table FADT
204 //
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;
211 }
212 }
213 }
214 else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
215 //
216 // Retrieve the addresses of RSDT and
217 // calculate the number of its table entries.
218 //
219 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
220 XenAcpiRsdpStructurePtr->RsdtAddress;
221 NumberOfTableEntries = (Rsdt->Length -
222 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
223 sizeof (UINT32);
224
225 //
226 // Install ACPI tables found in XSDT.
227 //
228 for (Index = 0; Index < NumberOfTableEntries; Index++) {
229 //
230 // Get the table entry from RSDT
231 //
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;
237
238 //
239 // Install the RSDT tables
240 //
241 Status = InstallAcpiTable (
242 AcpiProtocol,
243 CurrentTable,
244 CurrentTable->Length,
245 &TableHandle
246 );
247
248 if (EFI_ERROR (Status)) {
249 return Status;
250 }
251
252 //
253 // Get the FACS and DSDT table address from the table FADT
254 //
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;
261 }
262 }
263 }
264
265 //
266 // Install the FACS table.
267 //
268 if (Fadt2Table) {
269 //
270 // FACS 2.0
271 //
272 Status = InstallAcpiTable (
273 AcpiProtocol,
274 Facs2Table,
275 Facs2Table->Length,
276 &TableHandle
277 );
278 if (EFI_ERROR (Status)) {
279 return Status;
280 }
281 }
282 else if (Fadt1Table) {
283 //
284 // FACS 1.0
285 //
286 Status = 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 = 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 }
319