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