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