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