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