2 ACPI Table Protocol Implementation
4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "AcpiTable.h"
20 // The maximum number of tables that pre-allocated.
22 UINTN mEfiAcpiMaxNumTables
= EFI_ACPI_MAX_NUM_TABLES
;
25 This function adds an ACPI table to the table list. It will detect FACS and
26 allocate the correct type of memory and properly align the table.
28 @param AcpiTableInstance Instance of the protocol.
29 @param Table Table to add.
30 @param Checksum Does the table require checksumming.
31 @param Version The version of the list to add the table to.
32 @param Handle Pointer for returning the handle.
34 @return EFI_SUCCESS The function completed successfully.
35 @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.
36 @return EFI_ABORTED The table is a duplicate of a table that is required
42 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
,
45 IN EFI_ACPI_TABLE_VERSION Version
,
50 This function finds and removes the table specified by the handle.
52 @param AcpiTableInstance Instance of the protocol.
53 @param Version Bitmask of which versions to remove.
54 @param Handle Table to remove.
56 @return EFI_SUCCESS The function completed successfully.
57 @return EFI_ABORTED An error occurred.
58 @return EFI_NOT_FOUND Handle not found in table list.
63 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
,
64 IN EFI_ACPI_TABLE_VERSION Version
,
69 This function calculates and updates an UINT8 checksum.
71 @param Buffer Pointer to buffer to checksum
72 @param Size Number of bytes to checksum
73 @param ChecksumOffset Offset to place the checksum result in
75 @return EFI_SUCCESS The function completed successfully.
78 AcpiPlatformChecksum (
81 IN UINTN ChecksumOffset
85 Checksum all versions of the common tables, RSDP, RSDT, XSDT.
87 @param AcpiTableInstance Protocol instance private data.
89 @return EFI_SUCCESS The function completed successfully.
93 ChecksumCommonTables (
94 IN OUT EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
98 // Protocol function implementations.
102 This function publishes the specified versions of the ACPI tables by
103 installing EFI configuration table entries for them. Any combination of
104 table versions can be published.
106 @param AcpiTableInstance Instance of the protocol.
107 @param Version Version(s) to publish.
109 @return EFI_SUCCESS The function completed successfully.
110 @return EFI_ABORTED The function could not complete successfully.
116 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
,
117 IN EFI_ACPI_TABLE_VERSION Version
121 UINT32
*CurrentRsdtEntry
;
122 VOID
*CurrentXsdtEntry
;
126 // Reorder tables as some operating systems don't seem to find the
127 // FADT correctly if it is not in the first few entries
131 // Add FADT as the first entry
133 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
134 CurrentRsdtEntry
= (UINT32
*) ((UINT8
*) AcpiTableInstance
->Rsdt1
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
135 *CurrentRsdtEntry
= (UINT32
) (UINTN
) AcpiTableInstance
->Fadt1
;
137 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
138 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
139 CurrentRsdtEntry
= (UINT32
*) ((UINT8
*) AcpiTableInstance
->Rsdt3
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
140 *CurrentRsdtEntry
= (UINT32
) (UINTN
) AcpiTableInstance
->Fadt3
;
141 CurrentXsdtEntry
= (VOID
*) ((UINT8
*) AcpiTableInstance
->Xsdt
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
143 // Add entry to XSDT, XSDT expects 64 bit pointers, but
144 // the table pointers in XSDT are not aligned on 8 byte boundary.
146 Buffer64
= (UINT64
) (UINTN
) AcpiTableInstance
->Fadt3
;
155 // Do checksum again because Dsdt/Xsdt is updated.
157 ChecksumCommonTables (AcpiTableInstance
);
160 // Add the RSD_PTR to the system table and store that we have installed the
163 if (((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) &&
164 !AcpiTableInstance
->TablesInstalled1
) {
165 Status
= gBS
->InstallConfigurationTable (&gEfiAcpi10TableGuid
, AcpiTableInstance
->Rsdp1
);
166 if (EFI_ERROR (Status
)) {
170 AcpiTableInstance
->TablesInstalled1
= TRUE
;
173 if (((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
174 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) &&
175 !AcpiTableInstance
->TablesInstalled3
) {
176 Status
= gBS
->InstallConfigurationTable (&gEfiAcpiTableGuid
, AcpiTableInstance
->Rsdp3
);
177 if (EFI_ERROR (Status
)) {
181 AcpiTableInstance
->TablesInstalled3
= TRUE
;
189 Installs an ACPI table into the RSDT/XSDT.
190 Note that the ACPI table should be checksumed before installing it.
191 Otherwise it will assert.
193 @param This Protocol instance pointer.
194 @param AcpiTableBuffer A pointer to a buffer containing the ACPI table to be installed.
195 @param AcpiTableBufferSize Specifies the size, in bytes, of the AcpiTableBuffer buffer.
196 @param TableKey Reurns a key to refer to the ACPI table.
198 @return EFI_SUCCESS The table was successfully inserted.
199 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize
200 and the size field embedded in the ACPI table pointed to by AcpiTableBuffer
202 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
203 @retval EFI_ACCESS_DENIED The table signature matches a table already
204 present in the system and platform policy
205 does not allow duplicate tables of this type.
211 IN EFI_ACPI_TABLE_PROTOCOL
*This
,
212 IN VOID
*AcpiTableBuffer
,
213 IN UINTN AcpiTableBufferSize
,
217 EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
;
219 VOID
*AcpiTableBufferConst
;
222 // Check for invalid input parameters
224 if ((AcpiTableBuffer
== NULL
) || (TableKey
== NULL
)
225 || (((EFI_ACPI_DESCRIPTION_HEADER
*) AcpiTableBuffer
)->Length
!= AcpiTableBufferSize
)) {
226 return EFI_INVALID_PARAMETER
;
230 // Get the instance of the ACPI table protocol
232 AcpiTableInstance
= EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This
);
235 // Install the ACPI table
237 AcpiTableBufferConst
= AllocateCopyPool (AcpiTableBufferSize
,AcpiTableBuffer
);
239 Status
= AddTableToList (
241 AcpiTableBufferConst
,
243 EFI_ACPI_TABLE_VERSION_1_0B
| EFI_ACPI_TABLE_VERSION_2_0
| EFI_ACPI_TABLE_VERSION_3_0
,
246 if (!EFI_ERROR (Status
)) {
247 Status
= PublishTables (
249 EFI_ACPI_TABLE_VERSION_1_0B
| EFI_ACPI_TABLE_VERSION_2_0
| EFI_ACPI_TABLE_VERSION_3_0
252 FreePool (AcpiTableBufferConst
);
255 // Add a new table successfully, notify registed callback
257 if (FeaturePcdGet (PcdInstallAcpiSdtProtocol
)) {
258 if (!EFI_ERROR (Status
)) {
261 EFI_ACPI_TABLE_VERSION_1_0B
| EFI_ACPI_TABLE_VERSION_2_0
| EFI_ACPI_TABLE_VERSION_3_0
,
272 Removes an ACPI table from the RSDT/XSDT.
274 @param This Protocol instance pointer.
275 @param TableKey Specifies the table to uninstall. The key was returned from InstallAcpiTable().
277 @return EFI_SUCCESS The table was successfully uninstalled.
278 @return EFI_NOT_FOUND TableKey does not refer to a valid key for a table entry.
284 IN EFI_ACPI_TABLE_PROTOCOL
*This
,
288 EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
;
292 // Get the instance of the ACPI table protocol
294 AcpiTableInstance
= EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This
);
297 // Uninstall the ACPI table
299 Status
= RemoveTableFromList (
301 EFI_ACPI_TABLE_VERSION_1_0B
| EFI_ACPI_TABLE_VERSION_2_0
| EFI_ACPI_TABLE_VERSION_3_0
,
304 if (!EFI_ERROR (Status
)) {
305 Status
= PublishTables (
307 EFI_ACPI_TABLE_VERSION_1_0B
| EFI_ACPI_TABLE_VERSION_2_0
| EFI_ACPI_TABLE_VERSION_3_0
311 if (EFI_ERROR (Status
)) {
312 return EFI_NOT_FOUND
;
319 If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer.
321 @param AcpiTableInstance ACPI table protocol instance data structure.
323 @return EFI_SUCCESS reallocate the table beffer successfully.
324 @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.
328 ReallocateAcpiTableBuffer (
329 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
332 UINTN NewMaxTableNumber
;
335 EFI_PHYSICAL_ADDRESS PageAddress
;
336 EFI_ACPI_TABLE_INSTANCE TempPrivateData
;
340 CopyMem (&TempPrivateData
, AcpiTableInstance
, sizeof (EFI_ACPI_TABLE_INSTANCE
));
342 // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES
344 NewMaxTableNumber
= mEfiAcpiMaxNumTables
+ EFI_ACPI_MAX_NUM_TABLES
;
346 // Create RSDT, XSDT structures and allocate buffers.
348 TotalSize
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 1.0 RSDT
349 NewMaxTableNumber
* sizeof (UINT32
) +
350 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 2.0/3.0 RSDT
351 NewMaxTableNumber
* sizeof (UINT32
) +
352 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 2.0/3.0 XSDT
353 NewMaxTableNumber
* sizeof (UINT64
);
356 // Allocate memory in the lower 32 bit of address range for
357 // compatibility with ACPI 1.0 OS.
359 // This is done because ACPI 1.0 pointers are 32 bit values.
360 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
361 // There is no architectural reason these should be below 4GB, it is purely
362 // for convenience of implementation that we force memory below 4GB.
364 PageAddress
= 0xFFFFFFFF;
365 Status
= gBS
->AllocatePages (
367 EfiACPIReclaimMemory
,
368 EFI_SIZE_TO_PAGES (TotalSize
),
372 if (EFI_ERROR (Status
)) {
373 return EFI_OUT_OF_RESOURCES
;
376 Pointer
= (UINT8
*) (UINTN
) PageAddress
;
377 ZeroMem (Pointer
, TotalSize
);
379 AcpiTableInstance
->Rsdt1
= (EFI_ACPI_DESCRIPTION_HEADER
*) Pointer
;
380 Pointer
+= (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + NewMaxTableNumber
* sizeof (UINT32
));
381 AcpiTableInstance
->Rsdt3
= (EFI_ACPI_DESCRIPTION_HEADER
*) Pointer
;
382 Pointer
+= (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + NewMaxTableNumber
* sizeof (UINT32
));
383 AcpiTableInstance
->Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) Pointer
;
386 // Update RSDP to point to the new Rsdt and Xsdt address.
388 AcpiTableInstance
->Rsdp1
->RsdtAddress
= (UINT32
) (UINTN
) AcpiTableInstance
->Rsdt1
;
389 AcpiTableInstance
->Rsdp3
->RsdtAddress
= (UINT32
) (UINTN
) AcpiTableInstance
->Rsdt3
;
390 CurrentData
= (UINT64
) (UINTN
) AcpiTableInstance
->Xsdt
;
391 CopyMem (&AcpiTableInstance
->Rsdp3
->XsdtAddress
, &CurrentData
, sizeof (UINT64
));
394 // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer
396 CopyMem (AcpiTableInstance
->Rsdt1
, TempPrivateData
.Rsdt1
, (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + mEfiAcpiMaxNumTables
* sizeof (UINT32
)));
397 CopyMem (AcpiTableInstance
->Rsdt3
, TempPrivateData
.Rsdt3
, (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + mEfiAcpiMaxNumTables
* sizeof (UINT32
)));
398 CopyMem (AcpiTableInstance
->Xsdt
, TempPrivateData
.Xsdt
, (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + mEfiAcpiMaxNumTables
* sizeof (UINT64
)));
401 // Calculate orignal ACPI table buffer size
403 TotalSize
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 1.0 RSDT
404 mEfiAcpiMaxNumTables
* sizeof (UINT32
) +
405 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 2.0/3.0 RSDT
406 mEfiAcpiMaxNumTables
* sizeof (UINT32
) +
407 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 2.0/3.0 XSDT
408 mEfiAcpiMaxNumTables
* sizeof (UINT64
);
409 gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
)(UINTN
)TempPrivateData
.Rsdt1
, EFI_SIZE_TO_PAGES (TotalSize
));
412 // Update the Max ACPI table number
414 mEfiAcpiMaxNumTables
= NewMaxTableNumber
;
418 This function adds an ACPI table to the table list. It will detect FACS and
419 allocate the correct type of memory and properly align the table.
421 @param AcpiTableInstance Instance of the protocol.
422 @param Table Table to add.
423 @param Checksum Does the table require checksumming.
424 @param Version The version of the list to add the table to.
425 @param Handle Pointer for returning the handle.
427 @return EFI_SUCCESS The function completed successfully.
428 @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.
429 @retval EFI_ACCESS_DENIED The table signature matches a table already
430 present in the system and platform policy
431 does not allow duplicate tables of this type.
436 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
,
439 IN EFI_ACPI_TABLE_VERSION Version
,
444 EFI_ACPI_TABLE_LIST
*CurrentTableList
;
445 UINT32 CurrentTableSignature
;
446 UINT32 CurrentTableSize
;
447 UINT32
*CurrentRsdtEntry
;
448 VOID
*CurrentXsdtEntry
;
453 // Check for invalid input parameters
455 ASSERT (AcpiTableInstance
);
465 // Create a new list entry
467 CurrentTableList
= AllocatePool (sizeof (EFI_ACPI_TABLE_LIST
));
468 ASSERT (CurrentTableList
);
471 // Determine table type and size
473 CurrentTableSignature
= ((EFI_ACPI_COMMON_HEADER
*) Table
)->Signature
;
474 CurrentTableSize
= ((EFI_ACPI_COMMON_HEADER
*) Table
)->Length
;
477 // Allocate a buffer for the table. All tables are allocated in the lower 32 bits of address space
478 // for backwards compatibility with ACPI 1.0 OS.
480 // This is done because ACPI 1.0 pointers are 32 bit values.
481 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
482 // There is no architectural reason these should be below 4GB, it is purely
483 // for convenience of implementation that we force memory below 4GB.
485 CurrentTableList
->PageAddress
= 0xFFFFFFFF;
486 CurrentTableList
->NumberOfPages
= EFI_SIZE_TO_PAGES (CurrentTableSize
);
489 // Allocation memory type depends on the type of the table
491 if ((CurrentTableSignature
== EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
) ||
492 (CurrentTableSignature
== EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE
)) {
494 // Allocate memory for the FACS. This structure must be aligned
495 // on a 64 byte boundary and must be ACPI NVS memory.
496 // Using AllocatePages should ensure that it is always aligned.
497 // Do not change signature for new ACPI version because they are same.
499 // UEFI table also need to be in ACPI NVS memory, because some data field
500 // could be updated by OS present agent. For example, BufferPtrAddress in
501 // SMM communication ACPI table.
503 ASSERT ((EFI_PAGE_SIZE
% 64) == 0);
504 Status
= gBS
->AllocatePages (
507 CurrentTableList
->NumberOfPages
,
508 &CurrentTableList
->PageAddress
512 // All other tables are ACPI reclaim memory, no alignment requirements.
514 Status
= gBS
->AllocatePages (
516 EfiACPIReclaimMemory
,
517 CurrentTableList
->NumberOfPages
,
518 &CurrentTableList
->PageAddress
522 // Check return value from memory alloc.
524 if (EFI_ERROR (Status
)) {
525 gBS
->FreePool (CurrentTableList
);
526 return EFI_OUT_OF_RESOURCES
;
529 // Update the table pointer with the allocated memory start
531 CurrentTableList
->Table
= (EFI_ACPI_COMMON_HEADER
*) (UINTN
) CurrentTableList
->PageAddress
;
534 // Initialize the table contents
536 CurrentTableList
->Signature
= EFI_ACPI_TABLE_LIST_SIGNATURE
;
537 CopyMem (CurrentTableList
->Table
, Table
, CurrentTableSize
);
538 CurrentTableList
->Handle
= AcpiTableInstance
->CurrentHandle
++;
539 *Handle
= CurrentTableList
->Handle
;
540 CurrentTableList
->Version
= Version
;
543 // Update internal pointers if this is a required table. If it is a required
544 // table and a table of that type already exists, return an error.
546 // Calculate the checksum if the table is not FACS.
548 switch (CurrentTableSignature
) {
550 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
552 // We don't add the FADT in the standard way because some
553 // OS expect the FADT to be early in the table list.
554 // So we always add it as the first element in the list.
559 // Check that the table has not been previously added.
561 if (((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0 && AcpiTableInstance
->Fadt1
!= NULL
) ||
562 ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 && AcpiTableInstance
->Fadt3
!= NULL
) ||
563 ((Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0 && AcpiTableInstance
->Fadt3
!= NULL
)
565 gBS
->FreePages (CurrentTableList
->PageAddress
, CurrentTableList
->NumberOfPages
);
566 gBS
->FreePool (CurrentTableList
);
567 return EFI_ACCESS_DENIED
;
570 // Add the table to the appropriate table version
572 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
574 // Save a pointer to the table
576 AcpiTableInstance
->Fadt1
= (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
*) CurrentTableList
->Table
;
579 // Update pointers in FADT. If tables don't exist this will put NULL pointers there.
581 AcpiTableInstance
->Fadt1
->FirmwareCtrl
= (UINT32
) (UINTN
) AcpiTableInstance
->Facs1
;
582 AcpiTableInstance
->Fadt1
->Dsdt
= (UINT32
) (UINTN
) AcpiTableInstance
->Dsdt1
;
585 // RSDP OEM information is updated to match the FADT OEM information
588 &AcpiTableInstance
->Rsdp1
->OemId
,
589 &AcpiTableInstance
->Fadt1
->Header
.OemId
,
594 // RSDT OEM information is updated to match the FADT OEM information.
597 &AcpiTableInstance
->Rsdt1
->OemId
,
598 &AcpiTableInstance
->Fadt1
->Header
.OemId
,
603 &AcpiTableInstance
->Rsdt1
->OemTableId
,
604 &AcpiTableInstance
->Fadt1
->Header
.OemTableId
,
607 AcpiTableInstance
->Rsdt1
->OemRevision
= AcpiTableInstance
->Fadt1
->Header
.OemRevision
;
610 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
611 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
613 // Save a pointer to the table
615 AcpiTableInstance
->Fadt3
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*) CurrentTableList
->Table
;
618 // Update pointers in FADT. If tables don't exist this will put NULL pointers there.
619 // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and
622 if ((UINT64
)(UINTN
)AcpiTableInstance
->Facs3
< BASE_4GB
) {
623 AcpiTableInstance
->Fadt3
->FirmwareCtrl
= (UINT32
) (UINTN
) AcpiTableInstance
->Facs3
;
625 Buffer64
= (UINT64
) (UINTN
) AcpiTableInstance
->Facs3
;
627 &AcpiTableInstance
->Fadt3
->XFirmwareCtrl
,
632 AcpiTableInstance
->Fadt3
->Dsdt
= (UINT32
) (UINTN
) AcpiTableInstance
->Dsdt3
;
633 Buffer64
= (UINT64
) (UINTN
) AcpiTableInstance
->Dsdt3
;
635 &AcpiTableInstance
->Fadt3
->XDsdt
,
641 // RSDP OEM information is updated to match the FADT OEM information
644 &AcpiTableInstance
->Rsdp3
->OemId
,
645 &AcpiTableInstance
->Fadt3
->Header
.OemId
,
650 // RSDT OEM information is updated to match FADT OEM information.
653 &AcpiTableInstance
->Rsdt3
->OemId
,
654 &AcpiTableInstance
->Fadt3
->Header
.OemId
,
658 &AcpiTableInstance
->Rsdt3
->OemTableId
,
659 &AcpiTableInstance
->Fadt3
->Header
.OemTableId
,
662 AcpiTableInstance
->Rsdt3
->OemRevision
= AcpiTableInstance
->Fadt3
->Header
.OemRevision
;
665 // XSDT OEM information is updated to match FADT OEM information.
668 &AcpiTableInstance
->Xsdt
->OemId
,
669 &AcpiTableInstance
->Fadt3
->Header
.OemId
,
673 &AcpiTableInstance
->Xsdt
->OemTableId
,
674 &AcpiTableInstance
->Fadt3
->Header
.OemTableId
,
677 AcpiTableInstance
->Xsdt
->OemRevision
= AcpiTableInstance
->Fadt3
->Header
.OemRevision
;
680 // Checksum the table
683 AcpiPlatformChecksum (
684 CurrentTableList
->Table
,
685 CurrentTableList
->Table
->Length
,
686 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
692 case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
694 // Check that the table has not been previously added.
696 if (((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0 && AcpiTableInstance
->Facs1
!= NULL
) ||
697 ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 && AcpiTableInstance
->Facs3
!= NULL
) ||
698 ((Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0 && AcpiTableInstance
->Facs3
!= NULL
)
700 gBS
->FreePages (CurrentTableList
->PageAddress
, CurrentTableList
->NumberOfPages
);
701 gBS
->FreePool (CurrentTableList
);
702 return EFI_ACCESS_DENIED
;
705 // FACS is referenced by FADT and is not part of RSDT
710 // Add the table to the appropriate table version
712 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
714 // Save a pointer to the table
716 AcpiTableInstance
->Facs1
= (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*) CurrentTableList
->Table
;
719 // If FADT already exists, update table pointers.
721 if (AcpiTableInstance
->Fadt1
!= NULL
) {
722 AcpiTableInstance
->Fadt1
->FirmwareCtrl
= (UINT32
) (UINTN
) AcpiTableInstance
->Facs1
;
725 // Checksum FADT table
727 AcpiPlatformChecksum (
728 AcpiTableInstance
->Fadt1
,
729 AcpiTableInstance
->Fadt1
->Header
.Length
,
730 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
736 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
737 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
739 // Save a pointer to the table
741 AcpiTableInstance
->Facs3
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*) CurrentTableList
->Table
;
744 // If FADT already exists, update table pointers.
746 if (AcpiTableInstance
->Fadt3
!= NULL
) {
748 // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and
751 if ((UINT64
)(UINTN
)AcpiTableInstance
->Facs3
< BASE_4GB
) {
752 AcpiTableInstance
->Fadt3
->FirmwareCtrl
= (UINT32
) (UINTN
) AcpiTableInstance
->Facs3
;
754 Buffer64
= (UINT64
) (UINTN
) AcpiTableInstance
->Facs3
;
756 &AcpiTableInstance
->Fadt3
->XFirmwareCtrl
,
763 // Checksum FADT table
765 AcpiPlatformChecksum (
766 AcpiTableInstance
->Fadt3
,
767 AcpiTableInstance
->Fadt3
->Header
.Length
,
768 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
776 case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
778 // Check that the table has not been previously added.
780 if (((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0 && AcpiTableInstance
->Dsdt1
!= NULL
) ||
781 ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 && AcpiTableInstance
->Dsdt3
!= NULL
) ||
782 ((Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0 && AcpiTableInstance
->Dsdt3
!= NULL
)
784 gBS
->FreePages (CurrentTableList
->PageAddress
, CurrentTableList
->NumberOfPages
);
785 gBS
->FreePool (CurrentTableList
);
786 return EFI_ACCESS_DENIED
;
789 // DSDT is referenced by FADT and is not part of RSDT
794 // Add the table to the appropriate table version
796 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
798 // Save a pointer to the table
800 AcpiTableInstance
->Dsdt1
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTableList
->Table
;
803 // If FADT already exists, update table pointers.
805 if (AcpiTableInstance
->Fadt1
!= NULL
) {
806 AcpiTableInstance
->Fadt1
->Dsdt
= (UINT32
) (UINTN
) AcpiTableInstance
->Dsdt1
;
809 // Checksum FADT table
811 AcpiPlatformChecksum (
812 AcpiTableInstance
->Fadt1
,
813 AcpiTableInstance
->Fadt1
->Header
.Length
,
814 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
820 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
821 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
823 // Save a pointer to the table
825 AcpiTableInstance
->Dsdt3
= (EFI_ACPI_DESCRIPTION_HEADER
*) CurrentTableList
->Table
;
828 // If FADT already exists, update table pointers.
830 if (AcpiTableInstance
->Fadt3
!= NULL
) {
831 AcpiTableInstance
->Fadt3
->Dsdt
= (UINT32
) (UINTN
) AcpiTableInstance
->Dsdt3
;
832 Buffer64
= (UINT64
) (UINTN
) AcpiTableInstance
->Dsdt3
;
834 &AcpiTableInstance
->Fadt3
->XDsdt
,
840 // Checksum FADT table
842 AcpiPlatformChecksum (
843 AcpiTableInstance
->Fadt3
,
844 AcpiTableInstance
->Fadt3
->Header
.Length
,
845 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
851 // Checksum the table
854 AcpiPlatformChecksum (
855 CurrentTableList
->Table
,
856 CurrentTableList
->Table
->Length
,
857 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
865 // Checksum the table
868 AcpiPlatformChecksum (
869 CurrentTableList
->Table
,
870 CurrentTableList
->Table
->Length
,
871 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
878 // Add the table to the current list of tables
880 InsertTailList (&AcpiTableInstance
->TableList
, &CurrentTableList
->Link
);
883 // Add the table to RSDT and/or XSDT table entry lists.
886 // Add to ACPI 1.0b table tree
888 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
891 // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer
893 if (AcpiTableInstance
->NumberOfTableEntries1
>= mEfiAcpiMaxNumTables
) {
894 Status
= ReallocateAcpiTableBuffer (AcpiTableInstance
);
895 ASSERT_EFI_ERROR (Status
);
897 CurrentRsdtEntry
= (UINT32
*)
899 (UINT8
*) AcpiTableInstance
->Rsdt1
+
900 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
901 AcpiTableInstance
->NumberOfTableEntries1
*
906 // Add entry to the RSDT unless its the FACS or DSDT
908 *CurrentRsdtEntry
= (UINT32
) (UINTN
) CurrentTableList
->Table
;
911 // Update RSDT length
913 AcpiTableInstance
->Rsdt1
->Length
= AcpiTableInstance
->Rsdt1
->Length
+ sizeof (UINT32
);
915 AcpiTableInstance
->NumberOfTableEntries1
++;
919 // Add to ACPI 2.0/3.0 table tree
921 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
922 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
925 // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer
927 if (AcpiTableInstance
->NumberOfTableEntries3
>= mEfiAcpiMaxNumTables
) {
928 Status
= ReallocateAcpiTableBuffer (AcpiTableInstance
);
929 ASSERT_EFI_ERROR (Status
);
932 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
933 // If it becomes necessary to maintain separate table lists, changes will be required.
935 CurrentRsdtEntry
= (UINT32
*)
937 (UINT8
*) AcpiTableInstance
->Rsdt3
+
938 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
939 AcpiTableInstance
->NumberOfTableEntries3
*
944 // This pointer must not be directly dereferenced as the XSDT entries may not
945 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
947 CurrentXsdtEntry
= (VOID
*)
949 (UINT8
*) AcpiTableInstance
->Xsdt
+
950 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) +
951 AcpiTableInstance
->NumberOfTableEntries3
*
956 // Add entry to the RSDT
958 *CurrentRsdtEntry
= (UINT32
) (UINTN
) CurrentTableList
->Table
;
961 // Update RSDT length
963 AcpiTableInstance
->Rsdt3
->Length
= AcpiTableInstance
->Rsdt3
->Length
+ sizeof (UINT32
);
966 // Add entry to XSDT, XSDT expects 64 bit pointers, but
967 // the table pointers in XSDT are not aligned on 8 byte boundary.
969 Buffer64
= (UINT64
) (UINTN
) CurrentTableList
->Table
;
979 AcpiTableInstance
->Xsdt
->Length
= AcpiTableInstance
->Xsdt
->Length
+ sizeof (UINT64
);
981 AcpiTableInstance
->NumberOfTableEntries3
++;
985 ChecksumCommonTables (AcpiTableInstance
);
991 This function finds the table specified by the handle and returns a pointer to it.
992 If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are
995 @param Handle Table to find.
996 @param TableList Table list to search
997 @param Table Pointer to table found.
999 @return EFI_SUCCESS The function completed successfully.
1000 @return EFI_NOT_FOUND No table found matching the handle specified.
1006 IN LIST_ENTRY
*TableList
,
1007 OUT EFI_ACPI_TABLE_LIST
**Table
1010 LIST_ENTRY
*CurrentLink
;
1011 EFI_ACPI_TABLE_LIST
*CurrentTable
;
1014 // Check for invalid input parameters
1021 CurrentLink
= TableList
->ForwardLink
;
1023 while (CurrentLink
!= TableList
) {
1024 CurrentTable
= EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink
);
1025 if (CurrentTable
->Handle
== Handle
) {
1027 // Found handle, so return this table.
1029 *Table
= CurrentTable
;
1033 CurrentLink
= CurrentLink
->ForwardLink
;
1038 return EFI_NOT_FOUND
;
1043 This function removes a basic table from the RSDT and/or XSDT.
1044 For Acpi 1.0 tables, pass in the Rsdt.
1045 For Acpi 2.0 tables, pass in both Rsdt and Xsdt.
1047 @param Table Pointer to table found.
1048 @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT
1049 @param Rsdt Pointer to the RSDT to remove from
1050 @param Xsdt Pointer to the Xsdt to remove from
1052 @return EFI_SUCCESS The function completed successfully.
1053 @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt.
1057 RemoveTableFromRsdt (
1058 IN OUT EFI_ACPI_TABLE_LIST
* Table
,
1059 IN OUT UINTN
*NumberOfTableEntries
,
1060 IN OUT EFI_ACPI_DESCRIPTION_HEADER
* Rsdt
,
1061 IN OUT EFI_ACPI_DESCRIPTION_HEADER
* Xsdt OPTIONAL
1064 UINT32
*CurrentRsdtEntry
;
1065 VOID
*CurrentXsdtEntry
;
1066 UINT64 CurrentTablePointer64
;
1070 // Check for invalid input parameters
1073 ASSERT (NumberOfTableEntries
);
1077 // Find the table entry in the RSDT and XSDT
1079 for (Index
= 0; Index
< *NumberOfTableEntries
; Index
++) {
1081 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
1082 // If it becomes necessary to maintain separate table lists, changes will be required.
1084 CurrentRsdtEntry
= (UINT32
*) ((UINT8
*) Rsdt
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + Index
* sizeof (UINT32
));
1087 // This pointer must not be directly dereferenced as the XSDT entries may not
1088 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
1090 CurrentXsdtEntry
= (VOID
*) ((UINT8
*) Xsdt
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + Index
* sizeof (UINT64
));
1093 // Read the entry value out of the XSDT
1095 CopyMem (&CurrentTablePointer64
, CurrentXsdtEntry
, sizeof (UINT64
));
1098 // Initialize to NULL
1100 CurrentXsdtEntry
= 0;
1101 CurrentTablePointer64
= 0;
1104 // Check if we have found the corresponding entry in both RSDT and XSDT
1106 if (*CurrentRsdtEntry
== (UINT32
) (UINTN
) Table
->Table
&&
1107 ((Xsdt
== NULL
) || CurrentTablePointer64
== (UINT64
) (UINTN
) Table
->Table
)
1110 // Found entry, so copy all following entries and shrink table
1111 // We actually copy all + 1 to copy the initialized value of memory over
1114 CopyMem (CurrentRsdtEntry
, CurrentRsdtEntry
+ 1, (*NumberOfTableEntries
- Index
) * sizeof (UINT32
));
1115 Rsdt
->Length
= Rsdt
->Length
- sizeof (UINT32
);
1117 CopyMem (CurrentXsdtEntry
, ((UINT64
*) CurrentXsdtEntry
) + 1, (*NumberOfTableEntries
- Index
) * sizeof (UINT64
));
1118 Xsdt
->Length
= Xsdt
->Length
- sizeof (UINT64
);
1121 } else if (Index
+ 1 == *NumberOfTableEntries
) {
1123 // At the last entry, and table not found
1125 return EFI_INVALID_PARAMETER
;
1129 // Checksum the tables
1131 AcpiPlatformChecksum (
1134 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1139 AcpiPlatformChecksum (
1142 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1147 // Decrement the number of tables
1149 (*NumberOfTableEntries
)--;
1156 This function removes a table and frees any associated memory.
1158 @param AcpiTableInstance Instance of the protocol.
1159 @param Version Version(s) to delete.
1160 @param Table Pointer to table found.
1162 @return EFI_SUCCESS The function completed successfully.
1167 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
,
1168 IN EFI_ACPI_TABLE_VERSION Version
,
1169 IN OUT EFI_ACPI_TABLE_LIST
*Table
1172 UINT32 CurrentTableSignature
;
1173 BOOLEAN RemoveFromRsdt
;
1176 // Check for invalid input parameters
1178 ASSERT (AcpiTableInstance
);
1184 RemoveFromRsdt
= TRUE
;
1186 // Check for Table->Table
1188 ASSERT (Table
->Table
!= NULL
);
1189 CurrentTableSignature
= ((EFI_ACPI_COMMON_HEADER
*) Table
->Table
)->Signature
;
1192 // Basic tasks to accomplish delete are:
1193 // Determine removal requirements (in RSDT/XSDT or not)
1194 // Remove entry from RSDT/XSDT
1195 // Remove any table references to the table
1196 // If no one is using the table
1197 // Free the table (removing pointers from private data and tables)
1199 // Free list structure
1202 // Determine if this table is in the RSDT or XSDT
1204 if ((CurrentTableSignature
== EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
) ||
1205 (CurrentTableSignature
== EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
) ||
1206 (CurrentTableSignature
== EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
)
1208 RemoveFromRsdt
= FALSE
;
1211 // We don't remove the FADT in the standard way because some
1212 // OS expect the FADT to be early in the table list.
1213 // So we always put it as the first element in the list.
1215 if (CurrentTableSignature
== EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
1216 RemoveFromRsdt
= FALSE
;
1220 // Remove the table from RSDT and XSDT
1222 if (Table
->Table
!= NULL
) {
1224 // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt
1226 if (Version
& EFI_ACPI_TABLE_VERSION_NONE
& Table
->Version
) {
1228 // Remove this version from the table
1230 Table
->Version
= Table
->Version
&~EFI_ACPI_TABLE_VERSION_NONE
;
1233 if (Version
& EFI_ACPI_TABLE_VERSION_1_0B
& Table
->Version
) {
1235 // Remove this version from the table
1237 Table
->Version
= Table
->Version
&~EFI_ACPI_TABLE_VERSION_1_0B
;
1240 // Remove from Rsdt. We don't care about the return value because it is
1241 // acceptable for the table to not exist in Rsdt.
1242 // We didn't add some tables so we don't remove them.
1244 if (RemoveFromRsdt
) {
1245 RemoveTableFromRsdt (
1247 &AcpiTableInstance
->NumberOfTableEntries1
,
1248 AcpiTableInstance
->Rsdt1
,
1254 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
& Table
->Version
) ||
1255 (Version
& EFI_ACPI_TABLE_VERSION_3_0
& Table
->Version
)) {
1257 // Remove this version from the table
1259 if (Version
& EFI_ACPI_TABLE_VERSION_2_0
& Table
->Version
) {
1260 Table
->Version
= Table
->Version
&~EFI_ACPI_TABLE_VERSION_2_0
;
1262 if (Version
& EFI_ACPI_TABLE_VERSION_3_0
& Table
->Version
) {
1263 Table
->Version
= Table
->Version
&~EFI_ACPI_TABLE_VERSION_3_0
;
1267 // Remove from Rsdt and Xsdt. We don't care about the return value
1268 // because it is acceptable for the table to not exist in Rsdt/Xsdt.
1269 // We didn't add some tables so we don't remove them.
1271 if (RemoveFromRsdt
) {
1272 RemoveTableFromRsdt (
1274 &AcpiTableInstance
->NumberOfTableEntries3
,
1275 AcpiTableInstance
->Rsdt3
,
1276 AcpiTableInstance
->Xsdt
1281 // Free the table, clean up any dependent tables and our private data pointers.
1283 switch (Table
->Table
->Signature
) {
1285 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
1286 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
1287 AcpiTableInstance
->Fadt1
= NULL
;
1290 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
1291 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
1292 AcpiTableInstance
->Fadt3
= NULL
;
1296 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
1297 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
1298 AcpiTableInstance
->Facs1
= NULL
;
1301 // Update FADT table pointers
1303 if (AcpiTableInstance
->Fadt1
!= NULL
) {
1304 AcpiTableInstance
->Fadt1
->FirmwareCtrl
= 0;
1309 AcpiPlatformChecksum (
1310 AcpiTableInstance
->Fadt1
,
1311 AcpiTableInstance
->Fadt1
->Header
.Length
,
1312 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1318 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
1319 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
1320 AcpiTableInstance
->Facs3
= NULL
;
1323 // Update FADT table pointers
1325 if (AcpiTableInstance
->Fadt3
!= NULL
) {
1326 AcpiTableInstance
->Fadt3
->FirmwareCtrl
= 0;
1327 ZeroMem (&AcpiTableInstance
->Fadt3
->XFirmwareCtrl
, sizeof (UINT64
));
1332 AcpiPlatformChecksum (
1333 AcpiTableInstance
->Fadt3
,
1334 AcpiTableInstance
->Fadt3
->Header
.Length
,
1335 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1342 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
1343 if ((Version
& EFI_ACPI_TABLE_VERSION_1_0B
) != 0) {
1344 AcpiTableInstance
->Dsdt1
= NULL
;
1347 // Update FADT table pointers
1349 if (AcpiTableInstance
->Fadt1
!= NULL
) {
1350 AcpiTableInstance
->Fadt1
->Dsdt
= 0;
1355 AcpiPlatformChecksum (
1356 AcpiTableInstance
->Fadt1
,
1357 AcpiTableInstance
->Fadt1
->Header
.Length
,
1358 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1365 if ((Version
& EFI_ACPI_TABLE_VERSION_2_0
) != 0 ||
1366 (Version
& EFI_ACPI_TABLE_VERSION_3_0
) != 0) {
1367 AcpiTableInstance
->Dsdt3
= NULL
;
1370 // Update FADT table pointers
1372 if (AcpiTableInstance
->Fadt3
!= NULL
) {
1373 AcpiTableInstance
->Fadt3
->Dsdt
= 0;
1374 ZeroMem (&AcpiTableInstance
->Fadt3
->XDsdt
, sizeof (UINT64
));
1379 AcpiPlatformChecksum (
1380 AcpiTableInstance
->Fadt3
,
1381 AcpiTableInstance
->Fadt3
->Header
.Length
,
1382 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1397 // If no version is using this table anymore, remove and free list entry.
1399 if (Table
->Version
== 0) {
1403 gBS
->FreePages (Table
->PageAddress
, Table
->NumberOfPages
);
1404 RemoveEntryList (&(Table
->Link
));
1405 gBS
->FreePool (Table
);
1415 This function finds and removes the table specified by the handle.
1417 @param AcpiTableInstance Instance of the protocol.
1418 @param Version Bitmask of which versions to remove.
1419 @param Handle Table to remove.
1421 @return EFI_SUCCESS The function completed successfully.
1422 @return EFI_ABORTED An error occurred.
1423 @return EFI_NOT_FOUND Handle not found in table list.
1427 RemoveTableFromList (
1428 IN EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
,
1429 IN EFI_ACPI_TABLE_VERSION Version
,
1433 EFI_ACPI_TABLE_LIST
*Table
;
1436 Table
= (EFI_ACPI_TABLE_LIST
*) NULL
;
1439 // Check for invalid input parameters
1441 ASSERT (AcpiTableInstance
);
1446 Status
= FindTableByHandle (
1448 &AcpiTableInstance
->TableList
,
1451 if (EFI_ERROR (Status
)) {
1452 return EFI_NOT_FOUND
;
1457 Status
= DeleteTable (AcpiTableInstance
, Version
, Table
);
1458 if (EFI_ERROR (Status
)) {
1462 // Completed successfully
1469 This function calculates and updates an UINT8 checksum.
1471 @param Buffer Pointer to buffer to checksum
1472 @param Size Number of bytes to checksum
1473 @param ChecksumOffset Offset to place the checksum result in
1475 @return EFI_SUCCESS The function completed successfully.
1479 AcpiPlatformChecksum (
1482 IN UINTN ChecksumOffset
1490 // Initialize pointer
1495 // set checksum to 0 first
1497 Ptr
[ChecksumOffset
] = 0;
1500 // add all content of buffer
1502 while ((Size
--) != 0) {
1503 Sum
= (UINT8
) (Sum
+ (*Ptr
++));
1509 Ptr
[ChecksumOffset
] = (UINT8
) (0xff - Sum
+ 1);
1516 Checksum all versions of the common tables, RSDP, RSDT, XSDT.
1518 @param AcpiTableInstance Protocol instance private data.
1520 @return EFI_SUCCESS The function completed successfully.
1524 ChecksumCommonTables (
1525 IN OUT EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
1529 // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure
1531 AcpiPlatformChecksum (
1532 AcpiTableInstance
->Rsdp1
,
1533 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
),
1534 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
,
1539 // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure
1541 AcpiPlatformChecksum (
1542 AcpiTableInstance
->Rsdp3
,
1543 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
),
1544 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
,
1549 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
1551 AcpiPlatformChecksum (
1552 AcpiTableInstance
->Rsdp3
,
1553 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
),
1554 OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
,
1561 AcpiPlatformChecksum (
1562 AcpiTableInstance
->Rsdt1
,
1563 AcpiTableInstance
->Rsdt1
->Length
,
1564 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1568 AcpiPlatformChecksum (
1569 AcpiTableInstance
->Rsdt3
,
1570 AcpiTableInstance
->Rsdt3
->Length
,
1571 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1578 AcpiPlatformChecksum (
1579 AcpiTableInstance
->Xsdt
,
1580 AcpiTableInstance
->Xsdt
->Length
,
1581 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
,
1590 Constructor for the ACPI table protocol. Initializes instance
1593 @param AcpiTableInstance Instance to construct
1595 @return EFI_SUCCESS Instance initialized.
1596 @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1600 AcpiTableAcpiTableConstructor (
1601 EFI_ACPI_TABLE_INSTANCE
*AcpiTableInstance
1607 UINTN RsdpTableSize
;
1609 EFI_PHYSICAL_ADDRESS PageAddress
;
1612 // Check for invalid input parameters
1614 ASSERT (AcpiTableInstance
);
1616 InitializeListHead (&AcpiTableInstance
->TableList
);
1617 AcpiTableInstance
->CurrentHandle
= 1;
1619 AcpiTableInstance
->AcpiTableProtocol
.InstallAcpiTable
= InstallAcpiTable
;
1620 AcpiTableInstance
->AcpiTableProtocol
.UninstallAcpiTable
= UninstallAcpiTable
;
1622 if (FeaturePcdGet (PcdInstallAcpiSdtProtocol
)) {
1623 SdtAcpiTableAcpiSdtConstructor (AcpiTableInstance
);
1627 // Create RSDP table
1629 RsdpTableSize
= sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
) +
1630 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
);
1632 PageAddress
= 0xFFFFFFFF;
1633 Status
= gBS
->AllocatePages (
1635 EfiACPIReclaimMemory
,
1636 EFI_SIZE_TO_PAGES (RsdpTableSize
),
1640 if (EFI_ERROR (Status
)) {
1641 return EFI_OUT_OF_RESOURCES
;
1644 Pointer
= (UINT8
*) (UINTN
) PageAddress
;
1645 ZeroMem (Pointer
, RsdpTableSize
);
1647 AcpiTableInstance
->Rsdp1
= (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*) Pointer
;
1648 Pointer
+= sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
);
1649 AcpiTableInstance
->Rsdp3
= (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*) Pointer
;
1652 // Create RSDT, XSDT structures
1654 TotalSize
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 1.0 RSDT
1655 mEfiAcpiMaxNumTables
* sizeof (UINT32
) +
1656 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 2.0/3.0 RSDT
1657 mEfiAcpiMaxNumTables
* sizeof (UINT32
) +
1658 sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + // for ACPI 2.0/3.0 XSDT
1659 mEfiAcpiMaxNumTables
* sizeof (UINT64
);
1662 // Allocate memory in the lower 32 bit of address range for
1663 // compatibility with ACPI 1.0 OS.
1665 // This is done because ACPI 1.0 pointers are 32 bit values.
1666 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
1667 // There is no architectural reason these should be below 4GB, it is purely
1668 // for convenience of implementation that we force memory below 4GB.
1670 PageAddress
= 0xFFFFFFFF;
1671 Status
= gBS
->AllocatePages (
1673 EfiACPIReclaimMemory
,
1674 EFI_SIZE_TO_PAGES (TotalSize
),
1678 if (EFI_ERROR (Status
)) {
1679 gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
)(UINTN
)AcpiTableInstance
->Rsdp1
, EFI_SIZE_TO_PAGES (RsdpTableSize
));
1680 return EFI_OUT_OF_RESOURCES
;
1683 Pointer
= (UINT8
*) (UINTN
) PageAddress
;
1684 ZeroMem (Pointer
, TotalSize
);
1686 AcpiTableInstance
->Rsdt1
= (EFI_ACPI_DESCRIPTION_HEADER
*) Pointer
;
1687 Pointer
+= (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + EFI_ACPI_MAX_NUM_TABLES
* sizeof (UINT32
));
1688 AcpiTableInstance
->Rsdt3
= (EFI_ACPI_DESCRIPTION_HEADER
*) Pointer
;
1689 Pointer
+= (sizeof (EFI_ACPI_DESCRIPTION_HEADER
) + EFI_ACPI_MAX_NUM_TABLES
* sizeof (UINT32
));
1690 AcpiTableInstance
->Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*) Pointer
;
1695 CurrentData
= EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE
;
1696 CopyMem (&AcpiTableInstance
->Rsdp1
->Signature
, &CurrentData
, sizeof (UINT64
));
1697 CopyMem (AcpiTableInstance
->Rsdp1
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (AcpiTableInstance
->Rsdp1
->OemId
));
1698 AcpiTableInstance
->Rsdp1
->Reserved
= EFI_ACPI_RESERVED_BYTE
;
1699 AcpiTableInstance
->Rsdp1
->RsdtAddress
= (UINT32
) (UINTN
) AcpiTableInstance
->Rsdt1
;
1701 CurrentData
= EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE
;
1702 CopyMem (&AcpiTableInstance
->Rsdp3
->Signature
, &CurrentData
, sizeof (UINT64
));
1703 CopyMem (AcpiTableInstance
->Rsdp3
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (AcpiTableInstance
->Rsdp3
->OemId
));
1704 AcpiTableInstance
->Rsdp3
->Revision
= EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION
;
1705 AcpiTableInstance
->Rsdp3
->RsdtAddress
= (UINT32
) (UINTN
) AcpiTableInstance
->Rsdt3
;
1706 AcpiTableInstance
->Rsdp3
->Length
= sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
);
1707 CurrentData
= (UINT64
) (UINTN
) AcpiTableInstance
->Xsdt
;
1708 CopyMem (&AcpiTableInstance
->Rsdp3
->XsdtAddress
, &CurrentData
, sizeof (UINT64
));
1709 SetMem (AcpiTableInstance
->Rsdp3
->Reserved
, 3, EFI_ACPI_RESERVED_BYTE
);
1714 // Note that we "reserve" one entry for the FADT so it can always be
1715 // at the beginning of the list of tables. Some OS don't seem
1716 // to find it correctly if it is too far down the list.
1718 AcpiTableInstance
->Rsdt1
->Signature
= EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
;
1719 AcpiTableInstance
->Rsdt1
->Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
1720 AcpiTableInstance
->Rsdt1
->Revision
= EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION
;
1721 CopyMem (AcpiTableInstance
->Rsdt1
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (AcpiTableInstance
->Rsdt1
->OemId
));
1722 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1723 CopyMem (&AcpiTableInstance
->Rsdt1
->OemTableId
, &CurrentData
, sizeof (UINT64
));
1724 AcpiTableInstance
->Rsdt1
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1725 AcpiTableInstance
->Rsdt1
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1726 AcpiTableInstance
->Rsdt1
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1728 // We always reserve first one for FADT
1730 AcpiTableInstance
->NumberOfTableEntries1
= 1;
1731 AcpiTableInstance
->Rsdt1
->Length
= AcpiTableInstance
->Rsdt1
->Length
+ sizeof(UINT32
);
1733 AcpiTableInstance
->Rsdt3
->Signature
= EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
;
1734 AcpiTableInstance
->Rsdt3
->Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
1735 AcpiTableInstance
->Rsdt3
->Revision
= EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION
;
1736 CopyMem (AcpiTableInstance
->Rsdt3
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (AcpiTableInstance
->Rsdt3
->OemId
));
1737 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1738 CopyMem (&AcpiTableInstance
->Rsdt3
->OemTableId
, &CurrentData
, sizeof (UINT64
));
1739 AcpiTableInstance
->Rsdt3
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1740 AcpiTableInstance
->Rsdt3
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1741 AcpiTableInstance
->Rsdt3
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1743 // We always reserve first one for FADT
1745 AcpiTableInstance
->NumberOfTableEntries3
= 1;
1746 AcpiTableInstance
->Rsdt3
->Length
= AcpiTableInstance
->Rsdt3
->Length
+ sizeof(UINT32
);
1751 AcpiTableInstance
->Xsdt
->Signature
= EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
;
1752 AcpiTableInstance
->Xsdt
->Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
1753 AcpiTableInstance
->Xsdt
->Revision
= EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION
;
1754 CopyMem (AcpiTableInstance
->Xsdt
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (AcpiTableInstance
->Xsdt
->OemId
));
1755 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1756 CopyMem (&AcpiTableInstance
->Xsdt
->OemTableId
, &CurrentData
, sizeof (UINT64
));
1757 AcpiTableInstance
->Xsdt
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1758 AcpiTableInstance
->Xsdt
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1759 AcpiTableInstance
->Xsdt
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1761 // We always reserve first one for FADT
1763 AcpiTableInstance
->Xsdt
->Length
= AcpiTableInstance
->Xsdt
->Length
+ sizeof(UINT64
);
1765 ChecksumCommonTables (AcpiTableInstance
);
1768 // Completed successfully