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