]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AcpiPlatformDxe/Xen.c
OvmfPkg/AcpiPlatformDxe: Add Xen ACPI tables support
[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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "AcpiPlatform.h"
18 #include <Library/HobLib.h>
19 #include <Guid/XenInfo.h>
20
21 #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
22 #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
23
24 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;
25
26 /**
27 Calculates the checksum of the ACPI tables.
28
29 @param Buffer Address of the ACPI table.
30 @param Size Size of the ACPI table need to check.
31
32 **/
33 UINT8
34 CalculateTableChecksum (
35 IN VOID *Buffer,
36 IN UINTN Size
37 )
38 {
39 UINT8 Sum;
40 UINT8 *Ptr;
41
42 Sum = 0;
43 //
44 // Initialize pointer
45 //
46 Ptr = Buffer;
47
48 //
49 // Add all content of buffer
50 //
51 while ((Size--) != 0) {
52 Sum = (UINT8) (Sum + (*Ptr++));
53 }
54
55 return Sum;
56 }
57
58 /**
59 This function detects if OVMF is running on Xen.
60
61 **/
62 BOOLEAN
63 XenDetected (
64 VOID
65 )
66 {
67 EFI_HOB_GUID_TYPE *GuidHob;
68
69 //
70 // See if a XenInfo HOB is available
71 //
72 GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
73 if (GuidHob == NULL) {
74 return FALSE;
75 }
76
77 return TRUE;
78 }
79
80 /**
81 Get the address of Xen ACPI Root System Description Pointer (RSDP)
82 structure.
83
84 @param RsdpStructurePtr Return pointer to RSDP structure
85
86 @return EFI_SUCCESS Find Xen RSDP structure successfully.
87 @return EFI_NOT_FOUND Don't find Xen RSDP structure.
88 @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
89
90 **/
91 EFI_STATUS
92 EFIAPI
93 GetXenAcpiRsdp (
94 OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
95 )
96 {
97 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
98 UINT8 *XenAcpiPtr;
99 UINT8 Sum;
100
101 //
102 // Detect the RSDP structure
103 //
104 for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;
105 XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;
106 XenAcpiPtr += 0x10) {
107
108 RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
109 (UINTN) XenAcpiPtr;
110
111 if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
112 //
113 // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
114 // This is only the first 20 bytes of the structure
115 //
116 Sum = CalculateTableChecksum (
117 RsdpStructurePtr,
118 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
119 );
120 if (Sum != 0) {
121 return EFI_ABORTED;
122 }
123
124 if (RsdpStructurePtr->Revision >= 2) {
125 //
126 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
127 //
128 Sum = CalculateTableChecksum (
129 RsdpStructurePtr,
130 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
131 );
132 if (Sum != 0) {
133 return EFI_ABORTED;
134 }
135 }
136 *RsdpPtr = RsdpStructurePtr;
137 return EFI_SUCCESS;
138 }
139 }
140
141 return EFI_NOT_FOUND;
142 }
143
144 /**
145 Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
146 into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
147 ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
148
149 @param AcpiProtocol Protocol instance pointer.
150
151 @return EFI_SUCCESS The table was successfully inserted.
152 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
153 NULL, or AcpiTableBufferSize and the size
154 field embedded in the ACPI table pointed to
155 by AcpiTableBuffer are not in sync.
156 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
157
158 **/
159 EFI_STATUS
160 EFIAPI
161 InstallXenTables (
162 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
163 )
164 {
165 EFI_STATUS Status;
166 UINTN TableHandle;
167
168 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
169 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
170 VOID *CurrentTableEntry;
171 UINTN CurrentTablePointer;
172 EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
173 UINTN Index;
174 UINTN NumberOfTableEntries;
175 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
176 EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;
177 EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;
178 EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;
179 EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
180
181 Fadt2Table = NULL;
182 Fadt1Table = NULL;
183 Facs2Table = NULL;
184 Facs1Table = NULL;
185 DsdtTable = NULL;
186 TableHandle = 0;
187 NumberOfTableEntries = 0;
188
189 //
190 // Try to find Xen ACPI tables
191 //
192 Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);
193 if (EFI_ERROR (Status)) {
194 return Status;
195 }
196
197 //
198 // If XSDT table is find, just install its tables.
199 // Otherwise, try to find and install the RSDT tables.
200 //
201 if (XenAcpiRsdpStructurePtr->XsdtAddress) {
202 //
203 // Retrieve the addresses of XSDT and
204 // calculate the number of its table entries.
205 //
206 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
207 XenAcpiRsdpStructurePtr->XsdtAddress;
208 NumberOfTableEntries = (Xsdt->Length -
209 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
210 sizeof (UINT64);
211
212 //
213 // Install ACPI tables found in XSDT.
214 //
215 for (Index = 0; Index < NumberOfTableEntries; Index++) {
216 //
217 // Get the table entry from XSDT
218 //
219 CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +
220 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
221 Index * sizeof (UINT64));
222 CurrentTablePointer = *(UINT64 *)CurrentTableEntry;
223 CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
224
225 //
226 // Install the XSDT tables
227 //
228 Status = InstallAcpiTable (
229 AcpiProtocol,
230 CurrentTable,
231 CurrentTable->Length,
232 &TableHandle
233 );
234
235 if (EFI_ERROR (Status)) {
236 return Status;
237 }
238
239 //
240 // Get the FACS and DSDT table address from the table FADT
241 //
242 if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
243 Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
244 (UINTN) CurrentTablePointer;
245 Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
246 (UINTN) Fadt2Table->FirmwareCtrl;
247 DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt2Table->Dsdt;
248 }
249 }
250 }
251 else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
252 //
253 // Retrieve the addresses of RSDT and
254 // calculate the number of its table entries.
255 //
256 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
257 XenAcpiRsdpStructurePtr->RsdtAddress;
258 NumberOfTableEntries = (Rsdt->Length -
259 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
260 sizeof (UINT32);
261
262 //
263 // Install ACPI tables found in XSDT.
264 //
265 for (Index = 0; Index < NumberOfTableEntries; Index++) {
266 //
267 // Get the table entry from RSDT
268 //
269 CurrentTableEntry = (UINT32 *) ((UINT8 *) Rsdt +
270 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
271 Index * sizeof (UINT32));
272 CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
273 CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
274
275 //
276 // Install the RSDT tables
277 //
278 Status = InstallAcpiTable (
279 AcpiProtocol,
280 CurrentTable,
281 CurrentTable->Length,
282 &TableHandle
283 );
284
285 if (EFI_ERROR (Status)) {
286 return Status;
287 }
288
289 //
290 // Get the FACS and DSDT table address from the table FADT
291 //
292 if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
293 Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)
294 (UINTN) CurrentTablePointer;
295 Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
296 (UINTN) Fadt1Table->FirmwareCtrl;
297 DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt1Table->Dsdt;
298 }
299 }
300 }
301
302 //
303 // Install the FACS table.
304 //
305 if (Fadt2Table) {
306 //
307 // FACS 2.0
308 //
309 Status = InstallAcpiTable (
310 AcpiProtocol,
311 Facs2Table,
312 Facs2Table->Length,
313 &TableHandle
314 );
315 if (EFI_ERROR (Status)) {
316 return Status;
317 }
318 }
319 else if (Fadt1Table) {
320 //
321 // FACS 1.0
322 //
323 Status = InstallAcpiTable (
324 AcpiProtocol,
325 Facs1Table,
326 Facs1Table->Length,
327 &TableHandle
328 );
329 if (EFI_ERROR (Status)) {
330 return Status;
331 }
332 }
333
334 //
335 // Install DSDT table.
336 //
337 Status = InstallAcpiTable (
338 AcpiProtocol,
339 DsdtTable,
340 DsdtTable->Length,
341 &TableHandle
342 );
343 if (EFI_ERROR (Status)) {
344 return Status;
345 }
346
347 return EFI_SUCCESS;
348 }
349