Home | History | Annotate | Download | only in AcpiPlatform
      1 /** @file
      2 ACPI Platform Driver
      3 
      4 Copyright (c) 2013-2015 Intel Corporation.
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <Protocol/AcpiTable.h>
     17 #include <IndustryStandard/Pci22.h>
     18 #include "AcpiPlatform.h"
     19 
     20 //
     21 // Global Variable
     22 //
     23 EFI_GLOBAL_NVS_AREA_PROTOCOL  mGlobalNvsArea;
     24 EFI_ACPI_SDT_PROTOCOL         *mAcpiSdt;
     25 
     26 EFI_ACPI_HANDLE mDsdtHandle = NULL;
     27 
     28 
     29 EFI_STATUS
     30 LocateSupportProtocol (
     31   IN  EFI_GUID                       *Protocol,
     32   OUT VOID                           **Instance,
     33   IN  UINT32                         Type
     34   )
     35 /*++
     36 
     37 Routine Description:
     38 
     39   Locate the first instance of a protocol.  If the protocol requested is an
     40   FV protocol, then it will return the first FV that contains the ACPI table
     41   storage file.
     42 
     43 Arguments:
     44 
     45   Protocol      The protocol to find.
     46   Instance      Return pointer to the first instance of the protocol
     47 
     48 Returns:
     49 
     50   EFI_SUCCESS           The function completed successfully.
     51   EFI_NOT_FOUND         The protocol could not be located.
     52   EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
     53 
     54 --*/
     55 {
     56   EFI_STATUS              Status;
     57   EFI_HANDLE              *HandleBuffer;
     58   UINTN                   NumberOfHandles;
     59   EFI_FV_FILETYPE         FileType;
     60   UINT32                  FvStatus;
     61   EFI_FV_FILE_ATTRIBUTES  Attributes;
     62   UINTN                   Size;
     63   UINTN                   i;
     64 
     65   FvStatus = 0;
     66 
     67   //
     68   // Locate protocol.
     69   //
     70   Status = gBS->LocateHandleBuffer (
     71                    ByProtocol,
     72                    Protocol,
     73                    NULL,
     74                    &NumberOfHandles,
     75                    &HandleBuffer
     76                    );
     77   if (EFI_ERROR (Status)) {
     78 
     79     //
     80     // Defined errors at this time are not found and out of resources.
     81     //
     82     return Status;
     83   }
     84 
     85 
     86 
     87   //
     88   // Looking for FV with ACPI storage file
     89   //
     90 
     91   for (i = 0; i < NumberOfHandles; i++) {
     92     //
     93     // Get the protocol on this handle
     94     // This should not fail because of LocateHandleBuffer
     95     //
     96     Status = gBS->HandleProtocol (
     97                      HandleBuffer[i],
     98                      Protocol,
     99                      Instance
    100                      );
    101     ASSERT_EFI_ERROR (Status);
    102 
    103     if (!Type) {
    104       //
    105       // Not looking for the FV protocol, so find the first instance of the
    106       // protocol.  There should not be any errors because our handle buffer
    107       // should always contain at least one or LocateHandleBuffer would have
    108       // returned not found.
    109       //
    110       break;
    111     }
    112 
    113     //
    114     // See if it has the ACPI storage file
    115     //
    116 
    117     Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
    118                                                               (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
    119                                                               NULL,
    120                                                               &Size,
    121                                                               &FileType,
    122                                                               &Attributes,
    123                                                               &FvStatus
    124                                                               );
    125 
    126     //
    127     // If we found it, then we are done
    128     //
    129     if (Status == EFI_SUCCESS) {
    130       break;
    131     }
    132   }
    133 
    134   //
    135   // Our exit status is determined by the success of the previous operations
    136   // If the protocol was found, Instance already points to it.
    137   //
    138 
    139   //
    140   // Free any allocated buffers
    141   //
    142   gBS->FreePool (HandleBuffer);
    143 
    144   return Status;
    145 }
    146 
    147 
    148 VOID
    149 DsdtTableUpdate (
    150   IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
    151   IN OUT   EFI_ACPI_TABLE_VERSION       *Version
    152   )
    153 /*++
    154 
    155   Routine Description:
    156 
    157     Update the DSDT table
    158 
    159   Arguments:
    160 
    161     Table   - The table to be set
    162     Version - Version to publish
    163 
    164   Returns:
    165 
    166     None
    167 
    168 --*/
    169 {
    170 
    171   UINT8      *CurrPtr;
    172   UINT8      *DsdtPointer;
    173   UINT32     *Signature;
    174   UINT8      *Operation;
    175   UINT32     *Address;
    176   UINT16     *Size;
    177   //
    178   // Loop through the ASL looking for values that we must fix up.
    179   //
    180   CurrPtr = (UINT8 *) TableHeader;
    181   for (DsdtPointer = CurrPtr;
    182        DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
    183        DsdtPointer++
    184       )
    185   {
    186     Signature = (UINT32 *) DsdtPointer;
    187     switch (*Signature) {
    188     //
    189     // MNVS operation region
    190     //
    191     case (SIGNATURE_32 ('M', 'N', 'V', 'S')):
    192       //
    193       // Conditional match.  For Region Objects, the Operator will always be the
    194       // byte immediately before the specific name.  Therefore, subtract 1 to check
    195       // the Operator.
    196       //
    197       Operation = DsdtPointer - 1;
    198       if (*Operation == AML_OPREGION_OP) {
    199         Address   = (UINT32 *) (DsdtPointer + 6);
    200         *Address  = (UINT32) (UINTN) mGlobalNvsArea.Area;
    201         Size      = (UINT16 *) (DsdtPointer + 11);
    202         *Size     = sizeof (EFI_GLOBAL_NVS_AREA);
    203       }
    204       break;
    205 
    206     //
    207     // Update processor PBLK register I/O base address
    208     //
    209     case (SIGNATURE_32 ('P', 'R', 'I', 'O')):
    210       //
    211       // Conditional match. Update the following ASL code:
    212       // Processor (CPU0, 0x01, 0x4F495250, 0x06) {}
    213       // The 3rd parameter will be updated to the actual PBLK I/O base address.
    214       // the Operator.
    215       //
    216       Operation = DsdtPointer - 8;
    217       if ((*Operation == AML_EXT_OP) && (*(Operation + 1) == AML_EXT_PROCESSOR_OP)) {
    218         *(UINT32 *)DsdtPointer = PcdGet16(PcdPmbaIoBaseAddress);
    219       }
    220       break;
    221     default:
    222       break;
    223     }
    224   }
    225 }
    226 
    227 
    228 VOID
    229 ApicTableUpdate (
    230   IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
    231   IN OUT   EFI_ACPI_TABLE_VERSION       *Version
    232   )
    233 /*++
    234 
    235   Routine Description:
    236 
    237     Update the processors information in the APIC table
    238 
    239   Arguments:
    240 
    241     Table   - The table to be set
    242     Version - Version to publish
    243 
    244   Returns:
    245 
    246     None
    247 
    248 --*/
    249 {
    250   EFI_STATUS                 Status;
    251   EFI_MP_SERVICES_PROTOCOL   *MpService;
    252   UINT8                      *CurrPtr;
    253   UINT8                      *EndPtr;
    254   UINT8                      CurrIoApic;
    255   UINT8                      CurrProcessor;
    256   UINTN                      NumberOfCPUs;
    257   UINTN                      NumberOfEnabledCPUs;
    258   UINTN                      BufferSize;
    259   EFI_PROCESSOR_INFORMATION  MpContext;
    260   ACPI_APIC_STRUCTURE_PTR    *ApicPtr;
    261 
    262   CurrIoApic    = 0;
    263   CurrProcessor = 0;
    264   //
    265   // Find the MP Protocol. This is an MP platform, so MP protocol must be
    266   // there.
    267   //
    268   Status = gBS->LocateProtocol (
    269                    &gEfiMpServiceProtocolGuid,
    270                    NULL,
    271                   (VOID**)&MpService
    272                    );
    273   if (EFI_ERROR (Status)) {
    274     //
    275     // Failed to get MP information, doesn't publish the invalid table
    276     //
    277     *Version = EFI_ACPI_TABLE_VERSION_NONE;
    278     return;
    279   }
    280 
    281   //
    282   // Determine the number of processors
    283   //
    284   MpService->GetNumberOfProcessors (
    285               MpService,
    286               &NumberOfCPUs,
    287               &NumberOfEnabledCPUs
    288               );
    289 
    290   CurrPtr = (UINT8*) &(TableHeader[1]);
    291   CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag
    292   EndPtr  = (UINT8*) TableHeader;
    293   EndPtr  = EndPtr + TableHeader->Length;
    294 
    295   while (CurrPtr < EndPtr) {
    296 
    297     ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr;
    298     switch (ApicPtr->AcpiApicCommon.Type) {
    299 
    300       case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC:
    301         BufferSize = sizeof (EFI_PROCESSOR_INFORMATION);
    302         ApicPtr->AcpiLocalApic.Flags = 0;
    303         ApicPtr->AcpiLocalApic.ApicId = 0;
    304         Status = MpService->GetProcessorInfo (
    305                               MpService,
    306                               CurrProcessor,
    307                               &MpContext
    308                               );
    309 
    310         if (!EFI_ERROR (Status)) {
    311           if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) {
    312             ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED;
    313           }
    314           ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId;
    315         }
    316         CurrProcessor++;
    317         break;
    318 
    319       case EFI_ACPI_1_0_IO_APIC:
    320         //
    321         // IO APIC entries can be patched here
    322         //
    323         if (CurrIoApic == 0) {
    324           //
    325           // Update SOC internel IOAPIC base
    326           //
    327           ApicPtr->AcpiIoApic.IoApicId      =  PcdGet8 (PcdIoApicSettingIoApicId);
    328           ApicPtr->AcpiIoApic.IoApicAddress =  (UINT32)PcdGet64(PcdIoApicBaseAddress);
    329           ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0;
    330         } else {
    331           //
    332           // Porting is required to update other IOAPIC entries if available
    333           //
    334           ASSERT (0);
    335         }
    336         CurrIoApic++;
    337         break;
    338 
    339       default:
    340         break;
    341       };
    342     CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
    343   }
    344 }
    345 
    346 VOID
    347 AcpiUpdateTable (
    348   IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
    349   IN OUT   EFI_ACPI_TABLE_VERSION       *Version
    350   )
    351 /*++
    352 
    353   Routine Description:
    354 
    355     Set the correct table revision upon the setup value
    356 
    357   Arguments:
    358 
    359     Table   - The table to be set
    360     Version - Version to publish
    361 
    362   Returns:
    363 
    364     None
    365 
    366 --*/
    367 
    368 {
    369   EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader1;
    370   EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader2;
    371   EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader3;
    372   EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *AllocationStructurePtr;
    373 
    374   if (TableHeader != NULL && Version != NULL) {
    375 
    376     *Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
    377     //
    378     // Here we use all 3.0 signature because all version use same signature if they supported
    379     //
    380     switch (TableHeader->Signature) {
    381     //
    382     // "APIC" Multiple APIC Description Table
    383     //
    384     case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
    385       ApicTableUpdate (TableHeader, Version);
    386       break;
    387     //
    388     // "DSDT" Differentiated System Description Table
    389     //
    390     case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
    391       DsdtTableUpdate (TableHeader, Version);
    392       break;
    393 
    394     //
    395     // "FACP" Fixed ACPI Description Table (FADT)
    396     //
    397     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
    398       *Version = EFI_ACPI_TABLE_VERSION_NONE;
    399       if (TableHeader->Revision == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
    400         *Version = EFI_ACPI_TABLE_VERSION_1_0B;
    401         FadtHeader1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
    402         FadtHeader1->SmiCmd     = PcdGet16(PcdSmmActivationPort);
    403         FadtHeader1->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
    404         FadtHeader1->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
    405         FadtHeader1->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
    406         FadtHeader1->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
    407       } else if (TableHeader->Revision == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
    408         *Version = EFI_ACPI_TABLE_VERSION_2_0;
    409         FadtHeader2 = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
    410         FadtHeader2->SmiCmd     = PcdGet16(PcdSmmActivationPort);
    411         FadtHeader2->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
    412         FadtHeader2->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
    413         FadtHeader2->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
    414         FadtHeader2->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
    415         FadtHeader2->XPm1aEvtBlk.Address = FadtHeader2->Pm1aEvtBlk;
    416         FadtHeader2->XPm1aCntBlk.Address = FadtHeader2->Pm1aCntBlk;
    417         FadtHeader2->XPmTmrBlk.Address   = FadtHeader2->PmTmrBlk;
    418         FadtHeader2->XGpe0Blk.Address    = FadtHeader2->Gpe0Blk;
    419       } else if (TableHeader->Revision == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
    420         *Version = EFI_ACPI_TABLE_VERSION_3_0;
    421         FadtHeader3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
    422         FadtHeader3->SmiCmd     = PcdGet16(PcdSmmActivationPort);
    423         FadtHeader3->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
    424         FadtHeader3->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
    425         FadtHeader3->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
    426         FadtHeader3->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
    427         FadtHeader3->XPm1aEvtBlk.Address = FadtHeader3->Pm1aEvtBlk;
    428         FadtHeader3->XPm1aCntBlk.Address = FadtHeader3->Pm1aCntBlk;
    429         FadtHeader3->XPmTmrBlk.Address   = FadtHeader3->PmTmrBlk;
    430         FadtHeader3->XGpe0Blk.Address    = FadtHeader3->Gpe0Blk;
    431       }
    432       break;
    433     //
    434     // "FACS" Firmware ACPI Control Structure
    435     //
    436     case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
    437       break;
    438     //
    439     // "SSDT" Secondary System Description Table
    440     //
    441     case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
    442     break;
    443     //
    444     // "HPET" IA-PC High Precision Event Timer Table
    445     //
    446     case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
    447       //
    448       // If HPET is disabled in setup, don't publish the table.
    449       //
    450       if (mGlobalNvsArea.Area->HpetEnable == 0) {
    451         *Version = EFI_ACPI_TABLE_VERSION_NONE;
    452       }
    453       ((EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) TableHeader)->BaseAddressLower32Bit.Address
    454         = PcdGet64 (PcdHpetBaseAddress);
    455       break;
    456     //
    457     // "SPCR" Serial Port Concole Redirection Table
    458     //
    459     case EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
    460       break;
    461     //
    462     // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
    463     //
    464     case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
    465       AllocationStructurePtr = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)
    466         ((UINT8 *)TableHeader + sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER));
    467       AllocationStructurePtr->BaseAddress = PcdGet64(PcdPciExpressBaseAddress);
    468       break;
    469     // Lakeport platform doesn't support the following table
    470     /*
    471       //
    472     // "ECDT" Embedded Controller Boot Resources Table
    473         //
    474     case EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE:
    475       break;
    476         //
    477     // "PSDT" Persistent System Description Table
    478           //
    479     case EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
    480       break;
    481           //
    482     // "SBST" Smart Battery Specification Table
    483     //
    484     case EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE:
    485           break;
    486     //
    487     // "SLIT" System Locality Information Table
    488     //
    489     case EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
    490           break;
    491     //
    492     // "SRAT" Static Resource Affinity Table
    493     //
    494     case EFI_ACPI_3_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE:
    495     break;
    496   //
    497     // "XSDT" Extended System Description Table
    498   //
    499     case EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
    500       break;
    501   //
    502     // "BOOT" MS Simple Boot Spec
    503   //
    504     case EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE:
    505       break;
    506   //
    507     // "CPEP" Corrected Platform Error Polling Table
    508   //
    509     case EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE:
    510       break;
    511   //
    512     // "DBGP" MS Debug Port Spec
    513   //
    514     case EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE:
    515       break;
    516     //
    517     // "ETDT" Event Timer Description Table
    518     //
    519     case EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE:
    520       break;
    521     //
    522     // "SPMI" Server Platform Management Interface Table
    523     //
    524     case EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE:
    525       break;
    526     //
    527     // "TCPA" Trusted Computing Platform Alliance Capabilities Table
    528     //
    529     case EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE:
    530       break;
    531     */
    532     default:
    533       break;
    534     }
    535   }
    536 }
    537 
    538 //
    539 // Description:
    540 //    Entrypoint of Acpi Platform driver
    541 // In:
    542 //    ImageHandle
    543 //    SystemTable
    544 // Out:
    545 //    EFI_SUCCESS
    546 //    EFI_LOAD_ERROR
    547 //    EFI_OUT_OF_RESOURCES
    548 //
    549 
    550 EFI_STATUS
    551 AcpiPlatformEntryPoint (
    552   IN EFI_HANDLE     ImageHandle,
    553   IN EFI_SYSTEM_TABLE   *SystemTable
    554   )
    555 {
    556   EFI_STATUS                    Status;
    557   EFI_ACPI_TABLE_PROTOCOL       *AcpiTable;
    558   EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
    559   INTN                          Instance;
    560   EFI_ACPI_COMMON_HEADER        *CurrentTable;
    561   UINTN                         TableHandle;
    562   UINT32                        FvStatus;
    563   UINTN                         Size;
    564   EFI_ACPI_TABLE_VERSION        Version;
    565   QNC_DEVICE_ENABLES            QNCDeviceEnables;
    566   EFI_HANDLE                    Handle;
    567   UINTN                         Index;
    568   PCI_DEVICE_INFO               *PciDeviceInfo;
    569   EFI_ACPI_HANDLE               PciRootHandle;
    570   BOOLEAN                       UpdatePRT;
    571   BOOLEAN                       UpdatePRW;
    572   PCI_DEVICE_SETTING            *mConfigData;
    573 
    574   DEBUG((DEBUG_INFO, "ACPI Platform start...\n"));
    575 
    576   Instance = 0;
    577   TableHandle = 0;
    578   CurrentTable = NULL;
    579   mConfigData  = NULL;
    580   QNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);
    581 
    582   //
    583   // Initialize the EFI Driver Library
    584   //
    585 
    586   ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512);
    587 
    588   Status = gBS->AllocatePool (
    589                    EfiACPIMemoryNVS,
    590                    sizeof (EFI_GLOBAL_NVS_AREA),
    591                    (VOID**)&mGlobalNvsArea.Area
    592                    );
    593 
    594   Handle = NULL;
    595   Status = gBS->InstallProtocolInterface (
    596                   &Handle,
    597                   &gEfiGlobalNvsAreaProtocolGuid,
    598                   EFI_NATIVE_INTERFACE,
    599                   &mGlobalNvsArea
    600                   );
    601 
    602   ASSERT_EFI_ERROR (Status);
    603   if (!EFI_ERROR (Status)) {
    604     SetMem (
    605       mGlobalNvsArea.Area,
    606       sizeof (EFI_GLOBAL_NVS_AREA),
    607       0
    608       );
    609   }
    610 
    611   //
    612   // Initialize the data.  Eventually, this will be controlled by setup options.
    613   //
    614   mGlobalNvsArea.Area->HpetEnable           =  PcdGetBool (PcdHpetEnable);
    615   mGlobalNvsArea.Area->Pm1blkIoBaseAddress  =  PcdGet16(PcdPm1blkIoBaseAddress);
    616   mGlobalNvsArea.Area->PmbaIoBaseAddress    =  PcdGet16(PcdPmbaIoBaseAddress);
    617   mGlobalNvsArea.Area->Gpe0blkIoBaseAddress =  PcdGet16(PcdGpe0blkIoBaseAddress);
    618   mGlobalNvsArea.Area->GbaIoBaseAddress     =  PcdGet16(PcdGbaIoBaseAddress);
    619   mGlobalNvsArea.Area->SmbaIoBaseAddress    =  PcdGet16(PcdSmbaIoBaseAddress);
    620   mGlobalNvsArea.Area->WdtbaIoBaseAddress   =  PcdGet16(PcdWdtbaIoBaseAddress);
    621   mGlobalNvsArea.Area->HpetBaseAddress      =  (UINT32)PcdGet64(PcdHpetBaseAddress);
    622   mGlobalNvsArea.Area->HpetSize             =  (UINT32)PcdGet64(PcdHpetSize);
    623   mGlobalNvsArea.Area->PciExpressBaseAddress=  (UINT32)PcdGet64(PcdPciExpressBaseAddress);
    624   mGlobalNvsArea.Area->PciExpressSize       =  (UINT32)PcdGet64(PcdPciExpressSize);
    625   mGlobalNvsArea.Area->RcbaMmioBaseAddress  =  (UINT32)PcdGet64(PcdRcbaMmioBaseAddress);
    626   mGlobalNvsArea.Area->RcbaMmioSize         =  (UINT32)PcdGet64(PcdRcbaMmioSize);
    627   mGlobalNvsArea.Area->IoApicBaseAddress    =  (UINT32)PcdGet64(PcdIoApicBaseAddress);
    628   mGlobalNvsArea.Area->IoApicSize           =  (UINT32)PcdGet64(PcdIoApicSize);
    629   mGlobalNvsArea.Area->TpmPresent           =  (UINT32)(FALSE);
    630   mGlobalNvsArea.Area->DBG2Present          =  (UINT32)(FALSE);
    631   mGlobalNvsArea.Area->PlatformType         =  (UINT32)PcdGet16 (PcdPlatformType);
    632 
    633   //
    634   // Configure platform IO expander I2C Slave Address.
    635   //
    636   if (mGlobalNvsArea.Area->PlatformType == Galileo) {
    637     if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
    638       mGlobalNvsArea.Area->AlternateSla = FALSE;
    639     } else {
    640       mGlobalNvsArea.Area->AlternateSla = TRUE;
    641     }
    642   }
    643 
    644   //
    645   // Find the AcpiTable protocol
    646   //
    647   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
    648   if (EFI_ERROR (Status)) {
    649     return EFI_ABORTED;
    650   }
    651 
    652   //
    653   // Initialize MADT table
    654   //
    655   Status = MadtTableInitialize (&CurrentTable, &Size);
    656   ASSERT_EFI_ERROR (Status);
    657   //
    658   // Perform any table specific updates.
    659   //
    660   AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
    661 
    662   //
    663   // Update the check sum
    664   // It needs to be zeroed before the checksum calculation
    665   //
    666   ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
    667   ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
    668     CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
    669 
    670   //
    671   // Add the table
    672   //
    673   TableHandle = 0;
    674   Status = AcpiTable->InstallAcpiTable (
    675                             AcpiTable,
    676                             CurrentTable,
    677                             CurrentTable->Length,
    678                           &TableHandle
    679                           );
    680   ASSERT_EFI_ERROR (Status);
    681   CurrentTable = NULL;
    682 
    683   //
    684   // Init Pci Device PRT PRW information structure from PCD
    685   //
    686   mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING));
    687   ASSERT_EFI_ERROR (mConfigData);
    688   InitPciDeviceInfoStructure (mConfigData);
    689   //
    690   // Get the Acpi SDT protocol for manipulation on acpi table
    691   //
    692   Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt);
    693   ASSERT_EFI_ERROR (Status);
    694   //
    695   // Locate the firmware volume protocol
    696   //
    697   Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
    698   if (EFI_ERROR (Status)) {
    699     return EFI_ABORTED;
    700   }
    701   //
    702   // Read tables from the storage file.
    703   //
    704 
    705   while (Status == EFI_SUCCESS) {
    706 
    707     Status = FwVol->ReadSection (
    708                       FwVol,
    709                       (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
    710                       EFI_SECTION_RAW,
    711                       Instance,
    712                       (VOID**)&CurrentTable,
    713                       &Size,
    714                       &FvStatus
    715                       );
    716 
    717     if (!EFI_ERROR(Status)) {
    718       //
    719       // Perform any table specific updates.
    720       //
    721       AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
    722 
    723       //
    724       // Update the check sum
    725       // It needs to be zeroed before the checksum calculation
    726       //
    727       ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
    728       ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
    729         CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
    730 
    731       //
    732       // Add the table
    733       //
    734       TableHandle = 0;
    735       Status = AcpiTable->InstallAcpiTable (
    736                             AcpiTable,
    737                               CurrentTable,
    738                             ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length,
    739                               &TableHandle
    740                               );
    741       if (EFI_ERROR(Status)) {
    742         return EFI_ABORTED;
    743       }
    744       //
    745       // If this table is the DSDT table, then update the _PRT and _PRW based on
    746       // the settings from pcds
    747       //
    748       if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
    749         //
    750         // Create the root handle for DSDT table
    751         //
    752         Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle);
    753         ASSERT_EFI_ERROR (Status);
    754 
    755         PciRootHandle = NULL;
    756         PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle);
    757         ASSERT (PciRootHandle != NULL);
    758 
    759         PciDeviceInfo = NULL;
    760         for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) {
    761           PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]);
    762 
    763           //
    764           // Check whether this is a valid item
    765           //
    766           if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) {
    767 
    768             //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress));
    769 
    770             UpdatePRT = FALSE;
    771             UpdatePRW = FALSE;
    772 
    773             SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW);
    774             //
    775             // Check whether there is any valid pci routing item
    776             //
    777             if (UpdatePRT) {
    778               //
    779               // Update the pci routing information
    780               //
    781               //DEBUG ((EFI_D_ERROR, "Update _PRT\n"));
    782               SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo);
    783             }
    784             //
    785             // Check whether there is any valid pci routing item
    786             //
    787             if (UpdatePRW) {
    788               //
    789               // Update the pci wakeup information
    790               //
    791               //DEBUG ((EFI_D_ERROR, "Update _PRW\n"));
    792               SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo);
    793             }
    794           }
    795         }
    796         Status = mAcpiSdt->Close (PciRootHandle);
    797         ASSERT_EFI_ERROR (Status);
    798         //
    799         // Mark the root handle as modified , let SDT protocol recaculate the checksum
    800         //
    801         ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE;
    802         Status = mAcpiSdt->Close (mDsdtHandle);
    803         ASSERT_EFI_ERROR (Status);
    804       }
    805       //
    806       // Increment the instance
    807       //
    808       Instance++;
    809       CurrentTable = NULL;
    810     }
    811   }
    812 
    813   gBS->FreePool (mConfigData);
    814   return EFI_SUCCESS;
    815 }
    816