]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
MdeModulePkg AcpiTableDxe: Install config table at ACPI data change
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiTableProtocol.c
CommitLineData
5f55c700 1/** @file\r
2 ACPI Table Protocol Implementation\r
3\r
f0071740 4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5 This program and the accompanying materials\r
5f55c700 6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15//\r
16// Includes\r
17//\r
18#include "AcpiTable.h"\r
da935a5c 19//\r
20// The maximum number of tables that pre-allocated. \r
21//\r
22UINTN mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES; \r
5f55c700 23\r
24/**\r
25 This function adds an ACPI table to the table list. It will detect FACS and\r
26 allocate the correct type of memory and properly align the table.\r
27\r
28 @param AcpiTableInstance Instance of the protocol.\r
29 @param Table Table to add.\r
30 @param Checksum Does the table require checksumming.\r
31 @param Version The version of the list to add the table to.\r
32 @param Handle Pointer for returning the handle.\r
33\r
34 @return EFI_SUCCESS The function completed successfully.\r
35 @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.\r
36 @return EFI_ABORTED The table is a duplicate of a table that is required\r
37 to be unique.\r
38\r
39**/\r
40EFI_STATUS\r
41AddTableToList (\r
42 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
43 IN VOID *Table,\r
44 IN BOOLEAN Checksum,\r
45 IN EFI_ACPI_TABLE_VERSION Version,\r
46 OUT UINTN *Handle\r
47 );\r
48\r
49/**\r
50 This function finds and removes the table specified by the handle.\r
51\r
52 @param AcpiTableInstance Instance of the protocol.\r
53 @param Version Bitmask of which versions to remove.\r
54 @param Handle Table to remove.\r
55\r
56 @return EFI_SUCCESS The function completed successfully.\r
57 @return EFI_ABORTED An error occurred.\r
58 @return EFI_NOT_FOUND Handle not found in table list.\r
59\r
60**/\r
61EFI_STATUS\r
62RemoveTableFromList (\r
63 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
64 IN EFI_ACPI_TABLE_VERSION Version,\r
65 IN UINTN Handle\r
66 );\r
67\r
68/**\r
69 This function calculates and updates an UINT8 checksum.\r
70\r
71 @param Buffer Pointer to buffer to checksum\r
72 @param Size Number of bytes to checksum\r
73 @param ChecksumOffset Offset to place the checksum result in\r
74\r
75 @return EFI_SUCCESS The function completed successfully.\r
5f55c700 76**/\r
77EFI_STATUS\r
78AcpiPlatformChecksum (\r
79 IN VOID *Buffer,\r
80 IN UINTN Size,\r
81 IN UINTN ChecksumOffset\r
82 );\r
83\r
84/**\r
85 Checksum all versions of the common tables, RSDP, RSDT, XSDT.\r
86\r
87 @param AcpiTableInstance Protocol instance private data.\r
88\r
89 @return EFI_SUCCESS The function completed successfully.\r
90\r
91**/\r
92EFI_STATUS\r
93ChecksumCommonTables (\r
94 IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
95 );\r
96\r
97//\r
98// Protocol function implementations.\r
99//\r
100\r
5f55c700 101/**\r
102 This function publishes the specified versions of the ACPI tables by\r
103 installing EFI configuration table entries for them. Any combination of\r
104 table versions can be published.\r
105\r
106 @param AcpiTableInstance Instance of the protocol.\r
107 @param Version Version(s) to publish.\r
108\r
109 @return EFI_SUCCESS The function completed successfully.\r
110 @return EFI_ABORTED The function could not complete successfully.\r
111\r
112**/\r
113EFI_STATUS\r
114EFIAPI\r
115PublishTables (\r
116 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
117 IN EFI_ACPI_TABLE_VERSION Version\r
118 )\r
119{\r
120 EFI_STATUS Status;\r
121 UINT32 *CurrentRsdtEntry;\r
122 VOID *CurrentXsdtEntry;\r
123 UINT64 Buffer64;\r
124\r
125 //\r
126 // Reorder tables as some operating systems don't seem to find the\r
127 // FADT correctly if it is not in the first few entries\r
128 //\r
129\r
130 //\r
131 // Add FADT as the first entry\r
132 //\r
133 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
134 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
135 *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt1;\r
136 }\r
f0071740 137 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 138 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
139 *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt3;\r
140 CurrentXsdtEntry = (VOID *) ((UINT8 *) AcpiTableInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
141 //\r
142 // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
143 // the table pointers in XSDT are not aligned on 8 byte boundary.\r
144 //\r
145 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Fadt3;\r
146 CopyMem (\r
147 CurrentXsdtEntry,\r
148 &Buffer64,\r
149 sizeof (UINT64)\r
150 );\r
151 }\r
152\r
153 //\r
154 // Do checksum again because Dsdt/Xsdt is updated.\r
155 //\r
156 ChecksumCommonTables (AcpiTableInstance);\r
157\r
158 //\r
159 // Add the RSD_PTR to the system table and store that we have installed the\r
160 // tables.\r
161 //\r
01267e22 162 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
5f55c700 163 Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiTableInstance->Rsdp1);\r
164 if (EFI_ERROR (Status)) {\r
165 return EFI_ABORTED;\r
166 }\r
5f55c700 167 }\r
168\r
01267e22 169 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 170 Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiTableInstance->Rsdp3);\r
171 if (EFI_ERROR (Status)) {\r
172 return EFI_ABORTED;\r
173 }\r
5f55c700 174 }\r
175\r
176 return EFI_SUCCESS;\r
177}\r
178\r
179\r
180/**\r
181 Installs an ACPI table into the RSDT/XSDT.\r
2fd3009f 182 Note that the ACPI table should be checksumed before installing it.\r
183 Otherwise it will assert.\r
5f55c700 184\r
185 @param This Protocol instance pointer.\r
186 @param AcpiTableBuffer A pointer to a buffer containing the ACPI table to be installed.\r
187 @param AcpiTableBufferSize Specifies the size, in bytes, of the AcpiTableBuffer buffer.\r
188 @param TableKey Reurns a key to refer to the ACPI table.\r
189\r
190 @return EFI_SUCCESS The table was successfully inserted.\r
191 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize \r
192 and the size field embedded in the ACPI table pointed to by AcpiTableBuffer\r
193 are not in sync.\r
194 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.\r
5966402e
SZ
195 @retval EFI_ACCESS_DENIED The table signature matches a table already\r
196 present in the system and platform policy\r
197 does not allow duplicate tables of this type.\r
5f55c700 198\r
199**/\r
200EFI_STATUS\r
201EFIAPI\r
202InstallAcpiTable (\r
db0f0d3c 203 IN EFI_ACPI_TABLE_PROTOCOL *This,\r
204 IN VOID *AcpiTableBuffer,\r
205 IN UINTN AcpiTableBufferSize,\r
206 OUT UINTN *TableKey\r
5f55c700 207 )\r
208{\r
209 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
210 EFI_STATUS Status;\r
211 VOID *AcpiTableBufferConst;\r
212\r
213 //\r
214 // Check for invalid input parameters\r
215 //\r
216 if ((AcpiTableBuffer == NULL) || (TableKey == NULL)\r
217 || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) {\r
218 return EFI_INVALID_PARAMETER;\r
219 }\r
220\r
221 //\r
222 // Get the instance of the ACPI table protocol\r
223 //\r
224 AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);\r
225\r
226 //\r
227 // Install the ACPI table\r
228 //\r
229 AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize,AcpiTableBuffer);\r
230 *TableKey = 0;\r
5966402e 231 Status = AddTableToList (\r
5f55c700 232 AcpiTableInstance,\r
233 AcpiTableBufferConst,\r
71824dd8 234 TRUE,\r
f0071740 235 EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,\r
5f55c700 236 TableKey\r
237 );\r
238 if (!EFI_ERROR (Status)) {\r
239 Status = PublishTables (\r
240 AcpiTableInstance,\r
f0071740 241 EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0\r
5f55c700 242 );\r
243 }\r
244 FreePool (AcpiTableBufferConst);\r
245 \r
3dc8585e
JY
246 //\r
247 // Add a new table successfully, notify registed callback\r
248 //\r
249 if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {\r
250 if (!EFI_ERROR (Status)) {\r
251 SdtNotifyAcpiList (\r
252 AcpiTableInstance,\r
f0071740 253 EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,\r
3dc8585e
JY
254 *TableKey\r
255 );\r
256 }\r
257 }\r
258\r
5f55c700 259 return Status;\r
260}\r
261\r
262\r
263/**\r
264 Removes an ACPI table from the RSDT/XSDT.\r
265\r
266 @param This Protocol instance pointer.\r
267 @param TableKey Specifies the table to uninstall. The key was returned from InstallAcpiTable().\r
268\r
269 @return EFI_SUCCESS The table was successfully uninstalled.\r
270 @return EFI_NOT_FOUND TableKey does not refer to a valid key for a table entry.\r
271\r
272**/\r
273EFI_STATUS\r
274EFIAPI\r
275UninstallAcpiTable (\r
db0f0d3c 276 IN EFI_ACPI_TABLE_PROTOCOL *This,\r
277 IN UINTN TableKey\r
5f55c700 278 )\r
279{\r
280 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
281 EFI_STATUS Status;\r
282\r
283 //\r
284 // Get the instance of the ACPI table protocol\r
285 //\r
286 AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);\r
287\r
288 //\r
289 // Uninstall the ACPI table\r
290 //\r
5966402e 291 Status = RemoveTableFromList (\r
5f55c700 292 AcpiTableInstance,\r
f0071740 293 EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,\r
5966402e 294 TableKey\r
5f55c700 295 );\r
296 if (!EFI_ERROR (Status)) {\r
297 Status = PublishTables (\r
298 AcpiTableInstance,\r
f0071740 299 EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0\r
5f55c700 300 );\r
301 }\r
302\r
303 if (EFI_ERROR (Status)) {\r
304 return EFI_NOT_FOUND;\r
305 } else {\r
306 return EFI_SUCCESS;\r
307 }\r
308}\r
309\r
da935a5c 310/**\r
311 If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer.\r
312\r
313 @param AcpiTableInstance ACPI table protocol instance data structure.\r
314\r
315 @return EFI_SUCCESS reallocate the table beffer successfully.\r
316 @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
317\r
318**/\r
319EFI_STATUS\r
320ReallocateAcpiTableBuffer (\r
321 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
322 )\r
323{\r
324 UINTN NewMaxTableNumber;\r
325 UINTN TotalSize;\r
326 UINT8 *Pointer;\r
327 EFI_PHYSICAL_ADDRESS PageAddress;\r
328 EFI_ACPI_TABLE_INSTANCE TempPrivateData;\r
329 EFI_STATUS Status;\r
330 UINT64 CurrentData;\r
331 \r
332 CopyMem (&TempPrivateData, AcpiTableInstance, sizeof (EFI_ACPI_TABLE_INSTANCE)); \r
333 //\r
334 // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES\r
335 //\r
336 NewMaxTableNumber = mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES;\r
337 //\r
37abfb7e 338 // Create RSDT, XSDT structures and allocate buffers.\r
da935a5c 339 //\r
37abfb7e
LG
340 TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT\r
341 NewMaxTableNumber * sizeof (UINT32) +\r
342 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT\r
343 NewMaxTableNumber * sizeof (UINT32) +\r
344 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT\r
345 NewMaxTableNumber * sizeof (UINT64);\r
da935a5c 346\r
347 //\r
348 // Allocate memory in the lower 32 bit of address range for\r
349 // compatibility with ACPI 1.0 OS.\r
350 //\r
351 // This is done because ACPI 1.0 pointers are 32 bit values.\r
352 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
353 // There is no architectural reason these should be below 4GB, it is purely\r
354 // for convenience of implementation that we force memory below 4GB.\r
355 //\r
356 PageAddress = 0xFFFFFFFF;\r
357 Status = gBS->AllocatePages (\r
358 AllocateMaxAddress,\r
359 EfiACPIReclaimMemory,\r
360 EFI_SIZE_TO_PAGES (TotalSize),\r
361 &PageAddress\r
362 );\r
363\r
364 if (EFI_ERROR (Status)) {\r
365 return EFI_OUT_OF_RESOURCES;\r
366 }\r
367\r
368 Pointer = (UINT8 *) (UINTN) PageAddress;\r
369 ZeroMem (Pointer, TotalSize);\r
370 \r
da935a5c 371 AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
372 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
373 AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
374 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
da935a5c 375 AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
5f55c700 376\r
da935a5c 377 //\r
37abfb7e 378 // Update RSDP to point to the new Rsdt and Xsdt address.\r
da935a5c 379 //\r
da935a5c 380 AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
da935a5c 381 AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
382 CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;\r
383 CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));\r
384\r
385 //\r
386 // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer \r
387 //\r
388 CopyMem (AcpiTableInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); \r
389 CopyMem (AcpiTableInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); \r
390 CopyMem (AcpiTableInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64)));\r
391 \r
392 //\r
393 // Calculate orignal ACPI table buffer size\r
394 //\r
37abfb7e
LG
395 TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT\r
396 mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
397 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT\r
398 mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
399 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT\r
400 mEfiAcpiMaxNumTables * sizeof (UINT64);\r
401 gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));\r
da935a5c 402 \r
403 //\r
404 // Update the Max ACPI table number\r
405 // \r
406 mEfiAcpiMaxNumTables = NewMaxTableNumber;\r
407 return EFI_SUCCESS;\r
408}\r
5f55c700 409/**\r
410 This function adds an ACPI table to the table list. It will detect FACS and\r
411 allocate the correct type of memory and properly align the table.\r
412\r
413 @param AcpiTableInstance Instance of the protocol.\r
414 @param Table Table to add.\r
415 @param Checksum Does the table require checksumming.\r
416 @param Version The version of the list to add the table to.\r
417 @param Handle Pointer for returning the handle.\r
418\r
419 @return EFI_SUCCESS The function completed successfully.\r
420 @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.\r
5966402e
SZ
421 @retval EFI_ACCESS_DENIED The table signature matches a table already\r
422 present in the system and platform policy\r
423 does not allow duplicate tables of this type.\r
5f55c700 424\r
425**/\r
426EFI_STATUS\r
427AddTableToList (\r
428 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
429 IN VOID *Table,\r
430 IN BOOLEAN Checksum,\r
431 IN EFI_ACPI_TABLE_VERSION Version,\r
432 OUT UINTN *Handle\r
433 )\r
434{\r
435 EFI_STATUS Status;\r
436 EFI_ACPI_TABLE_LIST *CurrentTableList;\r
437 UINT32 CurrentTableSignature;\r
438 UINT32 CurrentTableSize;\r
439 UINT32 *CurrentRsdtEntry;\r
440 VOID *CurrentXsdtEntry;\r
441 UINT64 Buffer64;\r
442 BOOLEAN AddToRsdt;\r
443\r
444 //\r
445 // Check for invalid input parameters\r
446 //\r
447 ASSERT (AcpiTableInstance);\r
448 ASSERT (Table);\r
449 ASSERT (Handle);\r
450\r
451 //\r
452 // Init locals\r
453 //\r
454 AddToRsdt = TRUE;\r
455\r
456 //\r
457 // Create a new list entry\r
458 //\r
459 CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST));\r
460 ASSERT (CurrentTableList);\r
461\r
462 //\r
463 // Determine table type and size\r
464 //\r
465 CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature;\r
466 CurrentTableSize = ((EFI_ACPI_COMMON_HEADER *) Table)->Length;\r
467\r
468 //\r
469 // Allocate a buffer for the table. All tables are allocated in the lower 32 bits of address space\r
470 // for backwards compatibility with ACPI 1.0 OS.\r
471 //\r
472 // This is done because ACPI 1.0 pointers are 32 bit values.\r
473 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
474 // There is no architectural reason these should be below 4GB, it is purely\r
475 // for convenience of implementation that we force memory below 4GB.\r
476 //\r
477 CurrentTableList->PageAddress = 0xFFFFFFFF;\r
478 CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);\r
479\r
480 //\r
481 // Allocation memory type depends on the type of the table\r
482 //\r
36d58153
JY
483 if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || \r
484 (CurrentTableSignature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE)) {\r
5f55c700 485 //\r
486 // Allocate memory for the FACS. This structure must be aligned\r
487 // on a 64 byte boundary and must be ACPI NVS memory.\r
488 // Using AllocatePages should ensure that it is always aligned.\r
36d58153
JY
489 // Do not change signature for new ACPI version because they are same.\r
490 //\r
491 // UEFI table also need to be in ACPI NVS memory, because some data field\r
492 // could be updated by OS present agent. For example, BufferPtrAddress in\r
493 // SMM communication ACPI table.\r
5f55c700 494 //\r
495 ASSERT ((EFI_PAGE_SIZE % 64) == 0);\r
496 Status = gBS->AllocatePages (\r
497 AllocateMaxAddress,\r
498 EfiACPIMemoryNVS,\r
499 CurrentTableList->NumberOfPages,\r
500 &CurrentTableList->PageAddress\r
501 );\r
502 } else {\r
503 //\r
504 // All other tables are ACPI reclaim memory, no alignment requirements.\r
505 //\r
506 Status = gBS->AllocatePages (\r
507 AllocateMaxAddress,\r
508 EfiACPIReclaimMemory,\r
509 CurrentTableList->NumberOfPages,\r
510 &CurrentTableList->PageAddress\r
511 );\r
512 }\r
513 //\r
514 // Check return value from memory alloc.\r
515 //\r
516 if (EFI_ERROR (Status)) {\r
517 gBS->FreePool (CurrentTableList);\r
518 return EFI_OUT_OF_RESOURCES;\r
519 }\r
520 //\r
521 // Update the table pointer with the allocated memory start\r
522 //\r
523 CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;\r
524\r
525 //\r
526 // Initialize the table contents\r
527 //\r
528 CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE;\r
529 CopyMem (CurrentTableList->Table, Table, CurrentTableSize);\r
530 CurrentTableList->Handle = AcpiTableInstance->CurrentHandle++;\r
531 *Handle = CurrentTableList->Handle;\r
532 CurrentTableList->Version = Version;\r
533\r
534 //\r
535 // Update internal pointers if this is a required table. If it is a required\r
536 // table and a table of that type already exists, return an error.\r
537 //\r
538 // Calculate the checksum if the table is not FACS.\r
539 //\r
540 switch (CurrentTableSignature) {\r
541\r
542 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
543 //\r
544 // We don't add the FADT in the standard way because some\r
545 // OS expect the FADT to be early in the table list.\r
546 // So we always add it as the first element in the list.\r
547 //\r
548 AddToRsdt = FALSE;\r
549\r
550 //\r
551 // Check that the table has not been previously added.\r
552 //\r
553 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Fadt1 != NULL) ||\r
f0071740 554 ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0 && AcpiTableInstance->Fadt3 != NULL)\r
5f55c700 555 ) {\r
556 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);\r
557 gBS->FreePool (CurrentTableList);\r
5966402e 558 return EFI_ACCESS_DENIED;\r
5f55c700 559 }\r
560 //\r
561 // Add the table to the appropriate table version\r
562 //\r
563 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
564 //\r
565 // Save a pointer to the table\r
566 //\r
567 AcpiTableInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;\r
568\r
569 //\r
570 // Update pointers in FADT. If tables don't exist this will put NULL pointers there.\r
571 //\r
572 AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;\r
573 AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;\r
574\r
575 //\r
576 // RSDP OEM information is updated to match the FADT OEM information\r
577 //\r
578 CopyMem (\r
579 &AcpiTableInstance->Rsdp1->OemId,\r
580 &AcpiTableInstance->Fadt1->Header.OemId,\r
581 6\r
582 );\r
583\r
584 //\r
585 // RSDT OEM information is updated to match the FADT OEM information.\r
586 //\r
587 CopyMem (\r
588 &AcpiTableInstance->Rsdt1->OemId,\r
589 &AcpiTableInstance->Fadt1->Header.OemId,\r
590 6\r
591 );\r
592\r
593 CopyMem (\r
594 &AcpiTableInstance->Rsdt1->OemTableId,\r
595 &AcpiTableInstance->Fadt1->Header.OemTableId,\r
596 sizeof (UINT64)\r
597 );\r
598 AcpiTableInstance->Rsdt1->OemRevision = AcpiTableInstance->Fadt1->Header.OemRevision;\r
599 }\r
600\r
f0071740 601 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 602 //\r
603 // Save a pointer to the table\r
604 //\r
605 AcpiTableInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;\r
606\r
607 //\r
608 // Update pointers in FADT. If tables don't exist this will put NULL pointers there.\r
c93776c2
JY
609 // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and \r
610 // vice-versa.\r
5f55c700 611 //\r
10342a64 612 if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) {\r
c93776c2 613 AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;\r
f798e8bf 614 ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));\r
c93776c2
JY
615 } else {\r
616 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;\r
617 CopyMem (\r
618 &AcpiTableInstance->Fadt3->XFirmwareCtrl,\r
619 &Buffer64,\r
620 sizeof (UINT64)\r
621 );\r
f798e8bf 622 AcpiTableInstance->Fadt3->FirmwareCtrl = 0;\r
c93776c2 623 }\r
f0c855b2 624 AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
625 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
626 CopyMem (\r
627 &AcpiTableInstance->Fadt3->XDsdt,\r
628 &Buffer64,\r
629 sizeof (UINT64)\r
630 );\r
5f55c700 631\r
f0c855b2 632 //\r
633 // RSDP OEM information is updated to match the FADT OEM information\r
634 //\r
635 CopyMem (\r
636 &AcpiTableInstance->Rsdp3->OemId,\r
637 &AcpiTableInstance->Fadt3->Header.OemId,\r
638 6\r
639 );\r
640 \r
641 //\r
642 // RSDT OEM information is updated to match FADT OEM information.\r
643 //\r
644 CopyMem (\r
645 &AcpiTableInstance->Rsdt3->OemId,\r
646 &AcpiTableInstance->Fadt3->Header.OemId,\r
647 6\r
648 );\r
649 CopyMem (\r
650 &AcpiTableInstance->Rsdt3->OemTableId,\r
651 &AcpiTableInstance->Fadt3->Header.OemTableId,\r
652 sizeof (UINT64)\r
653 );\r
654 AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
655 \r
656 //\r
657 // XSDT OEM information is updated to match FADT OEM information.\r
658 //\r
659 CopyMem (\r
660 &AcpiTableInstance->Xsdt->OemId,\r
661 &AcpiTableInstance->Fadt3->Header.OemId,\r
662 6\r
663 );\r
664 CopyMem (\r
665 &AcpiTableInstance->Xsdt->OemTableId,\r
666 &AcpiTableInstance->Fadt3->Header.OemTableId,\r
667 sizeof (UINT64)\r
668 );\r
669 AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
5f55c700 670 } \r
671 //\r
672 // Checksum the table\r
673 //\r
674 if (Checksum) {\r
675 AcpiPlatformChecksum (\r
676 CurrentTableList->Table,\r
677 CurrentTableList->Table->Length,\r
678 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
679 Checksum)\r
680 );\r
681 }\r
682 break;\r
683\r
684 case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
685 //\r
686 // Check that the table has not been previously added.\r
687 //\r
688 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||\r
f0071740 689 ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0 && AcpiTableInstance->Facs3 != NULL)\r
5f55c700 690 ) {\r
691 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);\r
692 gBS->FreePool (CurrentTableList);\r
5966402e 693 return EFI_ACCESS_DENIED;\r
5f55c700 694 }\r
695 //\r
696 // FACS is referenced by FADT and is not part of RSDT\r
697 //\r
698 AddToRsdt = FALSE;\r
699\r
700 //\r
701 // Add the table to the appropriate table version\r
702 //\r
703 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
704 //\r
705 // Save a pointer to the table\r
706 //\r
707 AcpiTableInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;\r
708\r
709 //\r
710 // If FADT already exists, update table pointers.\r
711 //\r
712 if (AcpiTableInstance->Fadt1 != NULL) {\r
713 AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;\r
714\r
715 //\r
716 // Checksum FADT table\r
717 //\r
718 AcpiPlatformChecksum (\r
719 AcpiTableInstance->Fadt1,\r
720 AcpiTableInstance->Fadt1->Header.Length,\r
721 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
722 Checksum)\r
723 );\r
724 }\r
725 }\r
726\r
f0071740 727 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 728 //\r
729 // Save a pointer to the table\r
730 //\r
731 AcpiTableInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;\r
732\r
733 //\r
734 // If FADT already exists, update table pointers.\r
735 //\r
736 if (AcpiTableInstance->Fadt3 != NULL) {\r
c93776c2
JY
737 //\r
738 // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and \r
739 // vice-versa.\r
740 //\r
10342a64 741 if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) {\r
c93776c2 742 AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;\r
f798e8bf 743 ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));\r
c93776c2
JY
744 } else {\r
745 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;\r
746 CopyMem (\r
747 &AcpiTableInstance->Fadt3->XFirmwareCtrl,\r
748 &Buffer64,\r
749 sizeof (UINT64)\r
750 );\r
f798e8bf 751 AcpiTableInstance->Fadt3->FirmwareCtrl = 0;\r
c93776c2 752 }\r
5f55c700 753\r
754 //\r
755 // Checksum FADT table\r
756 //\r
757 AcpiPlatformChecksum (\r
758 AcpiTableInstance->Fadt3,\r
759 AcpiTableInstance->Fadt3->Header.Length,\r
760 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
761 Checksum)\r
762 );\r
763 }\r
764 }\r
765\r
766 break;\r
767\r
768 case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
769 //\r
770 // Check that the table has not been previously added.\r
771 //\r
772 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||\r
f0071740 773 ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0 && AcpiTableInstance->Dsdt3 != NULL)\r
5f55c700 774 ) {\r
775 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);\r
776 gBS->FreePool (CurrentTableList);\r
5966402e 777 return EFI_ACCESS_DENIED;\r
5f55c700 778 }\r
779 //\r
780 // DSDT is referenced by FADT and is not part of RSDT\r
781 //\r
782 AddToRsdt = FALSE;\r
783\r
784 //\r
785 // Add the table to the appropriate table version\r
786 //\r
787 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
788 //\r
789 // Save a pointer to the table\r
790 //\r
791 AcpiTableInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;\r
792\r
793 //\r
794 // If FADT already exists, update table pointers.\r
795 //\r
796 if (AcpiTableInstance->Fadt1 != NULL) {\r
797 AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;\r
798\r
799 //\r
800 // Checksum FADT table\r
801 //\r
802 AcpiPlatformChecksum (\r
803 AcpiTableInstance->Fadt1,\r
804 AcpiTableInstance->Fadt1->Header.Length,\r
805 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
806 Checksum)\r
807 );\r
808 }\r
809 }\r
810 \r
f0071740 811 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 812 //\r
813 // Save a pointer to the table\r
814 //\r
815 AcpiTableInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;\r
816\r
817 //\r
818 // If FADT already exists, update table pointers.\r
819 //\r
820 if (AcpiTableInstance->Fadt3 != NULL) {\r
821 AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
822 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
823 CopyMem (\r
824 &AcpiTableInstance->Fadt3->XDsdt,\r
825 &Buffer64,\r
826 sizeof (UINT64)\r
827 );\r
828\r
829 //\r
830 // Checksum FADT table\r
831 //\r
832 AcpiPlatformChecksum (\r
833 AcpiTableInstance->Fadt3,\r
834 AcpiTableInstance->Fadt3->Header.Length,\r
835 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
836 Checksum)\r
837 );\r
838 }\r
839 } \r
840 //\r
841 // Checksum the table\r
842 //\r
843 if (Checksum) {\r
844 AcpiPlatformChecksum (\r
845 CurrentTableList->Table,\r
846 CurrentTableList->Table->Length,\r
847 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
848 Checksum)\r
849 );\r
850 }\r
851 break;\r
852\r
853 default:\r
854 //\r
855 // Checksum the table\r
856 //\r
857 if (Checksum) {\r
858 AcpiPlatformChecksum (\r
859 CurrentTableList->Table,\r
860 CurrentTableList->Table->Length,\r
861 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
862 Checksum)\r
863 );\r
864 }\r
865 break;\r
866 }\r
867 //\r
868 // Add the table to the current list of tables\r
869 //\r
870 InsertTailList (&AcpiTableInstance->TableList, &CurrentTableList->Link);\r
871\r
872 //\r
873 // Add the table to RSDT and/or XSDT table entry lists.\r
874 //\r
875 //\r
876 // Add to ACPI 1.0b table tree\r
877 //\r
878 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
5f55c700 879 if (AddToRsdt) {\r
880 //\r
da935a5c 881 // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer\r
5f55c700 882 //\r
da935a5c 883 if (AcpiTableInstance->NumberOfTableEntries1 >= mEfiAcpiMaxNumTables) {\r
884 Status = ReallocateAcpiTableBuffer (AcpiTableInstance);\r
885 ASSERT_EFI_ERROR (Status);\r
886 }\r
5f55c700 887 CurrentRsdtEntry = (UINT32 *)\r
888 (\r
da935a5c 889 (UINT8 *) AcpiTableInstance->Rsdt1 +\r
5f55c700 890 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
da935a5c 891 AcpiTableInstance->NumberOfTableEntries1 *\r
5f55c700 892 sizeof (UINT32)\r
893 );\r
894\r
895 //\r
da935a5c 896 // Add entry to the RSDT unless its the FACS or DSDT\r
5f55c700 897 //\r
898 *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
899\r
900 //\r
901 // Update RSDT length\r
902 //\r
da935a5c 903 AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);\r
5f55c700 904\r
da935a5c 905 AcpiTableInstance->NumberOfTableEntries1++;\r
906 }\r
907 }\r
908 //\r
909 // Add to ACPI 2.0/3.0 table tree\r
910 //\r
f0071740 911 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
da935a5c 912 if (AddToRsdt) {\r
913 //\r
914 // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer\r
915 //\r
916 if (AcpiTableInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) {\r
917 Status = ReallocateAcpiTableBuffer (AcpiTableInstance);\r
918 ASSERT_EFI_ERROR (Status);\r
919 }\r
920 //\r
921 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
922 // If it becomes necessary to maintain separate table lists, changes will be required.\r
923 //\r
924 CurrentRsdtEntry = (UINT32 *)\r
925 (\r
926 (UINT8 *) AcpiTableInstance->Rsdt3 +\r
927 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
928 AcpiTableInstance->NumberOfTableEntries3 *\r
929 sizeof (UINT32)\r
930 );\r
931\r
932 //\r
933 // This pointer must not be directly dereferenced as the XSDT entries may not\r
934 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.\r
935 //\r
936 CurrentXsdtEntry = (VOID *)\r
937 (\r
938 (UINT8 *) AcpiTableInstance->Xsdt +\r
939 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
940 AcpiTableInstance->NumberOfTableEntries3 *\r
941 sizeof (UINT64)\r
942 );\r
943\r
944 //\r
945 // Add entry to the RSDT\r
946 //\r
947 *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
948\r
949 //\r
950 // Update RSDT length\r
951 //\r
952 AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);\r
953\r
954 //\r
955 // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
956 // the table pointers in XSDT are not aligned on 8 byte boundary.\r
957 //\r
958 Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;\r
959 CopyMem (\r
960 CurrentXsdtEntry,\r
961 &Buffer64,\r
962 sizeof (UINT64)\r
963 );\r
964\r
965 //\r
966 // Update length\r
967 //\r
968 AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);\r
969\r
970 AcpiTableInstance->NumberOfTableEntries3++;\r
5f55c700 971 }\r
5f55c700 972 }\r
973\r
974 ChecksumCommonTables (AcpiTableInstance);\r
975 return EFI_SUCCESS;\r
976}\r
977\r
978\r
979/**\r
980 This function finds the table specified by the handle and returns a pointer to it.\r
981 If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are\r
982 undefined.\r
983\r
984 @param Handle Table to find.\r
985 @param TableList Table list to search\r
986 @param Table Pointer to table found. \r
987\r
988 @return EFI_SUCCESS The function completed successfully.\r
989 @return EFI_NOT_FOUND No table found matching the handle specified.\r
990\r
991**/\r
992EFI_STATUS\r
993FindTableByHandle (\r
994 IN UINTN Handle,\r
995 IN LIST_ENTRY *TableList,\r
996 OUT EFI_ACPI_TABLE_LIST **Table\r
997 )\r
998{\r
999 LIST_ENTRY *CurrentLink;\r
1000 EFI_ACPI_TABLE_LIST *CurrentTable;\r
1001\r
1002 //\r
1003 // Check for invalid input parameters\r
1004 //\r
1005 ASSERT (Table);\r
1006\r
1007 //\r
1008 // Find the table\r
1009 //\r
1010 CurrentLink = TableList->ForwardLink;\r
1011\r
1012 while (CurrentLink != TableList) {\r
1013 CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);\r
1014 if (CurrentTable->Handle == Handle) {\r
1015 //\r
1016 // Found handle, so return this table.\r
1017 //\r
1018 *Table = CurrentTable;\r
1019 return EFI_SUCCESS;\r
1020 }\r
1021\r
1022 CurrentLink = CurrentLink->ForwardLink;\r
1023 }\r
1024 //\r
1025 // Table not found\r
1026 //\r
1027 return EFI_NOT_FOUND;\r
1028}\r
1029\r
1030\r
1031/**\r
1032 This function removes a basic table from the RSDT and/or XSDT.\r
1033 For Acpi 1.0 tables, pass in the Rsdt.\r
1034 For Acpi 2.0 tables, pass in both Rsdt and Xsdt.\r
1035\r
1036 @param Table Pointer to table found. \r
1037 @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT\r
1038 @param Rsdt Pointer to the RSDT to remove from\r
1039 @param Xsdt Pointer to the Xsdt to remove from\r
1040\r
1041 @return EFI_SUCCESS The function completed successfully.\r
1042 @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt.\r
1043\r
1044**/\r
1045EFI_STATUS\r
1046RemoveTableFromRsdt (\r
1047 IN OUT EFI_ACPI_TABLE_LIST * Table,\r
1048 IN OUT UINTN *NumberOfTableEntries,\r
1049 IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt,\r
1050 IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL\r
1051 )\r
1052{\r
1053 UINT32 *CurrentRsdtEntry;\r
1054 VOID *CurrentXsdtEntry;\r
1055 UINT64 CurrentTablePointer64;\r
1056 UINTN Index;\r
1057\r
1058 //\r
1059 // Check for invalid input parameters\r
1060 //\r
1061 ASSERT (Table);\r
1062 ASSERT (NumberOfTableEntries);\r
1063 ASSERT (Rsdt);\r
1064\r
1065 //\r
1066 // Find the table entry in the RSDT and XSDT\r
1067 //\r
1068 for (Index = 0; Index < *NumberOfTableEntries; Index++) {\r
1069 //\r
1070 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
1071 // If it becomes necessary to maintain separate table lists, changes will be required.\r
1072 //\r
1073 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));\r
1074 if (Xsdt != NULL) {\r
1075 //\r
1076 // This pointer must not be directly dereferenced as the XSDT entries may not\r
1077 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.\r
1078 //\r
1079 CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64));\r
1080\r
1081 //\r
1082 // Read the entry value out of the XSDT\r
1083 //\r
1084 CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64));\r
1085 } else {\r
1086 //\r
1087 // Initialize to NULL\r
1088 //\r
1089 CurrentXsdtEntry = 0;\r
1090 CurrentTablePointer64 = 0;\r
1091 }\r
1092 //\r
1093 // Check if we have found the corresponding entry in both RSDT and XSDT\r
1094 //\r
1095 if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table &&\r
1096 ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)\r
1097 ) {\r
1098 //\r
1099 // Found entry, so copy all following entries and shrink table\r
1100 // We actually copy all + 1 to copy the initialized value of memory over\r
1101 // the last entry.\r
1102 //\r
1103 CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));\r
1104 Rsdt->Length = Rsdt->Length - sizeof (UINT32);\r
1105 if (Xsdt != NULL) {\r
1106 CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));\r
1107 Xsdt->Length = Xsdt->Length - sizeof (UINT64);\r
1108 }\r
1109 break;\r
1110 } else if (Index + 1 == *NumberOfTableEntries) {\r
1111 //\r
1112 // At the last entry, and table not found\r
1113 //\r
1114 return EFI_INVALID_PARAMETER;\r
1115 }\r
1116 }\r
1117 //\r
1118 // Checksum the tables\r
1119 //\r
1120 AcpiPlatformChecksum (\r
1121 Rsdt,\r
1122 Rsdt->Length,\r
1123 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1124 Checksum)\r
1125 );\r
1126\r
1127 if (Xsdt != NULL) {\r
1128 AcpiPlatformChecksum (\r
1129 Xsdt,\r
1130 Xsdt->Length,\r
1131 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1132 Checksum)\r
1133 );\r
1134 }\r
1135 //\r
1136 // Decrement the number of tables\r
1137 //\r
1138 (*NumberOfTableEntries)--;\r
1139\r
1140 return EFI_SUCCESS;\r
1141}\r
1142\r
1143\r
1144/**\r
1145 This function removes a table and frees any associated memory.\r
1146\r
1147 @param AcpiTableInstance Instance of the protocol.\r
1148 @param Version Version(s) to delete.\r
1149 @param Table Pointer to table found.\r
1150\r
1151 @return EFI_SUCCESS The function completed successfully.\r
1152\r
1153**/\r
1154EFI_STATUS\r
1155DeleteTable (\r
1156 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
1157 IN EFI_ACPI_TABLE_VERSION Version,\r
1158 IN OUT EFI_ACPI_TABLE_LIST *Table\r
1159 )\r
1160{\r
1161 UINT32 CurrentTableSignature;\r
1162 BOOLEAN RemoveFromRsdt;\r
1163\r
1164 //\r
1165 // Check for invalid input parameters\r
1166 //\r
1167 ASSERT (AcpiTableInstance);\r
1168 ASSERT (Table);\r
1169\r
1170 //\r
1171 // Init locals\r
1172 //\r
1173 RemoveFromRsdt = TRUE;\r
6198c346 1174 //\r
1175 // Check for Table->Table\r
1176 //\r
1177 ASSERT (Table->Table != NULL);\r
5f55c700 1178 CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature;\r
1179\r
1180 //\r
1181 // Basic tasks to accomplish delete are:\r
1182 // Determine removal requirements (in RSDT/XSDT or not)\r
1183 // Remove entry from RSDT/XSDT\r
1184 // Remove any table references to the table\r
1185 // If no one is using the table\r
1186 // Free the table (removing pointers from private data and tables)\r
1187 // Remove from list\r
1188 // Free list structure\r
1189 //\r
1190 //\r
1191 // Determine if this table is in the RSDT or XSDT\r
1192 //\r
1193 if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||\r
1194 (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||\r
1195 (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)\r
1196 ) {\r
1197 RemoveFromRsdt = FALSE;\r
1198 }\r
1199 //\r
1200 // We don't remove the FADT in the standard way because some\r
1201 // OS expect the FADT to be early in the table list.\r
1202 // So we always put it as the first element in the list.\r
1203 //\r
1204 if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {\r
1205 RemoveFromRsdt = FALSE;\r
1206 }\r
1207\r
1208 //\r
1209 // Remove the table from RSDT and XSDT\r
1210 //\r
1211 if (Table->Table != NULL) {\r
1212 //\r
1213 // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt\r
1214 //\r
1215 if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) {\r
1216 //\r
1217 // Remove this version from the table\r
1218 //\r
1219 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE;\r
1220 }\r
1221\r
1222 if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) {\r
1223 //\r
1224 // Remove this version from the table\r
1225 //\r
1226 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B;\r
1227\r
1228 //\r
1229 // Remove from Rsdt. We don't care about the return value because it is\r
1230 // acceptable for the table to not exist in Rsdt.\r
1231 // We didn't add some tables so we don't remove them.\r
1232 //\r
1233 if (RemoveFromRsdt) {\r
1234 RemoveTableFromRsdt (\r
1235 Table,\r
1236 &AcpiTableInstance->NumberOfTableEntries1,\r
1237 AcpiTableInstance->Rsdt1,\r
1238 NULL\r
1239 );\r
1240 }\r
1241 }\r
1242\r
f0071740 1243 if (Version & ACPI_TABLE_VERSION_GTE_2_0 & Table->Version) {\r
5f55c700 1244 //\r
1245 // Remove this version from the table\r
1246 //\r
f0071740 1247 Table->Version = Table->Version &~(Version & ACPI_TABLE_VERSION_GTE_2_0);\r
5f55c700 1248 \r
1249 //\r
1250 // Remove from Rsdt and Xsdt. We don't care about the return value\r
1251 // because it is acceptable for the table to not exist in Rsdt/Xsdt.\r
1252 // We didn't add some tables so we don't remove them.\r
1253 //\r
1254 if (RemoveFromRsdt) {\r
1255 RemoveTableFromRsdt (\r
1256 Table,\r
1257 &AcpiTableInstance->NumberOfTableEntries3,\r
1258 AcpiTableInstance->Rsdt3,\r
1259 AcpiTableInstance->Xsdt\r
1260 );\r
1261 }\r
1262 } \r
1263 //\r
1264 // Free the table, clean up any dependent tables and our private data pointers.\r
1265 //\r
1266 switch (Table->Table->Signature) {\r
1267\r
1268 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
1269 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
1270 AcpiTableInstance->Fadt1 = NULL;\r
1271 }\r
1272\r
f0071740 1273 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 1274 AcpiTableInstance->Fadt3 = NULL;\r
1275 }\r
1276 break;\r
1277\r
1278 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
1279 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
1280 AcpiTableInstance->Facs1 = NULL;\r
1281\r
1282 //\r
1283 // Update FADT table pointers\r
1284 //\r
1285 if (AcpiTableInstance->Fadt1 != NULL) {\r
1286 AcpiTableInstance->Fadt1->FirmwareCtrl = 0;\r
1287\r
1288 //\r
1289 // Checksum table\r
1290 //\r
1291 AcpiPlatformChecksum (\r
1292 AcpiTableInstance->Fadt1,\r
1293 AcpiTableInstance->Fadt1->Header.Length,\r
1294 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1295 Checksum)\r
1296 );\r
1297 }\r
1298 }\r
1299\r
f0071740 1300 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 1301 AcpiTableInstance->Facs3 = NULL;\r
1302\r
1303 //\r
1304 // Update FADT table pointers\r
1305 //\r
1306 if (AcpiTableInstance->Fadt3 != NULL) {\r
1307 AcpiTableInstance->Fadt3->FirmwareCtrl = 0;\r
1308 ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));\r
1309\r
1310 //\r
1311 // Checksum table\r
1312 //\r
1313 AcpiPlatformChecksum (\r
1314 AcpiTableInstance->Fadt3,\r
1315 AcpiTableInstance->Fadt3->Header.Length,\r
1316 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1317 Checksum)\r
1318 );\r
1319 }\r
1320 } \r
1321 break;\r
1322\r
1323 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
1324 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
1325 AcpiTableInstance->Dsdt1 = NULL;\r
1326\r
1327 //\r
1328 // Update FADT table pointers\r
1329 //\r
1330 if (AcpiTableInstance->Fadt1 != NULL) {\r
1331 AcpiTableInstance->Fadt1->Dsdt = 0;\r
1332\r
1333 //\r
1334 // Checksum table\r
1335 //\r
1336 AcpiPlatformChecksum (\r
1337 AcpiTableInstance->Fadt1,\r
1338 AcpiTableInstance->Fadt1->Header.Length,\r
1339 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1340 Checksum)\r
1341 );\r
1342 }\r
1343 }\r
1344\r
1345 \r
f0071740 1346 if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
5f55c700 1347 AcpiTableInstance->Dsdt3 = NULL;\r
1348\r
1349 //\r
1350 // Update FADT table pointers\r
1351 //\r
1352 if (AcpiTableInstance->Fadt3 != NULL) {\r
1353 AcpiTableInstance->Fadt3->Dsdt = 0;\r
1354 ZeroMem (&AcpiTableInstance->Fadt3->XDsdt, sizeof (UINT64));\r
1355\r
1356 //\r
1357 // Checksum table\r
1358 //\r
1359 AcpiPlatformChecksum (\r
1360 AcpiTableInstance->Fadt3,\r
1361 AcpiTableInstance->Fadt3->Header.Length,\r
1362 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1363 Checksum)\r
1364 );\r
1365 }\r
1366 }\r
1367 break;\r
1368\r
1369 default:\r
1370 //\r
1371 // Do nothing\r
1372 //\r
1373 break;\r
1374 }\r
1375 }\r
1376 //\r
1377 // If no version is using this table anymore, remove and free list entry.\r
1378 //\r
1379 if (Table->Version == 0) {\r
1380 //\r
1381 // Free the Table\r
1382 //\r
1383 gBS->FreePages (Table->PageAddress, Table->NumberOfPages);\r
1384 RemoveEntryList (&(Table->Link));\r
1385 gBS->FreePool (Table);\r
1386 }\r
1387 //\r
1388 // Done\r
1389 //\r
1390 return EFI_SUCCESS;\r
1391}\r
1392\r
1393\r
1394/**\r
1395 This function finds and removes the table specified by the handle.\r
1396\r
1397 @param AcpiTableInstance Instance of the protocol.\r
1398 @param Version Bitmask of which versions to remove.\r
1399 @param Handle Table to remove.\r
1400\r
1401 @return EFI_SUCCESS The function completed successfully.\r
1402 @return EFI_ABORTED An error occurred.\r
1403 @return EFI_NOT_FOUND Handle not found in table list.\r
1404\r
1405**/\r
1406EFI_STATUS\r
1407RemoveTableFromList (\r
1408 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
1409 IN EFI_ACPI_TABLE_VERSION Version,\r
1410 IN UINTN Handle\r
1411 )\r
1412{\r
1413 EFI_ACPI_TABLE_LIST *Table;\r
1414 EFI_STATUS Status;\r
1415\r
b474ed49 1416 Table = (EFI_ACPI_TABLE_LIST*) NULL;\r
1417\r
5f55c700 1418 //\r
1419 // Check for invalid input parameters\r
1420 //\r
1421 ASSERT (AcpiTableInstance);\r
1422\r
1423 //\r
1424 // Find the table\r
1425 //\r
1426 Status = FindTableByHandle (\r
1427 Handle,\r
1428 &AcpiTableInstance->TableList,\r
1429 &Table\r
1430 );\r
1431 if (EFI_ERROR (Status)) {\r
1432 return EFI_NOT_FOUND;\r
1433 }\r
1434 //\r
1435 // Remove the table\r
1436 //\r
1437 Status = DeleteTable (AcpiTableInstance, Version, Table);\r
1438 if (EFI_ERROR (Status)) {\r
1439 return EFI_ABORTED;\r
1440 }\r
1441 //\r
1442 // Completed successfully\r
1443 //\r
1444 return EFI_SUCCESS;\r
1445}\r
1446\r
1447\r
1448/**\r
1449 This function calculates and updates an UINT8 checksum.\r
1450\r
1451 @param Buffer Pointer to buffer to checksum\r
1452 @param Size Number of bytes to checksum\r
1453 @param ChecksumOffset Offset to place the checksum result in\r
1454\r
1455 @return EFI_SUCCESS The function completed successfully.\r
1456\r
1457**/\r
1458EFI_STATUS\r
1459AcpiPlatformChecksum (\r
1460 IN VOID *Buffer,\r
1461 IN UINTN Size,\r
1462 IN UINTN ChecksumOffset\r
1463 )\r
1464{\r
1465 UINT8 Sum;\r
1466 UINT8 *Ptr;\r
1467\r
1468 Sum = 0;\r
1469 //\r
1470 // Initialize pointer\r
1471 //\r
1472 Ptr = Buffer;\r
1473\r
1474 //\r
1475 // set checksum to 0 first\r
1476 //\r
1477 Ptr[ChecksumOffset] = 0;\r
1478\r
1479 //\r
1480 // add all content of buffer\r
1481 //\r
1482 while ((Size--) != 0) {\r
1483 Sum = (UINT8) (Sum + (*Ptr++));\r
1484 }\r
1485 //\r
1486 // set checksum\r
1487 //\r
1488 Ptr = Buffer;\r
1489 Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);\r
1490\r
1491 return EFI_SUCCESS;\r
1492}\r
1493\r
1494\r
1495/**\r
1496 Checksum all versions of the common tables, RSDP, RSDT, XSDT.\r
1497\r
1498 @param AcpiTableInstance Protocol instance private data.\r
1499\r
1500 @return EFI_SUCCESS The function completed successfully.\r
1501\r
1502**/\r
1503EFI_STATUS\r
1504ChecksumCommonTables (\r
1505 IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
1506 )\r
1507{\r
1508 //\r
1509 // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure\r
1510 //\r
1511 AcpiPlatformChecksum (\r
1512 AcpiTableInstance->Rsdp1,\r
1513 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),\r
1514 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,\r
1515 Checksum)\r
1516 );\r
1517\r
1518 //\r
1519 // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure\r
1520 //\r
1521 AcpiPlatformChecksum (\r
1522 AcpiTableInstance->Rsdp3,\r
1523 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),\r
1524 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,\r
1525 Checksum)\r
1526 );\r
1527\r
1528 //\r
1529 // RSDP ACPI 2.0/3.0 checksum, this is the entire table\r
1530 //\r
1531 AcpiPlatformChecksum (\r
1532 AcpiTableInstance->Rsdp3,\r
1533 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER),\r
1534 OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER,\r
1535 ExtendedChecksum)\r
1536 );\r
1537\r
1538 //\r
1539 // RSDT checksums\r
1540 //\r
1541 AcpiPlatformChecksum (\r
1542 AcpiTableInstance->Rsdt1,\r
1543 AcpiTableInstance->Rsdt1->Length,\r
1544 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1545 Checksum)\r
1546 );\r
1547\r
1548 AcpiPlatformChecksum (\r
1549 AcpiTableInstance->Rsdt3,\r
1550 AcpiTableInstance->Rsdt3->Length,\r
1551 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1552 Checksum)\r
1553 );\r
1554\r
1555 //\r
1556 // XSDT checksum\r
1557 //\r
1558 AcpiPlatformChecksum (\r
1559 AcpiTableInstance->Xsdt,\r
1560 AcpiTableInstance->Xsdt->Length,\r
1561 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
1562 Checksum)\r
1563 );\r
1564 \r
1565 return EFI_SUCCESS;\r
1566}\r
1567\r
1568\r
1569/**\r
1570 Constructor for the ACPI table protocol. Initializes instance\r
1571 data.\r
1572\r
1573 @param AcpiTableInstance Instance to construct\r
1574\r
1575 @return EFI_SUCCESS Instance initialized.\r
1576 @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
1577\r
1578**/\r
1579EFI_STATUS\r
1580AcpiTableAcpiTableConstructor (\r
1581 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
1582 )\r
1583{\r
1584 EFI_STATUS Status;\r
1585 UINT64 CurrentData;\r
1586 UINTN TotalSize;\r
37abfb7e 1587 UINTN RsdpTableSize;\r
5f55c700 1588 UINT8 *Pointer;\r
1589 EFI_PHYSICAL_ADDRESS PageAddress;\r
1590\r
1591 //\r
1592 // Check for invalid input parameters\r
1593 //\r
1594 ASSERT (AcpiTableInstance);\r
1595\r
1596 InitializeListHead (&AcpiTableInstance->TableList);\r
1597 AcpiTableInstance->CurrentHandle = 1;\r
1598\r
1599 AcpiTableInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable;\r
1600 AcpiTableInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;\r
3dc8585e
JY
1601\r
1602 if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {\r
1603 SdtAcpiTableAcpiSdtConstructor (AcpiTableInstance);\r
1604 }\r
1605\r
5f55c700 1606 //\r
37abfb7e
LG
1607 // Create RSDP table\r
1608 //\r
1609 RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
1610 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
1611\r
1612 PageAddress = 0xFFFFFFFF;\r
1613 Status = gBS->AllocatePages (\r
1614 AllocateMaxAddress,\r
1615 EfiACPIReclaimMemory,\r
1616 EFI_SIZE_TO_PAGES (RsdpTableSize),\r
1617 &PageAddress\r
1618 );\r
1619\r
1620 if (EFI_ERROR (Status)) {\r
1621 return EFI_OUT_OF_RESOURCES;\r
1622 }\r
1623\r
1624 Pointer = (UINT8 *) (UINTN) PageAddress;\r
1625 ZeroMem (Pointer, RsdpTableSize);\r
1626\r
1627 AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;\r
1628 Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
1629 AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;\r
1630\r
1631 //\r
1632 // Create RSDT, XSDT structures\r
5f55c700 1633 //\r
37abfb7e
LG
1634 TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT\r
1635 mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
1636 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT\r
1637 mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
1638 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT\r
1639 mEfiAcpiMaxNumTables * sizeof (UINT64);\r
5f55c700 1640\r
1641 //\r
1642 // Allocate memory in the lower 32 bit of address range for\r
1643 // compatibility with ACPI 1.0 OS.\r
1644 //\r
1645 // This is done because ACPI 1.0 pointers are 32 bit values.\r
1646 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
1647 // There is no architectural reason these should be below 4GB, it is purely\r
1648 // for convenience of implementation that we force memory below 4GB.\r
1649 //\r
1650 PageAddress = 0xFFFFFFFF;\r
1651 Status = gBS->AllocatePages (\r
1652 AllocateMaxAddress,\r
1653 EfiACPIReclaimMemory,\r
1654 EFI_SIZE_TO_PAGES (TotalSize),\r
1655 &PageAddress\r
1656 );\r
1657\r
1658 if (EFI_ERROR (Status)) {\r
37abfb7e 1659 gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiTableInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize));\r
5f55c700 1660 return EFI_OUT_OF_RESOURCES;\r
1661 }\r
1662\r
1663 Pointer = (UINT8 *) (UINTN) PageAddress;\r
1664 ZeroMem (Pointer, TotalSize);\r
1665\r
5f55c700 1666 AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
1667 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));\r
1668 AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
1669 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));\r
5f55c700 1670 AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
1671\r
1672 //\r
1673 // Initialize RSDP\r
1674 //\r
1675 CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;\r
1676 CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));\r
e84f07b5 1677 CopyMem (AcpiTableInstance->Rsdp1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdp1->OemId));\r
5f55c700 1678 AcpiTableInstance->Rsdp1->Reserved = EFI_ACPI_RESERVED_BYTE;\r
1679 AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
1680\r
1681 CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;\r
1682 CopyMem (&AcpiTableInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));\r
e84f07b5 1683 CopyMem (AcpiTableInstance->Rsdp3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdp3->OemId));\r
5f55c700 1684 AcpiTableInstance->Rsdp3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;\r
1685 AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
1686 AcpiTableInstance->Rsdp3->Length = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
1687 CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;\r
1688 CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));\r
1689 SetMem (AcpiTableInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);\r
1690\r
1691 //\r
1692 // Initialize Rsdt\r
1693 //\r
1694 // Note that we "reserve" one entry for the FADT so it can always be\r
1695 // at the beginning of the list of tables. Some OS don't seem\r
1696 // to find it correctly if it is too far down the list.\r
1697 //\r
1698 AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
1699 AcpiTableInstance->Rsdt1->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
1700 AcpiTableInstance->Rsdt1->Revision = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
e84f07b5
SZ
1701 CopyMem (AcpiTableInstance->Rsdt1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdt1->OemId));\r
1702 CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);\r
5f55c700 1703 CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));\r
e84f07b5
SZ
1704 AcpiTableInstance->Rsdt1->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1705 AcpiTableInstance->Rsdt1->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1706 AcpiTableInstance->Rsdt1->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
5f55c700 1707 //\r
1708 // We always reserve first one for FADT\r
1709 //\r
1710 AcpiTableInstance->NumberOfTableEntries1 = 1;\r
1711 AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);\r
1712\r
1713 AcpiTableInstance->Rsdt3->Signature = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
1714 AcpiTableInstance->Rsdt3->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
1715 AcpiTableInstance->Rsdt3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
e84f07b5
SZ
1716 CopyMem (AcpiTableInstance->Rsdt3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdt3->OemId));\r
1717 CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);\r
5f55c700 1718 CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));\r
e84f07b5
SZ
1719 AcpiTableInstance->Rsdt3->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1720 AcpiTableInstance->Rsdt3->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1721 AcpiTableInstance->Rsdt3->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
5f55c700 1722 //\r
1723 // We always reserve first one for FADT\r
1724 //\r
1725 AcpiTableInstance->NumberOfTableEntries3 = 1;\r
1726 AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);\r
1727\r
1728 //\r
1729 // Initialize Xsdt\r
1730 //\r
1731 AcpiTableInstance->Xsdt->Signature = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
1732 AcpiTableInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
1733 AcpiTableInstance->Xsdt->Revision = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
e84f07b5
SZ
1734 CopyMem (AcpiTableInstance->Xsdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Xsdt->OemId));\r
1735 CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);\r
5f55c700 1736 CopyMem (&AcpiTableInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));\r
e84f07b5
SZ
1737 AcpiTableInstance->Xsdt->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1738 AcpiTableInstance->Xsdt->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1739 AcpiTableInstance->Xsdt->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
5f55c700 1740 //\r
1741 // We always reserve first one for FADT\r
1742 //\r
1743 AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof(UINT64);\r
1744\r
1745 ChecksumCommonTables (AcpiTableInstance);\r
1746\r
1747 //\r
1748 // Completed successfully\r
1749 //\r
1750 return EFI_SUCCESS;\r
1751}\r
1752\r