VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c

Last change on this file was 99404, checked in by vboxsync, 13 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 12.0 KB
Line 
1/** @file
2 Sample ACPI Platform Driver
3
4 Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <PiDxe.h>
10
11#include <Protocol/AcpiTable.h>
12#include <Protocol/FirmwareVolume2.h>
13
14#include <Library/BaseLib.h>
15#include <Library/UefiBootServicesTableLib.h>
16#include <Library/DebugLib.h>
17#include <Library/PcdLib.h>
18
19#include <IndustryStandard/Acpi.h>
20
21/**
22 Locate the first instance of a protocol. If the protocol requested is an
23 FV protocol, then it will return the first FV that contains the ACPI table
24 storage file.
25
26 @param Instance Return pointer to the first instance of the protocol
27
28 @return EFI_SUCCESS The function completed successfully.
29 @return EFI_NOT_FOUND The protocol could not be located.
30 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
31
32**/
33EFI_STATUS
34LocateFvInstanceWithTables (
35 OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
36 )
37{
38 EFI_STATUS Status;
39 EFI_HANDLE *HandleBuffer;
40 UINTN NumberOfHandles;
41 EFI_FV_FILETYPE FileType;
42 UINT32 FvStatus;
43 EFI_FV_FILE_ATTRIBUTES Attributes;
44 UINTN Size;
45 UINTN Index;
46 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
47
48 FvStatus = 0;
49
50 //
51 // Locate protocol.
52 //
53 Status = gBS->LocateHandleBuffer (
54 ByProtocol,
55 &gEfiFirmwareVolume2ProtocolGuid,
56 NULL,
57 &NumberOfHandles,
58 &HandleBuffer
59 );
60 if (EFI_ERROR (Status)) {
61 //
62 // Defined errors at this time are not found and out of resources.
63 //
64 return Status;
65 }
66
67 //
68 // Looking for FV with ACPI storage file
69 //
70
71 for (Index = 0; Index < NumberOfHandles; Index++) {
72 //
73 // Get the protocol on this handle
74 // This should not fail because of LocateHandleBuffer
75 //
76 Status = gBS->HandleProtocol (
77 HandleBuffer[Index],
78 &gEfiFirmwareVolume2ProtocolGuid,
79 (VOID **)&FvInstance
80 );
81 ASSERT_EFI_ERROR (Status);
82
83 //
84 // See if it has the ACPI storage file
85 //
86 Status = FvInstance->ReadFile (
87 FvInstance,
88 (EFI_GUID *)PcdGetPtr (PcdAcpiTableStorageFile),
89 NULL,
90 &Size,
91 &FileType,
92 &Attributes,
93 &FvStatus
94 );
95
96 //
97 // If we found it, then we are done
98 //
99 if (Status == EFI_SUCCESS) {
100 *Instance = FvInstance;
101 break;
102 }
103 }
104
105 //
106 // Our exit status is determined by the success of the previous operations
107 // If the protocol was found, Instance already points to it.
108 //
109
110 //
111 // Free any allocated buffers
112 //
113 gBS->FreePool (HandleBuffer);
114
115 return Status;
116}
117
118/**
119 This function calculates and updates an UINT8 checksum.
120
121 @param Buffer Pointer to buffer to checksum
122 @param Size Number of bytes to checksum
123
124**/
125VOID
126AcpiPlatformChecksum (
127 IN UINT8 *Buffer,
128 IN UINTN Size
129 )
130{
131 UINTN ChecksumOffset;
132
133 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
134
135 //
136 // Set checksum to 0 first
137 //
138 Buffer[ChecksumOffset] = 0;
139
140 //
141 // Update checksum value
142 //
143 Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
144}
145
146#ifdef VBOX
147
148/* Disables the old code only copying a selection of tables, missing out a bunch of things available in the XSDT/RSDT. */
149# define ACPI_NO_STATIC_TABLES_SELECTION 1
150
151# define ACPI_RSD_PTR SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ')
152# define EBDA_BASE (0x9FC0 << 4)
153
154VOID *
155FindAcpiRsdPtr(VOID)
156{
157 UINTN Address;
158 UINTN Index;
159
160 //
161 // First Search 0x0e0000 - 0x0fffff for RSD Ptr
162 //
163 for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) {
164 if (*(UINT64 *)(Address) == ACPI_RSD_PTR) {
165 return (VOID *)Address;
166 }
167 }
168
169 //
170 // Search EBDA
171 //
172 Address = EBDA_BASE;
173 for (Index = 0; Index < 0x400 ; Index += 16) {
174 if (*(UINT64 *)(Address + Index) == ACPI_RSD_PTR) {
175 return (VOID *)Address;
176 }
177 }
178 return NULL;
179}
180
181#ifndef ACPI_NO_STATIC_TABLES_SELECTION
182VOID *FindSignature(VOID* Start, UINT32 Signature, BOOLEAN NoChecksum)
183{
184 UINT8 *Ptr = (UINT8*)Start;
185 UINT32 Count = 0x10000; // 16 pages
186
187 while (Count-- > 0) {
188 if ( *(UINT32*)Ptr == Signature
189 && ((EFI_ACPI_DESCRIPTION_HEADER *)Ptr)->Length <= Count
190 && (NoChecksum ||
191 CalculateCheckSum8(Ptr, ((EFI_ACPI_DESCRIPTION_HEADER *)Ptr)->Length) == 0
192 )) {
193 return Ptr;
194 }
195
196 Ptr++;
197 }
198 return NULL;
199}
200#endif
201
202VOID
203FillSysTablesInfo(VOID **Tables, UINT32 TablesSize)
204{
205 UINT32 Table = 0;
206 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdPtr;
207#ifndef ACPI_NO_STATIC_TABLES_SELECTION
208 VOID *TablesPage;
209#else
210 EFI_ACPI_DESCRIPTION_HEADER *RsdtTbl;
211#endif
212 UINT64 *PtrTbl;
213 UINT32 Index;
214
215 RsdPtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER*)FindAcpiRsdPtr();
216 ASSERT(RsdPtr != NULL);
217
218#ifndef ACPI_NO_STATIC_TABLES_SELECTION
219#define FLAG_OPTIONAL 1<<0
220#define FLAG_NO_CHECKSUM 1<<1
221 static struct {
222 UINT32 Signature;
223 UINT32 Flags;
224 CHAR8* Name;
225 } TableInfo[] = {
226 // MADT, optional
227 { SIGNATURE_32('A', 'P', 'I', 'C'), FLAG_OPTIONAL, "MADT"},
228 // FACP (also called FADT)
229 { SIGNATURE_32('F', 'A', 'C', 'P'), 0, "FADT"},
230 // FACS, according 5.2.9 of ACPI v2. spec FACS doesn't have checksum field
231 { SIGNATURE_32('F', 'A', 'C', 'S'), FLAG_NO_CHECKSUM, "FACS"},
232 // DSDT
233 { SIGNATURE_32('D', 'S', 'D', 'T'), 0, "DSDT"},
234 // SSDT
235 { SIGNATURE_32('S', 'S', 'D', 'T'), FLAG_OPTIONAL, "SSDT"},
236 // HPET
237 { SIGNATURE_32('H', 'P', 'E', 'T'), FLAG_OPTIONAL, "HPET"},
238 // MCFG
239 { SIGNATURE_32('M', 'C', 'F', 'G'), FLAG_OPTIONAL, "MCFG"}
240 };
241
242 TablesPage = (VOID *)(UINTN)((RsdPtr->RsdtAddress) & ~0xfff);
243 DEBUG((DEBUG_INFO, "TablesPage:%p\n", TablesPage));
244
245 for (Index = 0; Index < sizeof TableInfo / sizeof TableInfo[0]; Index++)
246 {
247 VOID *Ptr = FindSignature(TablesPage, TableInfo[Index].Signature,
248 (BOOLEAN)((TableInfo[Index].Flags & FLAG_NO_CHECKSUM) != 0));
249 if (TableInfo[Index].Signature == SIGNATURE_32('F', 'A', 'C', 'P'))
250 {
251 // we actually have 2 FADTs, see https://xtracker.innotek.de/index.php?bug=4082
252 Ptr = FindSignature((UINT8*)Ptr+32, SIGNATURE_32('F', 'A', 'C', 'P'), FALSE);
253 }
254 if (!(TableInfo[Index].Flags & FLAG_OPTIONAL))
255 {
256 if (!Ptr)
257 DEBUG((EFI_D_ERROR, "%a: isn't optional %p\n", TableInfo[Index].Name, Ptr));
258 ASSERT(Ptr != NULL);
259 }
260 DEBUG((EFI_D_ERROR, "%a: %p\n", TableInfo[Index].Name, Ptr));
261 if (Ptr)
262 Tables[Table++] = Ptr;
263 }
264#else
265 RsdtTbl = (EFI_ACPI_DESCRIPTION_HEADER*)(UINTN)RsdPtr->XsdtAddress;
266 DEBUG((DEBUG_INFO, "RsdtTbl:%p\n", RsdtTbl));
267
268 PtrTbl = (UINT64 *)(RsdtTbl + 1);
269 for (Index = 0; Index < (RsdtTbl->Length - sizeof(*RsdtTbl)) / sizeof(UINT64); Index++)
270 {
271 EFI_ACPI_DESCRIPTION_HEADER *Header = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)*PtrTbl++;
272 DEBUG ((DEBUG_VERBOSE, "Table %p found \"%-4.4a\" size 0x%x\n", Header, (CONST CHAR8 *)&Header->Signature, Header->Length));
273
274 if (Header->Signature == SIGNATURE_32('F', 'A', 'C', 'P'))
275 {
276 /* Add the DSDT pointer from there. */
277 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)Header;
278 DEBUG((DEBUG_INFO, "Found FACP: DSDT 0x%x FACS 0x%x XDsdt %p XFacs %p\n", Fadt->Dsdt, Fadt->FirmwareCtrl, Fadt->XDsdt, Fadt->XFirmwareCtrl));
279 Tables[Table++] = (VOID *)(UINTN)Fadt->FirmwareCtrl;
280 Tables[Table++] = (VOID *)(UINTN)Fadt->Dsdt;
281 }
282
283 Tables[Table++] = Header;
284 }
285#endif
286
287#if 0
288 // RSDT
289 ASSERT(Table < TablesSize);
290 Tables[Table] = FindSignature(TablesPage, SIGNATURE_32('R', 'S', 'D', 'T'));
291 DEBUG ((EFI_D_ERROR, "RSDT: %p\n", Tables[Table]));
292 ASSERT(Tables[Table] != NULL);
293 Table++;
294
295 // XSDT
296 ASSERT(Table < TablesSize);
297 Tables[Table] = FindSignature(TablesPage, SIGNATURE_32('X', 'S', 'D', 'T'));
298 DEBUG ((EFI_D_ERROR, "XSDT: %p\n", Tables[Table]));
299 ASSERT(Tables[Table] != NULL);
300 Table++;
301#endif
302
303 DEBUG((DEBUG_INFO, "We found %d tables (max allowed %d)\n", Table, TablesSize));
304 Tables[Table] = NULL;
305}
306
307#endif /* VBOX */
308
309
310/**
311 Entrypoint of Acpi Platform driver.
312
313 @param ImageHandle
314 @param SystemTable
315
316 @return EFI_SUCCESS
317 @return EFI_LOAD_ERROR
318 @return EFI_OUT_OF_RESOURCES
319
320**/
321EFI_STATUS
322EFIAPI
323AcpiPlatformEntryPoint (
324 IN EFI_HANDLE ImageHandle,
325 IN EFI_SYSTEM_TABLE *SystemTable
326 )
327{
328 EFI_STATUS Status;
329 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
330#ifdef VBOX
331# ifndef ACPI_NO_STATIC_TABLES_SELECTION
332 VOID *VBoxTables[10];
333# else
334 VOID *VBoxTables[128];
335# endif
336#else
337 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
338#endif
339 INTN Instance;
340 EFI_ACPI_COMMON_HEADER *CurrentTable;
341 UINTN TableHandle;
342#ifndef VBOX
343 UINT32 FvStatus;
344#endif
345 UINTN TableSize;
346 UINTN Size;
347
348 Instance = 0;
349 CurrentTable = NULL;
350 TableHandle = 0;
351
352 //
353 // Find the AcpiTable protocol
354 //
355 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
356 if (EFI_ERROR (Status)) {
357 return EFI_ABORTED;
358 }
359
360#ifdef VBOX
361 //
362 // VBOX already has tables prepared in memory - just reuse them.
363 //
364 FillSysTablesInfo(VBoxTables, sizeof(VBoxTables)/sizeof(VBoxTables[0]));
365#else
366 //
367 //
368 // Locate the firmware volume protocol
369 //
370 Status = LocateFvInstanceWithTables (&FwVol);
371 if (EFI_ERROR (Status)) {
372 return EFI_ABORTED;
373 }
374#endif
375
376 //
377 // Read tables from the storage file.
378 //
379 while (Status == EFI_SUCCESS) {
380#ifdef VBOX
381 CurrentTable = (EFI_ACPI_COMMON_HEADER *)VBoxTables[Instance];
382 Status = (CurrentTable == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
383 if (CurrentTable) {
384 Size = CurrentTable->Length;
385 DEBUG((EFI_D_ERROR, "adding %p %d\n", CurrentTable, Size));
386 } else
387 Size = 0; // Just to shut up the compiler.
388#else
389 Status = FwVol->ReadSection (
390 FwVol,
391 (EFI_GUID *)PcdGetPtr (PcdAcpiTableStorageFile),
392 EFI_SECTION_RAW,
393 Instance,
394 (VOID **)&CurrentTable,
395 &Size,
396 &FvStatus
397 );
398#endif
399 if (!EFI_ERROR (Status)) {
400 //
401 // Add the table
402 //
403 TableHandle = 0;
404
405 TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *)CurrentTable)->Length;
406#ifdef VBOX
407 DEBUG((DEBUG_INFO, "Size:%d, TableSize:%d\n", Size, TableSize));
408#endif
409 ASSERT (Size >= TableSize);
410
411 //
412 // Checksum ACPI table
413 //
414 AcpiPlatformChecksum ((UINT8 *)CurrentTable, TableSize);
415
416 //
417 // Install ACPI table
418 //
419 Status = AcpiTable->InstallAcpiTable (
420 AcpiTable,
421 CurrentTable,
422 TableSize,
423 &TableHandle
424 );
425
426#ifndef VBOX /* In case we're reading ACPI tables from memory we haven't
427 allocated this memory, so it isn't required to free it */
428 //
429 // Free memory allocated by ReadSection
430 //
431 gBS->FreePool (CurrentTable);
432
433 if (EFI_ERROR (Status)) {
434 return EFI_ABORTED;
435 }
436#endif
437
438 //
439 // Increment the instance
440 //
441 Instance++;
442 CurrentTable = NULL;
443 }
444 }
445
446 //
447 // The driver does not require to be kept loaded.
448 //
449 return EFI_REQUEST_UNLOAD_IMAGE;
450}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use