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