3 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
8 the terms and conditions of the BSD License that accompanies this distribution.
10 The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php.
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
37 #include <Protocol/TcgService.h>
38 #include <Protocol/FirmwareVolume.h>
39 #include "AcpiPlatform.h"
40 #include "AcpiPlatformHooks.h"
41 #include "AcpiPlatformHooksLib.h"
46 #include <Guid/GlobalVariable.h>
47 #include <Guid/SetupVariable.h>
48 #include <Guid/PlatformInfo.h>
49 #include <Protocol/CpuIo.h>
50 #include <Guid/BoardFeatures.h>
51 #include <Protocol/AcpiSupport.h>
52 #include <Protocol/AcpiS3Save.h>
53 #include <Protocol/Ps2Policy.h>
54 #include <Library/CpuIA32.h>
55 #include <SetupMode.h>
56 #include <Guid/AcpiTableStorage.h>
57 #include <Guid/EfiVpdData.h>
58 #include <PchAccess.h>
59 #include <Guid/Vlv2Variable.h>
60 #include <Guid/PlatformCpuInfo.h>
61 #include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
64 CHAR16 EfiPlatformCpuInfoVariable
[] = L
"PlatformCpuInfo";
65 CHAR16 gACPIOSFRModelStringVariableName
[] = ACPI_OSFR_MODEL_STRING_VARIABLE_NAME
;
66 CHAR16 gACPIOSFRRefDataBlockVariableName
[] = ACPI_OSFR_REF_DATA_BLOCK_VARIABLE_NAME
;
67 CHAR16 gACPIOSFRMfgStringVariableName
[] = ACPI_OSFR_MFG_STRING_VARIABLE_NAME
;
69 EFI_CPU_IO_PROTOCOL
*mCpuIo
;
71 #pragma optimize("", off)
74 EFI_PLATFORM_INFO_HOB
*mPlatformInfo
;
75 EFI_GUID mSystemConfigurationGuid
= SYSTEM_CONFIGURATION_GUID
;
76 SYSTEM_CONFIGURATION mSystemConfiguration
;
77 SYSTEM_CONFIGURATION mSystemConfig
;
79 UINT8 mSmbusRsvdAddresses
[] = PLATFORM_SMBUS_RSVD_ADDRESSES
;
80 UINT8 mNumberSmbusAddress
= sizeof( mSmbusRsvdAddresses
) / sizeof( mSmbusRsvdAddresses
[0] );
83 Locate the first instance of a protocol. If the protocol requested is an
84 FV protocol, then it will return the first FV that contains the ACPI table
87 @param[in] Protocol The protocol to find.
88 @param[in] Instance Return pointer to the first instance of the protocol.
89 @param[in] Type The type of protocol to locate.
91 @retval EFI_SUCCESS The function completed successfully.
92 @retval EFI_NOT_FOUND The protocol could not be located.
93 @retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
97 LocateSupportProtocol (
98 IN EFI_GUID
*Protocol
,
104 EFI_HANDLE
*HandleBuffer
;
105 UINTN NumberOfHandles
;
106 EFI_FV_FILETYPE FileType
;
108 EFI_FV_FILE_ATTRIBUTES Attributes
;
117 Status
= gBS
->LocateHandleBuffer (
124 if (EFI_ERROR (Status
)) {
126 // Defined errors at this time are not found and out of resources.
132 // Looking for FV with ACPI storage file.
134 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
136 // Get the protocol on this handle.
137 // This should not fail because of LocateHandleBuffer.
139 Status
= gBS
->HandleProtocol (
144 ASSERT (!EFI_ERROR (Status
));
148 // Not looking for the FV protocol, so find the first instance of the
149 // protocol. There should not be any errors because our handle buffer
150 // should always contain at least one or LocateHandleBuffer would have
151 // returned not found.
157 // See if it has the ACPI storage file.
159 Status
= ((EFI_FIRMWARE_VOLUME_PROTOCOL
*) (*Instance
))->ReadFile (
161 &gEfiAcpiTableStorageGuid
,
170 // If we found it, then we are done.
172 if (!EFI_ERROR (Status
)) {
178 // Our exit status is determined by the success of the previous operations.
179 // If the protocol was found, Instance already points to it.
182 // Free any allocated buffers.
184 gBS
->FreePool (HandleBuffer
);
190 This function will update any runtime platform specific information.
191 This currently includes:
192 Setting OEM table values, ID, table ID, creator ID and creator revision.
193 Enabling the proper processor entries in the APIC tables.
195 @param[in] Table The table to update.
197 @retval EFI_SUCCESS The function completed successfully.
201 PlatformUpdateTables (
202 IN OUT EFI_ACPI_COMMON_HEADER
*Table
205 EFI_ACPI_DESCRIPTION_HEADER
*TableHeader
;
208 ACPI_APIC_STRUCTURE_PTR
*ApicPtr
;
211 EFI_MP_SERVICES_PROTOCOL
*MpService
;
212 UINTN MaximumNumberOfCPUs
;
213 UINTN NumberOfEnabledCPUs
;
215 ACPI_APIC_STRUCTURE_PTR
*ProcessorLocalApicEntry
;
217 EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE
*AsfEntry
;
218 EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER
*HpetTbl
;
221 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*Facp
;
222 EFI_ACPI_OSFR_TABLE
*OsfrTable
;
223 EFI_ACPI_OSFR_OCUR_OBJECT
*pOcurObject
;
224 EFI_ACPI_OSFR_OCUR_OBJECT OcurObject
= {{0xB46F133D, 0x235F, 0x4634, 0x9F, 0x03, 0xB1, 0xC0, 0x1C, 0x54, 0x78, 0x5B}, 0, 0, 0, 0, 0};
225 CHAR16
*OcurMfgStringBuffer
= NULL
;
226 CHAR16
*OcurModelStringBuffer
= NULL
;
227 UINT8
*OcurRefDataBlockBuffer
= NULL
;
228 UINTN OcurMfgStringBufferSize
;
229 UINTN OcurModelStringBufferSize
;
230 UINTN OcurRefDataBlockBufferSize
;
231 #if defined (IDCC2_SUPPORTED) && IDCC2_SUPPORTED
232 EFI_ACPI_ASPT_TABLE
*pSpttTable
;
234 UINT16 NumberOfHpets
;
235 UINT16 HpetCapIdValue
;
237 UINTN LocalApicCounter
;
238 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
240 EFI_ACPI_3_0_IO_APIC_STRUCTURE
*IOApicType
;
241 EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
*APICTableHeader
;
242 EFI_ACPI_WSMT_TABLE
*WsmtTable
;
247 LocalApicCounter
= 0;
249 ProcessorLocalApicEntry
= NULL
;
252 if (Table
->Signature
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
) {
253 TableHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*) Table
;
257 OemIdValue
= mPlatformInfo
->AcpiOemId
;
259 *(UINT32
*)(TableHeader
->OemId
) = (UINT32
)OemIdValue
;
260 *(UINT16
*)(TableHeader
->OemId
+ 4) = *(UINT16
*)(((UINT8
*)&OemIdValue
) + 4);
262 if ((Table
->Signature
!= EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
)) {
264 // Update the OEM Table ID.
266 TableHeader
->OemTableId
= mPlatformInfo
->AcpiOemTableId
;
270 // Update the OEM Table ID.
272 TableHeader
->OemRevision
= EFI_ACPI_OEM_REVISION
;
275 // Update the creator ID.
277 TableHeader
->CreatorId
= EFI_ACPI_CREATOR_ID
;
280 // Update the creator revision.
282 TableHeader
->CreatorRevision
= EFI_ACPI_CREATOR_REVISION
;
286 // Complete this function.
289 // Locate the MP services protocol.
292 // Find the MP Protocol. This is an MP platform, so MP protocol must be
295 Status
= gBS
->LocateProtocol (
296 &gEfiMpServiceProtocolGuid
,
300 if (EFI_ERROR (Status
)) {
305 // Determine the number of processors.
307 MpService
->GetNumberOfProcessors (
309 &MaximumNumberOfCPUs
,
313 ASSERT (MaximumNumberOfCPUs
<= MAX_CPU_NUM
&& NumberOfEnabledCPUs
>= 1);
317 // Assign a invalid intial value for update.
320 // Update the processors in the APIC table.
322 switch (Table
->Signature
) {
323 case EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_SIGNATURE
:
325 // Update the table if ASF is enabled. Otherwise, return error so caller will not install.
327 if (mSystemConfig
.Asf
== 1) {
328 return EFI_UNSUPPORTED
;
330 AsfEntry
= (EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE
*) Table
;
331 TempVal
= (mNumberSmbusAddress
< ASF_ADDR_DEVICE_ARRAY_LENGTH
)? mNumberSmbusAddress
: ASF_ADDR_DEVICE_ARRAY_LENGTH
;
332 for (Index
= 0; Index
< TempVal
; Index
++) {
333 AsfEntry
->AsfAddr
.FixedSmbusAddresses
[Index
] = mSmbusRsvdAddresses
[Index
];
337 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
339 Status
= MpService
->WhoAmI (
345 // PCAT_COMPAT Set to 1 indicate 8259 vectors should be disabled.
347 APICTableHeader
= (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
*)Table
;
348 APICTableHeader
->Flags
|= EFI_ACPI_3_0_PCAT_COMPAT
;
350 CurrPtr
= (UINT8
*) &((EFI_ACPI_DESCRIPTION_HEADER
*) Table
)[1];
351 CurrPtr
= CurrPtr
+ 8;
354 // Size of Local APIC Address & Flag.
356 EndPtr
= (UINT8
*) Table
;
357 EndPtr
= EndPtr
+ Table
->Length
;
358 while (CurrPtr
< EndPtr
) {
359 ApicPtr
= (ACPI_APIC_STRUCTURE_PTR
*) CurrPtr
;
360 switch (ApicPtr
->AcpiApicCommon
.Type
) {
361 case EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC
:
364 // Fix for Ordering of MADT to be maintained as it is in MADT table.
366 // Update processor enabled or disabled and keep the local APIC
367 // order in MADT intact.
369 // Sanity check to make sure proc-id is not arbitrary.
371 DEBUG ((EFI_D_ERROR
, "ApicPtr->AcpiLocalApic.AcpiProcessorId = %x, MaximumNumberOfCPUs = %x\n", \
372 ApicPtr
->AcpiLocalApic
.AcpiProcessorId
, MaximumNumberOfCPUs
));
373 if(ApicPtr
->AcpiLocalApic
.AcpiProcessorId
> MaximumNumberOfCPUs
) {
374 ApicPtr
->AcpiLocalApic
.AcpiProcessorId
= (UINT8
)MaximumNumberOfCPUs
;
378 ApicPtr
->AcpiLocalApic
.Flags
= 0;
380 for (CurrProcessor
= 0; CurrProcessor
< MaximumNumberOfCPUs
; CurrProcessor
++) {
381 Status
= MpService
->GetProcessorInfo (
387 if (Status
== EFI_SUCCESS
&& ProcessorInfoBuffer
.ProcessorId
== ApicPtr
->AcpiLocalApic
.ApicId
) {
389 // Check to see whether or not a processor (or thread) is enabled.
391 if ((BspIndex
== CurrProcessor
) || ((ProcessorInfoBuffer
.StatusFlag
& PROCESSOR_ENABLED_BIT
) != 0)) {
393 // Go on and check if Hyper Threading is enabled. If HT not enabled
394 // hide this thread from OS by not setting the flag to 1. This is the
395 // software way to disable Hyper Threading. Basically we just hide it
398 ApicPtr
->AcpiLocalApic
.Flags
= EFI_ACPI_1_0_LOCAL_APIC_ENABLED
;
401 if(ProcessorInfoBuffer
.Location
.Thread
!= 0) {
402 ApicPtr
->AcpiLocalApic
.Flags
= 0;
405 AppendCpuMapTableEntry (&(ApicPtr
->AcpiLocalApic
));
412 // If no APIC-ID match, the cpu may not be populated.
416 case EFI_ACPI_3_0_IO_APIC
:
418 IOApicType
= (EFI_ACPI_3_0_IO_APIC_STRUCTURE
*)CurrPtr
;
419 IOApicType
->IoApicId
= 0x02;
421 // IO APIC entries can be patched here.
426 CurrPtr
= CurrPtr
+ ApicPtr
->AcpiApicCommon
.Length
;
430 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
432 Facp
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*) Table
;
433 Facp
->Flags
&= (UINT32
)(~(3<<2));
437 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
439 // Patch the memory resource.
441 PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER
*) Table
);
444 case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
448 // TBD: Need re-design based on the ValleyTrail platform.
452 case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE
:
454 // Adjust HPET Table to correct the Base Address.
456 // Enable HPET always as Hpet.asi always indicates that Hpet is enabled.
458 MmioOr8 (R_PCH_PCH_HPET
+ R_PCH_PCH_HPET_GCFG
, B_PCH_PCH_HPET_GCFG_EN
);
461 HpetTbl
= (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER
*) Table
;
462 HpetTbl
->BaseAddressLower32Bit
.Address
= HPET_BASE_ADDRESS
;
463 HpetTbl
->EventTimerBlockId
= *((UINT32
*)(UINTN
)HPET_BASE_ADDRESS
);
465 HpetCapIdValue
= *(UINT16
*)(UINTN
)(HPET_BASE_ADDRESS
);
466 NumberOfHpets
= HpetCapIdValue
& B_PCH_PCH_HPET_GCID_NT
; // Bits [8:12] contains the number of Hpets
467 HpetBlockID
= EFI_ACPI_EVENT_TIMER_BLOCK_ID
;
469 if((NumberOfHpets
) && (NumberOfHpets
& B_PCH_PCH_HPET_GCID_NT
)) {
470 HpetBlockID
|= (NumberOfHpets
);
472 HpetTbl
->EventTimerBlockId
= HpetBlockID
;
476 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
478 // Update MCFG base and end bus number.
480 ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE
*) Table
)->Segment
[0].BaseAddress
481 = mPlatformInfo
->PciData
.PciExpressBase
;
482 ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE
*) Table
)->Segment
[0].EndBusNumber
483 = (UINT8
)RShiftU64 (mPlatformInfo
->PciData
.PciExpressSize
, 20) - 1;
487 case EFI_ACPI_OSFR_TABLE_SIGNATURE
:
489 // Get size of OSFR variable.
491 OcurMfgStringBufferSize
= 0;
492 Status
= gRT
->GetVariable (
493 gACPIOSFRMfgStringVariableName
,
494 &gACPIOSFRMfgStringVariableGuid
,
496 &OcurMfgStringBufferSize
,
499 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
501 // Variable must not be present on the system.
503 return EFI_UNSUPPORTED
;
507 // Allocate memory for variable data.
509 OcurMfgStringBuffer
= AllocatePool (OcurMfgStringBufferSize
);
510 Status
= gRT
->GetVariable (
511 gACPIOSFRMfgStringVariableName
,
512 &gACPIOSFRMfgStringVariableGuid
,
514 &OcurMfgStringBufferSize
,
517 if (!EFI_ERROR (Status
)) {
518 OcurModelStringBufferSize
= 0;
519 Status
= gRT
->GetVariable (
520 gACPIOSFRModelStringVariableName
,
521 &gACPIOSFRModelStringVariableGuid
,
523 &OcurModelStringBufferSize
,
526 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
528 // Variable must not be present on the system.
530 return EFI_UNSUPPORTED
;
534 // Allocate memory for variable data.
536 OcurModelStringBuffer
= AllocatePool (OcurModelStringBufferSize
);
537 Status
= gRT
->GetVariable (
538 gACPIOSFRModelStringVariableName
,
539 &gACPIOSFRModelStringVariableGuid
,
541 &OcurModelStringBufferSize
,
542 OcurModelStringBuffer
544 if (!EFI_ERROR (Status
)) {
545 OcurRefDataBlockBufferSize
= 0;
546 Status
= gRT
->GetVariable (
547 gACPIOSFRRefDataBlockVariableName
,
548 &gACPIOSFRRefDataBlockVariableGuid
,
550 &OcurRefDataBlockBufferSize
,
553 if (Status
== EFI_BUFFER_TOO_SMALL
) {
555 // Allocate memory for variable data.
557 OcurRefDataBlockBuffer
= AllocatePool (OcurRefDataBlockBufferSize
);
558 Status
= gRT
->GetVariable (
559 gACPIOSFRRefDataBlockVariableName
,
560 &gACPIOSFRRefDataBlockVariableGuid
,
562 &OcurRefDataBlockBufferSize
,
563 OcurRefDataBlockBuffer
566 OsfrTable
= (EFI_ACPI_OSFR_TABLE
*) Table
;
568 // Currently only one object is defined: OCUR_OSFR_TABLE.
570 OsfrTable
->ObjectCount
= 1;
572 // Initialize table length to fixed portion of the ACPI OSFR table.
574 OsfrTable
->Header
.Length
= sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION
);
575 *(UINT32
*)((UINTN
) OsfrTable
+ sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION
)) = \
576 (UINT32
) (sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION
) + sizeof (UINT32
));
577 pOcurObject
= (EFI_ACPI_OSFR_OCUR_OBJECT
*)((UINTN
) OsfrTable
+ sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION
) + \
579 CopyMem (pOcurObject
, &OcurObject
, sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
));
580 pOcurObject
->ManufacturerNameStringOffset
= (UINT32
)((UINTN
) pOcurObject
- (UINTN
) OsfrTable
+ \
581 sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
));
582 pOcurObject
->ModelNameStringOffset
= (UINT32
)((UINTN
) pOcurObject
- (UINTN
) OsfrTable
+ \
583 sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
) + OcurMfgStringBufferSize
);
584 if (OcurRefDataBlockBufferSize
> 0) {
585 pOcurObject
->MicrosoftReferenceOffset
= (UINT32
)((UINTN
) pOcurObject
- (UINTN
) OsfrTable
+ \
586 sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
) + OcurMfgStringBufferSize
+ OcurModelStringBufferSize
);
588 CopyMem ((UINTN
*)((UINTN
) pOcurObject
+ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
)), OcurMfgStringBuffer
, \
589 OcurMfgStringBufferSize
);
590 CopyMem ((UINTN
*)((UINTN
) pOcurObject
+ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
) + OcurMfgStringBufferSize
), \
591 OcurModelStringBuffer
, OcurModelStringBufferSize
);
592 if (OcurRefDataBlockBufferSize
> 0) {
593 CopyMem ((UINTN
*)((UINTN
) pOcurObject
+ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
) + OcurMfgStringBufferSize
+ \
594 OcurModelStringBufferSize
),OcurRefDataBlockBuffer
, OcurRefDataBlockBufferSize
);
596 OsfrTable
->Header
.Length
+= (UINT32
)(OcurMfgStringBufferSize
+ OcurModelStringBufferSize
+ OcurRefDataBlockBufferSize
);
597 OsfrTable
->Header
.Length
+= sizeof (EFI_ACPI_OSFR_OCUR_OBJECT
) + sizeof (UINT32
);
600 gBS
->FreePool (OcurMfgStringBuffer
);
601 gBS
->FreePool (OcurModelStringBuffer
);
602 gBS
->FreePool (OcurRefDataBlockBuffer
);
606 case EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE
:
607 WsmtTable
= (EFI_ACPI_WSMT_TABLE
*) Table
;
609 // Update Microsoft WSMT table Protections flags.
611 WsmtTable
->ProtectionFlags
= ((WsmtTable
->ProtectionFlags
) | (EFI_WSMT_PROTECTION_FLAGS_FIXED_COMM_BUFFERS
| EFI_WSMT_PROTECTION_FLAGS_COMM_BUFFER_NESTED_PTR_PROTECTION
));
621 // Update the hardware signature in the FACS structure.
624 // Locate the SPCR table and update based on current settings.
625 // The user may change CR settings via setup or other methods.
626 // The SPCR table must match.
635 GC_TODO: Add function description.
639 Event - GC_TODO: add argument description
640 Context - GC_TODO: add argument description
644 GC_TODO: add return values
656 EFI_ACPI_TABLE_VERSION TableVersion
;
657 EFI_ACPI_SUPPORT_PROTOCOL
*AcpiSupport
;
658 EFI_ACPI_S3_SAVE_PROTOCOL
*AcpiS3Save
;
659 SYSTEM_CONFIGURATION SetupVarBuffer
;
661 EFI_PLATFORM_CPU_INFO
*PlatformCpuInfoPtr
= NULL
;
662 EFI_PLATFORM_CPU_INFO PlatformCpuInfo
;
663 EFI_PEI_HOB_POINTERS GuidHob
;
672 // To avoid compiler warning of "C4701: potentially uninitialized local variable 'PlatformCpuInfo' used".
674 PlatformCpuInfo
.CpuVersion
.FullCpuId
= 0;
677 // Get Platform CPU Info HOB.
679 PlatformCpuInfoPtr
= NULL
;
680 ZeroMem (&PlatformCpuInfo
, sizeof(EFI_PLATFORM_CPU_INFO
));
681 VariableSize
= sizeof(EFI_PLATFORM_CPU_INFO
);
682 Status
= gRT
->GetVariable(
683 EfiPlatformCpuInfoVariable
,
684 &gEfiVlv2VariableGuid
,
689 if (EFI_ERROR(Status
)) {
690 GuidHob
.Raw
= GetHobList ();
691 if (GuidHob
.Raw
!= NULL
) {
692 if ((GuidHob
.Raw
= GetNextGuidHob (&gEfiPlatformCpuInfoGuid
, GuidHob
.Raw
)) != NULL
) {
693 PlatformCpuInfoPtr
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
698 if ((PlatformCpuInfoPtr
!= NULL
)) {
699 CopyMem(&PlatformCpuInfo
, PlatformCpuInfoPtr
, sizeof(EFI_PLATFORM_CPU_INFO
));
703 // Update the ACPI parameter blocks finally.
705 VariableSize
= sizeof (SYSTEM_CONFIGURATION
);
706 Status
= gRT
->GetVariable (
708 &mSystemConfigurationGuid
,
713 if (EFI_ERROR (Status
) || VariableSize
!= sizeof(SYSTEM_CONFIGURATION
)) {
714 //The setup variable is corrupted
715 VariableSize
= sizeof(SYSTEM_CONFIGURATION
);
716 Status
= gRT
->GetVariable(
718 &mSystemConfigurationGuid
,
723 ASSERT_EFI_ERROR (Status
);
727 // Find the AcpiSupport protocol.
729 Status
= LocateSupportProtocol (&gEfiAcpiSupportProtocolGuid
, (VOID
**) &AcpiSupport
, 0);
730 ASSERT_EFI_ERROR (Status
);
732 TableVersion
= EFI_ACPI_TABLE_VERSION_2_0
;
735 // Publish ACPI 1.0 or 2.0 Tables.
737 Status
= AcpiSupport
->PublishTables (
741 ASSERT_EFI_ERROR (Status
);
746 Status
= gBS
->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid
, NULL
, (VOID
**) &AcpiS3Save
);
747 if (!EFI_ERROR (Status
)) {
748 AcpiS3Save
->S3Save (AcpiS3Save
, NULL
);
761 if (mPlatformInfo
->BoardId
== BOARD_ID_BL_FFRD
&& mPlatformInfo
->BoardRev
>= PR1
) {
762 DEBUG((EFI_D_ERROR
, "Set FSA status = 1 for FFRD PR1\n"));
763 mGlobalNvsArea
.Area
->FsaStatus
= mSystemConfiguration
.PchFSAOn
;
765 if (mPlatformInfo
->BoardId
== BOARD_ID_BL_FFRD8
) {
766 DEBUG((EFI_D_ERROR
, "Set FSA status = 1 for FFRD8\n"));
767 mGlobalNvsArea
.Area
->FsaStatus
= mSystemConfiguration
.PchFSAOn
;
773 Entry point for Acpi platform driver.
775 @param[in] ImageHandle A handle for the image that is initializing this driver.
776 @param[in] SystemTable A pointer to the EFI system table.
778 @retval EFI_SUCCESS Driver initialized successfully.
779 @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded.
780 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
785 AcpiPlatformEntryPoint (
786 IN EFI_HANDLE ImageHandle
,
787 IN EFI_SYSTEM_TABLE
*SystemTable
791 EFI_STATUS AcpiStatus
;
792 EFI_ACPI_SUPPORT_PROTOCOL
*AcpiSupport
;
793 EFI_FIRMWARE_VOLUME_PROTOCOL
*FwVol
;
795 EFI_ACPI_COMMON_HEADER
*CurrentTable
;
800 EFI_ACPI_TABLE_VERSION TableVersion
;
804 EFI_PS2_POLICY_PROTOCOL
*Ps2Policy
;
805 EFI_PEI_HOB_POINTERS GuidHob
;
807 EFI_MP_SERVICES_PROTOCOL
*MpService
;
808 UINTN MaximumNumberOfCPUs
;
809 UINTN NumberOfEnabledCPUs
;
811 PCH_STEPPING pchStepping
;
813 mFirstNotify
= FALSE
;
815 TableVersion
= EFI_ACPI_TABLE_VERSION_2_0
;
822 // Update HOB variable for PCI resource information.
823 // Get the HOB list. If it is not present, then ASSERT.
825 GuidHob
.Raw
= GetHobList ();
826 if (GuidHob
.Raw
!= NULL
) {
827 if ((GuidHob
.Raw
= GetNextGuidHob (&gEfiPlatformInfoGuid
, GuidHob
.Raw
)) != NULL
) {
828 mPlatformInfo
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
833 // Search for the Memory Configuration GUID HOB. If it is not present, then
834 // there's nothing we can do. It may not exist on the update path.
836 VarSize
= sizeof(SYSTEM_CONFIGURATION
);
837 Status
= gRT
->GetVariable(
839 &mSystemConfigurationGuid
,
842 &mSystemConfiguration
844 if (EFI_ERROR (Status
) || VarSize
!= sizeof(SYSTEM_CONFIGURATION
)) {
845 //The setup variable is corrupted
846 VarSize
= sizeof(SYSTEM_CONFIGURATION
);
847 Status
= gRT
->GetVariable(
849 &mSystemConfigurationGuid
,
852 &mSystemConfiguration
854 ASSERT_EFI_ERROR (Status
);
858 // Find the AcpiSupport protocol.
860 Status
= LocateSupportProtocol (&gEfiAcpiSupportProtocolGuid
, (VOID
**) &AcpiSupport
, 0);
861 ASSERT_EFI_ERROR (Status
);
864 // Locate the firmware volume protocol.
866 Status
= LocateSupportProtocol (&gEfiFirmwareVolumeProtocolGuid
, (VOID
**) &FwVol
, 1);
867 ASSERT_EFI_ERROR (Status
);
870 // Read the current system configuration variable store.
872 SysCfgSize
= sizeof(SYSTEM_CONFIGURATION
);
873 Status
= gRT
->GetVariable (
875 &gEfiNormalSetupGuid
,
880 if (EFI_ERROR (Status
) || SysCfgSize
!= sizeof(SYSTEM_CONFIGURATION
)) {
881 //The setup variable is corrupted
882 SysCfgSize
= sizeof(SYSTEM_CONFIGURATION
);
883 Status
= gRT
->GetVariable(
885 &gEfiNormalSetupGuid
,
890 ASSERT_EFI_ERROR (Status
);
894 Status
= EFI_SUCCESS
;
898 // TBD: Need re-design based on the ValleyTrail platform.
900 Status
= gBS
->LocateProtocol (
901 &gEfiMpServiceProtocolGuid
,
905 if (EFI_ERROR (Status
)) {
910 // Determine the number of processors.
912 MpService
->GetNumberOfProcessors (
914 &MaximumNumberOfCPUs
,
919 // Allocate and initialize the NVS area for SMM and ASL communication.
921 Status
= gBS
->AllocatePool (
923 sizeof (EFI_GLOBAL_NVS_AREA
),
924 (void **)&mGlobalNvsArea
.Area
926 ASSERT_EFI_ERROR (Status
);
929 sizeof (EFI_GLOBAL_NVS_AREA
),
932 DEBUG((EFI_D_ERROR
, "mGlobalNvsArea.Area is at 0x%X\n", mGlobalNvsArea
.Area
));
935 // Update global NVS area for ASL and SMM init code to use.
937 mGlobalNvsArea
.Area
->ApicEnable
= 1;
938 mGlobalNvsArea
.Area
->EmaEnable
= 0;
940 mGlobalNvsArea
.Area
->NumberOfBatteries
= 1;
941 mGlobalNvsArea
.Area
->BatteryCapacity0
= 100;
942 mGlobalNvsArea
.Area
->BatteryStatus0
= 84;
943 mGlobalNvsArea
.Area
->OnboardCom
= 1;
944 mGlobalNvsArea
.Area
->IdeMode
= 0;
945 mGlobalNvsArea
.Area
->PowerState
= 0;
947 mGlobalNvsArea
.Area
->LogicalProcessorCount
= (UINT8
)NumberOfEnabledCPUs
;
949 mGlobalNvsArea
.Area
->PassiveThermalTripPoint
= mSystemConfiguration
.PassiveThermalTripPoint
;
950 mGlobalNvsArea
.Area
->PassiveTc1Value
= mSystemConfiguration
.PassiveTc1Value
;
951 mGlobalNvsArea
.Area
->PassiveTc2Value
= mSystemConfiguration
.PassiveTc2Value
;
952 mGlobalNvsArea
.Area
->PassiveTspValue
= mSystemConfiguration
.PassiveTspValue
;
953 mGlobalNvsArea
.Area
->CriticalThermalTripPoint
= mSystemConfiguration
.CriticalThermalTripPoint
;
955 mGlobalNvsArea
.Area
->IgdPanelType
= mSystemConfiguration
.IgdFlatPanel
;
956 mGlobalNvsArea
.Area
->IgdPanelScaling
= mSystemConfiguration
.PanelScaling
;
957 mGlobalNvsArea
.Area
->IgdSciSmiMode
= 0;
958 mGlobalNvsArea
.Area
->IgdTvFormat
= 0;
959 mGlobalNvsArea
.Area
->IgdTvMinor
= 0;
960 mGlobalNvsArea
.Area
->IgdSscConfig
= 1;
961 mGlobalNvsArea
.Area
->IgdBiaConfig
= mSystemConfiguration
.IgdLcdIBia
;
962 mGlobalNvsArea
.Area
->IgdBlcConfig
= mSystemConfiguration
.IgdLcdIGmchBlc
;
963 mGlobalNvsArea
.Area
->IgdDvmtMemSize
= mSystemConfiguration
.IgdDvmt50TotalAlloc
;
964 mGlobalNvsArea
.Area
->IgdPAVP
= mSystemConfiguration
.PavpMode
;
966 mGlobalNvsArea
.Area
->AlsEnable
= mSystemConfiguration
.AlsEnable
;
967 mGlobalNvsArea
.Area
->BacklightControlSupport
= 2;
968 mGlobalNvsArea
.Area
->BrightnessPercentage
= 100;
969 mGlobalNvsArea
.Area
->IgdState
= 1;
970 mGlobalNvsArea
.Area
->LidState
= 1;
972 mGlobalNvsArea
.Area
->DeviceId1
= 0x80000100 ;
973 mGlobalNvsArea
.Area
->DeviceId2
= 0x80000400 ;
974 mGlobalNvsArea
.Area
->DeviceId3
= 0x80000200 ;
975 mGlobalNvsArea
.Area
->DeviceId4
= 0x04;
976 mGlobalNvsArea
.Area
->DeviceId5
= 0x05;
977 mGlobalNvsArea
.Area
->NumberOfValidDeviceId
= 4 ;
978 mGlobalNvsArea
.Area
->CurrentDeviceList
= 0x0F ;
979 mGlobalNvsArea
.Area
->PreviousDeviceList
= 0x0F ;
981 mGlobalNvsArea
.Area
->UartSelection
= mSystemConfiguration
.UartInterface
;
982 mGlobalNvsArea
.Area
->PcuUart1Enable
= mSystemConfiguration
.PcuUart1
;
983 mGlobalNvsArea
.Area
->NativePCIESupport
= 1;
984 mGlobalNvsArea
.Area
->RtcBattery
= mSystemConfiguration
.RtcBattery
;
991 // Update BootMode: 0:ACPI mode; 1:PCI mode
993 mGlobalNvsArea
.Area
->LpssSccMode
= mSystemConfiguration
.LpssPciModeEnabled
;
994 if (mSystemConfiguration
.LpssMipiHsi
== 0) {
995 mGlobalNvsArea
.Area
->MipiHsiAddr
= 0;
996 mGlobalNvsArea
.Area
->MipiHsiLen
= 0;
997 mGlobalNvsArea
.Area
->MipiHsi1Addr
= 0;
998 mGlobalNvsArea
.Area
->MipiHsi1Len
= 0;
1004 mGlobalNvsArea
.Area
->PlatformFlavor
= mPlatformInfo
->PlatformFlavor
;
1007 // Update the Platform id
1009 mGlobalNvsArea
.Area
->BoardID
= mPlatformInfo
->BoardId
;
1012 // Update the Board Revision
1014 mGlobalNvsArea
.Area
->FabID
= mPlatformInfo
->BoardRev
;
1017 // Update SOC Stepping
1019 mGlobalNvsArea
.Area
->SocStepping
= (UINT8
)(PchStepping());
1021 mGlobalNvsArea
.Area
->OtgMode
= mSystemConfiguration
.PchUsbOtg
;
1023 pchStepping
= PchStepping();
1024 if (mSystemConfiguration
.UsbAutoMode
== 1) {
1026 // Auto mode is enabled.
1028 if (PchA0
== pchStepping
) {
1030 // For A0, EHCI is enabled as default.
1032 mSystemConfiguration
.PchUsb20
= 1;
1033 mSystemConfiguration
.PchUsb30Mode
= 0;
1034 mSystemConfiguration
.UsbXhciSupport
= 0;
1035 DEBUG ((EFI_D_INFO
, "EHCI is enabled as default. SOC 0x%x\n", pchStepping
));
1038 // For A1 and later, XHCI is enabled as default.
1040 mSystemConfiguration
.PchUsb20
= 0;
1041 mSystemConfiguration
.PchUsb30Mode
= 1;
1042 mSystemConfiguration
.UsbXhciSupport
= 1;
1043 DEBUG ((EFI_D_INFO
, "XHCI is enabled as default. SOC 0x%x\n", pchStepping
));
1047 mGlobalNvsArea
.Area
->XhciMode
= mSystemConfiguration
.PchUsb30Mode
;
1049 mGlobalNvsArea
.Area
->Stepping
= mPlatformInfo
->IchRevision
;
1052 // Override invalid Pre-Boot Driver and XhciMode combination.
1054 if ((mSystemConfiguration
.UsbXhciSupport
== 0) && (mSystemConfiguration
.PchUsb30Mode
== 3)) {
1055 mGlobalNvsArea
.Area
->XhciMode
= 2;
1057 if ((mSystemConfiguration
.UsbXhciSupport
== 1) && (mSystemConfiguration
.PchUsb30Mode
== 2)) {
1058 mGlobalNvsArea
.Area
->XhciMode
= 3;
1061 DEBUG ((EFI_D_ERROR
, "ACPI NVS XHCI:0x%x\n", mGlobalNvsArea
.Area
->XhciMode
));
1063 mGlobalNvsArea
.Area
->PmicEnable
= GLOBAL_NVS_DEVICE_DISABLE
;
1064 mGlobalNvsArea
.Area
->BatteryChargingSolution
= GLOBAL_NVS_DEVICE_DISABLE
;
1065 mGlobalNvsArea
.Area
->ISPDevSel
= mSystemConfiguration
.ISPDevSel
;
1066 mGlobalNvsArea
.Area
->LpeEnable
= mSystemConfiguration
.Lpe
;
1067 mGlobalNvsArea
.Area
->LpeAudioReportedByDSDT
= mSystemConfiguration
.LpeAudioReportedByDSDT
;
1069 if (mSystemConfiguration
.ISPEn
== 0) {
1070 mGlobalNvsArea
.Area
->ISPDevSel
= GLOBAL_NVS_DEVICE_DISABLE
;
1073 mGlobalNvsArea
.Area
->WittEnable
= mSystemConfiguration
.WittEnable
;
1074 mGlobalNvsArea
.Area
->UtsEnable
= mSystemConfiguration
.UtsEnable
;
1075 mGlobalNvsArea
.Area
->SarEnable
= mSystemConfiguration
.SAR1
;
1078 mGlobalNvsArea
.Area
->ReservedO
= 1;
1080 SettingI2CTouchAddress();
1081 mGlobalNvsArea
.Area
->IdleReserve
= mSystemConfiguration
.IdleReserve
;
1083 // Read BMBOUND and store it in GlobalNVS to pass into ASL.
1085 // BUGBUG: code was moved into silicon reference code.
1087 if (mSystemConfiguration
.eMMCBootMode
== 1) {
1089 // Auto detect mode.
1091 DEBUG ((EFI_D_ERROR
, "Auto detect mode------------start\n"));
1094 // Silicon Steppings.
1096 switch (PchStepping()) {
1097 case PchA0
: // A0/A1
1099 DEBUG ((EFI_D_ERROR
, "SOC A0/A1: eMMC 4.41 Configuration\n"));
1100 mSystemConfiguration
.LpsseMMCEnabled
= 1;
1101 mSystemConfiguration
.LpsseMMC45Enabled
= 0;
1104 case PchB0
: // B0 and later.
1106 DEBUG ((EFI_D_ERROR
, "SOC B0 and later: eMMC 4.5 Configuration\n"));
1107 mSystemConfiguration
.LpsseMMCEnabled
= 0;
1108 mSystemConfiguration
.LpsseMMC45Enabled
= 1;
1111 } else if (mSystemConfiguration
.eMMCBootMode
== 2) {
1115 DEBUG ((EFI_D_ERROR
, "Force to eMMC 4.41 Configuration\n"));
1116 mSystemConfiguration
.LpsseMMCEnabled
= 1;
1117 mSystemConfiguration
.LpsseMMC45Enabled
= 0;
1118 } else if (mSystemConfiguration
.eMMCBootMode
== 3) {
1122 DEBUG ((EFI_D_ERROR
, "Force to eMMC 4.5 Configuration\n"));
1123 mSystemConfiguration
.LpsseMMCEnabled
= 0;
1124 mSystemConfiguration
.LpsseMMC45Enabled
= 1;
1128 // Disable eMMC controllers.
1130 DEBUG ((EFI_D_ERROR
, "Disable eMMC controllers\n"));
1131 mSystemConfiguration
.LpsseMMCEnabled
= 0;
1132 mSystemConfiguration
.LpsseMMC45Enabled
= 0;
1135 mGlobalNvsArea
.Area
->emmcVersion
= 0;
1136 if (mSystemConfiguration
.LpsseMMCEnabled
) {
1137 DEBUG ((EFI_D_ERROR
, "mGlobalNvsArea.Area->emmcVersion = 0\n"));
1138 mGlobalNvsArea
.Area
->emmcVersion
= 0;
1141 if (mSystemConfiguration
.LpsseMMC45Enabled
) {
1142 DEBUG ((EFI_D_ERROR
, "mGlobalNvsArea.Area->emmcVersion = 1\n"));
1143 mGlobalNvsArea
.Area
->emmcVersion
= 1;
1146 mGlobalNvsArea
.Area
->SdCardRemovable
= mSystemConfiguration
.SdCardRemovable
;
1151 if ((mSystemConfiguration
.LpssHsuart0FlowControlEnabled
== 1) && \
1152 (mSystemConfiguration
.LpssPwm0Enabled
== 0) && \
1153 (mSystemConfiguration
.LpssPwm1Enabled
== 0)) {
1154 mGlobalNvsArea
.Area
->MicrosoftIoT
= GLOBAL_NVS_DEVICE_ENABLE
;
1155 DEBUG ((EFI_D_ERROR
, "JP1 is set to be MSFT IOT configuration.\n"));
1157 mGlobalNvsArea
.Area
->MicrosoftIoT
= GLOBAL_NVS_DEVICE_DISABLE
;
1158 DEBUG ((EFI_D_ERROR
, "JP1 is not set to be MSFT IOT configuration.\n"));
1162 // SIO related option.
1164 Status
= gBS
->LocateProtocol (&gEfiCpuIoProtocolGuid
, NULL
, (void **)&mCpuIo
);
1165 ASSERT_EFI_ERROR (Status
);
1167 mGlobalNvsArea
.Area
->WPCN381U
= GLOBAL_NVS_DEVICE_DISABLE
;
1169 mGlobalNvsArea
.Area
->DockedSioPresent
= GLOBAL_NVS_DEVICE_DISABLE
;
1171 if (mGlobalNvsArea
.Area
->DockedSioPresent
!= GLOBAL_NVS_DEVICE_ENABLE
) {
1173 // Check ID for SIO WPCN381U.
1175 Status
= mCpuIo
->Io
.Read (
1178 WPCN381U_CONFIG_INDEX
,
1182 ASSERT_EFI_ERROR (Status
);
1183 if (PortData
!= 0xFF) {
1185 Status
= mCpuIo
->Io
.Write (
1188 WPCN381U_CONFIG_INDEX
,
1192 ASSERT_EFI_ERROR (Status
);
1193 Status
= mCpuIo
->Io
.Read (
1196 WPCN381U_CONFIG_DATA
,
1200 ASSERT_EFI_ERROR (Status
);
1201 if ((PortData
== WPCN381U_CHIP_ID
) || (PortData
== WDCP376_CHIP_ID
)) {
1202 mGlobalNvsArea
.Area
->WPCN381U
= GLOBAL_NVS_DEVICE_ENABLE
;
1203 mGlobalNvsArea
.Area
->OnboardCom
= GLOBAL_NVS_DEVICE_ENABLE
;
1204 mGlobalNvsArea
.Area
->OnboardComCir
= GLOBAL_NVS_DEVICE_DISABLE
;
1212 // Get Ps2 policy to set. Will be use if present.
1214 Status
= gBS
->LocateProtocol (
1215 &gEfiPs2PolicyProtocolGuid
,
1219 if (!EFI_ERROR (Status
)) {
1220 Status
= Ps2Policy
->Ps2InitHardware (ImageHandle
);
1223 mGlobalNvsArea
.Area
->SDIOMode
= mSystemConfiguration
.LpssSdioMode
;
1226 Status
= gBS
->InstallMultipleProtocolInterfaces (
1228 &gEfiGlobalNvsAreaProtocolGuid
,
1234 // Read tables from the storage file.
1236 while (!EFI_ERROR (Status
)) {
1237 CurrentTable
= NULL
;
1239 Status
= FwVol
->ReadSection (
1241 &gEfiAcpiTableStorageGuid
,
1244 (VOID
**) &CurrentTable
,
1249 if (!EFI_ERROR (Status
)) {
1251 // Allow platform specific code to reject the table or update it.
1253 AcpiStatus
= AcpiPlatformHooksIsActiveTable (CurrentTable
);
1255 if (!EFI_ERROR (AcpiStatus
)) {
1257 // Perform any table specific updates.
1259 AcpiStatus
= PlatformUpdateTables (CurrentTable
);
1260 if (!EFI_ERROR (AcpiStatus
)) {
1265 AcpiStatus
= AcpiSupport
->SetAcpiTable (
1272 ASSERT_EFI_ERROR (AcpiStatus
);
1277 // Increment the instance.
1283 Status
= EfiCreateEventReadyToBootEx (
1303 IoWrite8(0x72, Index
);
1304 Data
= IoRead8 (0x73);
1309 WriteCmosBank1Byte (
1314 IoWrite8 (0x72, Index
);
1315 IoWrite8 (0x73, Data
);
1321 SettingI2CTouchAddress (
1325 if (mSystemConfiguration
.I2CTouchAd
== 0) {
1327 // If setup menu select auto set I2C Touch Address base on board id.
1329 if (mPlatformInfo
->BoardId
== BOARD_ID_BL_RVP
||
1330 mPlatformInfo
->BoardId
== BOARD_ID_BL_STHI
||
1331 mPlatformInfo
->BoardId
== BOARD_ID_BL_RVP_DDR3L
) {
1335 mGlobalNvsArea
.Area
->I2CTouchAddress
= 0x4B;
1336 } else if (mPlatformInfo
->BoardId
== BOARD_ID_BL_FFRD
) {
1340 mGlobalNvsArea
.Area
->I2CTouchAddress
= 0x4A;
1341 } else if (mPlatformInfo
->BoardId
== BOARD_ID_BB_RVP
) {
1342 mGlobalNvsArea
.Area
->I2CTouchAddress
= 0x4C;
1343 } else if (mPlatformInfo
->BoardId
== BOARD_ID_CVH
) {
1344 mGlobalNvsArea
.Area
->I2CTouchAddress
= 0x4C;
1345 } else if (mPlatformInfo
->BoardId
== BOARD_ID_BL_FFRD8
) {
1349 mGlobalNvsArea
.Area
->I2CTouchAddress
= 0x4A;
1352 mGlobalNvsArea
.Area
->I2CTouchAddress
= mSystemConfiguration
.I2CTouchAd
;
1354 DEBUG((EFI_D_ERROR
, "GlobalNvsArea.Area->I2CTouchAddress: [%02x]\n", mGlobalNvsArea
.Area
->I2CTouchAddress
));