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