15f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/** @file
25f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ACPI Table Protocol Implementation
35f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4f0071740ec3c7a536201cb02cec013442805760aStar Zeng  Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5e5eed7d3641d71d7ea539e5379ea9c6a5cd97004hhtian  This program and the accompanying materials
65f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  are licensed and made available under the terms and conditions of the BSD License
75f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  which accompanies this distribution.  The full text of the license may be found at
85f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  http://opensource.org/licenses/bsd-license.php
95f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten//
165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten// Includes
175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten//
185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten#include "AcpiTable.h"
19da935a5c97f733f0662b83464abbbfa0acab76d1jchen//
20da935a5c97f733f0662b83464abbbfa0acab76d1jchen// The maximum number of tables that pre-allocated.
21da935a5c97f733f0662b83464abbbfa0acab76d1jchen//
22da935a5c97f733f0662b83464abbbfa0acab76d1jchenUINTN         mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES;
235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function adds an ACPI table to the table list.  It will detect FACS and
265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  allocate the correct type of memory and properly align the table.
275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance         Instance of the protocol.
295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Table                     Table to add.
305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Checksum                  Does the table require checksumming.
315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Version                   The version of the list to add the table to.
325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Handle                    Pointer for returning the handle.
335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS               The function completed successfully.
355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_OUT_OF_RESOURCES      Could not allocate a required resource.
365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_ABORTED               The table is a duplicate of a table that is required
375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                                    to be unique.
385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenAddTableToList (
425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,
435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN VOID                                 *Table,
445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN BOOLEAN                              Checksum,
455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_VERSION               Version,
465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  OUT UINTN                               *Handle
475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  );
485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function finds and removes the table specified by the handle.
515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance  Instance of the protocol.
535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Version            Bitmask of which versions to remove.
545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Handle             Table to remove.
555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS    The function completed successfully.
575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_ABORTED    An error occurred.
585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_NOT_FOUND  Handle not found in table list.
595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenRemoveTableFromList (
635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,
645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_VERSION               Version,
655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN                                Handle
665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  );
675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function calculates and updates an UINT8 checksum.
705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Buffer          Pointer to buffer to checksum
725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Size            Number of bytes to checksum
735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  ChecksumOffset  Offset to place the checksum result in
745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS             The function completed successfully.
765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenAcpiPlatformChecksum (
795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN VOID       *Buffer,
805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN      Size,
815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN      ChecksumOffset
825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  );
835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Checksum all versions of the common tables, RSDP, RSDT, XSDT.
865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance  Protocol instance private data.
885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS        The function completed successfully.
905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenChecksumCommonTables (
945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT EFI_ACPI_TABLE_INSTANCE          *AcpiTableInstance
955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  );
965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten//
985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten// Protocol function implementations.
995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten//
1005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
1025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function publishes the specified versions of the ACPI tables by
1035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  installing EFI configuration table entries for them.  Any combination of
1045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  table versions can be published.
1055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance  Instance of the protocol.
1075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Version            Version(s) to publish.
1085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS  The function completed successfully.
1105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_ABORTED  The function could not complete successfully.
1115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
1135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
1145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFIAPI
1155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenPublishTables (
1165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,
1175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_VERSION               Version
1185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
1195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
1205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_STATUS                Status;
1215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT32                    *CurrentRsdtEntry;
1225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  VOID                      *CurrentXsdtEntry;
1235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT64                    Buffer64;
1245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Reorder tables as some operating systems don't seem to find the
1275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // FADT correctly if it is not in the first few entries
1285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Add FADT as the first entry
1325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CurrentRsdtEntry  = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
1355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt1;
1365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
137f0071740ec3c7a536201cb02cec013442805760aStar Zeng  if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
1385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CurrentRsdtEntry  = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
1395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt3;
1405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CurrentXsdtEntry  = (VOID *) ((UINT8 *) AcpiTableInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
1415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
1425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Add entry to XSDT, XSDT expects 64 bit pointers, but
1435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // the table pointers in XSDT are not aligned on 8 byte boundary.
1445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
1455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Fadt3;
1465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CopyMem (
1475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CurrentXsdtEntry,
1485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      &Buffer64,
1495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      sizeof (UINT64)
1505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      );
1515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
1525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Do checksum again because Dsdt/Xsdt is updated.
1555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ChecksumCommonTables (AcpiTableInstance);
1575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
1595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Add the RSD_PTR to the system table and store that we have installed the
1605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // tables.
1615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16201267e224b8f3247e3b360851f6781be6bb80129Star Zeng  if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiTableInstance->Rsdp1);
1645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (EFI_ERROR (Status)) {
1655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      return EFI_ABORTED;
1665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
1675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
1685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16901267e224b8f3247e3b360851f6781be6bb80129Star Zeng  if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
1705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiTableInstance->Rsdp3);
1715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (EFI_ERROR (Status)) {
1725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      return EFI_ABORTED;
1735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
1745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
1755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
1775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
1785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
1815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Installs an ACPI table into the RSDT/XSDT.
1822fd3009fb25d79d53cc6ae6cdd872d78b41e4bc1eric_tian  Note that the ACPI table should be checksumed before installing it.
1832fd3009fb25d79d53cc6ae6cdd872d78b41e4bc1eric_tian  Otherwise it will assert.
1845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  This                 Protocol instance pointer.
1865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableBuffer      A pointer to a buffer containing the ACPI table to be installed.
1875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableBufferSize  Specifies the size, in bytes, of the AcpiTableBuffer buffer.
1885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  TableKey             Reurns a key to refer to the ACPI table.
1895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS            The table was successfully inserted.
1915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize
1925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                                 and the size field embedded in the ACPI table pointed to by AcpiTableBuffer
1935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                                 are not in sync.
1945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_OUT_OF_RESOURCES   Insufficient resources exist to complete the request.
1955966402ed51c5b611bf437c812047dc9c432a47eStar Zeng  @retval EFI_ACCESS_DENIED      The table signature matches a table already
1965966402ed51c5b611bf437c812047dc9c432a47eStar Zeng                                 present in the system and platform policy
1975966402ed51c5b611bf437c812047dc9c432a47eStar Zeng                                 does not allow duplicate tables of this type.
1985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
2005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
2015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFIAPI
2025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenInstallAcpiTable (
203db0f0d3c7945dbdc90d5f7ca1612565d7cebb4e3erictian  IN   EFI_ACPI_TABLE_PROTOCOL                    *This,
204db0f0d3c7945dbdc90d5f7ca1612565d7cebb4e3erictian  IN   VOID                                       *AcpiTableBuffer,
205db0f0d3c7945dbdc90d5f7ca1612565d7cebb4e3erictian  IN   UINTN                                      AcpiTableBufferSize,
206db0f0d3c7945dbdc90d5f7ca1612565d7cebb4e3erictian  OUT  UINTN                                      *TableKey
2075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
2085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
2095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
2105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_STATUS                Status;
2115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  VOID                      *AcpiTableBufferConst;
2125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
2155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if ((AcpiTableBuffer == NULL) || (TableKey == NULL)
2175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten     || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) {
2185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_INVALID_PARAMETER;
2195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
2205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Get the instance of the ACPI table protocol
2235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);
2255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Install the ACPI table
2285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize,AcpiTableBuffer);
2305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  *TableKey = 0;
2315966402ed51c5b611bf437c812047dc9c432a47eStar Zeng  Status = AddTableToList (
2325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten             AcpiTableInstance,
2335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten             AcpiTableBufferConst,
23471824dd8dbcf54019de02a8ec112266222afb98ejyao             TRUE,
235f0071740ec3c7a536201cb02cec013442805760aStar Zeng             EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,
2365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten             TableKey
2375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten             );
2385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (!EFI_ERROR (Status)) {
2395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Status = PublishTables (
2405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten               AcpiTableInstance,
241f0071740ec3c7a536201cb02cec013442805760aStar Zeng               EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0
2425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten               );
2435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
2445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  FreePool (AcpiTableBufferConst);
2455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2463dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  //
2473dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  // Add a new table successfully, notify registed callback
2483dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  //
2493dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {
2503dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao    if (!EFI_ERROR (Status)) {
2513dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao      SdtNotifyAcpiList (
2523dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao        AcpiTableInstance,
253f0071740ec3c7a536201cb02cec013442805760aStar Zeng        EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,
2543dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao        *TableKey
2553dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao        );
2563dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao    }
2573dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  }
2583dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao
2595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return Status;
2605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
2615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
2645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Removes an ACPI table from the RSDT/XSDT.
2655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  This      Protocol instance pointer.
2675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  TableKey  Specifies the table to uninstall.  The key was returned from InstallAcpiTable().
2685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS    The table was successfully uninstalled.
2705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_NOT_FOUND  TableKey does not refer to a valid key for a table entry.
2715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
2735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
2745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFIAPI
2755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenUninstallAcpiTable (
276db0f0d3c7945dbdc90d5f7ca1612565d7cebb4e3erictian  IN  EFI_ACPI_TABLE_PROTOCOL                    *This,
277db0f0d3c7945dbdc90d5f7ca1612565d7cebb4e3erictian  IN  UINTN                                      TableKey
2785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
2795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
2805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;
2815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_STATUS                Status;
2825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Get the instance of the ACPI table protocol
2855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);
2875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
2885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Uninstall the ACPI table
2905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
2915966402ed51c5b611bf437c812047dc9c432a47eStar Zeng  Status = RemoveTableFromList (
2925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten             AcpiTableInstance,
293f0071740ec3c7a536201cb02cec013442805760aStar Zeng             EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,
2945966402ed51c5b611bf437c812047dc9c432a47eStar Zeng             TableKey
2955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten             );
2965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (!EFI_ERROR (Status)) {
2975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Status = PublishTables (
2985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten               AcpiTableInstance,
299f0071740ec3c7a536201cb02cec013442805760aStar Zeng               EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0
3005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten               );
3015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
3025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
3035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (EFI_ERROR (Status)) {
3045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_NOT_FOUND;
3055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  } else {
3065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_SUCCESS;
3075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
3085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
3095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
310da935a5c97f733f0662b83464abbbfa0acab76d1jchen/**
311da935a5c97f733f0662b83464abbbfa0acab76d1jchen  If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer.
312da935a5c97f733f0662b83464abbbfa0acab76d1jchen
313da935a5c97f733f0662b83464abbbfa0acab76d1jchen  @param  AcpiTableInstance       ACPI table protocol instance data structure.
314da935a5c97f733f0662b83464abbbfa0acab76d1jchen
315da935a5c97f733f0662b83464abbbfa0acab76d1jchen  @return EFI_SUCCESS             reallocate the table beffer successfully.
316da935a5c97f733f0662b83464abbbfa0acab76d1jchen  @return EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
317da935a5c97f733f0662b83464abbbfa0acab76d1jchen
318da935a5c97f733f0662b83464abbbfa0acab76d1jchen**/
319da935a5c97f733f0662b83464abbbfa0acab76d1jchenEFI_STATUS
320da935a5c97f733f0662b83464abbbfa0acab76d1jchenReallocateAcpiTableBuffer (
321da935a5c97f733f0662b83464abbbfa0acab76d1jchen  IN EFI_ACPI_TABLE_INSTANCE                   *AcpiTableInstance
322da935a5c97f733f0662b83464abbbfa0acab76d1jchen  )
323da935a5c97f733f0662b83464abbbfa0acab76d1jchen{
324da935a5c97f733f0662b83464abbbfa0acab76d1jchen  UINTN                    NewMaxTableNumber;
325da935a5c97f733f0662b83464abbbfa0acab76d1jchen  UINTN                    TotalSize;
326da935a5c97f733f0662b83464abbbfa0acab76d1jchen  UINT8                    *Pointer;
327da935a5c97f733f0662b83464abbbfa0acab76d1jchen  EFI_PHYSICAL_ADDRESS     PageAddress;
328da935a5c97f733f0662b83464abbbfa0acab76d1jchen  EFI_ACPI_TABLE_INSTANCE  TempPrivateData;
329da935a5c97f733f0662b83464abbbfa0acab76d1jchen  EFI_STATUS               Status;
330da935a5c97f733f0662b83464abbbfa0acab76d1jchen  UINT64                   CurrentData;
331da935a5c97f733f0662b83464abbbfa0acab76d1jchen
332da935a5c97f733f0662b83464abbbfa0acab76d1jchen  CopyMem (&TempPrivateData, AcpiTableInstance, sizeof (EFI_ACPI_TABLE_INSTANCE));
333da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
334da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES
335da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
336da935a5c97f733f0662b83464abbbfa0acab76d1jchen  NewMaxTableNumber = mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES;
337da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
33837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  // Create RSDT, XSDT structures and allocate buffers.
339da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
34037abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT
34137abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              NewMaxTableNumber * sizeof (UINT32) +
34237abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT
34337abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              NewMaxTableNumber * sizeof (UINT32) +
34437abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT
34537abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              NewMaxTableNumber * sizeof (UINT64);
346da935a5c97f733f0662b83464abbbfa0acab76d1jchen
347da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
348da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // Allocate memory in the lower 32 bit of address range for
349da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // compatibility with ACPI 1.0 OS.
350da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
351da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // This is done because ACPI 1.0 pointers are 32 bit values.
352da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
353da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // There is no architectural reason these should be below 4GB, it is purely
354da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // for convenience of implementation that we force memory below 4GB.
355da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
356da935a5c97f733f0662b83464abbbfa0acab76d1jchen  PageAddress = 0xFFFFFFFF;
357da935a5c97f733f0662b83464abbbfa0acab76d1jchen  Status = gBS->AllocatePages (
358da935a5c97f733f0662b83464abbbfa0acab76d1jchen                  AllocateMaxAddress,
359da935a5c97f733f0662b83464abbbfa0acab76d1jchen                  EfiACPIReclaimMemory,
360da935a5c97f733f0662b83464abbbfa0acab76d1jchen                  EFI_SIZE_TO_PAGES (TotalSize),
361da935a5c97f733f0662b83464abbbfa0acab76d1jchen                  &PageAddress
362da935a5c97f733f0662b83464abbbfa0acab76d1jchen                  );
363da935a5c97f733f0662b83464abbbfa0acab76d1jchen
364da935a5c97f733f0662b83464abbbfa0acab76d1jchen  if (EFI_ERROR (Status)) {
365da935a5c97f733f0662b83464abbbfa0acab76d1jchen    return EFI_OUT_OF_RESOURCES;
366da935a5c97f733f0662b83464abbbfa0acab76d1jchen  }
367da935a5c97f733f0662b83464abbbfa0acab76d1jchen
368da935a5c97f733f0662b83464abbbfa0acab76d1jchen  Pointer = (UINT8 *) (UINTN) PageAddress;
369da935a5c97f733f0662b83464abbbfa0acab76d1jchen  ZeroMem (Pointer, TotalSize);
370da935a5c97f733f0662b83464abbbfa0acab76d1jchen
371da935a5c97f733f0662b83464abbbfa0acab76d1jchen  AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
372da935a5c97f733f0662b83464abbbfa0acab76d1jchen  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));
373da935a5c97f733f0662b83464abbbfa0acab76d1jchen  AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
374da935a5c97f733f0662b83464abbbfa0acab76d1jchen  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));
375da935a5c97f733f0662b83464abbbfa0acab76d1jchen  AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
3765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
377da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
37837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  // Update RSDP to point to the new Rsdt and Xsdt address.
379da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
380da935a5c97f733f0662b83464abbbfa0acab76d1jchen  AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;
381da935a5c97f733f0662b83464abbbfa0acab76d1jchen  AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;
382da935a5c97f733f0662b83464abbbfa0acab76d1jchen  CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;
383da935a5c97f733f0662b83464abbbfa0acab76d1jchen  CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
384da935a5c97f733f0662b83464abbbfa0acab76d1jchen
385da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
386da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer
387da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
388da935a5c97f733f0662b83464abbbfa0acab76d1jchen  CopyMem (AcpiTableInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32)));
389da935a5c97f733f0662b83464abbbfa0acab76d1jchen  CopyMem (AcpiTableInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32)));
390da935a5c97f733f0662b83464abbbfa0acab76d1jchen  CopyMem (AcpiTableInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64)));
391da935a5c97f733f0662b83464abbbfa0acab76d1jchen
392da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
393da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // Calculate orignal ACPI table buffer size
394da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
39537abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT
39637abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              mEfiAcpiMaxNumTables * sizeof (UINT32) +
39737abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT
39837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              mEfiAcpiMaxNumTables * sizeof (UINT32) +
39937abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT
40037abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              mEfiAcpiMaxNumTables * sizeof (UINT64);
40137abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));
402da935a5c97f733f0662b83464abbbfa0acab76d1jchen
403da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
404da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // Update the Max ACPI table number
405da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
406da935a5c97f733f0662b83464abbbfa0acab76d1jchen  mEfiAcpiMaxNumTables = NewMaxTableNumber;
407da935a5c97f733f0662b83464abbbfa0acab76d1jchen  return EFI_SUCCESS;
408da935a5c97f733f0662b83464abbbfa0acab76d1jchen}
4095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
4105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function adds an ACPI table to the table list.  It will detect FACS and
4115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  allocate the correct type of memory and properly align the table.
4125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance         Instance of the protocol.
4145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Table                     Table to add.
4155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Checksum                  Does the table require checksumming.
4165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Version                   The version of the list to add the table to.
4175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Handle                    Pointer for returning the handle.
4185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS               The function completed successfully.
4205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_OUT_OF_RESOURCES      Could not allocate a required resource.
4215966402ed51c5b611bf437c812047dc9c432a47eStar Zeng  @retval EFI_ACCESS_DENIED         The table signature matches a table already
4225966402ed51c5b611bf437c812047dc9c432a47eStar Zeng                                    present in the system and platform policy
4235966402ed51c5b611bf437c812047dc9c432a47eStar Zeng                                    does not allow duplicate tables of this type.
4245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
4265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
4275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenAddTableToList (
4285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,
4295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN VOID                                 *Table,
4305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN BOOLEAN                              Checksum,
4315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_VERSION               Version,
4325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  OUT UINTN                               *Handle
4335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
4345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
4355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_STATUS          Status;
4365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_ACPI_TABLE_LIST *CurrentTableList;
4375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT32              CurrentTableSignature;
4385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT32              CurrentTableSize;
4395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT32              *CurrentRsdtEntry;
4405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  VOID                *CurrentXsdtEntry;
4415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT64              Buffer64;
4425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  BOOLEAN             AddToRsdt;
4435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
4465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (AcpiTableInstance);
4485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (Table);
4495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (Handle);
4505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Init locals
4535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AddToRsdt = TRUE;
4555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Create a new list entry
4585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST));
4605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (CurrentTableList);
4615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Determine table type and size
4645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature;
4665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableSize      = ((EFI_ACPI_COMMON_HEADER *) Table)->Length;
4675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Allocate a buffer for the table.  All tables are allocated in the lower 32 bits of address space
4705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // for backwards compatibility with ACPI 1.0 OS.
4715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // This is done because ACPI 1.0 pointers are 32 bit values.
4735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
4745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // There is no architectural reason these should be below 4GB, it is purely
4755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // for convenience of implementation that we force memory below 4GB.
4765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList->PageAddress   = 0xFFFFFFFF;
4785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);
4795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
4805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
4815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Allocation memory type depends on the type of the table
4825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
48336d58153b16c21a097b9a11a085dd064f5112a05jyao  if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
48436d58153b16c21a097b9a11a085dd064f5112a05jyao      (CurrentTableSignature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE)) {
4855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
4865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Allocate memory for the FACS.  This structure must be aligned
4875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // on a 64 byte boundary and must be ACPI NVS memory.
4885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Using AllocatePages should ensure that it is always aligned.
48936d58153b16c21a097b9a11a085dd064f5112a05jyao    // Do not change signature for new ACPI version because they are same.
49036d58153b16c21a097b9a11a085dd064f5112a05jyao    //
49136d58153b16c21a097b9a11a085dd064f5112a05jyao    // UEFI table also need to be in ACPI NVS memory, because some data field
49236d58153b16c21a097b9a11a085dd064f5112a05jyao    // could be updated by OS present agent. For example, BufferPtrAddress in
49336d58153b16c21a097b9a11a085dd064f5112a05jyao    // SMM communication ACPI table.
4945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
4955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    ASSERT ((EFI_PAGE_SIZE % 64) == 0);
4965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Status = gBS->AllocatePages (
4975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    AllocateMaxAddress,
4985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    EfiACPIMemoryNVS,
4995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    CurrentTableList->NumberOfPages,
5005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    &CurrentTableList->PageAddress
5015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    );
5025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  } else {
5035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // All other tables are ACPI reclaim memory, no alignment requirements.
5055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Status = gBS->AllocatePages (
5075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    AllocateMaxAddress,
5085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    EfiACPIReclaimMemory,
5095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    CurrentTableList->NumberOfPages,
5105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    &CurrentTableList->PageAddress
5115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                    );
5125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
5135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check return value from memory alloc.
5155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (EFI_ERROR (Status)) {
5175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    gBS->FreePool (CurrentTableList);
5185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_OUT_OF_RESOURCES;
5195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
5205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Update the table pointer with the allocated memory start
5225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;
5245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Initialize the table contents
5275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE;
5295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (CurrentTableList->Table, Table, CurrentTableSize);
5305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList->Handle  = AcpiTableInstance->CurrentHandle++;
5315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  *Handle                   = CurrentTableList->Handle;
5325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableList->Version = Version;
5335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Update internal pointers if this is a required table.  If it is a required
5365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // table and a table of that type already exists, return an error.
5375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Calculate the checksum if the table is not FACS.
5395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
5405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  switch (CurrentTableSignature) {
5415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
5435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // We don't add the FADT in the standard way because some
5455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // OS expect the FADT to be early in the table list.
5465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // So we always add it as the first element in the list.
5475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AddToRsdt = FALSE;
5495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Check that the table has not been previously added.
5525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Fadt1 != NULL) ||
554f0071740ec3c7a536201cb02cec013442805760aStar Zeng        ((Version & ACPI_TABLE_VERSION_GTE_2_0)  != 0 && AcpiTableInstance->Fadt3 != NULL)
5555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        ) {
5565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
5575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      gBS->FreePool (CurrentTableList);
5585966402ed51c5b611bf437c812047dc9c432a47eStar Zeng      return EFI_ACCESS_DENIED;
5595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
5605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Add the table to the appropriate table version
5625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
5635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
5645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Save a pointer to the table
5665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
5685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Update pointers in FADT.  If tables don't exist this will put NULL pointers there.
5715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Fadt1->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs1;
5735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Fadt1->Dsdt          = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
5745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // RSDP OEM information is updated to match the FADT OEM information
5775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CopyMem (
5795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        &AcpiTableInstance->Rsdp1->OemId,
5805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        &AcpiTableInstance->Fadt1->Header.OemId,
5815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        6
5825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
5835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // RSDT OEM information is updated to match the FADT OEM information.
5865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
5875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CopyMem (
5885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        &AcpiTableInstance->Rsdt1->OemId,
5895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        &AcpiTableInstance->Fadt1->Header.OemId,
5905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        6
5915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
5925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
5935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CopyMem (
5945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        &AcpiTableInstance->Rsdt1->OemTableId,
5955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        &AcpiTableInstance->Fadt1->Header.OemTableId,
5965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        sizeof (UINT64)
5975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
5985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Rsdt1->OemRevision = AcpiTableInstance->Fadt1->Header.OemRevision;
5995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
6005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
601f0071740ec3c7a536201cb02cec013442805760aStar Zeng    if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
6025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
6035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Save a pointer to the table
6045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
6055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
6065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
6075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
6085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Update pointers in FADT.  If tables don't exist this will put NULL pointers there.
609c93776c2d47b23b5e64691753efc7ab47ba257c0jyao      // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and
610c93776c2d47b23b5e64691753efc7ab47ba257c0jyao      // vice-versa.
6115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
61210342a643f4a6f89a86746c42f2ebcc1f02359f0jyao      if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) {
613c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        AcpiTableInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs3;
614f798e8bff773c833837c71fa806a7604fff7b503Laszlo Ersek        ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
615c93776c2d47b23b5e64691753efc7ab47ba257c0jyao      } else {
616c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
617c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        CopyMem (
618c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          &AcpiTableInstance->Fadt3->XFirmwareCtrl,
619c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          &Buffer64,
620c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          sizeof (UINT64)
621c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          );
622f798e8bff773c833837c71fa806a7604fff7b503Laszlo Ersek        AcpiTableInstance->Fadt3->FirmwareCtrl = 0;
623c93776c2d47b23b5e64691753efc7ab47ba257c0jyao      }
624f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
625f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
626f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      CopyMem (
627f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Fadt3->XDsdt,
628f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &Buffer64,
629f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        sizeof (UINT64)
630f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        );
6315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
632f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      //
633f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      // RSDP OEM information is updated to match the FADT OEM information
634f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      //
635f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      CopyMem (
636f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Rsdp3->OemId,
637f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Fadt3->Header.OemId,
638f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        6
639f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        );
640f0c855b26386c16ba0a70600d72cd09c090db0e0rsun
641f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      //
642f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      // RSDT OEM information is updated to match FADT OEM information.
643f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      //
644f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      CopyMem (
645f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Rsdt3->OemId,
646f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Fadt3->Header.OemId,
647f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        6
648f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        );
649f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      CopyMem (
650f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Rsdt3->OemTableId,
651f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Fadt3->Header.OemTableId,
652f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        sizeof (UINT64)
653f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        );
654f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;
655f0c855b26386c16ba0a70600d72cd09c090db0e0rsun
656f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      //
657f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      // XSDT OEM information is updated to match FADT OEM information.
658f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      //
659f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      CopyMem (
660f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Xsdt->OemId,
661f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Fadt3->Header.OemId,
662f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        6
663f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        );
664f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      CopyMem (
665f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Xsdt->OemTableId,
666f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        &AcpiTableInstance->Fadt3->Header.OemTableId,
667f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        sizeof (UINT64)
668f0c855b26386c16ba0a70600d72cd09c090db0e0rsun        );
669f0c855b26386c16ba0a70600d72cd09c090db0e0rsun      AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;
6705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
6715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
6725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Checksum the table
6735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
6745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (Checksum) {
6755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiPlatformChecksum (
6765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CurrentTableList->Table,
6775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CurrentTableList->Table->Length,
6785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
6795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        Checksum)
6805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
6815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
6825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    break;
6835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
6845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
6855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
6865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Check that the table has not been previously added.
6875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
6885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||
689f0071740ec3c7a536201cb02cec013442805760aStar Zeng        ((Version & ACPI_TABLE_VERSION_GTE_2_0)  != 0 && AcpiTableInstance->Facs3 != NULL)
6905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        ) {
6915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
6925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      gBS->FreePool (CurrentTableList);
6935966402ed51c5b611bf437c812047dc9c432a47eStar Zeng      return EFI_ACCESS_DENIED;
6945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
6955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
6965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // FACS is referenced by FADT and is not part of RSDT
6975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
6985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AddToRsdt = FALSE;
6995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Add the table to the appropriate table version
7025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
7045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Save a pointer to the table
7065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
7085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // If FADT already exists, update table pointers.
7115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (AcpiTableInstance->Fadt1 != NULL) {
7135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;
7145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
7165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Checksum FADT table
7175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
7185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiPlatformChecksum (
7195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt1,
7205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt1->Header.Length,
7215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
7225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          Checksum)
7235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
7245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
7255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
7265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
727f0071740ec3c7a536201cb02cec013442805760aStar Zeng    if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
7285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Save a pointer to the table
7305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
7325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // If FADT already exists, update table pointers.
7355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (AcpiTableInstance->Fadt3 != NULL) {
737c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        //
738c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and
739c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        // vice-versa.
740c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        //
74110342a643f4a6f89a86746c42f2ebcc1f02359f0jyao        if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) {
742c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          AcpiTableInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs3;
743f798e8bff773c833837c71fa806a7604fff7b503Laszlo Ersek          ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
744c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        } else {
745c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
746c93776c2d47b23b5e64691753efc7ab47ba257c0jyao          CopyMem (
747c93776c2d47b23b5e64691753efc7ab47ba257c0jyao            &AcpiTableInstance->Fadt3->XFirmwareCtrl,
748c93776c2d47b23b5e64691753efc7ab47ba257c0jyao            &Buffer64,
749c93776c2d47b23b5e64691753efc7ab47ba257c0jyao            sizeof (UINT64)
750c93776c2d47b23b5e64691753efc7ab47ba257c0jyao            );
751f798e8bff773c833837c71fa806a7604fff7b503Laszlo Ersek          AcpiTableInstance->Fadt3->FirmwareCtrl = 0;
752c93776c2d47b23b5e64691753efc7ab47ba257c0jyao        }
7535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
7555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Checksum FADT table
7565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
7575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiPlatformChecksum (
7585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt3,
7595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt3->Header.Length,
7605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
7615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          Checksum)
7625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
7635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
7645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
7655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    break;
7675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
7695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Check that the table has not been previously added.
7715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||
773f0071740ec3c7a536201cb02cec013442805760aStar Zeng        ((Version & ACPI_TABLE_VERSION_GTE_2_0)  != 0 && AcpiTableInstance->Dsdt3 != NULL)
7745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        ) {
7755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
7765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      gBS->FreePool (CurrentTableList);
7775966402ed51c5b611bf437c812047dc9c432a47eStar Zeng      return EFI_ACCESS_DENIED;
7785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
7795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // DSDT is referenced by FADT and is not part of RSDT
7815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AddToRsdt = FALSE;
7835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Add the table to the appropriate table version
7865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
7875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
7885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Save a pointer to the table
7905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
7925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // If FADT already exists, update table pointers.
7955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
7965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (AcpiTableInstance->Fadt1 != NULL) {
7975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
7985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
7995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
8005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Checksum FADT table
8015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
8025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiPlatformChecksum (
8035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt1,
8045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt1->Header.Length,
8055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
8065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          Checksum)
8075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
8085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
8095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
8105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
811f0071740ec3c7a536201cb02cec013442805760aStar Zeng    if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
8125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
8135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Save a pointer to the table
8145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
8155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiTableInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
8165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
8175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
8185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // If FADT already exists, update table pointers.
8195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
8205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (AcpiTableInstance->Fadt3 != NULL) {
8215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
8225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
8235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CopyMem (
8245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          &AcpiTableInstance->Fadt3->XDsdt,
8255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          &Buffer64,
8265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          sizeof (UINT64)
8275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
8285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
8295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
8305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Checksum FADT table
8315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
8325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiPlatformChecksum (
8335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt3,
8345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt3->Header.Length,
8355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
8365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          Checksum)
8375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
8385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
8395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
8405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
8415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Checksum the table
8425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
8435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (Checksum) {
8445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiPlatformChecksum (
8455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CurrentTableList->Table,
8465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CurrentTableList->Table->Length,
8475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
8485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        Checksum)
8495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
8505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
8515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    break;
8525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
8535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  default:
8545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
8555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Checksum the table
8565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
8575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (Checksum) {
8585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      AcpiPlatformChecksum (
8595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CurrentTableList->Table,
8605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CurrentTableList->Table->Length,
8615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
8625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        Checksum)
8635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
8645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
8655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    break;
8665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
8675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
8685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Add the table to the current list of tables
8695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
8705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  InsertTailList (&AcpiTableInstance->TableList, &CurrentTableList->Link);
8715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
8725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
8735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Add the table to RSDT and/or XSDT table entry lists.
8745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
8755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
8765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Add to ACPI 1.0b table tree
8775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
8785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
8795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (AddToRsdt) {
8805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
881da935a5c97f733f0662b83464abbbfa0acab76d1jchen      // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer
8825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
883da935a5c97f733f0662b83464abbbfa0acab76d1jchen      if (AcpiTableInstance->NumberOfTableEntries1 >= mEfiAcpiMaxNumTables) {
884da935a5c97f733f0662b83464abbbfa0acab76d1jchen        Status = ReallocateAcpiTableBuffer (AcpiTableInstance);
885da935a5c97f733f0662b83464abbbfa0acab76d1jchen        ASSERT_EFI_ERROR (Status);
886da935a5c97f733f0662b83464abbbfa0acab76d1jchen      }
8875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CurrentRsdtEntry = (UINT32 *)
8885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        (
889da935a5c97f733f0662b83464abbbfa0acab76d1jchen          (UINT8 *) AcpiTableInstance->Rsdt1 +
8905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
891da935a5c97f733f0662b83464abbbfa0acab76d1jchen          AcpiTableInstance->NumberOfTableEntries1 *
8925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          sizeof (UINT32)
8935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        );
8945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
8955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
896da935a5c97f733f0662b83464abbbfa0acab76d1jchen      // Add entry to the RSDT unless its the FACS or DSDT
8975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
8985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
8995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
9015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Update RSDT length
9025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
903da935a5c97f733f0662b83464abbbfa0acab76d1jchen      AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);
9045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
905da935a5c97f733f0662b83464abbbfa0acab76d1jchen      AcpiTableInstance->NumberOfTableEntries1++;
906da935a5c97f733f0662b83464abbbfa0acab76d1jchen    }
907da935a5c97f733f0662b83464abbbfa0acab76d1jchen  }
908da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
909da935a5c97f733f0662b83464abbbfa0acab76d1jchen  // Add to ACPI 2.0/3.0  table tree
910da935a5c97f733f0662b83464abbbfa0acab76d1jchen  //
911f0071740ec3c7a536201cb02cec013442805760aStar Zeng  if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
912da935a5c97f733f0662b83464abbbfa0acab76d1jchen     if (AddToRsdt) {
913da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
914da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer
915da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
916da935a5c97f733f0662b83464abbbfa0acab76d1jchen       if (AcpiTableInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) {
917da935a5c97f733f0662b83464abbbfa0acab76d1jchen         Status = ReallocateAcpiTableBuffer (AcpiTableInstance);
918da935a5c97f733f0662b83464abbbfa0acab76d1jchen         ASSERT_EFI_ERROR (Status);
919da935a5c97f733f0662b83464abbbfa0acab76d1jchen       }
920da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
921da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
922da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // If it becomes necessary to maintain separate table lists, changes will be required.
923da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
924da935a5c97f733f0662b83464abbbfa0acab76d1jchen       CurrentRsdtEntry = (UINT32 *)
925da935a5c97f733f0662b83464abbbfa0acab76d1jchen         (
926da935a5c97f733f0662b83464abbbfa0acab76d1jchen           (UINT8 *) AcpiTableInstance->Rsdt3 +
927da935a5c97f733f0662b83464abbbfa0acab76d1jchen           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
928da935a5c97f733f0662b83464abbbfa0acab76d1jchen           AcpiTableInstance->NumberOfTableEntries3 *
929da935a5c97f733f0662b83464abbbfa0acab76d1jchen           sizeof (UINT32)
930da935a5c97f733f0662b83464abbbfa0acab76d1jchen         );
931da935a5c97f733f0662b83464abbbfa0acab76d1jchen
932da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
933da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // This pointer must not be directly dereferenced as the XSDT entries may not
934da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.
935da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
936da935a5c97f733f0662b83464abbbfa0acab76d1jchen       CurrentXsdtEntry = (VOID *)
937da935a5c97f733f0662b83464abbbfa0acab76d1jchen         (
938da935a5c97f733f0662b83464abbbfa0acab76d1jchen           (UINT8 *) AcpiTableInstance->Xsdt +
939da935a5c97f733f0662b83464abbbfa0acab76d1jchen           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
940da935a5c97f733f0662b83464abbbfa0acab76d1jchen           AcpiTableInstance->NumberOfTableEntries3 *
941da935a5c97f733f0662b83464abbbfa0acab76d1jchen           sizeof (UINT64)
942da935a5c97f733f0662b83464abbbfa0acab76d1jchen         );
943da935a5c97f733f0662b83464abbbfa0acab76d1jchen
944da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
945da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // Add entry to the RSDT
946da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
947da935a5c97f733f0662b83464abbbfa0acab76d1jchen       *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
948da935a5c97f733f0662b83464abbbfa0acab76d1jchen
949da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
950da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // Update RSDT length
951da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
952da935a5c97f733f0662b83464abbbfa0acab76d1jchen       AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);
953da935a5c97f733f0662b83464abbbfa0acab76d1jchen
954da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
955da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // Add entry to XSDT, XSDT expects 64 bit pointers, but
956da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // the table pointers in XSDT are not aligned on 8 byte boundary.
957da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
958da935a5c97f733f0662b83464abbbfa0acab76d1jchen       Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;
959da935a5c97f733f0662b83464abbbfa0acab76d1jchen       CopyMem (
960da935a5c97f733f0662b83464abbbfa0acab76d1jchen         CurrentXsdtEntry,
961da935a5c97f733f0662b83464abbbfa0acab76d1jchen         &Buffer64,
962da935a5c97f733f0662b83464abbbfa0acab76d1jchen         sizeof (UINT64)
963da935a5c97f733f0662b83464abbbfa0acab76d1jchen         );
964da935a5c97f733f0662b83464abbbfa0acab76d1jchen
965da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
966da935a5c97f733f0662b83464abbbfa0acab76d1jchen       // Update length
967da935a5c97f733f0662b83464abbbfa0acab76d1jchen       //
968da935a5c97f733f0662b83464abbbfa0acab76d1jchen       AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);
969da935a5c97f733f0662b83464abbbfa0acab76d1jchen
970da935a5c97f733f0662b83464abbbfa0acab76d1jchen       AcpiTableInstance->NumberOfTableEntries3++;
9715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
9725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
9735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ChecksumCommonTables (AcpiTableInstance);
9755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
9765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
9775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
9805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function finds the table specified by the handle and returns a pointer to it.
9815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are
9825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  undefined.
9835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Handle      Table to find.
9855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  TableList   Table list to search
9865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Table       Pointer to table found.
9875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS    The function completed successfully.
9895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_NOT_FOUND  No table found matching the handle specified.
9905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
9915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
9925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
9935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenFindTableByHandle (
9945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN                                Handle,
9955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN LIST_ENTRY                       *TableList,
9965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  OUT EFI_ACPI_TABLE_LIST                 **Table
9975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
9985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
9995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  LIST_ENTRY      *CurrentLink;
10005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_ACPI_TABLE_LIST *CurrentTable;
10015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
10045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (Table);
10065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Find the table
10095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentLink = TableList->ForwardLink;
10115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  while (CurrentLink != TableList) {
10135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
10145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (CurrentTable->Handle == Handle) {
10155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Found handle, so return this table.
10175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      *Table = CurrentTable;
10195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      return EFI_SUCCESS;
10205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
10215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CurrentLink = CurrentLink->ForwardLink;
10235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
10245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Table not found
10265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_NOT_FOUND;
10285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
10295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
10325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function removes a basic table from the RSDT and/or XSDT.
10335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  For Acpi 1.0 tables, pass in the Rsdt.
10345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  For Acpi 2.0 tables, pass in both Rsdt and Xsdt.
10355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Table                 Pointer to table found.
10375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  NumberOfTableEntries  Current number of table entries in the RSDT/XSDT
10385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Rsdt                  Pointer to the RSDT to remove from
10395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Xsdt                  Pointer to the Xsdt to remove from
10405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS            The function completed successfully.
10425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_INVALID_PARAMETER  The table was not found in both Rsdt and Xsdt.
10435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
10455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
10465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenRemoveTableFromRsdt (
10475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT EFI_ACPI_TABLE_LIST              * Table,
10485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT UINTN                            *NumberOfTableEntries,
10495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Rsdt,
10505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Xsdt OPTIONAL
10515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
10525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
10535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT32  *CurrentRsdtEntry;
10545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  VOID    *CurrentXsdtEntry;
10555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT64  CurrentTablePointer64;
10565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINTN   Index;
10575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
10605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (Table);
10625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (NumberOfTableEntries);
10635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (Rsdt);
10645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Find the table entry in the RSDT and XSDT
10675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
10685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  for (Index = 0; Index < *NumberOfTableEntries; Index++) {
10695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
10705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
10715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // If it becomes necessary to maintain separate table lists, changes will be required.
10725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
10735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));
10745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (Xsdt != NULL) {
10755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // This pointer must not be directly dereferenced as the XSDT entries may not
10775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.
10785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64));
10805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
10815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Read the entry value out of the XSDT
10835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64));
10855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    } else {
10865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Initialize to NULL
10885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CurrentXsdtEntry      = 0;
10905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CurrentTablePointer64 = 0;
10915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
10925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
10935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Check if we have found the corresponding entry in both RSDT and XSDT
10945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
10955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table &&
10965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)
10975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        ) {
10985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
10995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Found entry, so copy all following entries and shrink table
11005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // We actually copy all + 1 to copy the initialized value of memory over
11015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // the last entry.
11025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
11035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));
11045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      Rsdt->Length = Rsdt->Length - sizeof (UINT32);
11055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (Xsdt != NULL) {
11065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));
11075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        Xsdt->Length = Xsdt->Length - sizeof (UINT64);
11085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
11095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      break;
11105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    } else if (Index + 1 == *NumberOfTableEntries) {
11115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
11125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // At the last entry, and table not found
11135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
11145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      return EFI_INVALID_PARAMETER;
11155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
11165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
11175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Checksum the tables
11195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
11215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Rsdt,
11225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Rsdt->Length,
11235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
11245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Checksum)
11255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
11265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (Xsdt != NULL) {
11285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiPlatformChecksum (
11295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      Xsdt,
11305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      Xsdt->Length,
11315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
11325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      Checksum)
11335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      );
11345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
11355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Decrement the number of tables
11375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  (*NumberOfTableEntries)--;
11395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
11415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
11425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
11455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function removes a table and frees any associated memory.
11465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance  Instance of the protocol.
11485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Version            Version(s) to delete.
11495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Table              Pointer to table found.
11505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS  The function completed successfully.
11525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
11545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
11555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenDeleteTable (
11565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,
11575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_VERSION               Version,
11585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT EFI_ACPI_TABLE_LIST              *Table
11595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
11605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
11615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT32  CurrentTableSignature;
11625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  BOOLEAN RemoveFromRsdt;
11635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
11665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (AcpiTableInstance);
11685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (Table);
11695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Init locals
11725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  RemoveFromRsdt        = TRUE;
11746198c34621b38815bbfb116f8fcf656a54470920vanjeff  //
11756198c34621b38815bbfb116f8fcf656a54470920vanjeff  // Check for Table->Table
11766198c34621b38815bbfb116f8fcf656a54470920vanjeff  //
11776198c34621b38815bbfb116f8fcf656a54470920vanjeff  ASSERT (Table->Table != NULL);
11785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature;
11795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
11805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Basic tasks to accomplish delete are:
11825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //   Determine removal requirements (in RSDT/XSDT or not)
11835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //   Remove entry from RSDT/XSDT
11845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //   Remove any table references to the table
11855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //   If no one is using the table
11865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //      Free the table (removing pointers from private data and tables)
11875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //      Remove from list
11885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //      Free list structure
11895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Determine if this table is in the RSDT or XSDT
11925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
11935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
11945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||
11955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)
11965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      ) {
11975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    RemoveFromRsdt = FALSE;
11985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
11995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
12005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // We don't remove the FADT in the standard way because some
12015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // OS expect the FADT to be early in the table list.
12025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // So we always put it as the first element in the list.
12035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
12045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
12055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    RemoveFromRsdt = FALSE;
12065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
12075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
12095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Remove the table from RSDT and XSDT
12105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
12115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (Table->Table != NULL) {
12125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
12135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt
12145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
12155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) {
12165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Remove this version from the table
12185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE;
12205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
12215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) {
12235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Remove this version from the table
12255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B;
12275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Remove from Rsdt.  We don't care about the return value because it is
12305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // acceptable for the table to not exist in Rsdt.
12315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // We didn't add some tables so we don't remove them.
12325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (RemoveFromRsdt) {
12345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        RemoveTableFromRsdt (
12355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          Table,
12365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          &AcpiTableInstance->NumberOfTableEntries1,
12375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Rsdt1,
12385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          NULL
12395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
12405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
12415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
12425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1243f0071740ec3c7a536201cb02cec013442805760aStar Zeng    if (Version & ACPI_TABLE_VERSION_GTE_2_0 & Table->Version) {
12445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Remove this version from the table
12465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
1247f0071740ec3c7a536201cb02cec013442805760aStar Zeng      Table->Version = Table->Version &~(Version & ACPI_TABLE_VERSION_GTE_2_0);
12485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Remove from Rsdt and Xsdt.  We don't care about the return value
12515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // because it is acceptable for the table to not exist in Rsdt/Xsdt.
12525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // We didn't add some tables so we don't remove them.
12535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
12545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if (RemoveFromRsdt) {
12555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        RemoveTableFromRsdt (
12565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          Table,
12575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          &AcpiTableInstance->NumberOfTableEntries3,
12585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Rsdt3,
12595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Xsdt
12605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          );
12615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
12625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
12635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
12645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Free the table, clean up any dependent tables and our private data pointers.
12655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
12665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    switch (Table->Table->Signature) {
12675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
12695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
12705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Fadt1 = NULL;
12715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
12725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1273f0071740ec3c7a536201cb02cec013442805760aStar Zeng      if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
12745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Fadt3 = NULL;
12755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
12765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      break;
12775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
12795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
12805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Facs1 = NULL;
12815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
12835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Update FADT table pointers
12845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
12855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        if (AcpiTableInstance->Fadt1 != NULL) {
12865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt1->FirmwareCtrl = 0;
12875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
12885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
12895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          // Checksum table
12905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
12915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiPlatformChecksum (
12925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt1,
12935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt1->Header.Length,
12945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
12955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            Checksum)
12965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            );
12975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        }
12985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
12995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1300f0071740ec3c7a536201cb02cec013442805760aStar Zeng      if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
13015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Facs3 = NULL;
13025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
13045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Update FADT table pointers
13055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
13065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        if (AcpiTableInstance->Fadt3 != NULL) {
13075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt3->FirmwareCtrl = 0;
13085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
13095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
13115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          // Checksum table
13125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
13135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiPlatformChecksum (
13145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt3,
13155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt3->Header.Length,
13165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
13175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            Checksum)
13185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            );
13195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        }
13205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
13215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      break;
13225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
13245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
13255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Dsdt1 = NULL;
13265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
13285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Update FADT table pointers
13295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
13305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        if (AcpiTableInstance->Fadt1 != NULL) {
13315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt1->Dsdt = 0;
13325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
13345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          // Checksum table
13355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
13365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiPlatformChecksum (
13375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt1,
13385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt1->Header.Length,
13395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
13405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            Checksum)
13415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            );
13425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        }
13435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
13445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1346f0071740ec3c7a536201cb02cec013442805760aStar Zeng      if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {
13475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        AcpiTableInstance->Dsdt3 = NULL;
13485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
13505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        // Update FADT table pointers
13515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        //
13525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        if (AcpiTableInstance->Fadt3 != NULL) {
13535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiTableInstance->Fadt3->Dsdt = 0;
13545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          ZeroMem (&AcpiTableInstance->Fadt3->XDsdt, sizeof (UINT64));
13555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
13575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          // Checksum table
13585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          //
13595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten          AcpiPlatformChecksum (
13605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt3,
13615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            AcpiTableInstance->Fadt3->Header.Length,
13625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
13635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            Checksum)
13645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            );
13655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten        }
13665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      }
13675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      break;
13685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    default:
13705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
13715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      // Do nothing
13725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      //
13735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten      break;
13745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    }
13755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
13765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
13775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // If no version is using this table anymore, remove and free list entry.
13785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
13795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (Table->Version == 0) {
13805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
13815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    // Free the Table
13825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    //
13835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    gBS->FreePages (Table->PageAddress, Table->NumberOfPages);
13845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    RemoveEntryList (&(Table->Link));
13855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    gBS->FreePool (Table);
13865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
13875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
13885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Done
13895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
13905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
13915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
13925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
13955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function finds and removes the table specified by the handle.
13965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
13975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance  Instance of the protocol.
13985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Version            Bitmask of which versions to remove.
13995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Handle             Table to remove.
14005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS    The function completed successfully.
14025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_ABORTED    An error occurred.
14035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_NOT_FOUND  Handle not found in table list.
14045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
14065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
14075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenRemoveTableFromList (
14085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,
14095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN EFI_ACPI_TABLE_VERSION               Version,
14105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN                                Handle
14115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
14125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
14135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_ACPI_TABLE_LIST *Table;
14145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_STATUS          Status;
14155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1416b474ed4944e20485d730bcb91bdf5ae6f8ca70f6jljusten  Table = (EFI_ACPI_TABLE_LIST*) NULL;
1417b474ed4944e20485d730bcb91bdf5ae6f8ca70f6jljusten
14185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
14205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (AcpiTableInstance);
14225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Find the table
14255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Status = FindTableByHandle (
14275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            Handle,
14285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            &AcpiTableInstance->TableList,
14295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            &Table
14305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten            );
14315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (EFI_ERROR (Status)) {
14325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_NOT_FOUND;
14335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
14345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Remove the table
14365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Status = DeleteTable (AcpiTableInstance, Version, Table);
14385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (EFI_ERROR (Status)) {
14395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_ABORTED;
14405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
14415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Completed successfully
14435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
14455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
14465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
14495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  This function calculates and updates an UINT8 checksum.
14505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Buffer          Pointer to buffer to checksum
14525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  Size            Number of bytes to checksum
14535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  ChecksumOffset  Offset to place the checksum result in
14545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS             The function completed successfully.
14565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
14585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
14595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenAcpiPlatformChecksum (
14605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN VOID       *Buffer,
14615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN      Size,
14625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN UINTN      ChecksumOffset
14635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
14645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
14655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT8 Sum;
14665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT8 *Ptr;
14675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Sum = 0;
14695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Initialize pointer
14715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Ptr = Buffer;
14735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // set checksum to 0 first
14765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Ptr[ChecksumOffset] = 0;
14785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // add all content of buffer
14815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  while ((Size--) != 0) {
14835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Sum = (UINT8) (Sum + (*Ptr++));
14845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
14855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // set checksum
14875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
14885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Ptr                 = Buffer;
14895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
14905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
14925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
14935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
14965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Checksum all versions of the common tables, RSDP, RSDT, XSDT.
14975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
14985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance  Protocol instance private data.
14995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS        The function completed successfully.
15015f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15025f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
15035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
15045f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenChecksumCommonTables (
15055f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  IN OUT EFI_ACPI_TABLE_INSTANCE                   *AcpiTableInstance
15065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
15075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
15085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // RSDP ACPI 1.0 checksum for 1.0 table.  This is only the first 20 bytes of the structure
15105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
15125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdp1,
15135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
15145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
15155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Checksum)
15165f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
15175f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15195f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // RSDP ACPI 1.0 checksum for 2.0/3.0 table.  This is only the first 20 bytes of the structure
15205f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15215f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
15225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdp3,
15235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
15245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
15255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Checksum)
15265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
15275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // RSDP ACPI 2.0/3.0 checksum, this is the entire table
15305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
15325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdp3,
15335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
15345f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
15355f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    ExtendedChecksum)
15365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
15375f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15385f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15395f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // RSDT checksums
15405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
15425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdt1,
15435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdt1->Length,
15445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
15455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Checksum)
15465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
15475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
15495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdt3,
15505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Rsdt3->Length,
15515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
15525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Checksum)
15535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
15545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // XSDT checksum
15575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiPlatformChecksum (
15595f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Xsdt,
15605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    AcpiTableInstance->Xsdt->Length,
15615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
15625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    Checksum)
15635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    );
15645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
15665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
15675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten/**
15705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Constructor for the ACPI table protocol.  Initializes instance
15715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  data.
15725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @param  AcpiTableInstance   Instance to construct
15745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_SUCCESS             Instance initialized.
15765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  @return EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
15775f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten**/
15795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenEFI_STATUS
15805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljustenAcpiTableAcpiTableConstructor (
15815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_ACPI_TABLE_INSTANCE                   *AcpiTableInstance
15825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  )
15835f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten{
15845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_STATUS            Status;
15855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT64                CurrentData;
15865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINTN                 TotalSize;
158737abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  UINTN                 RsdpTableSize;
15885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  UINT8                 *Pointer;
15895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  EFI_PHYSICAL_ADDRESS  PageAddress;
15905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Check for invalid input parameters
15935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
15945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ASSERT (AcpiTableInstance);
15955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  InitializeListHead (&AcpiTableInstance->TableList);
15975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->CurrentHandle              = 1;
15985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
15995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->AcpiTableProtocol.InstallAcpiTable   = InstallAcpiTable;
16005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
16013dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao
16023dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {
16033dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao    SdtAcpiTableAcpiSdtConstructor (AcpiTableInstance);
16043dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao  }
16053dc8585e0a9fd4b2cb383f3ceb4961c7a88a8e71jyao
16065f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
160737abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  // Create RSDP table
160837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  //
160937abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
161037abfb7ea1ce909c0cab34c98fd92841634dab9dlgao                  sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
161137abfb7ea1ce909c0cab34c98fd92841634dab9dlgao
161237abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  PageAddress = 0xFFFFFFFF;
161337abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  Status = gBS->AllocatePages (
161437abfb7ea1ce909c0cab34c98fd92841634dab9dlgao                  AllocateMaxAddress,
161537abfb7ea1ce909c0cab34c98fd92841634dab9dlgao                  EfiACPIReclaimMemory,
161637abfb7ea1ce909c0cab34c98fd92841634dab9dlgao                  EFI_SIZE_TO_PAGES (RsdpTableSize),
161737abfb7ea1ce909c0cab34c98fd92841634dab9dlgao                  &PageAddress
161837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao                  );
161937abfb7ea1ce909c0cab34c98fd92841634dab9dlgao
162037abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  if (EFI_ERROR (Status)) {
162137abfb7ea1ce909c0cab34c98fd92841634dab9dlgao    return EFI_OUT_OF_RESOURCES;
162237abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  }
162337abfb7ea1ce909c0cab34c98fd92841634dab9dlgao
162437abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  Pointer = (UINT8 *) (UINTN) PageAddress;
162537abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  ZeroMem (Pointer, RsdpTableSize);
162637abfb7ea1ce909c0cab34c98fd92841634dab9dlgao
162737abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
162837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
162937abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
163037abfb7ea1ce909c0cab34c98fd92841634dab9dlgao
163137abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  //
163237abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  // Create RSDT, XSDT structures
16335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
163437abfb7ea1ce909c0cab34c98fd92841634dab9dlgao  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT
163537abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              mEfiAcpiMaxNumTables * sizeof (UINT32) +
163637abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT
163737abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              mEfiAcpiMaxNumTables * sizeof (UINT32) +
163837abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT
163937abfb7ea1ce909c0cab34c98fd92841634dab9dlgao              mEfiAcpiMaxNumTables * sizeof (UINT64);
16405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Allocate memory in the lower 32 bit of address range for
16435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // compatibility with ACPI 1.0 OS.
16445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // This is done because ACPI 1.0 pointers are 32 bit values.
16465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
16475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // There is no architectural reason these should be below 4GB, it is purely
16485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // for convenience of implementation that we force memory below 4GB.
16495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  PageAddress = 0xFFFFFFFF;
16515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Status = gBS->AllocatePages (
16525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                  AllocateMaxAddress,
16535f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                  EfiACPIReclaimMemory,
16545f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                  EFI_SIZE_TO_PAGES (TotalSize),
16555f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                  &PageAddress
16565f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten                  );
16575f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16585f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  if (EFI_ERROR (Status)) {
165937abfb7ea1ce909c0cab34c98fd92841634dab9dlgao    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiTableInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize));
16605f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten    return EFI_OUT_OF_RESOURCES;
16615f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  }
16625f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16635f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Pointer = (UINT8 *) (UINTN) PageAddress;
16645f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ZeroMem (Pointer, TotalSize);
16655f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16665f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
16675f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
16685f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
16695f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
16705f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
16715f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16725f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16735f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Initialize RSDP
16745f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16755f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
16765f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));
1677e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CopyMem (AcpiTableInstance->Rsdp1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdp1->OemId));
16785f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdp1->Reserved    = EFI_ACPI_RESERVED_BYTE;
16795f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;
16805f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16815f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
16825f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (&AcpiTableInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));
1683e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CopyMem (AcpiTableInstance->Rsdp3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdp3->OemId));
16845f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdp3->Revision    = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;
16855f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;
16865f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdp3->Length      = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
16875f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;
16885f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
16895f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  SetMem (AcpiTableInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);
16905f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
16915f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16925f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Initialize Rsdt
16935f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16945f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Note that we "reserve" one entry for the FADT so it can always be
16955f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // at the beginning of the list of tables.  Some OS don't seem
16965f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // to find it correctly if it is too far down the list.
16975f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
16985f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
16995f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt1->Length    = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
17005f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt1->Revision  = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1701e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CopyMem (AcpiTableInstance->Rsdt1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdt1->OemId));
1702e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);
17035f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));
1704e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Rsdt1->OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);
1705e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Rsdt1->CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);
1706e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Rsdt1->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
17075f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17085f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // We always reserve first one for FADT
17095f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17105f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->NumberOfTableEntries1  = 1;
17115f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt1->Length          = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);
17125f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
17135f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt3->Signature       = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
17145f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt3->Length          = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
17155f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt3->Revision        = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1716e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CopyMem (AcpiTableInstance->Rsdt3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdt3->OemId));
1717e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);
17185f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));
1719e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Rsdt3->OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);
1720e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Rsdt3->CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);
1721e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Rsdt3->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
17225f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17235f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // We always reserve first one for FADT
17245f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17255f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->NumberOfTableEntries3  = 1;
17265f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Rsdt3->Length          = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);
17275f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
17285f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17295f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Initialize Xsdt
17305f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17315f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Xsdt->Signature  = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
17325f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Xsdt->Length     = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
17335f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Xsdt->Revision   = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;
1734e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CopyMem (AcpiTableInstance->Xsdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Xsdt->OemId));
1735e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);
17365f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  CopyMem (&AcpiTableInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));
1737e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Xsdt->OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
1738e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Xsdt->CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
1739e84f07b5fc919fcb13292aa6c33925c81f642e32Star Zeng  AcpiTableInstance->Xsdt->CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
17405f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17415f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // We always reserve first one for FADT
17425f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17435f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  AcpiTableInstance->Xsdt->Length           = AcpiTableInstance->Xsdt->Length + sizeof(UINT64);
17445f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
17455f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  ChecksumCommonTables (AcpiTableInstance);
17465f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
17475f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17485f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  // Completed successfully
17495f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  //
17505f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten  return EFI_SUCCESS;
17515f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten}
17525f55c7004666d6bf8cb421b09781cbd1ceb9eddcjljusten
1753