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