• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 ACPI Platform Driver
3 
4 Copyright (c) 2013-2016 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
LocateSupportProtocol(IN EFI_GUID * Protocol,OUT VOID ** Instance,IN UINT32 Type)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
DsdtTableUpdate(IN OUT EFI_ACPI_DESCRIPTION_HEADER * TableHeader,IN OUT EFI_ACPI_TABLE_VERSION * Version)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
ApicTableUpdate(IN OUT EFI_ACPI_DESCRIPTION_HEADER * TableHeader,IN OUT EFI_ACPI_TABLE_VERSION * Version)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   EFI_PROCESSOR_INFORMATION  MpContext;
259   ACPI_APIC_STRUCTURE_PTR    *ApicPtr;
260 
261   CurrIoApic    = 0;
262   CurrProcessor = 0;
263   //
264   // Find the MP Protocol. This is an MP platform, so MP protocol must be
265   // there.
266   //
267   Status = gBS->LocateProtocol (
268                    &gEfiMpServiceProtocolGuid,
269                    NULL,
270                   (VOID**)&MpService
271                    );
272   if (EFI_ERROR (Status)) {
273     //
274     // Failed to get MP information, doesn't publish the invalid table
275     //
276     *Version = EFI_ACPI_TABLE_VERSION_NONE;
277     return;
278   }
279 
280   //
281   // Determine the number of processors
282   //
283   MpService->GetNumberOfProcessors (
284               MpService,
285               &NumberOfCPUs,
286               &NumberOfEnabledCPUs
287               );
288 
289   CurrPtr = (UINT8*) &(TableHeader[1]);
290   CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag
291   EndPtr  = (UINT8*) TableHeader;
292   EndPtr  = EndPtr + TableHeader->Length;
293 
294   while (CurrPtr < EndPtr) {
295 
296     ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr;
297     switch (ApicPtr->AcpiApicCommon.Type) {
298 
299       case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC:
300         ApicPtr->AcpiLocalApic.Flags = 0;
301         ApicPtr->AcpiLocalApic.ApicId = 0;
302         Status = MpService->GetProcessorInfo (
303                               MpService,
304                               CurrProcessor,
305                               &MpContext
306                               );
307 
308         if (!EFI_ERROR (Status)) {
309           if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) {
310             ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED;
311           }
312           ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId;
313         }
314         CurrProcessor++;
315         break;
316 
317       case EFI_ACPI_1_0_IO_APIC:
318         //
319         // IO APIC entries can be patched here
320         //
321         if (CurrIoApic == 0) {
322           //
323           // Update SOC internel IOAPIC base
324           //
325           ApicPtr->AcpiIoApic.IoApicId      =  PcdGet8 (PcdIoApicSettingIoApicId);
326           ApicPtr->AcpiIoApic.IoApicAddress =  (UINT32)PcdGet64(PcdIoApicBaseAddress);
327           ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0;
328         } else {
329           //
330           // Porting is required to update other IOAPIC entries if available
331           //
332           ASSERT (0);
333         }
334         CurrIoApic++;
335         break;
336 
337       default:
338         break;
339       };
340     CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
341   }
342 }
343 
344 VOID
AcpiUpdateTable(IN OUT EFI_ACPI_DESCRIPTION_HEADER * TableHeader,IN OUT EFI_ACPI_TABLE_VERSION * Version)345 AcpiUpdateTable (
346   IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader,
347   IN OUT   EFI_ACPI_TABLE_VERSION       *Version
348   )
349 /*++
350 
351   Routine Description:
352 
353     Set the correct table revision upon the setup value
354 
355   Arguments:
356 
357     Table   - The table to be set
358     Version - Version to publish
359 
360   Returns:
361 
362     None
363 
364 --*/
365 
366 {
367   EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader1;
368   EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader2;
369   EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader3;
370   EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *AllocationStructurePtr;
371 
372   if (TableHeader != NULL && Version != NULL) {
373 
374     *Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
375     //
376     // Here we use all 3.0 signature because all version use same signature if they supported
377     //
378     switch (TableHeader->Signature) {
379     //
380     // "APIC" Multiple APIC Description Table
381     //
382     case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
383       ApicTableUpdate (TableHeader, Version);
384       break;
385     //
386     // "DSDT" Differentiated System Description Table
387     //
388     case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
389       DsdtTableUpdate (TableHeader, Version);
390       break;
391 
392     //
393     // "FACP" Fixed ACPI Description Table (FADT)
394     //
395     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
396       *Version = EFI_ACPI_TABLE_VERSION_NONE;
397       if (TableHeader->Revision == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
398         *Version = EFI_ACPI_TABLE_VERSION_1_0B;
399         FadtHeader1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
400         FadtHeader1->SmiCmd     = PcdGet16(PcdSmmActivationPort);
401         FadtHeader1->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
402         FadtHeader1->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
403         FadtHeader1->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
404         FadtHeader1->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
405       } else if (TableHeader->Revision == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
406         *Version = EFI_ACPI_TABLE_VERSION_2_0;
407         FadtHeader2 = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
408         FadtHeader2->SmiCmd     = PcdGet16(PcdSmmActivationPort);
409         FadtHeader2->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
410         FadtHeader2->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
411         FadtHeader2->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
412         FadtHeader2->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
413         FadtHeader2->XPm1aEvtBlk.Address = FadtHeader2->Pm1aEvtBlk;
414         FadtHeader2->XPm1aCntBlk.Address = FadtHeader2->Pm1aCntBlk;
415         FadtHeader2->XPmTmrBlk.Address   = FadtHeader2->PmTmrBlk;
416         FadtHeader2->XGpe0Blk.Address    = FadtHeader2->Gpe0Blk;
417       } else if (TableHeader->Revision == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
418         *Version = EFI_ACPI_TABLE_VERSION_3_0;
419         FadtHeader3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
420         FadtHeader3->SmiCmd     = PcdGet16(PcdSmmActivationPort);
421         FadtHeader3->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
422         FadtHeader3->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
423         FadtHeader3->PmTmrBlk   = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
424         FadtHeader3->Gpe0Blk    = PcdGet16(PcdGpe0blkIoBaseAddress);
425         FadtHeader3->XPm1aEvtBlk.Address = FadtHeader3->Pm1aEvtBlk;
426         FadtHeader3->XPm1aCntBlk.Address = FadtHeader3->Pm1aCntBlk;
427         FadtHeader3->XPmTmrBlk.Address   = FadtHeader3->PmTmrBlk;
428         FadtHeader3->XGpe0Blk.Address    = FadtHeader3->Gpe0Blk;
429       }
430       break;
431     //
432     // "FACS" Firmware ACPI Control Structure
433     //
434     case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
435       break;
436     //
437     // "SSDT" Secondary System Description Table
438     //
439     case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
440     break;
441     //
442     // "HPET" IA-PC High Precision Event Timer Table
443     //
444     case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
445       //
446       // If HPET is disabled in setup, don't publish the table.
447       //
448       if (mGlobalNvsArea.Area->HpetEnable == 0) {
449         *Version = EFI_ACPI_TABLE_VERSION_NONE;
450       }
451       ((EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) TableHeader)->BaseAddressLower32Bit.Address
452         = PcdGet64 (PcdHpetBaseAddress);
453       break;
454     //
455     // "SPCR" Serial Port Concole Redirection Table
456     //
457     case EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
458       break;
459     //
460     // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
461     //
462     case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
463       AllocationStructurePtr = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)
464         ((UINT8 *)TableHeader + sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER));
465       AllocationStructurePtr->BaseAddress = PcdGet64(PcdPciExpressBaseAddress);
466       break;
467     // Lakeport platform doesn't support the following table
468     /*
469       //
470     // "ECDT" Embedded Controller Boot Resources Table
471         //
472     case EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE:
473       break;
474         //
475     // "PSDT" Persistent System Description Table
476           //
477     case EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
478       break;
479           //
480     // "SBST" Smart Battery Specification Table
481     //
482     case EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE:
483           break;
484     //
485     // "SLIT" System Locality Information Table
486     //
487     case EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
488           break;
489     //
490     // "SRAT" Static Resource Affinity Table
491     //
492     case EFI_ACPI_3_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE:
493     break;
494   //
495     // "XSDT" Extended System Description Table
496   //
497     case EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
498       break;
499   //
500     // "BOOT" MS Simple Boot Spec
501   //
502     case EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE:
503       break;
504   //
505     // "CPEP" Corrected Platform Error Polling Table
506   //
507     case EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE:
508       break;
509   //
510     // "DBGP" MS Debug Port Spec
511   //
512     case EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE:
513       break;
514     //
515     // "ETDT" Event Timer Description Table
516     //
517     case EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE:
518       break;
519     //
520     // "SPMI" Server Platform Management Interface Table
521     //
522     case EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE:
523       break;
524     //
525     // "TCPA" Trusted Computing Platform Alliance Capabilities Table
526     //
527     case EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE:
528       break;
529     */
530     default:
531       break;
532     }
533   }
534 }
535 
536 //
537 // Description:
538 //    Entrypoint of Acpi Platform driver
539 // In:
540 //    ImageHandle
541 //    SystemTable
542 // Out:
543 //    EFI_SUCCESS
544 //    EFI_LOAD_ERROR
545 //    EFI_OUT_OF_RESOURCES
546 //
547 
548 EFI_STATUS
AcpiPlatformEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)549 AcpiPlatformEntryPoint (
550   IN EFI_HANDLE     ImageHandle,
551   IN EFI_SYSTEM_TABLE   *SystemTable
552   )
553 {
554   EFI_STATUS                    Status;
555   EFI_ACPI_TABLE_PROTOCOL       *AcpiTable;
556   EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
557   INTN                          Instance;
558   EFI_ACPI_COMMON_HEADER        *CurrentTable;
559   UINTN                         TableHandle;
560   UINT32                        FvStatus;
561   UINTN                         Size;
562   EFI_ACPI_TABLE_VERSION        Version;
563   EFI_HANDLE                    Handle;
564   UINTN                         Index;
565   PCI_DEVICE_INFO               *PciDeviceInfo;
566   EFI_ACPI_HANDLE               PciRootHandle;
567   BOOLEAN                       UpdatePRT;
568   BOOLEAN                       UpdatePRW;
569   PCI_DEVICE_SETTING            *mConfigData;
570 
571   DEBUG((DEBUG_INFO, "ACPI Platform start...\n"));
572 
573   Instance = 0;
574   TableHandle = 0;
575   CurrentTable = NULL;
576   mConfigData  = NULL;
577 
578   //
579   // Initialize the EFI Driver Library
580   //
581 
582   ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512);
583 
584   Status = gBS->AllocatePool (
585                    EfiACPIMemoryNVS,
586                    sizeof (EFI_GLOBAL_NVS_AREA),
587                    (VOID**)&mGlobalNvsArea.Area
588                    );
589 
590   Handle = NULL;
591   Status = gBS->InstallProtocolInterface (
592                   &Handle,
593                   &gEfiGlobalNvsAreaProtocolGuid,
594                   EFI_NATIVE_INTERFACE,
595                   &mGlobalNvsArea
596                   );
597 
598   ASSERT_EFI_ERROR (Status);
599   if (!EFI_ERROR (Status)) {
600     SetMem (
601       mGlobalNvsArea.Area,
602       sizeof (EFI_GLOBAL_NVS_AREA),
603       0
604       );
605   }
606 
607   //
608   // Initialize the data.  Eventually, this will be controlled by setup options.
609   //
610   mGlobalNvsArea.Area->HpetEnable           =  PcdGetBool (PcdHpetEnable);
611   mGlobalNvsArea.Area->Pm1blkIoBaseAddress  =  PcdGet16(PcdPm1blkIoBaseAddress);
612   mGlobalNvsArea.Area->PmbaIoBaseAddress    =  PcdGet16(PcdPmbaIoBaseAddress);
613   mGlobalNvsArea.Area->Gpe0blkIoBaseAddress =  PcdGet16(PcdGpe0blkIoBaseAddress);
614   mGlobalNvsArea.Area->GbaIoBaseAddress     =  PcdGet16(PcdGbaIoBaseAddress);
615   mGlobalNvsArea.Area->SmbaIoBaseAddress    =  PcdGet16(PcdSmbaIoBaseAddress);
616   mGlobalNvsArea.Area->WdtbaIoBaseAddress   =  PcdGet16(PcdWdtbaIoBaseAddress);
617   mGlobalNvsArea.Area->HpetBaseAddress      =  (UINT32)PcdGet64(PcdHpetBaseAddress);
618   mGlobalNvsArea.Area->HpetSize             =  (UINT32)PcdGet64(PcdHpetSize);
619   mGlobalNvsArea.Area->PciExpressBaseAddress=  (UINT32)PcdGet64(PcdPciExpressBaseAddress);
620   mGlobalNvsArea.Area->PciExpressSize       =  (UINT32)PcdGet64(PcdPciExpressSize);
621   mGlobalNvsArea.Area->RcbaMmioBaseAddress  =  (UINT32)PcdGet64(PcdRcbaMmioBaseAddress);
622   mGlobalNvsArea.Area->RcbaMmioSize         =  (UINT32)PcdGet64(PcdRcbaMmioSize);
623   mGlobalNvsArea.Area->IoApicBaseAddress    =  (UINT32)PcdGet64(PcdIoApicBaseAddress);
624   mGlobalNvsArea.Area->IoApicSize           =  (UINT32)PcdGet64(PcdIoApicSize);
625   mGlobalNvsArea.Area->TpmPresent           =  (UINT32)(FALSE);
626   mGlobalNvsArea.Area->DBG2Present          =  (UINT32)(FALSE);
627   mGlobalNvsArea.Area->PlatformType         =  (UINT32)PcdGet16 (PcdPlatformType);
628 
629   //
630   // Configure platform IO expander I2C Slave Address.
631   //
632   if (mGlobalNvsArea.Area->PlatformType == Galileo) {
633     if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
634       mGlobalNvsArea.Area->AlternateSla = FALSE;
635     } else {
636       mGlobalNvsArea.Area->AlternateSla = TRUE;
637     }
638   }
639 
640   //
641   // Find the AcpiTable protocol
642   //
643   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
644   if (EFI_ERROR (Status)) {
645     return EFI_ABORTED;
646   }
647 
648   //
649   // Initialize MADT table
650   //
651   Status = MadtTableInitialize (&CurrentTable, &Size);
652   ASSERT_EFI_ERROR (Status);
653   //
654   // Perform any table specific updates.
655   //
656   AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
657 
658   //
659   // Update the check sum
660   // It needs to be zeroed before the checksum calculation
661   //
662   ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
663   ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
664     CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
665 
666   //
667   // Add the table
668   //
669   TableHandle = 0;
670   Status = AcpiTable->InstallAcpiTable (
671                             AcpiTable,
672                             CurrentTable,
673                             CurrentTable->Length,
674                           &TableHandle
675                           );
676   ASSERT_EFI_ERROR (Status);
677   CurrentTable = NULL;
678 
679   //
680   // Init Pci Device PRT PRW information structure from PCD
681   //
682   mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING));
683   ASSERT (mConfigData != NULL);
684   InitPciDeviceInfoStructure (mConfigData);
685   //
686   // Get the Acpi SDT protocol for manipulation on acpi table
687   //
688   Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt);
689   ASSERT_EFI_ERROR (Status);
690   //
691   // Locate the firmware volume protocol
692   //
693   Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
694   if (EFI_ERROR (Status)) {
695     return EFI_ABORTED;
696   }
697   //
698   // Read tables from the storage file.
699   //
700 
701   while (Status == EFI_SUCCESS) {
702 
703     Status = FwVol->ReadSection (
704                       FwVol,
705                       (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
706                       EFI_SECTION_RAW,
707                       Instance,
708                       (VOID**)&CurrentTable,
709                       &Size,
710                       &FvStatus
711                       );
712 
713     if (!EFI_ERROR(Status)) {
714       //
715       // Perform any table specific updates.
716       //
717       AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
718 
719       //
720       // Update the check sum
721       // It needs to be zeroed before the checksum calculation
722       //
723       ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
724       ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
725         CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
726 
727       //
728       // Add the table
729       //
730       TableHandle = 0;
731       Status = AcpiTable->InstallAcpiTable (
732                             AcpiTable,
733                               CurrentTable,
734                             ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length,
735                               &TableHandle
736                               );
737       if (EFI_ERROR(Status)) {
738         return EFI_ABORTED;
739       }
740       //
741       // If this table is the DSDT table, then update the _PRT and _PRW based on
742       // the settings from pcds
743       //
744       if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
745         //
746         // Create the root handle for DSDT table
747         //
748         Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle);
749         ASSERT_EFI_ERROR (Status);
750 
751         PciRootHandle = NULL;
752         PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle);
753         ASSERT (PciRootHandle != NULL);
754 
755         PciDeviceInfo = NULL;
756         for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) {
757           PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]);
758 
759           //
760           // Check whether this is a valid item
761           //
762           if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) {
763 
764             //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress));
765 
766             UpdatePRT = FALSE;
767             UpdatePRW = FALSE;
768 
769             SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW);
770             //
771             // Check whether there is any valid pci routing item
772             //
773             if (UpdatePRT) {
774               //
775               // Update the pci routing information
776               //
777               //DEBUG ((EFI_D_ERROR, "Update _PRT\n"));
778               SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo);
779             }
780             //
781             // Check whether there is any valid pci routing item
782             //
783             if (UpdatePRW) {
784               //
785               // Update the pci wakeup information
786               //
787               //DEBUG ((EFI_D_ERROR, "Update _PRW\n"));
788               SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo);
789             }
790           }
791         }
792         Status = mAcpiSdt->Close (PciRootHandle);
793         ASSERT_EFI_ERROR (Status);
794         //
795         // Mark the root handle as modified , let SDT protocol recaculate the checksum
796         //
797         ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE;
798         Status = mAcpiSdt->Close (mDsdtHandle);
799         ASSERT_EFI_ERROR (Status);
800       }
801       //
802       // Increment the instance
803       //
804       Instance++;
805       CurrentTable = NULL;
806     }
807   }
808 
809   gBS->FreePool (mConfigData);
810   return EFI_SUCCESS;
811 }
812