summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2009-03-20 20:58:47 +0000
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>2009-03-20 20:58:47 +0000
commit5f55c7004666d6bf8cb421b09781cbd1ceb9eddc (patch)
tree569357b5d6771ef9c401dc1e6f64e15c0070fa75
parent3c506ddd9e06bfb5dee1030edb5ff835e00bfb80 (diff)
downloadedk2-platforms-5f55c7004666d6bf8cb421b09781cbd1ceb9eddc.tar.xz
Add ACPI drivers:
* Universal/Acpi/AcpiTableDxe Implementation of EFI_ACPI_TABLE_PROTOCOL (MdePkg/Include/Protocol/AcpiTable.h) * Universal/Acpi/AcpiPlatformDxe Sample "ACPI Platform Driver" which populates the system ACPI tables by reading them from an FFS file and using EFI_ACPI_TABLE_PROTOCOL to make them available to the system. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7917 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc3
-rwxr-xr-xMdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c254
-rwxr-xr-xMdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf55
-rwxr-xr-xMdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.c77
-rwxr-xr-xMdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h197
-rwxr-xr-xMdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf60
-rwxr-xr-xMdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c1703
7 files changed, 2349 insertions, 0 deletions
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 9fab0b92b8..98dbf0f2e0 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -330,6 +330,9 @@
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+
[Components.IA32, Components.X64]
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
diff --git a/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c b/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100755
index 0000000000..f7d7485c56
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,254 @@
+/** @file
+ Sample ACPI Platform Driver
+
+ Copyright (c) 2008 - 2009, Intel Corporation<BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+/**
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+ @param Protocol The protocol to find.
+ @param Instance Return pointer to the first instance of the protocol
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_NOT_FOUND The protocol could not be located.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateFvInstanceWithTables (
+ OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+
+
+
+ //
+ // Looking for FV with ACPI storage file
+ //
+
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID**) &FvInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // See if it has the ACPI storage file
+ //
+ Status = FvInstance->ReadFile (
+ FvInstance,
+ FixedPcdGetPtr (PcdAcpiTableStorageFile),
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ //
+ // If we found it, then we are done
+ //
+ if (Status == EFI_SUCCESS) {
+ *Instance = FvInstance;
+ break;
+ }
+ }
+
+ //
+ // Our exit status is determined by the success of the previous operations
+ // If the protocol was found, Instance already points to it.
+ //
+
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
+
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param Buffer Pointer to buffer to checksum
+ @param Size Number of bytes to checksum
+
+**/
+VOID
+AcpiPlatformChecksum (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+{
+ UINTN ChecksumOffset;
+
+ ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
+
+ //
+ // Set checksum to 0 first
+ //
+ Buffer[ChecksumOffset] = 0;
+
+ //
+ // Update checksum value
+ //
+ Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size);
+}
+
+
+/**
+ Entrypoint of Acpi Platform driver.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINTN TableSize;
+ UINTN Size;
+
+ Instance = 0;
+ CurrentTable = NULL;
+ TableHandle = 0;
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateFvInstanceWithTables (&FwVol);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Read tables from the storage file.
+ //
+ while (Status == EFI_SUCCESS) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ FixedPcdGetPtr (PcdAcpiTableStorageFile),
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID**) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+
+ TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
+ ASSERT (Size >= TableSize);
+
+ //
+ // Checksum ACPI table
+ //
+ AcpiPlatformChecksum ((UINT8*)CurrentTable, TableSize);
+
+ //
+ // Install ACPI table
+ //
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ TableSize,
+ &TableHandle
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf b/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100755
index 0000000000..14b9e10091
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,55 @@
+#/** @file
+# Sample ACPI Platform Driver
+#
+# Copyright (c) 2008 - 2009, Intel Corporation. <BR>
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = cb933912-df8f-4305-b1f9-7b44fa11395c
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ AcpiPlatform.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiLib
+ DxeServicesLib
+ PcdLib
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[FixedPcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
+
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.c
new file mode 100755
index 0000000000..773c0f7c80
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.c
@@ -0,0 +1,77 @@
+/** @file
+ ACPI Table Protocol Driver
+
+ Copyright (c) 2006, 2008, 2009, Intel Corporation<BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Includes
+//
+#include "AcpiTable.h"
+
+//
+// Handle to install ACPI Table Protocol
+//
+EFI_HANDLE mHandle = NULL;
+
+/**
+ Entry point of the ACPI table driver.
+ Creates and initializes an instance of the ACPI Table
+ Protocol and installs it on a new handle.
+
+ @param ImageHandle A handle for the image that is initializing this driver.
+ @param SystemTable A pointer to the EFI system table.
+
+ @return EFI_SUCCESS Driver initialized successfully.
+ @return EFI_LOAD_ERROR Failed to Initialize or has been loaded.
+ @return EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeAcpiTableDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_INSTANCE *PrivateData;
+
+ //
+ // Initialize our protocol
+ //
+ PrivateData = AllocateZeroPool (sizeof (EFI_ACPI_TABLE_INSTANCE));
+ ASSERT (PrivateData);
+ PrivateData->Signature = EFI_ACPI_TABLE_SIGNATURE;
+
+ //
+ // Call all constructors per produced protocols
+ //
+ Status = AcpiTableAcpiTableConstructor (PrivateData);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PrivateData);
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Install ACPI Table protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiAcpiTableProtocolGuid,
+ &PrivateData->AcpiTableProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
new file mode 100755
index 0000000000..3c40709d8e
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
@@ -0,0 +1,197 @@
+/** @file
+ ACPI Table Protocol Driver
+
+ Copyright (c) 2006 - 2009, Intel Corporation<BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ACPI_TABLE_H_
+#define _ACPI_TABLE_H_
+
+
+#include <PiDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Guid/Acpi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// From Protocol/AcpiSupport.h
+//
+
+//
+// ACPI Version bitmap definition:
+//
+// EFI_ACPI_TABLE_VERSION_1_0B - ACPI Version 1.0b
+// EFI_ACPI_TABLE_VERSION_2_0 - ACPI Version 2.0
+// EFI_ACPI_TABLE_VERSION_3_0 - ACPI Version 3.0
+// EFI_ACPI_TABLE_VERSION_NONE - No ACPI Versions. This might be used
+// to create memory-based operation regions or other information
+// that is not part of the ACPI "tree" but must still be found
+// in ACPI memory space and/or managed by the core ACPI driver.
+//
+// Note that EFI provides discrete GUIDs for each version of ACPI
+// that is supported. It is expected that each EFI GUIDed
+// version of ACPI will also have a corresponding bitmap
+// definition. This allows maintenance of separate ACPI trees
+// for each distinctly different version of ACPI.
+//
+#define EFI_ACPI_TABLE_VERSION UINT32
+
+#define EFI_ACPI_TABLE_VERSION_NONE (1 << 0)
+#define EFI_ACPI_TABLE_VERSION_1_0B (1 << 1)
+#define EFI_ACPI_TABLE_VERSION_2_0 (1 << 2)
+#define EFI_ACPI_TABLE_VERSION_3_0 (1 << 3)
+
+//
+// Private Driver Data
+//
+//
+// ACPI Table Linked List Signature.
+//
+#define EFI_ACPI_TABLE_LIST_SIGNATURE SIGNATURE_32 ('E', 'A', 'T', 'L')
+
+//
+// ACPI Table Linked List Entry definition.
+//
+// Signature must be set to EFI_ACPI_TABLE_LIST_SIGNATURE
+// Link is the linked list data.
+// Version is the versions of the ACPI tables that this table belongs in.
+// Table is a pointer to the table.
+// PageAddress is the address of the pages allocated for the table.
+// NumberOfPages is the number of pages allocated at PageAddress.
+// Handle is used to identify a particular table.
+//
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_COMMON_HEADER *Table;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN NumberOfPages;
+ UINTN Handle;
+} EFI_ACPI_TABLE_LIST;
+
+//
+// Containment record for linked list.
+//
+#define EFI_ACPI_TABLE_LIST_FROM_LINK(_link) CR (_link, EFI_ACPI_TABLE_LIST, Link, EFI_ACPI_TABLE_LIST_SIGNATURE)
+
+//
+// The maximum number of tables this driver supports
+//
+#define EFI_ACPI_MAX_NUM_TABLES 20
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID "INTEL "
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('E', 'D', 'K', '2', ' ', ' ', ' ', ' ')
+#define EFI_ACPI_OEM_REVISION 0x00000002
+#define EFI_ACPI_CREATOR_ID 0x20202020
+#define EFI_ACPI_CREATOR_REVISION 0x01000013
+
+//
+// Protocol private structure definition
+//
+//
+// ACPI support protocol instance signature definition.
+//
+#define EFI_ACPI_TABLE_SIGNATURE SIGNATURE_32 ('S', 'T', 'A', 'E')
+
+//
+// ACPI support protocol instance data structure
+//
+typedef struct {
+ UINTN Signature;
+ EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp1; // Pointer to RSD_PTR structure
+ EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp3; // Pointer to RSD_PTR structure
+ EFI_ACPI_DESCRIPTION_HEADER *Rsdt1; // Pointer to RSDT table header
+ EFI_ACPI_DESCRIPTION_HEADER *Rsdt3; // Pointer to RSDT table header
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt; // Pointer to XSDT table header
+ EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1; // Pointer to FADT table header
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt3; // Pointer to FADT table header
+ EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1; // Pointer to FACS table header
+ EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs3; // Pointer to FACS table header
+ EFI_ACPI_DESCRIPTION_HEADER *Dsdt1; // Pointer to DSDT table header
+ EFI_ACPI_DESCRIPTION_HEADER *Dsdt3; // Pointer to DSDT table header
+ LIST_ENTRY TableList;
+ UINTN NumberOfTableEntries1; // Number of ACPI 1.0 tables
+ UINTN NumberOfTableEntries3; // Number of ACPI 3.0 tables
+ UINTN CurrentHandle;
+ BOOLEAN TablesInstalled1; // ACPI 1.0 tables published
+ BOOLEAN TablesInstalled3; // ACPI 3.0 tables published
+ EFI_ACPI_TABLE_PROTOCOL AcpiTableProtocol;
+} EFI_ACPI_TABLE_INSTANCE;
+
+//
+// ACPI table protocol instance containing record macro
+//
+#define EFI_ACPI_TABLE_INSTANCE_FROM_THIS(a) \
+ CR (a, \
+ EFI_ACPI_TABLE_INSTANCE, \
+ AcpiTableProtocol, \
+ EFI_ACPI_TABLE_SIGNATURE \
+ )
+
+//
+// Protocol Constructor functions
+//
+
+/**
+ Constructor for the ACPI support protocol. Initializes instance
+ data.
+
+ @param AcpiTableInstance Instance to construct
+
+ @return EFI_SUCCESS Instance initialized.
+ @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.
+
+**/
+EFI_STATUS
+AcpiTableAcpiTableConstructor (
+ EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
+ );
+
+
+/**
+ Entry point of the ACPI table driver.
+ Creates and initializes an instance of the ACPI Table
+ Protocol and installs it on a new handle.
+
+ @param ImageHandle A handle for the image that is initializing this driver
+ @param SystemTable A pointer to the EFI system table
+
+ @return EFI_SUCCESS Driver initialized successfully
+ @return EFI_LOAD_ERROR Failed to Initialize or has been loaded
+ @return EFI_OUT_OF_RESOURCES Could not allocate needed resources
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeAcpiTableDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
new file mode 100755
index 0000000000..4eb4b571b6
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
@@ -0,0 +1,60 @@
+#/** @file
+# ACPI Table Protocol Driver
+#
+# Copyright (c) 2006, 2008, 2009 Intel Corporation<BR> All rights
+# reserved. This program and the accompanying materials are
+# licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiTableDxe
+ FILE_GUID = 506533a6-e626-4500-b14f-17939c0e5b60
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeAcpiTableDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ AcpiTableProtocol.c
+ AcpiTable.h
+ AcpiTable.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ UefiLib
+ DebugLib
+ BaseLib
+ PcdLib
+
+[Guids]
+ gEfiAcpi10TableGuid # ALWAYS_CONSUMED
+ gEfiAcpiTableGuid
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Depex]
+ TRUE
+
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
new file mode 100755
index 0000000000..febfde1c1e
--- /dev/null
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
@@ -0,0 +1,1703 @@
+/** @file
+ ACPI Table Protocol Implementation
+
+ Copyright (c) 2006, 2008, 2009, Intel Corporation<BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Includes
+//
+#include "AcpiTable.h"
+
+
+/**
+ This function adds an ACPI table to the table list. It will detect FACS and
+ allocate the correct type of memory and properly align the table.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Table Table to add.
+ @param Checksum Does the table require checksumming.
+ @param Version The version of the list to add the table to.
+ @param Handle Pointer for returning the handle.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.
+ @return EFI_ABORTED The table is a duplicate of a table that is required
+ to be unique.
+
+**/
+EFI_STATUS
+AddTableToList (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN VOID *Table,
+ IN BOOLEAN Checksum,
+ IN EFI_ACPI_TABLE_VERSION Version,
+ OUT UINTN *Handle
+ );
+
+/**
+ This function finds and removes the table specified by the handle.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Version Bitmask of which versions to remove.
+ @param Handle Table to remove.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_ABORTED An error occurred.
+ @return EFI_NOT_FOUND Handle not found in table list.
+
+**/
+EFI_STATUS
+RemoveTableFromList (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN EFI_ACPI_TABLE_VERSION Version,
+ IN UINTN Handle
+ );
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param Buffer Pointer to buffer to checksum
+ @param Size Number of bytes to checksum
+ @param ChecksumOffset Offset to place the checksum result in
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+AcpiPlatformChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ );
+
+/**
+ Checksum all versions of the common tables, RSDP, RSDT, XSDT.
+
+ @param AcpiTableInstance Protocol instance private data.
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+ChecksumCommonTables (
+ IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
+ );
+
+//
+// Protocol function implementations.
+//
+
+/**
+ This function adds, removes, or updates ACPI tables. If the address is not
+ null and the handle value is null, the table is added. If both the address and
+ handle are not null, the table at handle is updated with the table at address.
+ If the address is null and the handle is not, the table at handle is deleted.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Table Pointer to a table.
+ @param Checksum Boolean indicating if the checksum should be calculated.
+ @param Version Version(s) to set.
+ @param Handle Handle of the table.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_INVALID_PARAMETER Both the Table and *Handle were NULL.
+ @return EFI_ABORTED Could not complete the desired request.
+
+**/
+EFI_STATUS
+EFIAPI
+SetAcpiTable (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN VOID *Table OPTIONAL,
+ IN BOOLEAN Checksum,
+ IN EFI_ACPI_TABLE_VERSION Version,
+ IN OUT UINTN *Handle
+ )
+{
+ UINTN SavedHandle;
+ EFI_STATUS Status;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (Handle);
+
+ //
+ // Initialize locals
+ //
+ //
+ // Determine desired action
+ //
+ if (*Handle == 0) {
+ if (Table == NULL) {
+ //
+ // Invalid parameter combination
+ //
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Add table
+ //
+ Status = AddTableToList (AcpiTableInstance, Table, Checksum, Version, Handle);
+ }
+ } else {
+ if (Table != NULL) {
+ //
+ // Update table
+ //
+ //
+ // Delete the table list entry
+ //
+ Status = RemoveTableFromList (AcpiTableInstance, Version, *Handle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Should not get an error here ever, but abort if we do.
+ //
+ return EFI_ABORTED;
+ }
+ //
+ // Set the handle to replace the table at the same handle
+ //
+ SavedHandle = AcpiTableInstance->CurrentHandle;
+ AcpiTableInstance->CurrentHandle = *Handle;
+
+ //
+ // Add the table
+ //
+ Status = AddTableToList (AcpiTableInstance, Table, Checksum, Version, Handle);
+
+ //
+ // Restore the saved current handle
+ //
+ AcpiTableInstance->CurrentHandle = SavedHandle;
+ } else {
+ //
+ // Delete table
+ //
+ Status = RemoveTableFromList (AcpiTableInstance, Version, *Handle);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Should not get an error here ever, but abort if we do.
+ //
+ return EFI_ABORTED;
+ }
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ This function publishes the specified versions of the ACPI tables by
+ installing EFI configuration table entries for them. Any combination of
+ table versions can be published.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Version Version(s) to publish.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_ABORTED The function could not complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PublishTables (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN EFI_ACPI_TABLE_VERSION Version
+ )
+{
+ EFI_STATUS Status;
+ UINT32 *CurrentRsdtEntry;
+ VOID *CurrentXsdtEntry;
+ UINT64 Buffer64;
+
+ //
+ // Reorder tables as some operating systems don't seem to find the
+ // FADT correctly if it is not in the first few entries
+ //
+
+ //
+ // Add FADT as the first entry
+ //
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+ *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt1;
+ }
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+ *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt3;
+ CurrentXsdtEntry = (VOID *) ((UINT8 *) AcpiTableInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+ //
+ // Add entry to XSDT, XSDT expects 64 bit pointers, but
+ // the table pointers in XSDT are not aligned on 8 byte boundary.
+ //
+ Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Fadt3;
+ CopyMem (
+ CurrentXsdtEntry,
+ &Buffer64,
+ sizeof (UINT64)
+ );
+ }
+
+ //
+ // Do checksum again because Dsdt/Xsdt is updated.
+ //
+ ChecksumCommonTables (AcpiTableInstance);
+
+ //
+ // Add the RSD_PTR to the system table and store that we have installed the
+ // tables.
+ //
+ if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) &&
+ !AcpiTableInstance->TablesInstalled1) {
+ Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiTableInstance->Rsdp1);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ AcpiTableInstance->TablesInstalled1 = TRUE;
+ }
+
+ if (((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) &&
+ !AcpiTableInstance->TablesInstalled3) {
+ Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiTableInstance->Rsdp3);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ AcpiTableInstance->TablesInstalled3= TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Installs an ACPI table into the RSDT/XSDT.
+
+ @param This Protocol instance pointer.
+ @param AcpiTableBuffer A pointer to a buffer containing the ACPI table to be installed.
+ @param AcpiTableBufferSize Specifies the size, in bytes, of the AcpiTableBuffer buffer.
+ @param TableKey Reurns a key to refer to the ACPI table.
+
+ @return EFI_SUCCESS The table was successfully inserted.
+ @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize
+ and the size field embedded in the ACPI table pointed to by AcpiTableBuffer
+ are not in sync.
+ @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+ IN CONST EFI_ACPI_TABLE_PROTOCOL *This,
+ IN CONST VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;
+ EFI_STATUS Status;
+ VOID *AcpiTableBufferConst;
+
+ //
+ // Check for invalid input parameters
+ //
+ if ((AcpiTableBuffer == NULL) || (TableKey == NULL)
+ || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the instance of the ACPI table protocol
+ //
+ AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);
+
+ //
+ // Install the ACPI table
+ //
+ AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize,AcpiTableBuffer);
+ *TableKey = 0;
+ Status = SetAcpiTable (
+ AcpiTableInstance,
+ AcpiTableBufferConst,
+ FALSE,
+ EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0,
+ TableKey
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PublishTables (
+ AcpiTableInstance,
+ EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0
+ );
+ }
+ FreePool (AcpiTableBufferConst);
+
+ return Status;
+}
+
+
+/**
+ Removes an ACPI table from the RSDT/XSDT.
+
+ @param This Protocol instance pointer.
+ @param TableKey Specifies the table to uninstall. The key was returned from InstallAcpiTable().
+
+ @return EFI_SUCCESS The table was successfully uninstalled.
+ @return EFI_NOT_FOUND TableKey does not refer to a valid key for a table entry.
+
+**/
+EFI_STATUS
+EFIAPI
+UninstallAcpiTable (
+ IN CONST EFI_ACPI_TABLE_PROTOCOL *This,
+ IN UINTN TableKey
+ )
+{
+ EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;
+ EFI_STATUS Status;
+
+ //
+ // Get the instance of the ACPI table protocol
+ //
+ AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);
+
+ //
+ // Uninstall the ACPI table
+ //
+ Status = SetAcpiTable (
+ AcpiTableInstance,
+ NULL,
+ FALSE,
+ EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0,
+ &TableKey
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PublishTables (
+ AcpiTableInstance,
+ EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+
+/**
+ This function adds an ACPI table to the table list. It will detect FACS and
+ allocate the correct type of memory and properly align the table.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Table Table to add.
+ @param Checksum Does the table require checksumming.
+ @param Version The version of the list to add the table to.
+ @param Handle Pointer for returning the handle.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.
+ @return EFI_ABORTED The table is a duplicate of a table that is required
+ to be unique.
+
+**/
+EFI_STATUS
+AddTableToList (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN VOID *Table,
+ IN BOOLEAN Checksum,
+ IN EFI_ACPI_TABLE_VERSION Version,
+ OUT UINTN *Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_LIST *CurrentTableList;
+ UINT32 CurrentTableSignature;
+ UINT32 CurrentTableSize;
+ UINT32 *CurrentRsdtEntry;
+ VOID *CurrentXsdtEntry;
+ UINT64 Buffer64;
+ BOOLEAN AddToRsdt;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (AcpiTableInstance);
+ ASSERT (Table);
+ ASSERT (Handle);
+
+ //
+ // Init locals
+ //
+ AddToRsdt = TRUE;
+
+ //
+ // Create a new list entry
+ //
+ CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST));
+ ASSERT (CurrentTableList);
+
+ //
+ // Determine table type and size
+ //
+ CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature;
+ CurrentTableSize = ((EFI_ACPI_COMMON_HEADER *) Table)->Length;
+
+ //
+ // Allocate a buffer for the table. All tables are allocated in the lower 32 bits of address space
+ // for backwards compatibility with ACPI 1.0 OS.
+ //
+ // This is done because ACPI 1.0 pointers are 32 bit values.
+ // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
+ // There is no architectural reason these should be below 4GB, it is purely
+ // for convenience of implementation that we force memory below 4GB.
+ //
+ CurrentTableList->PageAddress = 0xFFFFFFFF;
+ CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);
+
+ //
+ // Allocation memory type depends on the type of the table
+ //
+ if (CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE ||
+ CurrentTableSignature == EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
+ //
+ // Allocate memory for the FACS. This structure must be aligned
+ // on a 64 byte boundary and must be ACPI NVS memory.
+ // Using AllocatePages should ensure that it is always aligned.
+ //
+ ASSERT ((EFI_PAGE_SIZE % 64) == 0);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ CurrentTableList->NumberOfPages,
+ &CurrentTableList->PageAddress
+ );
+ } else {
+ //
+ // All other tables are ACPI reclaim memory, no alignment requirements.
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIReclaimMemory,
+ CurrentTableList->NumberOfPages,
+ &CurrentTableList->PageAddress
+ );
+ }
+ //
+ // Check return value from memory alloc.
+ //
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (CurrentTableList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Update the table pointer with the allocated memory start
+ //
+ CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;
+
+ //
+ // Initialize the table contents
+ //
+ CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE;
+ CopyMem (CurrentTableList->Table, Table, CurrentTableSize);
+ CurrentTableList->Handle = AcpiTableInstance->CurrentHandle++;
+ *Handle = CurrentTableList->Handle;
+ CurrentTableList->Version = Version;
+
+ //
+ // Update internal pointers if this is a required table. If it is a required
+ // table and a table of that type already exists, return an error.
+ //
+ // Calculate the checksum if the table is not FACS.
+ //
+ switch (CurrentTableSignature) {
+
+ case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ //
+ // We don't add the FADT in the standard way because some
+ // OS expect the FADT to be early in the table list.
+ // So we always add it as the first element in the list.
+ //
+ AddToRsdt = FALSE;
+
+ //
+ // Check that the table has not been previously added.
+ //
+ if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Fadt1 != NULL) ||
+ ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Fadt3 != NULL) ||
+ ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Fadt3 != NULL)
+ ) {
+ gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
+ gBS->FreePool (CurrentTableList);
+ return EFI_ABORTED;
+ }
+ //
+ // Add the table to the appropriate table version
+ //
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ //
+ // Save a pointer to the table
+ //
+ AcpiTableInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
+
+ //
+ // Update pointers in FADT. If tables don't exist this will put NULL pointers there.
+ //
+ AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;
+ AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
+
+ //
+ // RSDP OEM information is updated to match the FADT OEM information
+ //
+ CopyMem (
+ &AcpiTableInstance->Rsdp1->OemId,
+ &AcpiTableInstance->Fadt1->Header.OemId,
+ 6
+ );
+
+ //
+ // RSDT OEM information is updated to match the FADT OEM information.
+ //
+ CopyMem (
+ &AcpiTableInstance->Rsdt1->OemId,
+ &AcpiTableInstance->Fadt1->Header.OemId,
+ 6
+ );
+
+ CopyMem (
+ &AcpiTableInstance->Rsdt1->OemTableId,
+ &AcpiTableInstance->Fadt1->Header.OemTableId,
+ sizeof (UINT64)
+ );
+ AcpiTableInstance->Rsdt1->OemRevision = AcpiTableInstance->Fadt1->Header.OemRevision;
+ }
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ //
+ // Save a pointer to the table
+ //
+ AcpiTableInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
+
+ //
+ // Update pointers in FADT. If tables don't exist this will put NULL pointers there.
+ //
+ if (AcpiTableInstance->Fadt3 != NULL) {
+ AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;
+ Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
+ CopyMem (
+ &AcpiTableInstance->Fadt3->XFirmwareCtrl,
+ &Buffer64,
+ sizeof (UINT64)
+ );
+ AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
+ Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
+ CopyMem (
+ &AcpiTableInstance->Fadt3->XDsdt,
+ &Buffer64,
+ sizeof (UINT64)
+ );
+ }
+ //
+ // RSDP OEM information is updated to match the FADT OEM information
+ //
+ CopyMem (
+ &AcpiTableInstance->Rsdp3->OemId,
+ &AcpiTableInstance->Fadt3->Header.OemId,
+ 6
+ );
+
+ //
+ // RSDT OEM information is updated to match FADT OEM information.
+ //
+ CopyMem (
+ &AcpiTableInstance->Rsdt3->OemId,
+ &AcpiTableInstance->Fadt3->Header.OemId,
+ 6
+ );
+ CopyMem (
+ &AcpiTableInstance->Rsdt3->OemTableId,
+ &AcpiTableInstance->Fadt3->Header.OemTableId,
+ sizeof (UINT64)
+ );
+ AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;
+
+ //
+ // XSDT OEM information is updated to match FADT OEM information.
+ //
+ CopyMem (
+ &AcpiTableInstance->Xsdt->OemId,
+ &AcpiTableInstance->Fadt3->Header.OemId,
+ 6
+ );
+ CopyMem (
+ &AcpiTableInstance->Xsdt->OemTableId,
+ &AcpiTableInstance->Fadt3->Header.OemTableId,
+ sizeof (UINT64)
+ );
+ AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;
+ }
+ //
+ // Checksum the table
+ //
+ if (Checksum) {
+ AcpiPlatformChecksum (
+ CurrentTableList->Table,
+ CurrentTableList->Table->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ break;
+
+ case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
+ //
+ // Check that the table has not been previously added.
+ //
+ if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||
+ ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Facs3 != NULL) ||
+ ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Facs3 != NULL)
+ ) {
+ gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
+ gBS->FreePool (CurrentTableList);
+ return EFI_ABORTED;
+ }
+ //
+ // FACS is referenced by FADT and is not part of RSDT
+ //
+ AddToRsdt = FALSE;
+
+ //
+ // Add the table to the appropriate table version
+ //
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ //
+ // Save a pointer to the table
+ //
+ AcpiTableInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
+
+ //
+ // If FADT already exists, update table pointers.
+ //
+ if (AcpiTableInstance->Fadt1 != NULL) {
+ AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;
+
+ //
+ // Checksum FADT table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt1,
+ AcpiTableInstance->Fadt1->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ //
+ // Save a pointer to the table
+ //
+ AcpiTableInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
+
+ //
+ // If FADT already exists, update table pointers.
+ //
+ if (AcpiTableInstance->Fadt3 != NULL) {
+ AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;
+ Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
+ CopyMem (
+ &AcpiTableInstance->Fadt3->XFirmwareCtrl,
+ &Buffer64,
+ sizeof (UINT64)
+ );
+
+ //
+ // Checksum FADT table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt3,
+ AcpiTableInstance->Fadt3->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+
+ break;
+
+ case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ //
+ // Check that the table has not been previously added.
+ //
+ if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||
+ ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Dsdt3 != NULL) ||
+ ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Dsdt3 != NULL)
+ ) {
+ gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
+ gBS->FreePool (CurrentTableList);
+ return EFI_ABORTED;
+ }
+ //
+ // DSDT is referenced by FADT and is not part of RSDT
+ //
+ AddToRsdt = FALSE;
+
+ //
+ // Add the table to the appropriate table version
+ //
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ //
+ // Save a pointer to the table
+ //
+ AcpiTableInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
+
+ //
+ // If FADT already exists, update table pointers.
+ //
+ if (AcpiTableInstance->Fadt1 != NULL) {
+ AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
+
+ //
+ // Checksum FADT table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt1,
+ AcpiTableInstance->Fadt1->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ //
+ // Save a pointer to the table
+ //
+ AcpiTableInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
+
+ //
+ // If FADT already exists, update table pointers.
+ //
+ if (AcpiTableInstance->Fadt3 != NULL) {
+ AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
+ Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
+ CopyMem (
+ &AcpiTableInstance->Fadt3->XDsdt,
+ &Buffer64,
+ sizeof (UINT64)
+ );
+
+ //
+ // Checksum FADT table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt3,
+ AcpiTableInstance->Fadt3->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+ //
+ // Checksum the table
+ //
+ if (Checksum) {
+ AcpiPlatformChecksum (
+ CurrentTableList->Table,
+ CurrentTableList->Table->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ break;
+
+ default:
+ //
+ // Checksum the table
+ //
+ if (Checksum) {
+ AcpiPlatformChecksum (
+ CurrentTableList->Table,
+ CurrentTableList->Table->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ break;
+ }
+ //
+ // Add the table to the current list of tables
+ //
+ InsertTailList (&AcpiTableInstance->TableList, &CurrentTableList->Link);
+
+ //
+ // Add the table to RSDT and/or XSDT table entry lists.
+ //
+ //
+ // Add to ACPI 1.0b table tree
+ //
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ CurrentRsdtEntry = (UINT32 *)
+ (
+ (UINT8 *) AcpiTableInstance->Rsdt1 +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
+ AcpiTableInstance->NumberOfTableEntries1 *
+ sizeof (UINT32)
+ );
+
+ //
+ // Add entry to the RSDT unless its the FACS or DSDT
+ //
+ if (AddToRsdt) {
+ *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
+
+ //
+ // Update RSDT length
+ //
+ AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);
+
+ AcpiTableInstance->NumberOfTableEntries1++;
+ }
+
+ ASSERT (AcpiTableInstance->NumberOfTableEntries1 <= EFI_ACPI_MAX_NUM_TABLES);
+ }
+ //
+ // Add to ACPI 2.0/3.0 table tree
+ //
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ if (AddToRsdt) {
+ //
+ // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
+ // If it becomes necessary to maintain separate table lists, changes will be required.
+ //
+ CurrentRsdtEntry = (UINT32 *)
+ (
+ (UINT8 *) AcpiTableInstance->Rsdt3 +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
+ AcpiTableInstance->NumberOfTableEntries3 *
+ sizeof (UINT32)
+ );
+
+ //
+ // This pointer must not be directly dereferenced as the XSDT entries may not
+ // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
+ //
+ CurrentXsdtEntry = (VOID *)
+ (
+ (UINT8 *) AcpiTableInstance->Xsdt +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
+ AcpiTableInstance->NumberOfTableEntries3 *
+ sizeof (UINT64)
+ );
+
+ //
+ // Add entry to the RSDT
+ //
+ *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
+
+ //
+ // Update RSDT length
+ //
+ AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);
+
+ //
+ // Add entry to XSDT, XSDT expects 64 bit pointers, but
+ // the table pointers in XSDT are not aligned on 8 byte boundary.
+ //
+ Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;
+ CopyMem (
+ CurrentXsdtEntry,
+ &Buffer64,
+ sizeof (UINT64)
+ );
+
+ //
+ // Update length
+ //
+ AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);
+
+ AcpiTableInstance->NumberOfTableEntries3++;
+ }
+
+ ASSERT (AcpiTableInstance->NumberOfTableEntries3 <= EFI_ACPI_MAX_NUM_TABLES);
+ }
+
+ ChecksumCommonTables (AcpiTableInstance);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function finds the table specified by the handle and returns a pointer to it.
+ If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are
+ undefined.
+
+ @param Handle Table to find.
+ @param TableList Table list to search
+ @param Table Pointer to table found.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_NOT_FOUND No table found matching the handle specified.
+
+**/
+EFI_STATUS
+FindTableByHandle (
+ IN UINTN Handle,
+ IN LIST_ENTRY *TableList,
+ OUT EFI_ACPI_TABLE_LIST **Table
+ )
+{
+ LIST_ENTRY *CurrentLink;
+ EFI_ACPI_TABLE_LIST *CurrentTable;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (Table);
+
+ //
+ // Find the table
+ //
+ CurrentLink = TableList->ForwardLink;
+
+ while (CurrentLink != TableList) {
+ CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
+ if (CurrentTable->Handle == Handle) {
+ //
+ // Found handle, so return this table.
+ //
+ *Table = CurrentTable;
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ //
+ // Table not found
+ //
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ This function removes a basic table from the RSDT and/or XSDT.
+ For Acpi 1.0 tables, pass in the Rsdt.
+ For Acpi 2.0 tables, pass in both Rsdt and Xsdt.
+
+ @param Table Pointer to table found.
+ @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT
+ @param Rsdt Pointer to the RSDT to remove from
+ @param Xsdt Pointer to the Xsdt to remove from
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt.
+
+**/
+EFI_STATUS
+RemoveTableFromRsdt (
+ IN OUT EFI_ACPI_TABLE_LIST * Table,
+ IN OUT UINTN *NumberOfTableEntries,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL
+ )
+{
+ UINT32 *CurrentRsdtEntry;
+ VOID *CurrentXsdtEntry;
+ UINT64 CurrentTablePointer64;
+ UINTN Index;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (Table);
+ ASSERT (NumberOfTableEntries);
+ ASSERT (Rsdt);
+
+ //
+ // Find the table entry in the RSDT and XSDT
+ //
+ for (Index = 0; Index < *NumberOfTableEntries; Index++) {
+ //
+ // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
+ // If it becomes necessary to maintain separate table lists, changes will be required.
+ //
+ CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));
+ if (Xsdt != NULL) {
+ //
+ // This pointer must not be directly dereferenced as the XSDT entries may not
+ // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
+ //
+ CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64));
+
+ //
+ // Read the entry value out of the XSDT
+ //
+ CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64));
+ } else {
+ //
+ // Initialize to NULL
+ //
+ CurrentXsdtEntry = 0;
+ CurrentTablePointer64 = 0;
+ }
+ //
+ // Check if we have found the corresponding entry in both RSDT and XSDT
+ //
+ if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table &&
+ ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)
+ ) {
+ //
+ // Found entry, so copy all following entries and shrink table
+ // We actually copy all + 1 to copy the initialized value of memory over
+ // the last entry.
+ //
+ CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));
+ Rsdt->Length = Rsdt->Length - sizeof (UINT32);
+ if (Xsdt != NULL) {
+ CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));
+ Xsdt->Length = Xsdt->Length - sizeof (UINT64);
+ }
+ break;
+ } else if (Index + 1 == *NumberOfTableEntries) {
+ //
+ // At the last entry, and table not found
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Checksum the tables
+ //
+ AcpiPlatformChecksum (
+ Rsdt,
+ Rsdt->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+
+ if (Xsdt != NULL) {
+ AcpiPlatformChecksum (
+ Xsdt,
+ Xsdt->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ //
+ // Decrement the number of tables
+ //
+ (*NumberOfTableEntries)--;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function removes a table and frees any associated memory.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Version Version(s) to delete.
+ @param Table Pointer to table found.
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+DeleteTable (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN EFI_ACPI_TABLE_VERSION Version,
+ IN OUT EFI_ACPI_TABLE_LIST *Table
+ )
+{
+ UINT32 CurrentTableSignature;
+ BOOLEAN RemoveFromRsdt;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (AcpiTableInstance);
+ ASSERT (Table);
+
+ //
+ // Init locals
+ //
+ RemoveFromRsdt = TRUE;
+ CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature;
+
+ //
+ // Basic tasks to accomplish delete are:
+ // Determine removal requirements (in RSDT/XSDT or not)
+ // Remove entry from RSDT/XSDT
+ // Remove any table references to the table
+ // If no one is using the table
+ // Free the table (removing pointers from private data and tables)
+ // Remove from list
+ // Free list structure
+ //
+ //
+ // Determine if this table is in the RSDT or XSDT
+ //
+ if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
+ (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||
+ (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)
+ ) {
+ RemoveFromRsdt = FALSE;
+ }
+ //
+ // We don't remove the FADT in the standard way because some
+ // OS expect the FADT to be early in the table list.
+ // So we always put it as the first element in the list.
+ //
+ if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ RemoveFromRsdt = FALSE;
+ }
+
+ //
+ // Remove the table from RSDT and XSDT
+ //
+ if (Table->Table != NULL) {
+ //
+ // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt
+ //
+ if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) {
+ //
+ // Remove this version from the table
+ //
+ Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE;
+ }
+
+ if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) {
+ //
+ // Remove this version from the table
+ //
+ Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B;
+
+ //
+ // Remove from Rsdt. We don't care about the return value because it is
+ // acceptable for the table to not exist in Rsdt.
+ // We didn't add some tables so we don't remove them.
+ //
+ if (RemoveFromRsdt) {
+ RemoveTableFromRsdt (
+ Table,
+ &AcpiTableInstance->NumberOfTableEntries1,
+ AcpiTableInstance->Rsdt1,
+ NULL
+ );
+ }
+ }
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) {
+ //
+ // Remove this version from the table
+ //
+ if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) {
+ Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0;
+ }
+ if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) {
+ Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0;
+ }
+
+ //
+ // Remove from Rsdt and Xsdt. We don't care about the return value
+ // because it is acceptable for the table to not exist in Rsdt/Xsdt.
+ // We didn't add some tables so we don't remove them.
+ //
+ if (RemoveFromRsdt) {
+ RemoveTableFromRsdt (
+ Table,
+ &AcpiTableInstance->NumberOfTableEntries3,
+ AcpiTableInstance->Rsdt3,
+ AcpiTableInstance->Xsdt
+ );
+ }
+ }
+ //
+ // Free the table, clean up any dependent tables and our private data pointers.
+ //
+ switch (Table->Table->Signature) {
+
+ case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ AcpiTableInstance->Fadt1 = NULL;
+ }
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ AcpiTableInstance->Fadt3 = NULL;
+ }
+ break;
+
+ case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ AcpiTableInstance->Facs1 = NULL;
+
+ //
+ // Update FADT table pointers
+ //
+ if (AcpiTableInstance->Fadt1 != NULL) {
+ AcpiTableInstance->Fadt1->FirmwareCtrl = 0;
+
+ //
+ // Checksum table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt1,
+ AcpiTableInstance->Fadt1->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ AcpiTableInstance->Facs3 = NULL;
+
+ //
+ // Update FADT table pointers
+ //
+ if (AcpiTableInstance->Fadt3 != NULL) {
+ AcpiTableInstance->Fadt3->FirmwareCtrl = 0;
+ ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
+
+ //
+ // Checksum table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt3,
+ AcpiTableInstance->Fadt3->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+ break;
+
+ case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ AcpiTableInstance->Dsdt1 = NULL;
+
+ //
+ // Update FADT table pointers
+ //
+ if (AcpiTableInstance->Fadt1 != NULL) {
+ AcpiTableInstance->Fadt1->Dsdt = 0;
+
+ //
+ // Checksum table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt1,
+ AcpiTableInstance->Fadt1->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+
+
+ if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
+ (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
+ AcpiTableInstance->Dsdt3 = NULL;
+
+ //
+ // Update FADT table pointers
+ //
+ if (AcpiTableInstance->Fadt3 != NULL) {
+ AcpiTableInstance->Fadt3->Dsdt = 0;
+ ZeroMem (&AcpiTableInstance->Fadt3->XDsdt, sizeof (UINT64));
+
+ //
+ // Checksum table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Fadt3,
+ AcpiTableInstance->Fadt3->Header.Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+ }
+ }
+ break;
+
+ default:
+ //
+ // Do nothing
+ //
+ break;
+ }
+ }
+ //
+ // If no version is using this table anymore, remove and free list entry.
+ //
+ if (Table->Version == 0) {
+ //
+ // Free the Table
+ //
+ gBS->FreePages (Table->PageAddress, Table->NumberOfPages);
+ RemoveEntryList (&(Table->Link));
+ gBS->FreePool (Table);
+ }
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function finds and removes the table specified by the handle.
+
+ @param AcpiTableInstance Instance of the protocol.
+ @param Version Bitmask of which versions to remove.
+ @param Handle Table to remove.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_ABORTED An error occurred.
+ @return EFI_NOT_FOUND Handle not found in table list.
+
+**/
+EFI_STATUS
+RemoveTableFromList (
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ IN EFI_ACPI_TABLE_VERSION Version,
+ IN UINTN Handle
+ )
+{
+ EFI_ACPI_TABLE_LIST *Table;
+ EFI_STATUS Status;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (AcpiTableInstance);
+
+ //
+ // Find the table
+ //
+ Status = FindTableByHandle (
+ Handle,
+ &AcpiTableInstance->TableList,
+ &Table
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Remove the table
+ //
+ Status = DeleteTable (AcpiTableInstance, Version, Table);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Completed successfully
+ //
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param Buffer Pointer to buffer to checksum
+ @param Size Number of bytes to checksum
+ @param ChecksumOffset Offset to place the checksum result in
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+AcpiPlatformChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ )
+{
+ UINT8 Sum;
+ UINT8 *Ptr;
+
+ Sum = 0;
+ //
+ // Initialize pointer
+ //
+ Ptr = Buffer;
+
+ //
+ // set checksum to 0 first
+ //
+ Ptr[ChecksumOffset] = 0;
+
+ //
+ // add all content of buffer
+ //
+ while ((Size--) != 0) {
+ Sum = (UINT8) (Sum + (*Ptr++));
+ }
+ //
+ // set checksum
+ //
+ Ptr = Buffer;
+ Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Checksum all versions of the common tables, RSDP, RSDT, XSDT.
+
+ @param AcpiTableInstance Protocol instance private data.
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+ChecksumCommonTables (
+ IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
+ )
+{
+ //
+ // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Rsdp1,
+ sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
+ OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
+ Checksum)
+ );
+
+ //
+ // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Rsdp3,
+ sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
+ OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
+ Checksum)
+ );
+
+ //
+ // RSDP ACPI 2.0/3.0 checksum, this is the entire table
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Rsdp3,
+ sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
+ OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
+ ExtendedChecksum)
+ );
+
+ //
+ // RSDT checksums
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Rsdt1,
+ AcpiTableInstance->Rsdt1->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Rsdt3,
+ AcpiTableInstance->Rsdt3->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+
+ //
+ // XSDT checksum
+ //
+ AcpiPlatformChecksum (
+ AcpiTableInstance->Xsdt,
+ AcpiTableInstance->Xsdt->Length,
+ OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
+ Checksum)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Constructor for the ACPI table protocol. Initializes instance
+ data.
+
+ @param AcpiTableInstance Instance to construct
+
+ @return EFI_SUCCESS Instance initialized.
+ @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.
+
+**/
+EFI_STATUS
+AcpiTableAcpiTableConstructor (
+ EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
+ )
+{
+ EFI_STATUS Status;
+ UINT64 CurrentData;
+ UINTN TotalSize;
+ UINT8 *Pointer;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+
+ //
+ // Check for invalid input parameters
+ //
+ ASSERT (AcpiTableInstance);
+
+ InitializeListHead (&AcpiTableInstance->TableList);
+ AcpiTableInstance->CurrentHandle = 1;
+
+ AcpiTableInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable;
+ AcpiTableInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
+ //
+ // Create RSDP, RSDT, XSDT structures
+ // Allocate all buffers
+ //
+ TotalSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
+ sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT
+ EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT
+ EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT
+ EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT64);
+
+ //
+ // Allocate memory in the lower 32 bit of address range for
+ // compatibility with ACPI 1.0 OS.
+ //
+ // This is done because ACPI 1.0 pointers are 32 bit values.
+ // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
+ // There is no architectural reason these should be below 4GB, it is purely
+ // for convenience of implementation that we force memory below 4GB.
+ //
+ PageAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIReclaimMemory,
+ EFI_SIZE_TO_PAGES (TotalSize),
+ &PageAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Pointer = (UINT8 *) (UINTN) PageAddress;
+ ZeroMem (Pointer, TotalSize);
+
+ AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
+ Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
+ AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
+ Pointer += sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
+
+ AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
+ Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
+ AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
+ Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
+
+ AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
+
+ //
+ // Initialize RSDP
+ //
+ CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
+ CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));
+ CopyMem (AcpiTableInstance->Rsdp1->OemId, EFI_ACPI_OEM_ID, 6);
+ AcpiTableInstance->Rsdp1->Reserved = EFI_ACPI_RESERVED_BYTE;
+ AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;
+
+ CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
+ CopyMem (&AcpiTableInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));
+ CopyMem (AcpiTableInstance->Rsdp3->OemId, EFI_ACPI_OEM_ID, 6);
+ AcpiTableInstance->Rsdp3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;
+ AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;
+ AcpiTableInstance->Rsdp3->Length = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
+ CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;
+ CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
+ SetMem (AcpiTableInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);
+
+ //
+ // Initialize Rsdt
+ //
+ // Note that we "reserve" one entry for the FADT so it can always be
+ // at the beginning of the list of tables. Some OS don't seem
+ // to find it correctly if it is too far down the list.
+ //
+ AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
+ AcpiTableInstance->Rsdt1->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+ AcpiTableInstance->Rsdt1->Revision = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
+ CopyMem (AcpiTableInstance->Rsdt1->OemId, EFI_ACPI_OEM_ID, 6);
+ CurrentData = EFI_ACPI_OEM_TABLE_ID;
+ CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));
+ AcpiTableInstance->Rsdt1->OemRevision = EFI_ACPI_OEM_REVISION;
+ AcpiTableInstance->Rsdt1->CreatorId = EFI_ACPI_CREATOR_ID;
+ AcpiTableInstance->Rsdt1->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+ //
+ // We always reserve first one for FADT
+ //
+ AcpiTableInstance->NumberOfTableEntries1 = 1;
+ AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);
+
+ AcpiTableInstance->Rsdt3->Signature = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
+ AcpiTableInstance->Rsdt3->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+ AcpiTableInstance->Rsdt3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
+ CopyMem (AcpiTableInstance->Rsdt3->OemId, EFI_ACPI_OEM_ID, 6);
+ CurrentData = EFI_ACPI_OEM_TABLE_ID;
+ CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));
+ AcpiTableInstance->Rsdt3->OemRevision = EFI_ACPI_OEM_REVISION;
+ AcpiTableInstance->Rsdt3->CreatorId = EFI_ACPI_CREATOR_ID;
+ AcpiTableInstance->Rsdt3->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+ //
+ // We always reserve first one for FADT
+ //
+ AcpiTableInstance->NumberOfTableEntries3 = 1;
+ AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);
+
+ //
+ // Initialize Xsdt
+ //
+ AcpiTableInstance->Xsdt->Signature = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
+ AcpiTableInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+ AcpiTableInstance->Xsdt->Revision = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;
+ CopyMem (AcpiTableInstance->Xsdt->OemId, EFI_ACPI_OEM_ID, 6);
+ CurrentData = EFI_ACPI_OEM_TABLE_ID;
+ CopyMem (&AcpiTableInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));
+ AcpiTableInstance->Xsdt->OemRevision = EFI_ACPI_OEM_REVISION;
+ AcpiTableInstance->Xsdt->CreatorId = EFI_ACPI_CREATOR_ID;
+ AcpiTableInstance->Xsdt->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+ //
+ // We always reserve first one for FADT
+ //
+ AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof(UINT64);
+
+ ChecksumCommonTables (AcpiTableInstance);
+
+ //
+ // Completed successfully
+ //
+ return EFI_SUCCESS;
+}
+