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