VirtualBox

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

Last change on this file since 89989 was 80721, checked in by vboxsync, 5 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

  • Property svn:eol-style set to native
File size: 10.5 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
69 //
70 // Looking for FV with ACPI storage file
71 //
72
73 for (Index = 0; Index < NumberOfHandles; Index++) {
74 //
75 // Get the protocol on this handle
76 // This should not fail because of LocateHandleBuffer
77 //
78 Status = gBS->HandleProtocol (
79 HandleBuffer[Index],
80 &gEfiFirmwareVolume2ProtocolGuid,
81 (VOID**) &FvInstance
82 );
83 ASSERT_EFI_ERROR (Status);
84
85 //
86 // See if it has the ACPI storage file
87 //
88 Status = FvInstance->ReadFile (
89 FvInstance,
90 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
91 NULL,
92 &Size,
93 &FileType,
94 &Attributes,
95 &FvStatus
96 );
97
98 //
99 // If we found it, then we are done
100 //
101 if (Status == EFI_SUCCESS) {
102 *Instance = FvInstance;
103 break;
104 }
105 }
106
107 //
108 // Our exit status is determined by the success of the previous operations
109 // If the protocol was found, Instance already points to it.
110 //
111
112 //
113 // Free any allocated buffers
114 //
115 gBS->FreePool (HandleBuffer);
116
117 return Status;
118}
119
120
121/**
122 This function calculates and updates an UINT8 checksum.
123
124 @param Buffer Pointer to buffer to checksum
125 @param Size Number of bytes to checksum
126
127**/
128VOID
129AcpiPlatformChecksum (
130 IN UINT8 *Buffer,
131 IN UINTN Size
132 )
133{
134 UINTN ChecksumOffset;
135
136 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
137
138 //
139 // Set checksum to 0 first
140 //
141 Buffer[ChecksumOffset] = 0;
142
143 //
144 // Update checksum value
145 //
146 Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size);
147}
148
149
150#ifdef VBOX
151
152# define ACPI_RSD_PTR SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ')
153# define EBDA_BASE (0x9FC0 << 4)
154
155VOID *
156FindAcpiRsdPtr(VOID)
157{
158 UINTN Address;
159 UINTN Index;
160
161 //
162 // First Search 0x0e0000 - 0x0fffff for RSD Ptr
163 //
164 for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) {
165 if (*(UINT64 *)(Address) == ACPI_RSD_PTR) {
166 return (VOID *)Address;
167 }
168 }
169
170 //
171 // Search EBDA
172 //
173 Address = EBDA_BASE;
174 for (Index = 0; Index < 0x400 ; Index += 16) {
175 if (*(UINT64 *)(Address + Index) == ACPI_RSD_PTR) {
176 return (VOID *)Address;
177 }
178 }
179 return NULL;
180}
181
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
201VOID
202FillSysTablesInfo(VOID **Tables, UINT32 TablesSize)
203{
204 UINT32 Table = 0;
205 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdPtr;
206 VOID *TablesPage;
207#define FLAG_OPTIONAL 1<<0
208#define FLAG_NO_CHECKSUM 1<<1
209 static struct {
210 UINT32 Signature;
211 UINT32 Flags;
212 CHAR8* Name;
213 } TableInfo[] = {
214 // MADT, optional
215 { SIGNATURE_32('A', 'P', 'I', 'C'), FLAG_OPTIONAL, "MADT"},
216 // FACP (also called FADT)
217 { SIGNATURE_32('F', 'A', 'C', 'P'), 0, "FADT"},
218 // FACS, according 5.2.9 of ACPI v2. spec FACS doesn't have checksum field
219 { SIGNATURE_32('F', 'A', 'C', 'S'), FLAG_NO_CHECKSUM, "FACS"},
220 // DSDT
221 { SIGNATURE_32('D', 'S', 'D', 'T'), 0, "DSDT"},
222 // SSDT
223 { SIGNATURE_32('S', 'S', 'D', 'T'), FLAG_OPTIONAL, "SSDT"},
224 // HPET
225 { SIGNATURE_32('H', 'P', 'E', 'T'), FLAG_OPTIONAL, "HPET"},
226 // MCFG
227 { SIGNATURE_32('M', 'C', 'F', 'G'), FLAG_OPTIONAL, "MCFG"}
228 };
229 UINT32 Index;
230
231 RsdPtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER*)FindAcpiRsdPtr();
232 ASSERT(RsdPtr != NULL);
233 TablesPage = (VOID*)(UINTN)((RsdPtr->RsdtAddress) & ~0xfff);
234 DEBUG((DEBUG_INFO, "TablesPage:%p\n", TablesPage));
235
236 for (Index = 0; Index < sizeof TableInfo / sizeof TableInfo[0]; Index++)
237 {
238 VOID *Ptr = FindSignature(TablesPage, TableInfo[Index].Signature,
239 (BOOLEAN)((TableInfo[Index].Flags & FLAG_NO_CHECKSUM) != 0));
240 if (TableInfo[Index].Signature == SIGNATURE_32('F', 'A', 'C', 'P'))
241 {
242 // we actually have 2 FADTs, see https://xtracker.innotek.de/index.php?bug=4082
243 Ptr = FindSignature((UINT8*)Ptr+32, SIGNATURE_32('F', 'A', 'C', 'P'), FALSE);
244 }
245 if (!(TableInfo[Index].Flags & FLAG_OPTIONAL))
246 {
247 if (!Ptr)
248 DEBUG((EFI_D_ERROR, "%a: isn't optional %p\n", TableInfo[Index].Name, Ptr));
249 ASSERT(Ptr != NULL);
250 }
251 DEBUG((EFI_D_ERROR, "%a: %p\n", TableInfo[Index].Name, Ptr));
252 if (Ptr)
253 Tables[Table++] = Ptr;
254 }
255
256#if 0
257 // RSDT
258 ASSERT(Table < TablesSize);
259 Tables[Table] = FindSignature(TablesPage, SIGNATURE_32('R', 'S', 'D', 'T'));
260 DEBUG ((EFI_D_ERROR, "RSDT: %p\n", Tables[Table]));
261 ASSERT(Tables[Table] != NULL);
262 Table++;
263
264 // XSDT
265 ASSERT(Table < TablesSize);
266 Tables[Table] = FindSignature(TablesPage, SIGNATURE_32('X', 'S', 'D', 'T'));
267 DEBUG ((EFI_D_ERROR, "XSDT: %p\n", Tables[Table]));
268 ASSERT(Tables[Table] != NULL);
269 Table++;
270#endif
271
272 DEBUG((DEBUG_INFO, "We found %d tables from %d\n", Table, TablesSize));
273 Tables[Table] = NULL;
274}
275
276#endif /* VBOX */
277
278
279/**
280 Entrypoint of Acpi Platform driver.
281
282 @param ImageHandle
283 @param SystemTable
284
285 @return EFI_SUCCESS
286 @return EFI_LOAD_ERROR
287 @return EFI_OUT_OF_RESOURCES
288
289**/
290EFI_STATUS
291EFIAPI
292AcpiPlatformEntryPoint (
293 IN EFI_HANDLE ImageHandle,
294 IN EFI_SYSTEM_TABLE *SystemTable
295 )
296{
297 EFI_STATUS Status;
298 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
299#ifdef VBOX
300 VOID *VBoxTables[10];
301#else
302 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
303#endif
304 INTN Instance;
305 EFI_ACPI_COMMON_HEADER *CurrentTable;
306 UINTN TableHandle;
307#ifndef VBOX
308 UINT32 FvStatus;
309#endif
310 UINTN TableSize;
311 UINTN Size;
312
313 Instance = 0;
314 CurrentTable = NULL;
315 TableHandle = 0;
316
317 //
318 // Find the AcpiTable protocol
319 //
320 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
321 if (EFI_ERROR (Status)) {
322 return EFI_ABORTED;
323 }
324
325#ifdef VBOX
326 //
327 // VBOX already has tables prepared in memory - just reuse them.
328 //
329 FillSysTablesInfo(VBoxTables, sizeof(VBoxTables)/sizeof(VBoxTables[0]));
330#else
331 //
332 //
333 // Locate the firmware volume protocol
334 //
335 Status = LocateFvInstanceWithTables (&FwVol);
336 if (EFI_ERROR (Status)) {
337 return EFI_ABORTED;
338 }
339#endif
340 //
341 // Read tables from the storage file.
342 //
343 while (Status == EFI_SUCCESS) {
344
345#ifdef VBOX
346 CurrentTable = (EFI_ACPI_COMMON_HEADER *)VBoxTables[Instance];
347 Status = (CurrentTable == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
348 if (CurrentTable) {
349 Size = CurrentTable->Length;
350 DEBUG((EFI_D_ERROR, "adding %p %d\n", CurrentTable, Size));
351 } else
352 Size = 0; // Just to shut up the compiler.
353#else
354 Status = FwVol->ReadSection (
355 FwVol,
356 (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
357 EFI_SECTION_RAW,
358 Instance,
359 (VOID**) &CurrentTable,
360 &Size,
361 &FvStatus
362 );
363#endif
364 if (!EFI_ERROR(Status)) {
365 //
366 // Add the table
367 //
368 TableHandle = 0;
369
370 TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
371#ifdef VBOX
372 DEBUG((DEBUG_INFO, "Size:%d, TableSize:%d\n", Size, TableSize));
373#endif
374 ASSERT (Size >= TableSize);
375
376 //
377 // Checksum ACPI table
378 //
379 AcpiPlatformChecksum ((UINT8*)CurrentTable, TableSize);
380
381 //
382 // Install ACPI table
383 //
384 Status = AcpiTable->InstallAcpiTable (
385 AcpiTable,
386 CurrentTable,
387 TableSize,
388 &TableHandle
389 );
390
391#ifndef VBOX /* In case we're reading ACPI tables from memory we haven't
392 allocated this memory, so it isn't required to free it */
393 //
394 // Free memory allocated by ReadSection
395 //
396 gBS->FreePool (CurrentTable);
397
398 if (EFI_ERROR(Status)) {
399 return EFI_ABORTED;
400 }
401#endif
402
403 //
404 // Increment the instance
405 //
406 Instance++;
407 CurrentTable = NULL;
408 }
409 }
410
411 //
412 // The driver does not require to be kept loaded.
413 //
414 return EFI_REQUEST_UNLOAD_IMAGE;
415}
416
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use