From 923b430effa8a55b6e5a1fcaa4fe385698231ecc Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Wed, 3 Aug 2016 09:43:39 +0800 Subject: BraswellPlatformPkg: Move Acpi to Common/Acpi Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang Reviewed-by: David Wei --- .../Common/Acpi/AcpiPlatform/AcpiPlatform.c | 1131 ++++++++++++++++++++ .../Common/Acpi/AcpiPlatform/AcpiPlatform.h | 302 ++++++ .../Common/Acpi/AcpiPlatform/AcpiPlatform.inf | 103 ++ BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.h | 243 +++++ .../Common/Acpi/AcpiSmm/AcpiSmm.inf | 103 ++ BraswellPlatformPkg/Common/Acpi/AcpiSmm/Platform.c | 831 ++++++++++++++ BraswellPlatformPkg/Common/Acpi/AcpiSmm/S3Save.c | 402 +++++++ 7 files changed, 3115 insertions(+) create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.c create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.h create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.inf create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.h create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.inf create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiSmm/Platform.c create mode 100644 BraswellPlatformPkg/Common/Acpi/AcpiSmm/S3Save.c (limited to 'BraswellPlatformPkg/Common/Acpi') diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.c b/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.c new file mode 100644 index 0000000000..68a6aa55ce --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.c @@ -0,0 +1,1131 @@ +/** @file + ACPI Platform Driver. + + Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include "AcpiPlatform.h" +#include "Platform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "CpuRegs.h" +#include + +#define AML_OPREGION_OP 0x80 + +typedef struct { + UINT32 RegEax; + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; +} EFI_CPUID_REGISTER; + +EFI_CPU_IO2_PROTOCOL *mCpuIo; + +#pragma optimize("", off) + +EFI_PLATFORM_INFO_HOB *mPlatformInfo; +SYSTEM_CONFIGURATION mSystemConfiguration; + +VOID +SettingI2CTouchAddress ( + IN VOID + ); + +VOID +LoadSsdtIsctTable ( + VOID + ); + +/** +Routine Description: + + Locate the first instance of a protocol. If the protocol requested is an + FV protocol, then it will return the first FV that contains the ACPI table + storage file. + + @param[in] Protocol The protocol to find. + @param[in] Instance Return pointer to the first instance of the protocol. + @param[in] Type The type of protocol to locate. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The protocol could not be located. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + OUT VOID **Instance, + IN UINT32 Type + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + EFI_FV_FILETYPE FileType; + UINT32 FvStatus; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN Index; + + FvStatus = 0; + // + // Locate protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + Protocol, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + // + // Defined errors at this time are not found and out of resources. + // + return Status; + } + + // + // Looking for FV with ACPI storage file + // + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + Protocol, + Instance + ); + ASSERT (!EFI_ERROR (Status)); + + if (!Type) { + // + // Not looking for the FV protocol, so find the first instance of the + // protocol. There should not be any errors because our handle buffer + // should always contain at least one or LocateHandleBuffer would have + // returned not found. + // + break; + } + + // + // See if it has the ACPI storage file + // + Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile ( + *Instance, + &gEfiAcpiTableStorageGuid, + NULL, + &Size, + &FileType, + &Attributes, + &FvStatus + ); + + // + // If we found it, then we are done + // + if (!EFI_ERROR (Status)) { + break; + } + } + // + // Our exit status is determined by the success of the previous operations + // If the protocol was found, Instance already points to it. + // + // + // Free any allocated buffers + // + gBS->FreePool (HandleBuffer); + + return Status; +} + +/** + Update the DSDT table. + + @param[in][out] *TableHeader The table to be set. + + @retval EFI_SUCCESS Returns EFI_SUCCESS. + +**/ +EFI_STATUS +PatchDsdtTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader + ) +{ + UINT8 *CurrPtr; + UINT8 *DsdtPointer; + UINT32 *Signature; + UINT8 *EndPtr; + UINT8 *Operation; + UINT32 *Address; + UINT16 *Size; + + CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0]; + EndPtr = (UINT8*) TableHeader; + EndPtr = EndPtr + TableHeader->Length; + while (CurrPtr < (EndPtr-2)) { + // + // Removed the _S3 tag to indicate that we do not support S3. The 4th byte is blank space + // since there are only 3 char "_S3". + // + if (mSystemConfiguration.AcpiSuspendState == 0) { + // + // For iasl compiler version 20061109. + // + if ((CurrPtr[0] == '_') && (CurrPtr[1] == 'S') && (CurrPtr[2] == '3') && (CurrPtr[3] == '_')) { + break; + } + // + // For iasl compiler version 20040527. + // + if ((CurrPtr[0] == '\\') && (CurrPtr[1] == '_') && (CurrPtr[2] == 'S') && (CurrPtr[3] == '3')) { + break; + } + } + CurrPtr++; + } + EndPtr = (UINT8*) TableHeader; + EndPtr = EndPtr + TableHeader->Length; + // + // Loop through the ASL looking for values that we must fix up. + // + CurrPtr = (UINT8 *) TableHeader; + for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) { + Signature = (UINT32 *) DsdtPointer; + + switch (*Signature) { + // + // GNVS operation region. + // + case (SIGNATURE_32 ('G', 'N', 'V', 'S')): + // + // Conditional match. For Region Objects, the Operator will always be the + // byte immediately before the specific name. Therefore, subtract 1 to check + // the Operator. + // + Operation = DsdtPointer - 1; + if (*Operation == AML_OPREGION_OP) { + Address = (UINT32 *) (DsdtPointer + 6); + *Address = (UINT32) (UINTN) mGlobalNvsArea.Area; + Size = (UINT16 *) (DsdtPointer + 11); + *Size = sizeof (EFI_GLOBAL_NVS_AREA); + } + break; + default: + break; + } + } + + return EFI_SUCCESS; +} + +/** +Routine Description: + + This function will update any runtime platform specific information. + This currently includes:Setting OEM table values, ID, table ID, creator ID and creator revision. + Enabling the proper processor entries in the APIC tables. + + @param[in] Table The table to update + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +PlatformUpdateTables ( + IN OUT EFI_ACPI_COMMON_HEADER *Table + ) +{ + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINT8 *CurrPtr; + UINT8 *EndPtr; + ACPI_APIC_STRUCTURE_PTR *ApicPtr; + UINT8 CurrProcessor; + EFI_STATUS Status; + EFI_MP_SERVICES_PROTOCOL *MpService; + UINTN MaximumNumberOfCPUs; + UINTN NumberOfEnabledCPUs; + UINTN BufferSize; + ACPI_APIC_STRUCTURE_PTR *ProcessorLocalApicEntry; + UINTN BspIndex; + EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTbl; + UINT64 OemIdValue; + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *pFACP; + UINT16 NumberOfHpets; + UINT16 HpetCapIdValue; + UINT32 HpetBlockID; + UINTN LocalApicCounter; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + EFI_ACPI_3_0_IO_APIC_STRUCTURE *IOApicType; + EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *APICTableHeader; + + CurrPtr = NULL; + EndPtr = NULL; + ApicPtr = NULL; + LocalApicCounter = 0; + CurrProcessor = 0; + ProcessorLocalApicEntry = NULL; + + if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; + + // + // Update the OEMID + // + OemIdValue = 0; + CopyMem (&OemIdValue, PcdGetPtr (PcdAcpiDefaultOemId), 6); + + *(UINT32 *)(TableHeader->OemId) = (UINT32) OemIdValue; + *(UINT16 *)(TableHeader->OemId + 4) = *(UINT16*)(((UINT8 *)&OemIdValue) + 4); + + if ((Table->Signature != EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { + // + // Update the OEM Table ID + // + TableHeader->OemTableId = PcdGet64(PcdAcpiDefaultOemTableId); + } + + // + // Update the OEM Table ID + // + TableHeader->OemRevision = EFI_ACPI_OEM_REVISION; + + // + // Update the creator ID + // + TableHeader->CreatorId = EFI_ACPI_CREATOR_ID; + + // + // Update the creator revision + // + TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION; + } + // + // Complete this function + // + // + // Locate the MP services protocol + // + // + // Find the MP Protocol. This is an MP platform, so MP protocol must be + // there. + // + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + &MpService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Determine the number of processors + // + MpService->GetNumberOfProcessors ( + MpService, + &MaximumNumberOfCPUs, + &NumberOfEnabledCPUs + ); + + ASSERT (MaximumNumberOfCPUs <= MAX_CPU_NUM && NumberOfEnabledCPUs >= 1); + + // + // Assign a invalid intial value for update + // + // + // Update the processors in the APIC table + // + switch (Table->Signature) { + case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: + + Status = MpService->WhoAmI ( + MpService, + &BspIndex + ); + + // + // PCAT_COMPAT Set to 1 indicate 8259 vectors should be disabled + // + APICTableHeader = (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)Table; + APICTableHeader->Flags |= EFI_ACPI_3_0_PCAT_COMPAT; + + CurrPtr = (UINT8 *) &((EFI_ACPI_DESCRIPTION_HEADER *) Table)[1]; + CurrPtr = CurrPtr + 8; + + // + // Size of Local APIC Address & Flag + // + EndPtr = (UINT8 *) Table; + EndPtr = EndPtr + Table->Length; + while (CurrPtr < EndPtr) { + ApicPtr = (ACPI_APIC_STRUCTURE_PTR *) CurrPtr; + switch (ApicPtr->AcpiApicCommon.Type) { + case EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC: + // + // ESS override + // Fix for Ordering of MADT to be maintained as it is in MADT table. + // + // Update processor enabled or disabled and keep the local APIC + // order in MADT intact + // + // Sanity check to make sure proc-id is not arbitrary + // + DEBUG ((EFI_D_ERROR, "ApicPtr->AcpiLocalApic.AcpiProcessorId = %x, MaximumNumberOfCPUs = %x\n", ApicPtr->AcpiLocalApic.AcpiProcessorId, MaximumNumberOfCPUs)); + if (ApicPtr->AcpiLocalApic.AcpiProcessorId > MaximumNumberOfCPUs) { + ApicPtr->AcpiLocalApic.AcpiProcessorId = (UINT8)MaximumNumberOfCPUs; + } + + BufferSize = 0; + ApicPtr->AcpiLocalApic.Flags = 0; + + for (CurrProcessor = 0; CurrProcessor < MaximumNumberOfCPUs; CurrProcessor++) { + Status = MpService->GetProcessorInfo ( + MpService, + CurrProcessor, + &ProcessorInfoBuffer + ); + + if (Status == EFI_SUCCESS && ProcessorInfoBuffer.ProcessorId == ApicPtr->AcpiLocalApic.ApicId) { + // + // Check to see whether or not a processor (or thread) is enabled + // + if (BspIndex == CurrProcessor || ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0)) { + // + // Go on and check if Hyper Threading is enabled. If HT not enabled + // hide this thread from OS by not setting the flag to 1. This is the + // software way to disable Hyper Threading. Basically we just hide it + // from the OS. + // + ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_1_0_LOCAL_APIC_ENABLED; + + if (!mSystemConfiguration.ProcessorHtMode) { + if (ProcessorInfoBuffer.Location.Thread != 0) { + ApicPtr->AcpiLocalApic.Flags = 0; + } + } + + if (mSystemConfiguration.ActiveProcessorCores) { + if (ProcessorInfoBuffer.Location.Core >= mSystemConfiguration.ActiveProcessorCores) { + ApicPtr->AcpiLocalApic.Flags = 0; + } + } + } + break; + } + } + + // + // If no APIC-ID match, the cpu may not be populated + // + break; + + case EFI_ACPI_3_0_IO_APIC: + + IOApicType = (EFI_ACPI_3_0_IO_APIC_STRUCTURE *)CurrPtr; + MmioWrite8 ((UINTN) R_PCH_IO_APIC_INDEX, R_PCH_IO_APIC_ID); + IOApicType->IoApicId = (UINT8) (MmioRead32 ((UINTN) R_PCH_IO_APIC_WINDOW) >> 24); + // + // IO APIC entries can be patched here + // + break; + } + + CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length; + } + break; + + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + // + // if Native ASPM is disabled, set FACP table to skip Native ASPM + // + if ((mSystemConfiguration.PciExpNative == 0)) { + pFACP = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table; + pFACP->IaPcBootArch |= 0x10; + } + break; + case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + // + // Patch the memory resource + // + PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER *) Table); + break; + + case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + + break; + + case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE: + // + // Adjust HPET Table to correct the Base Address + // + // Enable HPET always as Hpet.asi always indicates that Hpet is enabled. + MmioOr8 (R_PCH_PCH_HPET + R_PCH_PCH_HPET_GCFG, B_PCH_PCH_HPET_GCFG_EN); + + HpetTbl = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) Table; + HpetTbl->BaseAddressLower32Bit.Address = HPET_BASE_ADDRESS; + HpetTbl->EventTimerBlockId = *((UINT32*)(UINTN)HPET_BASE_ADDRESS); + + HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BASE_ADDRESS); + NumberOfHpets = HpetCapIdValue & B_PCH_PCH_HPET_GCID_NT; // Bits [8:12] contains the number of Hpets + HpetBlockID = EFI_ACPI_EVENT_TIMER_BLOCK_ID; + + if ((NumberOfHpets) && (NumberOfHpets & B_PCH_PCH_HPET_GCID_NT)) { + HpetBlockID |= (NumberOfHpets); + } + HpetTbl->EventTimerBlockId = HpetBlockID; + + break; + + case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: + // + // Update MCFG base and end bus number + // + ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].BaseAddress + = mPlatformInfo->PciData.PciExpressBase; + ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].EndBusNumber + = (UINT8)RShiftU64 (mPlatformInfo->PciData.PciExpressSize, 20) - 1; + break; + + default: + break; + } + // + // + // Update the hardware signature in the FACS structure + // + // + // Locate the SPCR table and update based on current settings. + // The user may change CR settings via setup or other methods. + // The SPCR table must match. + // + + return EFI_SUCCESS; +} + +/** +Routine Description: + + Entry point for Acpi platform driver. + + @param[in] ImageHandle A handle for the image that is initializing this driver. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS Driver initialized successfully. + @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_STATUS AcpiStatus; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + INTN Instance; + EFI_ACPI_COMMON_HEADER *CurrentTable; + UINTN TableHandle; + UINT32 FvStatus; + UINT32 Size; + EFI_ACPI_TABLE_VERSION TableVersion; + EFI_HANDLE Handle; + UINT8 PortData; + EFI_MP_SERVICES_PROTOCOL *MpService; + UINTN MaximumNumberOfCPUs; + UINTN NumberOfEnabledCPUs; + UINT32 Data32; + UINTN Pages; + EFI_PHYSICAL_ADDRESS Address; + EFI_EVENT EfiExitBootServicesEvent; + + Address = 0xffffffff; + + TableVersion = EFI_ACPI_TABLE_VERSION_2_0; + Instance = 0; + CurrentTable = NULL; + TableHandle = 0; + Data32 = 0; + + mPlatformInfo = PcdGetPtr (PcdPlatformInfo); + + // + // Search for the Memory Configuration GUID HOB. If it is not present, then + // there's nothing we can do. It may not exist on the update path. + // + CopyMem (&mSystemConfiguration, PcdGetPtr (PcdSystemConfiguration), sizeof(SYSTEM_CONFIGURATION)); + + // + // Locate the AcpiTable protocol + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); + ASSERT_EFI_ERROR (Status); + + // + // Locate the firmware volume protocol + // + Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, &FwVol, 1); + ASSERT_EFI_ERROR (Status); + + Instance = 0; + + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + &MpService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Determine the number of processors + // + MpService->GetNumberOfProcessors ( + MpService, + &MaximumNumberOfCPUs, + &NumberOfEnabledCPUs + ); + + // + // Allocate and initialize the NVS area for SMM and ASL communication. + // + Pages = EFI_SIZE_TO_PAGES ( sizeof (EFI_GLOBAL_NVS_AREA) ); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + Pages, + &Address + ); + ASSERT_EFI_ERROR (Status); + mGlobalNvsArea.Area = (EFI_GLOBAL_NVS_AREA*) (UINTN)Address; + + gBS->SetMem (mGlobalNvsArea.Area, sizeof (EFI_GLOBAL_NVS_AREA), 0); + DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area is at 0x%X\n", mGlobalNvsArea.Area)); + + // + // Update global NVS area for ASL and SMM init code to use + // + mGlobalNvsArea.Area->ApicEnable = 1; + mGlobalNvsArea.Area->NumberOfBatteries = 1; + mGlobalNvsArea.Area->BatteryCapacity0 = 100; + mGlobalNvsArea.Area->BatteryStatus0 = 84; + mGlobalNvsArea.Area->OnboardCom = 1; + mGlobalNvsArea.Area->PowerState = 0; + + mGlobalNvsArea.Area->LogicalProcessorCount = (UINT8)NumberOfEnabledCPUs; + + mGlobalNvsArea.Area->PassiveThermalTripPoint = 85; + mGlobalNvsArea.Area->PassiveTc1Value = 1; + mGlobalNvsArea.Area->PassiveTc2Value = 5; + mGlobalNvsArea.Area->PassiveTspValue = 50; + mGlobalNvsArea.Area->CriticalThermalTripPoint = 110; + + mGlobalNvsArea.Area->IgdPanelType = mSystemConfiguration.IgdFlatPanel; + mGlobalNvsArea.Area->IgdPanelScaling = mSystemConfiguration.PanelScaling; + mGlobalNvsArea.Area->IgdSciSmiMode = 0; + mGlobalNvsArea.Area->IgdTvFormat = 0; + mGlobalNvsArea.Area->IgdTvMinor = 0; + mGlobalNvsArea.Area->IgdSscConfig = 1; + mGlobalNvsArea.Area->IgdBiaConfig = mSystemConfiguration.IgdLcdIBia; + mGlobalNvsArea.Area->IgdBlcConfig = mSystemConfiguration.IgdLcdIGmchBlc; + mGlobalNvsArea.Area->IgdDvmtMemSize = mSystemConfiguration.IgdDvmt50TotalAlloc; + + mGlobalNvsArea.Area->AlsEnable = mSystemConfiguration.AlsEnable; + mGlobalNvsArea.Area->BacklightControlSupport = 2; + mGlobalNvsArea.Area->BrightnessPercentage = 100; + mGlobalNvsArea.Area->IgdState = 1; + mGlobalNvsArea.Area->LidState = 1; + + mGlobalNvsArea.Area->DeviceId1 = 0x80000100 ; + mGlobalNvsArea.Area->DeviceId2 = 0x80000400 ; + mGlobalNvsArea.Area->DeviceId3 = 0x80000200 ; + mGlobalNvsArea.Area->DeviceId4 = 0x04; + mGlobalNvsArea.Area->DeviceId5 = 0x05; + mGlobalNvsArea.Area->NumberOfValidDeviceId = 4 ; + mGlobalNvsArea.Area->CurrentDeviceList = 0x0F ; + mGlobalNvsArea.Area->PreviousDeviceList = 0x0F ; + + mGlobalNvsArea.Area->UartSelection = mSystemConfiguration.UartInterface; + + // + // DPTF related + // + mGlobalNvsArea.Area->DptfEnable = mSystemConfiguration.EnableDptf; + mGlobalNvsArea.Area->DptfSysThermal0 = mSystemConfiguration.DptfSysThermal0; + mGlobalNvsArea.Area->DptfSysThermal1 = mSystemConfiguration.DptfSysThermal1; + mGlobalNvsArea.Area->DptfSysThermal2 = mSystemConfiguration.DptfSysThermal2; + mGlobalNvsArea.Area->DptfSysThermal3 = mSystemConfiguration.DptfSysThermal3; + mGlobalNvsArea.Area->DptfSysThermal4 = mSystemConfiguration.DptfSysThermal4; + mGlobalNvsArea.Area->DptfCharger = mSystemConfiguration.DptfChargerDevice; + mGlobalNvsArea.Area->DptfDisplayDevice = mSystemConfiguration.DptfDisplayDevice; + mGlobalNvsArea.Area->DptfSocDevice = mSystemConfiguration.DptfSocDevice; + mGlobalNvsArea.Area->DptfProcessor = mSystemConfiguration.DptfProcessor; + mGlobalNvsArea.Area->DptfProcCriticalTemperature = mSystemConfiguration.CriticalThermalTripPoint; + mGlobalNvsArea.Area->DptfProcPassiveTemperature = mSystemConfiguration.PassiveThermalTripPoint; + + mGlobalNvsArea.Area->EnablePassivePolicy = mSystemConfiguration.EnablePassivePolicy; + mGlobalNvsArea.Area->EnableCriticalPolicy = mSystemConfiguration.EnableCriticalPolicy; + mGlobalNvsArea.Area->EnableActivePolicy = mSystemConfiguration.EnableActivePolicy; + + mGlobalNvsArea.Area->DptfGenericActiveTemperature0 = mSystemConfiguration.GenericActiveTemp0; + mGlobalNvsArea.Area->DptfGenericCR3Temperature0 = mSystemConfiguration.GenericCR3Temp0; + mGlobalNvsArea.Area->DptfGenericHotTemperature0 = mSystemConfiguration.GenericHotTemp0; + mGlobalNvsArea.Area->DptfGenericActiveTemperature1 = mSystemConfiguration.GenericActiveTemp1; + mGlobalNvsArea.Area->DptfGenericCR3Temperature1 = mSystemConfiguration.GenericCR3Temp1; + mGlobalNvsArea.Area->DptfGenericHotTemperature1 = mSystemConfiguration.GenericHotTemp1; + mGlobalNvsArea.Area->DptfGenericActiveTemperature2 = mSystemConfiguration.GenericActiveTemp2; + mGlobalNvsArea.Area->DptfGenericCR3Temperature2 = mSystemConfiguration.GenericCR3Temp2; + mGlobalNvsArea.Area->DptfGenericHotTemperature2 = mSystemConfiguration.GenericHotTemp2; + + mGlobalNvsArea.Area->DptfProcActiveTemperatureSA = mSystemConfiguration.ActiveThermalTripPointSA; + mGlobalNvsArea.Area->DptfProcCriticalTemperatureSA = mSystemConfiguration.CriticalThermalTripPointSA; + mGlobalNvsArea.Area->DptfProcCR3TemperatureSA = mSystemConfiguration.CR3ThermalTripPointSA; + mGlobalNvsArea.Area->DptfProcHotTemperatureSA = mSystemConfiguration.HotThermalTripPointSA; + mGlobalNvsArea.Area->DptfProcPassiveTemperatureSA = mSystemConfiguration.PassiveThermalTripPointSA; + + mGlobalNvsArea.Area->DptfGenericCriticalTemperature0 = mSystemConfiguration.GenericCriticalTemp0; + mGlobalNvsArea.Area->DptfGenericPassiveTemperature0 = mSystemConfiguration.GenericPassiveTemp0; + mGlobalNvsArea.Area->DptfGenericCriticalTemperature1 = mSystemConfiguration.GenericCriticalTemp1; + mGlobalNvsArea.Area->DptfGenericPassiveTemperature1 = mSystemConfiguration.GenericPassiveTemp1; + mGlobalNvsArea.Area->DptfGenericCriticalTemperature2 = mSystemConfiguration.GenericCriticalTemp2; + mGlobalNvsArea.Area->DptfGenericPassiveTemperature2 = mSystemConfiguration.GenericPassiveTemp2; + mGlobalNvsArea.Area->DptfGenericCriticalTemperature3 = mSystemConfiguration.GenericCriticalTemp3; + mGlobalNvsArea.Area->DptfGenericPassiveTemperature3 = mSystemConfiguration.GenericPassiveTemp3; + mGlobalNvsArea.Area->DptfGenericCriticalTemperature4 = mSystemConfiguration.GenericCriticalTemp4; + mGlobalNvsArea.Area->DptfGenericPassiveTemperature4 = mSystemConfiguration.GenericPassiveTemp4; + mGlobalNvsArea.Area->CLpmSetting = mSystemConfiguration.Clpm; + mGlobalNvsArea.Area->DptfSuperDbg = mSystemConfiguration.SuperDebug; + mGlobalNvsArea.Area->LPOEnable = mSystemConfiguration.LPOEnable; + mGlobalNvsArea.Area->LPOStartPState = mSystemConfiguration.LPOStartPState; + mGlobalNvsArea.Area->LPOStepSize = mSystemConfiguration.LPOStepSize; + mGlobalNvsArea.Area->LPOPowerControlSetting = mSystemConfiguration.LPOPowerControlSetting; + mGlobalNvsArea.Area->LPOPerformanceControlSetting = mSystemConfiguration.LPOPerformanceControlSetting; + mGlobalNvsArea.Area->DppmEnabled = mSystemConfiguration.EnableDppm; + mGlobalNvsArea.Area->AmbientTripPointChange = mSystemConfiguration.AmbientTripPointChange; + mGlobalNvsArea.Area->DptfWwanDevice = mSystemConfiguration.DptfWwanDevice; + mGlobalNvsArea.Area->DptfWwanCrt = mSystemConfiguration.DptfWwanCrt; + mGlobalNvsArea.Area->DptfWwanPsv = mSystemConfiguration.DptfWwanPsv; + mGlobalNvsArea.Area->DisplayHighLimit = mSystemConfiguration.DisplayHighLimit; + mGlobalNvsArea.Area->DisplayLowLimit = mSystemConfiguration.DisplayLowLimit; + + // + // Ambient temperature related data + // + mGlobalNvsArea.Area->AmbientConstants[0] = mSystemConfiguration.AmbientConstants[0]; + mGlobalNvsArea.Area->AmbientConstants[1] = mSystemConfiguration.AmbientConstants[1]; + mGlobalNvsArea.Area->AmbientConstants[2] = mSystemConfiguration.AmbientConstants[2]; + mGlobalNvsArea.Area->AmbientConstants[3] = mSystemConfiguration.AmbientConstants[3]; + mGlobalNvsArea.Area->AmbientConstants[4] = mSystemConfiguration.AmbientConstants[4]; + mGlobalNvsArea.Area->AmbientConstants[5] = mSystemConfiguration.AmbientConstants[5]; + mGlobalNvsArea.Area->AmbientConstantSign[0] = mSystemConfiguration.AmbientConstantSign[0]; + mGlobalNvsArea.Area->AmbientConstantSign[1] = mSystemConfiguration.AmbientConstantSign[1]; + mGlobalNvsArea.Area->AmbientConstantSign[2] = mSystemConfiguration.AmbientConstantSign[2]; + mGlobalNvsArea.Area->AmbientConstantSign[3] = mSystemConfiguration.AmbientConstantSign[3]; + mGlobalNvsArea.Area->AmbientConstantSign[4] = mSystemConfiguration.AmbientConstantSign[4]; + mGlobalNvsArea.Area->AmbientConstantSign[5] = mSystemConfiguration.AmbientConstantSign[5]; + mGlobalNvsArea.Area->Str2TspValue = mSystemConfiguration.Str2TspValue; + + DEBUG((EFI_D_INFO, "Dumping DPTF settings in global nvs init...\n")); + DEBUG((EFI_D_INFO, "DPTFEnabled = %d\n", mGlobalNvsArea.Area->DptfEnable)); + DEBUG((EFI_D_INFO, "CpuParticipantCriticalTemperature = %d\n", mGlobalNvsArea.Area->DptfProcCriticalTemperature)); + DEBUG((EFI_D_INFO, "CpuParticipantPassiveTemperature = %d\n", mGlobalNvsArea.Area->DptfProcPassiveTemperature)); + DEBUG((EFI_D_INFO, "GenParticipant0CriticalTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericCriticalTemperature0)); + DEBUG((EFI_D_INFO, "GenParticipant0PassiveTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericPassiveTemperature0)); + DEBUG((EFI_D_INFO, "GenParticipant1CriticalTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericCriticalTemperature1)); + DEBUG((EFI_D_INFO, "GenParticipant1PassiveTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericPassiveTemperature1)); + DEBUG((EFI_D_INFO, "GenParticipant2CriticalTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericCriticalTemperature2)); + DEBUG((EFI_D_INFO, "GenParticipant2PassiveTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericPassiveTemperature2)); + DEBUG((EFI_D_INFO, "GenParticipant3CriticalTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericCriticalTemperature3)); + DEBUG((EFI_D_INFO, "GenParticipant3PassiveTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericPassiveTemperature3)); + DEBUG((EFI_D_INFO, "GenParticipant4CriticalTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericCriticalTemperature4)); + DEBUG((EFI_D_INFO, "GenParticipant4PassiveTemperature = %d\n", mGlobalNvsArea.Area->DptfGenericPassiveTemperature4)); + DEBUG((EFI_D_INFO,"WwanDevice = %d Wwan PSv = %d WwanCrt = %d\n", mGlobalNvsArea.Area->DptfWwanDevice,mGlobalNvsArea.Area->DptfWwanPsv, mGlobalNvsArea.Area->DptfWwanCrt)); + DEBUG((EFI_D_INFO, "ClpmSetting = %d\n", mGlobalNvsArea.Area->CLpmSetting)); + DEBUG((EFI_D_INFO, "SuperDebug = %d\n", mGlobalNvsArea.Area->DptfSuperDbg)); + DEBUG((EFI_D_INFO, "LPOEnable = %d\n", mGlobalNvsArea.Area->LPOEnable)); + DEBUG((EFI_D_INFO, "LPOStartPState = %d\n", mGlobalNvsArea.Area->LPOStartPState)); + DEBUG((EFI_D_INFO, "LPOStepSize = %d\n", mGlobalNvsArea.Area->LPOStepSize)); + DEBUG((EFI_D_INFO, "LPOPowerControlSetting = %d\n", mGlobalNvsArea.Area->LPOPowerControlSetting)); + DEBUG((EFI_D_INFO, "LPOPerformanceControlSetting = %d\n", mGlobalNvsArea.Area->LPOPerformanceControlSetting)); + DEBUG((EFI_D_INFO, "bDppmEnabled = %d\n", mGlobalNvsArea.Area->DppmEnabled)); + + DEBUG((EFI_D_INFO, "DptfEnable = %d\n", mGlobalNvsArea.Area->DptfEnable)); + DEBUG((EFI_D_INFO, "DptfSysThermal0 = %d\n", mGlobalNvsArea.Area->DptfSysThermal0)); + DEBUG((EFI_D_INFO, "DptfSysThermal1 = %d\n", mGlobalNvsArea.Area->DptfSysThermal1)); + DEBUG((EFI_D_INFO, "DptfSysThermal2 = %d\n", mGlobalNvsArea.Area->DptfSysThermal2)); + DEBUG((EFI_D_INFO, "DptfSysThermal3 = %d\n", mGlobalNvsArea.Area->DptfSysThermal3)); + DEBUG((EFI_D_INFO, "DptfCharger = %d\n", mGlobalNvsArea.Area->DptfCharger)); + DEBUG((EFI_D_INFO, "DptfDisplayDevice = %d\n", mGlobalNvsArea.Area->DptfDisplayDevice)); + DEBUG((EFI_D_INFO, "DptfSocDevice = %d\n", mGlobalNvsArea.Area->DptfSocDevice)); + DEBUG((EFI_D_INFO, "DptfProcessor = %d\n", mGlobalNvsArea.Area->DptfProcessor)); + DEBUG((EFI_D_INFO, "Dptf Ambient Temperature Constants values = %d \t %d \t %d \t %d \t %d \t %d\n", mGlobalNvsArea.Area->AmbientConstants[0], \ + mGlobalNvsArea.Area->AmbientConstants[1], mGlobalNvsArea.Area->AmbientConstants[2], mGlobalNvsArea.Area->AmbientConstants[3], \ + mGlobalNvsArea.Area->AmbientConstants[4], mGlobalNvsArea.Area->AmbientConstants[5] )); + + // + // + // Platform Flavor + // + mGlobalNvsArea.Area->PlatformFlavor = mPlatformInfo->PlatformFlavor; + + // + // Update the Platform ID + // + mGlobalNvsArea.Area->BoardID = mPlatformInfo->BoardId; + + // + // Update the Board Revision + // + mGlobalNvsArea.Area->FabID = (UINT8)(mPlatformInfo->FABID + 1); + + mGlobalNvsArea.Area->ECSupport = mPlatformInfo->ECSupport; + mGlobalNvsArea.Area->FanSupport = mPlatformInfo->FanSupport; + mGlobalNvsArea.Area->BatterySupport = mPlatformInfo->BatterySupport; + + mGlobalNvsArea.Area->PmicType = mPlatformInfo->PmicId; + + DEBUG((EFI_D_INFO, "GlobalNvs BoardId = %d\n", mGlobalNvsArea.Area->BoardID)); + DEBUG((EFI_D_INFO, "GlobalNvs PmicType = %d\n", mGlobalNvsArea.Area->PmicType)); + + mGlobalNvsArea.Area->OtgMode = mSystemConfiguration.PchUsbOtg; + mGlobalNvsArea.Area->XhciMode = mSystemConfiguration.PchUsb30Mode; + + mGlobalNvsArea.Area->PmicEnable = GLOBAL_NVS_DEVICE_DISABLE; + + mGlobalNvsArea.Area->ISPDevSel = mSystemConfiguration.ISPDevSel; + + mGlobalNvsArea.Area->ISPEn = mSystemConfiguration.ISPEn; + mGlobalNvsArea.Area->GpioAcpiEnabled = mSystemConfiguration.GpioAcpiEnabled; + mGlobalNvsArea.Area->Sdcard1p8vSwitchingDelay = mSystemConfiguration.Sdcard1p8vSwitchingDelay; + mGlobalNvsArea.Area->Sdcard3p3vDischargeDelay = mSystemConfiguration.Sdcard3p3vDischargeDelay; + + // + // BSW Virtual Button Support + // + if (mSystemConfiguration.VirtualButtonEnable == 0) { + mGlobalNvsArea.Area->VirtualButtonSupport = 0x00; + } else if (mSystemConfiguration.VirtualButtonEnable == 1) { + mGlobalNvsArea.Area->VirtualButtonSupport = 0x01; + + if (mSystemConfiguration.ConvertibleState == 1) { + mGlobalNvsArea.Area->VirtualButtonSupport = mGlobalNvsArea.Area->VirtualButtonSupport | 0x08; + } + + if (mSystemConfiguration.DockIndicator == 1) { + mGlobalNvsArea.Area->VirtualButtonSupport = mGlobalNvsArea.Area->VirtualButtonSupport | 0x10; + } + } + + // + // LPE Audio Device Selection & NFC connection + // + mGlobalNvsArea.Area->PchLpeEnabled = mSystemConfiguration.PchLpeEnabled; + mGlobalNvsArea.Area->NfcConnection = PcdGet8(PcdNfcConnection); // NFC1 to I2C7 + + // + // BT Module Selection - BRCM(Default), 1 - STP(Stone Peak) + // + mGlobalNvsArea.Area->BTModuleSelect = mSystemConfiguration.BTModule; + + // + // WIFI Device Selection + // + mGlobalNvsArea.Area->WIFIModuleSelect = mSystemConfiguration.WIFIModule; + mGlobalNvsArea.Area->NativePCIESupport = mSystemConfiguration.PciExpNative; + + // + // Modem selection + // + mGlobalNvsArea.Area->AcpiModemSel = mSystemConfiguration.AcpiModemSel; + + // + // Camera selection + // + mGlobalNvsArea.Area->RvpCameraDevSel = mSystemConfiguration.RvpCameraDevSel; + mGlobalNvsArea.Area->EbCameraDevSel = mSystemConfiguration.EbCameraDevSel; + SettingI2CTouchAddress(); + mGlobalNvsArea.Area->S0ix= mSystemConfiguration.S0ix; + + // + // Read BMBOUND and store it in GlobalNVS to pass into ASL + // + mGlobalNvsArea.Area->BmBound = PcdGet32 (PcdMmioBase); + + if (mSystemConfiguration.ScceMMCEnabled != 0) { + DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->emmcVersion = 1\n")); + mGlobalNvsArea.Area->emmcVersion = 1; + } + mGlobalNvsArea.Area->ToggleSelfClkDisabling = mSystemConfiguration.ToggleSelfClkDisabling; + + // + // Support EllensBurg + // + mGlobalNvsArea.Area->Ellensburg = mSystemConfiguration.Ellensburg; + DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->Ellensburg = %d\n", mGlobalNvsArea.Area->Ellensburg)); + + #if (_PSSD_FIX_==1) + mGlobalNvsArea.Area->PssdFix = 1; + #else + mGlobalNvsArea.Area->PssdFix = 0; + #endif + + mGlobalNvsArea.Area->DisableBattery = 0; + + // + // SIO related option + // + Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, &mCpuIo); + ASSERT_EFI_ERROR (Status); + + mGlobalNvsArea.Area->WPCN381U = GLOBAL_NVS_DEVICE_DISABLE; + + mGlobalNvsArea.Area->DockedSioPresent = GLOBAL_NVS_DEVICE_DISABLE; + + if (mGlobalNvsArea.Area->DockedSioPresent != GLOBAL_NVS_DEVICE_ENABLE) { + // + // Check ID for SIO WPCN381U + // + Status = mCpuIo->Io.Read ( + mCpuIo, + EfiCpuIoWidthUint8, + WPCN381U_CONFIG_INDEX, + 1, + &PortData + ); + ASSERT_EFI_ERROR (Status); + if (PortData != 0xFF) { + PortData = 0x20; + Status = mCpuIo->Io.Write ( + mCpuIo, + EfiCpuIoWidthUint8, + WPCN381U_CONFIG_INDEX, + 1, + &PortData + ); + ASSERT_EFI_ERROR (Status); + Status = mCpuIo->Io.Read ( + mCpuIo, + EfiCpuIoWidthUint8, + WPCN381U_CONFIG_DATA, + 1, + &PortData + ); + ASSERT_EFI_ERROR (Status); + if ((PortData == WPCN381U_CHIP_ID) || (PortData == WDCP376_CHIP_ID)) { + mGlobalNvsArea.Area->WPCN381U = GLOBAL_NVS_DEVICE_ENABLE; + mGlobalNvsArea.Area->OnboardCom = GLOBAL_NVS_DEVICE_ENABLE; + mGlobalNvsArea.Area->OnboardComCir = GLOBAL_NVS_DEVICE_DISABLE; + } + } + } + + mGlobalNvsArea.Area->SDIOMode = mSystemConfiguration.LpssSdioMode; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiGlobalNvsAreaProtocolGuid, + &mGlobalNvsArea, + NULL + ); + + // + // Read tables from the storage file. + // + while (!EFI_ERROR (Status)) { + CurrentTable = NULL; + + Status = FwVol->ReadSection ( + FwVol, + &gEfiAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + &CurrentTable, + (UINTN *) &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + // + // Perform any table specific updates. + // + AcpiStatus = PlatformUpdateTables (CurrentTable); + if (!EFI_ERROR (AcpiStatus)) { + // + // Install the table + // + TableHandle = 0; + AcpiStatus = AcpiTable->InstallAcpiTable (AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle); + ASSERT_EFI_ERROR (AcpiStatus); + } + // + // Increment the instance + // + Instance++; + } + } + + // + //Audio Codec Support for EB and RVP + // + mGlobalNvsArea.Area->AudioCodecSuppport = mSystemConfiguration.AudioCodecSuppport; + DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->AudioCodecSuppport = %d\n", mGlobalNvsArea.Area->AudioCodecSuppport)); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + EnableAcpiCallback, + NULL, + &gEfiEventExitBootServicesGuid, + &EfiExitBootServicesEvent + ); + + // + // Finished + // + + return EFI_SUCCESS; +} + +VOID +SettingI2CTouchAddress ( + IN VOID + ) +{ + if (mSystemConfiguration.I2CTouchAd == 0) { // if setup menu select auto set I2C Touch Address base on board id + } else { + mGlobalNvsArea.Area->I2CTouchAddress = mSystemConfiguration.I2CTouchAd; + } + DEBUG((EFI_D_ERROR, "GlobalNvsArea.Area->I2CTouchAddress: [%02x]\n", mGlobalNvsArea.Area->I2CTouchAddress)); +} + +/** + Event Notification during exit boot service to enabel ACPI mode + + @param[in] Event EFI Event Handle + @param[in] Context Pointer to Notify Context + + @return + +**/ +VOID +EnableAcpiCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 RegData32; + UINT16 Pm1Cnt; + UINT16 AcpiBase; + UINT32 Gpe0aEn; + EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr; + EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol; + EFI_STATUS Status; + + GlobalNvsAreaProtocol = NULL; + + Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid, NULL, &GlobalNvsAreaProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to locate GlobalNvsAreaProtocol\n")); + return; + } + + mGlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area; + + AcpiBase = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ) + ) & B_PCH_LPC_ACPI_BASE_BAR; + + DEBUG ((EFI_D_INFO, "EnableAcpiCallback: AcpiBase = %x\n", AcpiBase)); + + // + // Disable PM sources except power button + // power button is enabled only for PCAT. Disabled it on Tablet platform + // + IoWrite16 (AcpiBase + R_PCH_ACPI_PM1_EN, B_PCH_ACPI_PM1_EN_PWRBTN); + IoWrite16 (AcpiBase + R_PCH_ACPI_PM1_STS, 0xffff); + + // + // Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm") + // Clear Status D reg VM bit, Date of month Alarm to make Data in CMOS RAM is no longer Valid + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D); + IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0); + + { + SendKscCommand (KSC_C_SMI_NOTIFY_DISABLE); + + RegData32 = IoRead32(AcpiBase + R_PCH_ALT_GP_SMI_EN); + RegData32 &= ~(BIT7); + IoWrite32 ((AcpiBase + R_PCH_ALT_GP_SMI_EN), RegData32); + + // + // Disable APM/SMI mode + // + SendKscCommand (KSC_C_SMI_DISABLE); + + // + // Disable ACPI/SCI mode + // + SendKscCommand (KSC_C_ACPI_ENABLE); + } + + // + // Enable SCI + // + Pm1Cnt = IoRead16(AcpiBase + R_PCH_ACPI_PM1_CNT); + Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SCI_EN; + IoWrite16 (AcpiBase + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + + IoWrite8 (0x80, 0xA0); //SW_SMI_ACPI_ENABLE + + // + // Enable PME_B0_EN in GPE0a_EN + // Caution: Enable PME_B0_EN must be placed after enabling SCI. + // Otherwise, USB PME could not be handled as SMI event since no handler is there. + // + if (mGlobalNvsAreaPtr->OSImageId == 1) { + Gpe0aEn = IoRead32 (AcpiBase + R_PCH_ACPI_GPE0a_EN); + Gpe0aEn |= B_PCH_ACPI_GPE0a_EN_PME_B0; + IoWrite32 (AcpiBase + R_PCH_ACPI_GPE0a_EN, Gpe0aEn); + } +} diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.h b/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.h new file mode 100644 index 0000000000..14a31c30e5 --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.h @@ -0,0 +1,302 @@ +/** @file + Implementation of the ACPI platform driver.Requirements for + this driver are defined in the Tiano ACPI External Product Specification, + revision 0.3.6. + + Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ACPI_PLATFORM_H_ +#define _ACPI_PLATFORM_H_ + +// +// Statements that include other header files. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Global variables +// +EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea; + +// +// ACPI table information used to initialize tables. +// +// SLP 2.0 equates +#define SLP20_MAGIC_NUMBER 0x00000001 +#define SLP20_VERIFIED_INDICATOR 0x91827364 +#define EFI_ACPI_OEM_REVISION 0x00000003 +#define EFI_ACPI_CREATOR_ID SIGNATURE_32 ('C', 'H', 'V', ' ') +#define EFI_ACPI_CREATOR_REVISION 0x0100000D + +#define WPCN381U_CONFIG_INDEX 0x2E +#define WPCN381U_CONFIG_DATA 0x2F +#define WPCN381U_CHIP_ID 0xF4 +#define WDCP376_CHIP_ID 0xF1 + +#define MOBILE_PLATFORM 1 +#define DESKTOP_PLATFORM 2 + +#define PCAT_RTC_ADDRESS_REGISTER 0x74 +#define PCAT_RTC_DATA_REGISTER 0x75 +#define RTC_ADDRESS_REGISTER_D 0x0D + +// +// Define macros to build data structure signatures from characters. +// +#ifndef EFI_SIGNATURE_16 +#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8)) +#endif +#ifndef EFI_SIGNATURE_32 +#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16)) +#endif +#ifndef EFI_SIGNATURE_64 +#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32)) +#endif +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++ +// ESS - GV3 Definitions +// +++++++++++++++++++++++++++++++++++++++++++++++++++ +// +#pragma pack(1) + +typedef struct { + UINT32 PlatformId; + UINT8 IoApicEnable; + UINT8 NMEN; // Node Manager Enable (aka NPTM) + UINT8 TpmEnable :1; + UINT8 CStateEnable :1; + UINT8 OSC2Report :1; + UINT8 C6Enable :1; + UINT8 C7Enable :1; + UINT8 MonitorMwaitEnable :1; + UINT8 PStateEnable :1; + UINT8 Rsvd :1; + UINT8 PSDT :2; // P-State Dependency Type + UINT8 StandbyToS1 :1; + UINT8 KBPresent :1; + UINT8 MousePresent :1; + UINT8 DualIohPresent :1; + UINT8 DummyBits :2; + UINT32 CpuIdInfo; // Used in PciCrs.asl to determine Havendale/Lynnfield Processor + UINT32 Tolm; // Used in PciCrs.asl + UINT16 OsSelect; // O/S Type. This is for ASL only. + UINT32 IgdOpRegionAddress; // IGD OpRegion Starting Address + UINT8 IgdBootType; // IGD Boot Display Device + UINT8 IgdPanelType; // IGD Panel Type CMOs option + UINT8 IgdTvFormat; // IGD TV Format CMOS option + UINT8 IgdTvMinor; // IGD TV Minor Format CMOS option + UINT8 IgdPanelScaling; // IGD Panel Scaling + UINT8 IgdBlcConfig; // IGD BLC Configuration + UINT8 IgdBiaConfig; // IGD BIA Configuration + UINT8 IgdSscConfig; // IGD SSC Configuration + UINT8 IgdDvmtMemSize; // IGD DVMT Memory Size + UINT8 IgdFunc1Enable; // IGD Function 1 Enable + UINT8 IgdHpllVco; // HPLL VCO + UINT8 IgdSciSmiMode; // GMCH SMI/SCI mode (0=SCI) + UINT8 IgdPAVP; // IGD PAVP data +} BIOS_ACPI_PARAM; + +typedef struct _AML_GV3_STATE_PACKAGE { + UINT8 PkgOp; // 0x12 + UINT8 PkgLeadByte; + UINT8 NoData; + UINT8 DWPrefix0; + UINT32 CoreFreq; + UINT8 DWPrefix1; + UINT32 PowerConsumption; + UINT8 DWPrefix2; + UINT32 TransactionLatency; + UINT8 DWPrefix3; + UINT32 BusMasterLatency; + UINT8 DWPrefix4; + UINT32 ControlValue; + UINT8 DWPrefix5; + UINT32 StatusValue; +} AML_GV3_STATE_PACKAGE; + +typedef struct _AML_PSS_PACKAGE { + UINT8 NameOp; // 0x08 + UINT8 Sign[4]; + UINT8 PkgOp; // 0x12 + UINT8 Res1[2]; + UINT8 NoOfGV3Packages; + AML_GV3_STATE_PACKAGE Pstates[16]; +} AML_PSS_PACKAGE; + +typedef struct _SMM_APICID_MAP { + UINT32 ApicID; + UINT16 PhysicalCpuNumber; + UINT16 CpuNumber; + UINT16 Version; +} SMM_APICID_MAP; + +typedef struct _SMM_GV3_FVID { + UINT16 VidValue : 8; + UINT16 FreqRatio : 8; + UINT16 SystemBusFreq : 16; +} SMM_GV3_FVID; + +#pragma pack() + +// +// Private Driver Data. +// +// +// Define Union of IO APIC & Local APIC structure. +// +typedef union { + EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic; + EFI_ACPI_2_0_IO_APIC_STRUCTURE AcpiIoApic; + struct { + UINT8 Type; + UINT8 Length; + } AcpiApicCommon; +} ACPI_APIC_STRUCTURE_PTR; + +// +// Protocol private structure definition. +// + +/** + Entry point of the ACPI platform driver. + + @param[in] ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver. + @param[in] SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table. + + @retval EFI_SUCCESS Driver initialized successfully. + @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +InstallAcpiPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Get Acpi Table Version. + + @param[in] ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver. + @param[in] SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table. + + @retval EFI_SUCCESS: Driver initialized successfully. + @retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES: Could not allocate needed resources. + +**/ +EFI_ACPI_TABLE_VERSION +GetAcpiTableVersion ( + VOID + ); + +/** + The funtion returns Oem specific information of Acpi Platform. + + @param[in] OemId OemId returned. + @param[in] OemTableId OemTableId returned. + @param[in] OemRevision OemRevision returned. + + @retval EFI_STATUS Status of function execution. + +**/ +EFI_STATUS +AcpiPlatformGetOemFields ( + OUT UINT8 *OemId, + OUT UINT64 *OemTableId, + OUT UINT32 *OemRevision + ); + +/** + The function returns Acpi table version. + + @param[in] + + @retval EFI_ACPI_TABLE_VERSION Acpi table version encoded as a UINT32. + +**/ +EFI_ACPI_TABLE_VERSION +AcpiPlatformGetAcpiSetting ( + VOID + ); + +/** + Entry point for Acpi platform driver. + + @param[in] ImageHandle A handle for the image that is initializing this driver. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS Driver initialized successfully. + @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +SelectNFCDevice ( + IN VOID + ); + +VOID +SettingI2CTouchAddress ( + IN VOID + ); + +/** + Event Notification during exit boot service to enabel ACPI mode + + @param[in] Event EFI Event Handle + @param[in] Context Pointer to Notify Context + + @return + +**/ +VOID +EnableAcpiCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.inf b/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.inf new file mode 100644 index 0000000000..ef89d2b55b --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiPlatform/AcpiPlatform.inf @@ -0,0 +1,103 @@ +## @file +# ACPI Platform Support Module +# +# Provides the ability for the platform to update the ACPI tables based on the +# platforms configuration at boot. +# +# Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiPlatform + FILE_GUID = 14CD4276-38F3-4F25-B9A3-BDA1288A1A52 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AcpiPlatformEntryPoint + +[Sources] + AcpiPlatform.c + +[Packages] + BraswellPlatformPkg/BraswellPlatformPkg.dec + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + MdeModulePkg/MdeModulePkg.dec + ChvRefCodePkg/ChvRefCodePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + HobLib + IoLib + PchPlatformLib + BaseLib + PciLib + MemoryAllocationLib + DxeKscLib + +[Guids] + ## CONSUMES ## File + gEfiAcpiTableStorageGuid + + ## CONSUMES ## Event + gEfiEventExitBootServicesGuid + +[Protocols] + ## CONSUMES + gEfiAcpiTableProtocolGuid + + ## SOMETIMES_CONSUMES + gEfiPlatformCpuProtocolGuid + + ## CONSUMES + gEfiAcpiS3SaveProtocolGuid + + ## CONSUMES + gEfiCpuIo2ProtocolGuid + + ## CONSUMES + gEfiFirmwareVolume2ProtocolGuid + + ## CONSUMES + gEfiMpServiceProtocolGuid + + ## PRODUCES + gEfiGlobalNvsAreaProtocolGuid + +[Pcd] + ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gEfiEdkIIPlatformTokenSpaceGuid.PcdPlatformInfo + + ## SOMETIMES_CONSUMES + gEfiCHVTokenSpaceGuid.PcdIsVlv2 + gEfiEdkIIPlatformTokenSpaceGuid.PcdNfcConnection + + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId + + ## SOMETIMES_CONSUMES + gIntelSiBasicPkgTokenSpaceGuid.PcdMmioBase + + gEfiEdkIIPlatformTokenSpaceGuid.PcdSystemConfiguration + +[Depex] + gEfiAcpiTableProtocolGuid AND + gEfiMpServiceProtocolGuid AND + gEfiCpuIo2ProtocolGuid + diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.h b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.h new file mode 100644 index 0000000000..256b8d844a --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.h @@ -0,0 +1,243 @@ +/** @file + SMM handler driver implementation. + + Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PLATFORM_H +#define _PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Protocol/GlobalNvsArea.h" +#include +#include +#include +#include +#include "PchAccess.h" +#include "PlatformBaseAddresses.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 ExtendedRegister; +} SMM_PCI_IO_ADDRESS; + +typedef struct { + CHAR8 BoardAaNumber[7]; + UINTN BoardFabNumber; +} BOARD_AA_NUMBER_DECODE; + +// +// BugBug -- Need to get these two values from acpi.h, but right now, they are +// declared in platform-specific variants of this file, so no easy +// way to pick-up the include file and work across platforms. +// Need these definitions to go into a file like common\acpi.h. +// +#define ACPI_ENABLE 0xA0 +#define ACPI_DISABLE 0xA1 + +#define APM_12_FUNCS 0x50 +#define SMI_SET_SMMVARIABLE_PROTOCOL 0x51 // this is used in Cpu\Pentium\Smm\Base\SmmBase.c + +#define SMI_CMD_GET_MSEG_STATUS 0x70 +#define SMI_CMD_UPDATE_MSEG_SIZE 0x71 +#define SMI_CMD_LOAD_STM 0x72 +#define SMI_CMD_UNLOAD_STM 0x73 +#define SMI_CMD_GET_SMRAM_RANGES 0x74 + +#define PCAT_RTC_ADDRESS_REGISTER 0x74 +#define PCAT_RTC_DATA_REGISTER 0x75 + +#define RTC_ADDRESS_SECOND 0x00 +#define RTC_ADDRESS_SECOND_ALARM 0x01 +#define RTC_ADDRESS_MINUTE 0x02 +#define RTC_ADDRESS_MINUTE_ALARM 0x03 +#define RTC_ADDRESS_HOUR 0x04 +#define RTC_ADDRESS_HOUR_ALARM 0x05 + +#define RTC_ADDRESS_REGISTER_A 0x0A +#define RTC_ADDRESS_REGISTER_B 0x0B +#define RTC_ADDRESS_REGISTER_C 0x0C +#define RTC_ADDRESS_REGISTER_D 0x0D + +#define B_RTC_ALARM_INT_ENABLE 0x20 +#define B_RTC_ALARM_INT_STATUS 0x20 + +#define B_RTC_DATE_ALARM_MASK 0x3F + +#define PCAT_CMOS_2_ADDRESS_REGISTER 0x72 +#define PCAT_CMOS_2_DATA_REGISTER 0x73 + +#define EC_C_PORT 0x66 +#define SMC_SMI_DISABLE 0xBC +#define SMC_ENABLE_ACPI_MODE 0xAA // Enable ACPI mode + +#define IO_MISC 156 + +#define MAXIMUM_NUMBER_OF_PSTATES 12 +#define ICH_SMM_DATA_PORT 0xB3 + +#define EFI_IA32_PMG_CST_CONFIG 0x000000E2 +#define B_EFI_CST_CONTROL_LOCK BIT15 +#define B_EFI_IO_MWAIT_REDIRECTION_ENABLE BIT10 +#define EFI_IA32_PMG_IO_CAPTURE_ADDR 0x000000E4 + +extern EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo; + +// +// Callback function prototypes +// +EFI_STATUS +EFIAPI +PowerButtonCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +S5SleepWakeOnLanCallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +S5SleepAcLossCallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +S4S5CallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +EnableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +DisableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +DummyTco1Callback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +VOID +PerrSerrCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +VOID +RiCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +VOID +SetAfterG3On ( + BOOLEAN Enable + ); + +VOID +TurnOffVregUsb ( + ); + +EFI_STATUS +PStateSupportCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +PStateTransitionCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +SxSleepEntryCallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ); + +EFI_STATUS +SaveRuntimeScriptTable ( + VOID + ); + +#endif + diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.inf b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.inf new file mode 100644 index 0000000000..6f9950266d --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/AcpiSmm.inf @@ -0,0 +1,103 @@ +## @file +# Component description file for SMM Platform handler module +# +# Provides platform specific handlers for different SMI events. The module will +# register handlers for sleep state transitions as well as other software SMI +# events. +# +# Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformSmm + FILE_GUID = 88802B98-ADFE-4414-A695-FB35CA8D11F2 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePlatformSmm + PI_SPECIFICATION_VERSION = 0x0001000A + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + S3Save.c + Platform.c + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DebugLib + IoLib + BaseLib + BaseMemoryLib + DevicePathLib + HobLib + S3BootScriptLib + StallSmmLib + PchPlatformLib + ReportStatusCodeLib + +[Guids] + + ## SOMETIMES_CONSUMES ## Variable:L"AcpiGlobalVariable" + gEfiAcpiVariableCompatiblityGuid + + ## SOMETIMES_CONSUMES + gEfiAcpiVariableGuid + +[Protocols] + ## CONSUMES + gEfiSmmIchnDispatchProtocolGuid + + ## CONSUMES + gEfiGlobalNvsAreaProtocolGuid + + ## CONSUMES + gEfiSmmSwDispatch2ProtocolGuid + + ## SOMETIMES_CONSUMES + gEfiSmmPowerButtonDispatch2ProtocolGuid + + ## CONSUMES + gEfiSmmSxDispatch2ProtocolGuid + + ## CONSUMES + gEfiSmmVariableProtocolGuid + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + ChvRefCodePkg/ChvRefCodePkg.dec + BraswellPlatformPkg/BraswellPlatformPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[Pcd] + ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES + gEfiEdkIIPlatformTokenSpaceGuid.PcdSystemConfiguration + +[Depex] + gEfiSmmBase2ProtocolGuid AND + gEfiSmmAccess2ProtocolGuid AND + gEfiSmmPowerButtonDispatch2ProtocolGuid AND + gEfiSmmSxDispatch2ProtocolGuid AND + gEfiSmmIchnDispatchProtocolGuid AND + gEfiSmmSwDispatch2ProtocolGuid AND + gEfiVariableArchProtocolGuid + diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiSmm/Platform.c b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/Platform.c new file mode 100644 index 0000000000..bf58f6ca41 --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/Platform.c @@ -0,0 +1,831 @@ +/** @file + Generic template for a child of the IchSmm driver. + + Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "AcpiSmm.h" +#include + +// +// Local variables +// +typedef struct { + UINT8 Device; + UINT8 Function; +} EFI_PCI_BUS_MASTER; + +EFI_PCI_BUS_MASTER mPciBm[] = { + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 }, +}; + +UINT16 mAcpiBaseAddr; +SYSTEM_CONFIGURATION mSystemConfiguration; +UINT16 mPM1_SaveState16; +UINT32 mGPE_SaveState32; + +// +// Variables. Need to initialize this from Setup +// +BOOLEAN mWakeOnLanS5Variable; +BOOLEAN mWakeOnRtcVariable; +UINT8 mWakeupDay; +UINT8 mWakeupHour; +UINT8 mWakeupMinute; +UINT8 mWakeupSecond; + +// +// Use an enum. 0 is Stay Off, 1 is Last State, 2 is Stay On +// +UINT8 mAcLossVariable; + +static +UINT8 mTco1Sources[] = { + IchnNmi +}; + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +VOID +S4S5ProgClock(); + +EFI_STATUS +InitRuntimeScriptTable ( + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +EnableS5WakeOnRtc(); + +UINT8 +HexToBcd ( + UINT8 HexValue + ); + +UINT8 +BcdToHex( + IN UINT8 BcdValue + ); + +VOID +CpuSmmSxWorkAround ( + ); + + +/*++ + Set the AC Loss to turn on or off. + + @param[in] Turn on or off. + + @retval None + +--*/ + +VOID +SetAfterG3On ( + BOOLEAN Enable + ) +{ + UINT8 PmCon1; + + // + // ICH handling portion + // + PmCon1 = MmioRead8 ( PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1 ); + PmCon1 &= ~B_PCH_PMC_GEN_PMCON_AFTERG3_EN; + if (Enable) { + PmCon1 |= B_PCH_PMC_GEN_PMCON_AFTERG3_EN; + } + MmioWrite8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, PmCon1); + +} + +/** + Allocate EfiACPIMemoryNVS below 4G memory address. + + This function allocates EfiACPIMemoryNVS below 4G memory address. + + @param Size Size of memory to allocate. + + @return Allocated address for output. + +**/ +VOID* +AllocateAcpiNvsMemoryBelow4G ( + IN UINTN Size + ) +{ + UINTN Pages; + EFI_PHYSICAL_ADDRESS Address; + EFI_STATUS Status; + VOID* Buffer; + + Pages = EFI_SIZE_TO_PAGES (Size); + Address = 0xffffffff; + + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + Pages, + &Address + ); + ASSERT_EFI_ERROR (Status); + + Buffer = (VOID *) (UINTN) Address; + ZeroMem (Buffer, Size); + + return Buffer; +} + +EFI_STATUS +EFIAPI +AllocateS3AcpiReservedMemory ( + VOID +) +{ + EFI_PEI_HOB_POINTERS Hob; + UINT64 MemoryLength; + RESERVED_ACPI_S3_RANGE *AcpiS3Range; + EFI_SMRAM_DESCRIPTOR *SmramDescriptor; + VOID *GuidHob; + VOID *AcpiReservedBase; + + // + // Calculate the system memory length by memory hobs + // + MemoryLength = 0x100000; + + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); + if (Hob.Raw == NULL) { + return EFI_NOT_FOUND; + } + + while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) { + if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + // + // Skip the memory region below 1MB + // + if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) { + MemoryLength += Hob.ResourceDescriptor->ResourceLength; + } + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); + } + + // + // Find the location of reserved page in TSEG. This was reserved by the MRC. + // + GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid); + if (GuidHob != NULL) { + SmramDescriptor = (EFI_SMRAM_DESCRIPTOR*) GET_GUID_HOB_DATA (GuidHob); + + // + // Now find the location of the data structure that is used to store the address + // of the S3 reserved memory. + // + AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (SmramDescriptor->PhysicalStart + + RESERVED_ACPI_S3_RANGE_OFFSET); + + // + // Allocate reserved ACPI memory for S3 resume. Pointer to this region is + // stored in SMRAM in the first page of TSEG. + // + AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G ( + PcdGet32 (PcdS3AcpiReservedMemorySize) + ); + if (AcpiReservedBase != NULL) { + AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase; + AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize); + } + + AcpiS3Range->SystemMemoryLength = (UINT32)MemoryLength; + + DEBUG ((EFI_D_ERROR, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase)); + DEBUG ((EFI_D_ERROR, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize)); + DEBUG ((EFI_D_ERROR, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength)); + } + + return EFI_SUCCESS; + +} + + +/** + Initializes the SMM Handler Driver + + @param[in] ImageHandle + @param[in] SystemTable + + @retval None + +**/ +EFI_STATUS +EFIAPI +InitializePlatformSmm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButtonContext; + EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL *PowerButtonDispatch; + EFI_SMM_ICHN_DISPATCH_PROTOCOL *IchnDispatch; + EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch; + EFI_SMM_SX_REGISTER_CONTEXT EntryDispatchContext; + EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch; + EFI_SMM_SW_REGISTER_CONTEXT SwContext; + EFI_BOOT_MODE BootMode; + + Handle = NULL; + + // + // Get the ACPI Base Address + // + + mAcpiBaseAddr = PchLpcPciCfg16( R_PCH_LPC_ACPI_BASE ) & B_PCH_LPC_ACPI_BASE_BAR; + + CopyMem (&mSystemConfiguration, PcdGetPtr (PcdSystemConfiguration), sizeof (SYSTEM_CONFIGURATION)); + mAcLossVariable = mSystemConfiguration.StateAfterG3; + mWakeOnRtcVariable = mSystemConfiguration.WakeOnRtcS5; + + BootMode = GetBootModeHob (); + + // + // Get the Power Button protocol + // + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmPowerButtonDispatch2ProtocolGuid, + NULL, + (VOID **) &PowerButtonDispatch + ); + ASSERT_EFI_ERROR (Status); + + if (BootMode != BOOT_ON_FLASH_UPDATE) { + // + // Register for the power button event + // + PowerButtonContext.Phase = EfiPowerButtonEntry; + Status = PowerButtonDispatch->Register ( + PowerButtonDispatch, + PowerButtonCallback, + &PowerButtonContext, + &Handle + ); + ASSERT_EFI_ERROR (Status); + } + // + // Get the Sx dispatch protocol + // + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmSxDispatch2ProtocolGuid, + NULL, + (VOID **) &SxDispatch + ); + ASSERT_EFI_ERROR (Status); + + // + // Register entry phase call back function + // + EntryDispatchContext.Type = SxS3; + EntryDispatchContext.Phase = SxEntry; + + Status = SxDispatch->Register ( + SxDispatch, + SxSleepEntryCallBack, + &EntryDispatchContext, + &Handle + ); + + EntryDispatchContext.Type = SxS4; + + Status = SxDispatch->Register ( + SxDispatch, + S4S5CallBack, + &EntryDispatchContext, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + EntryDispatchContext.Type = SxS5; + + Status = SxDispatch->Register ( + SxDispatch, + S4S5CallBack, + &EntryDispatchContext, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + Status = SxDispatch->Register ( + SxDispatch, + S5SleepAcLossCallBack, + &EntryDispatchContext, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + // + // Get the Sw dispatch protocol + // + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmSwDispatch2ProtocolGuid, + NULL, + (VOID **) &SwDispatch + ); + ASSERT_EFI_ERROR (Status); + + // + // Register ACPI enable handler + // + SwContext.SwSmiInputValue = ACPI_ENABLE; + Status = SwDispatch->Register ( + SwDispatch, + EnableAcpiCallback, + &SwContext, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + // + // Register ACPI disable handler + // + SwContext.SwSmiInputValue = ACPI_DISABLE; + Status = SwDispatch->Register ( + SwDispatch, + DisableAcpiCallback, + &SwContext, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + // + // Get the ICHn protocol + // + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmIchnDispatchProtocolGuid, + NULL, + (VOID **) &IchnDispatch + ); + ASSERT_EFI_ERROR (Status); + + SetAfterG3On (TRUE); + + AllocateS3AcpiReservedMemory (); + + return EFI_SUCCESS; +} + +/** + @param[in] DispatchHandle The handle of this callback, obtained when registering + @param[in] DispatchContext The predefined context which contained sleep type and phase + + @retval EFI_SUCCESS Operation successfully performed + +**/ +EFI_STATUS +SxSleepEntryCallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) + +{ +// +// EFI_STATUS Status; +// +// REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart)); +// Status = SaveRuntimeScriptTable (); +// if (EFI_ERROR (Status)) { +// return Status; +// } +// + return EFI_SUCCESS; +} + +/** + When a power button event happens, it shuts off the machine. + + @param[in] DispatchHandle The handle of this callback, obtained when registering + @param[in] DispatchContext The predefined context which contained sleep type and phase + + @retval + +**/ +EFI_STATUS +PowerButtonCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + + UINT16 data16; + + // + // Set what the state to return to after AC Loss. If Last State, then + // set it to Off. + // + SetAfterG3On (TRUE); + + if (mWakeOnRtcVariable) { + EnableS5WakeOnRtc(); + } + + data16 = (UINT16) (IoRead16 (mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN)); + data16 &= B_PCH_ACPI_GPE0a_EN_PCI_EXP; + + // + // Clear Sleep SMI Status + // + IoWrite16 (mAcpiBaseAddr + R_PCH_SMI_STS, + (UINT16) (IoRead16 (mAcpiBaseAddr + R_PCH_SMI_STS) | B_PCH_SMI_STS_ON_SLP_EN)); + // + // Clear Sleep Type Enable + // + IoWrite16 (mAcpiBaseAddr + R_PCH_SMI_EN, + (UINT16) (IoRead16 (mAcpiBaseAddr + R_PCH_SMI_EN) & (~B_PCH_SMI_EN_ON_SLP_EN))); + + // + // Clear Power Button Status + // + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PWRBTN); + + // + // Shut it off now! + // + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5); + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, B_PCH_ACPI_PM1_CNT_SLP_EN | V_PCH_ACPI_PM1_CNT_S5); + + // + // Should not return + // + return EFI_SUCCESS; +} + +/** + @param[in] DispatchHandle The handle of this callback, obtained when registering + @param[in] DispatchContext The predefined context which contained sleep type and phase + +**/ +EFI_STATUS +EFIAPI +S5SleepAcLossCallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + return EFI_SUCCESS; +} + +/** + @param[in] DispatchHandle The handle of this callback, obtained when registering + @param[in] DispatchContext The predefined context which contained sleep type and phase + + @retval Clears the Save State bit in the clock. + +**/ +EFI_STATUS +EFIAPI +S4S5CallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + return EFI_SUCCESS; +} + +VOID +S4S5ProgClock() +{ +} + +/** + SMI handler to enable ACPI mode + + Dispatched on reads from APM port with value 0xA0 + + Disables the SW SMI Timer. + ACPI events are disabled and ACPI event status is cleared. + SCI mode is then enabled. + + Disable SW SMI Timer + + Clear all ACPI event status and disable all ACPI events + Disable PM sources except power button + Clear status bits + + Disable GPE0 sources + Clear status bits + + Disable GPE1 sources + Clear status bits + + Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm") + + Enable SCI + + @param[in] DispatchHandle EFI Handle + @param[in] DispatchContext Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT + + @retval Nothing + +**/ +EFI_STATUS +EFIAPI +EnableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + UINT16 Pm1Cnt; + + // + // Enable SCI + // + Pm1Cnt = IoRead16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT); + Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SCI_EN; + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + + return EFI_SUCCESS; +} + +/** + SMI handler to disable ACPI mode + + Dispatched on reads from APM port with value 0xA1 + + ACPI events are disabled and ACPI event status is cleared. + SCI mode is then disabled. + Clear all ACPI event status and disable all ACPI events + Disable PM sources except power button + Clear status bits + Disable GPE0 sources + Clear status bits + Disable GPE1 sources + Clear status bits + Disable SCI + + @param[in] DispatchHandle EFI Handle + @param[in] DispatchContext Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT + + @retval Nothing + +**/ +EFI_STATUS +EFIAPI +DisableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + UINT16 Pm1Cnt; + + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, 0xffff); + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, mPM1_SaveState16); + + IoWrite32 (mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS, 0xffffffff); + IoWrite32 (mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN, mGPE_SaveState32); + + // + // Disable SCI + // + Pm1Cnt = IoRead16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT); + Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SCI_EN; + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + + return EFI_SUCCESS; +} + +/** + When an unknown event happen. + + @param[in] DispatchHandle The handle of this callback, obtained when registering + @param[in] DispatchContext The predefined context which contained sleep type and phase + + @retval None + +**/ +EFI_STATUS +EFIAPI +DummyTco1Callback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + return EFI_SUCCESS; +} + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!IsDevicePathEnd (DevicePath)) { + DevicePath = NextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL); +} + +/** + @param[in] DispatchHandle The handle of this callback, obtained when registering + @param[in] DispatchContext The predefined context which contained sleep type and phase + +**/ +EFI_STATUS +S5SleepWakeOnRtcCallBack ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *DispatchContext, + IN OUT VOID *CommBuffer OPTIONAL, + IN UINTN *CommBufferSize OPTIONAL + ) +{ + EnableS5WakeOnRtc(); + + return EFI_SUCCESS; +} + +/** + @retval 1. Check Alarm interrupt is not set. + 2. Clear Alarm interrupt. + 2. Set RTC wake up date and time. + 2. Enable RTC wake up alarm. + 3. Enable ICH PM1 EN Bit 10(RTC_EN) + +**/ +VOID +EnableS5WakeOnRtc() +{ + UINT8 CmosData; + UINTN i; + + if (!mSystemConfiguration.WakeOnRtcS5) { + return; + } + mWakeupDay = HexToBcd((UINT8) mSystemConfiguration.RTCWakeupDate); + mWakeupHour = HexToBcd((UINT8) mSystemConfiguration.RTCWakeupTimeHour); + mWakeupMinute = HexToBcd((UINT8) mSystemConfiguration.RTCWakeupTimeMinute); + mWakeupSecond = HexToBcd((UINT8) mSystemConfiguration.RTCWakeupTimeSecond); + + // + // Check RTC alarm interrupt is enabled. If enabled, someone already + // grabbed RTC alarm. Just return. + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B); + if (IoRead8 (PCAT_RTC_DATA_REGISTER) & B_RTC_ALARM_INT_ENABLE) { + return; + } + + // + // Set Date + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D); + CmosData = IoRead8 (PCAT_RTC_DATA_REGISTER); + CmosData &= ~(B_RTC_DATE_ALARM_MASK); + CmosData |= mWakeupDay; + for (i = 0; i < 0xffff; i++) { + IoWrite8 (PCAT_RTC_DATA_REGISTER, CmosData); + SmmStall (1); + if(((CmosData = IoRead8 (PCAT_RTC_DATA_REGISTER)) & B_RTC_DATE_ALARM_MASK) + == mWakeupDay) { + break; + } + } + + // + // Set Second + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECOND_ALARM); + for (i = 0; i < 0xffff; i++) { + IoWrite8 (PCAT_RTC_DATA_REGISTER, mWakeupSecond); + SmmStall (1); + if (IoRead8 (PCAT_RTC_DATA_REGISTER) == mWakeupSecond) { + break; + } + } + + // + // Set Minute + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTE_ALARM); + for (i = 0; i < 0xffff; i++) { + IoWrite8 (PCAT_RTC_DATA_REGISTER, mWakeupMinute); + SmmStall (1); + if (IoRead8 (PCAT_RTC_DATA_REGISTER) == mWakeupMinute) { + break; + } + } + + // + // Set Hour + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOUR_ALARM); + for (i = 0; i < 0xffff; i++) { + IoWrite8 (PCAT_RTC_DATA_REGISTER, mWakeupHour); + SmmStall (1); + if (IoRead8 (PCAT_RTC_DATA_REGISTER) == mWakeupHour) { + break; + } + } + + // + // Wait for UIP to arm RTC alarm + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A); + while (IoRead8 (PCAT_RTC_DATA_REGISTER) & 0x80); + + // + // Read RTC register 0C to clear pending RTC interrupts + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C); + IoRead8 (PCAT_RTC_DATA_REGISTER); + + // + // Enable RTC Alarm Interrupt + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B); + IoWrite8 (PCAT_RTC_DATA_REGISTER, IoRead8 (PCAT_RTC_DATA_REGISTER) | B_RTC_ALARM_INT_ENABLE); + + // + // Clear ICH RTC Status + // + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_RTC); + + // + // Enable ICH RTC event + // + IoWrite16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, + (UINT16) (IoRead16 (mAcpiBaseAddr + R_PCH_ACPI_PM1_EN) | B_PCH_ACPI_PM1_EN_RTC)); +} + +UINT8 +HexToBcd ( + IN UINT8 HexValue + ) +{ + UINTN HighByte; + UINTN LowByte; + + HighByte = (UINTN) HexValue / 10; + LowByte = (UINTN) HexValue % 10; + + return ((UINT8) (LowByte + (HighByte << 4))); +} + +UINT8 +BcdToHex ( + IN UINT8 BcdValue + ) +{ + UINTN HighByte; + UINTN LowByte; + + HighByte = (UINTN) ((BcdValue >> 4) * 10); + LowByte = (UINTN) (BcdValue & 0x0F); + + return ((UINT8) (LowByte + HighByte)); +} + diff --git a/BraswellPlatformPkg/Common/Acpi/AcpiSmm/S3Save.c b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/S3Save.c new file mode 100644 index 0000000000..690cb12b88 --- /dev/null +++ b/BraswellPlatformPkg/Common/Acpi/AcpiSmm/S3Save.c @@ -0,0 +1,402 @@ +/** @file + SMM S3 handler driver implementation. + + Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "AcpiSmm.h" + +extern UINT16 mAcpiBaseAddr; +EFI_PHYSICAL_ADDRESS mRuntimeScriptTableBase; + +EFI_STATUS +SaveRuntimeScriptTable ( + VOID + ) +{ + SMM_PCI_IO_ADDRESS PciAddress; + UINT32 Data32; + UINT16 Data16; + UINT8 Data8; + UINT8 Mask; + UINTN Index; + UINTN Offset; + UINT8 RegTable[] = { + + //Bus , Dev, Func, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + + //Bus , Dev, Func, CUnit Device + 0x00 , 0x00, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x00 , 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0xa0, + + //Bus , Dev, Func, IGD Device + 0x00 , 0x02, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x81, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, + + //Bus , Dev, Func, IUnit Device + 0x00 , 0x03, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, ISH Device + 0x00 , 0x0A, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, PUnit Device + 0x00 , 0x0B, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, eMMC Device + 0x00 , 0x10, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, SDIO Device + 0x00 , 0x11, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, SDCard Device + 0x00 , 0x12, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, SATA Device + 0x00 , 0x13, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0xA3, 0x27, 0x30, 0xF1, 0x1D, 0x00, 0x40, + + // + //Bus , Dev, Func, xHCI Device + 0x00 , 0x14, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + + //Bus , Dev, Func, LPE Device + 0x00 , 0x15, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, USB OTG Device + 0x00 , 0x16, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 DMA Device + 0x00 , 0x18, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C0 Device + 0x00 , 0x18, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C1 Device + 0x00 , 0x18, 0x02, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C2 Device + 0x00 , 0x18, 0x03, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C3 Device + 0x00 , 0x18, 0x04, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C4 Device + 0x00 , 0x18, 0x05, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C5 Device + 0x00 , 0x18, 0x06, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO2 I2C6 Device + 0x00 , 0x18, 0x07, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, SEC Device + 0x00 , 0x1A, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + + //Bus , Dev, Func, HD Audio Device + 0x00 , 0x1B, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + // + //Bus , Dev, Func, SMBUS device + // + //Bus , Dev, Func, PCIe Root Port #1 + 0x00 , 0x1C, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, PCIe Root Port #2 + 0x00 , 0x1C, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, PCIe Root Port #3 + 0x00 , 0x1C, 0x02, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, PCIe Root Port #4 + 0x00 , 0x1C, 0x03, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xC2 , 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, VGA bus1 + // + //Bus , Dev, Func, LPIO1 DMA Device + 0x00 , 0x1E, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 PWM0 Device + 0x00 , 0x1E, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 PWM1 Device + 0x00 , 0x1E, 0x02, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 HSUART0 Device + 0x00 , 0x1E, 0x03, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 HSUART1 Device + 0x00 , 0x1E, 0x04, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 SPI Device + 0x00 , 0x1E, 0x05, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 SPI2 Device + 0x00 , 0x1E, 0x06, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, LPIO1 SPI3 Device + 0x00 , 0x1E, 0x07, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xF2 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, PCU Device + 0x00 , 0x1F, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x00 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, SMBUS Device + 0x00 , 0x1F, 0x03, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x32 , 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, Bus 1 Function 0 + 0x01 , 0x00, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0x58 , 0x93, 0x18, 0x01, 0xb0, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 1 Function 1 + 0x01 , 0x00, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 2 Function 0 + 0x02 , 0x00, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 2 Function 1 + 0x02 , 0x00, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 3 Function 0 + 0x03 , 0x00, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 3 Function 1 + 0x03 , 0x00, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 4 Function 0 + 0x04 , 0x00, 0x00, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + //Bus , Dev, Func, Bus 4 Function 1 + 0x04 , 0x00, 0x01, + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + 0xFA , 0x93, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + // + //0xFF indicates the end of the table + // + 0xFF + }; + + // + // These registers have to set in byte order + // + UINT8 ExtReg[] = { 0x9E, 0x9D }; // SMRAM settings + + // + // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM + // and vital to S3 resume. That's why we put save code here + // + PciAddress.Bus = 0; + PciAddress.Device = 0; + PciAddress.Function = 0; + PciAddress.ExtendedRegister = 0; + + for (Index = 0; Index < 2; Index++) { + // + // Read SRAM setting from Pci(0, 0, 0) + // + PciAddress.Register = ExtReg[Index]; + Data8 = MmioRead8 ( + MmPciAddress (0, + PciAddress.Bus, + PciAddress.Device, + PciAddress.Function, + PciAddress.Register + ) + ); + + // + // Save latest settings to runtime script table + // + S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint8, + *(UINT64 *) &PciAddress, + 1, + &Data8 + ); + } + + // + // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM + // and vital to S3 resume. That's why we put save code here + // + Index = 0; + while (RegTable[Index] != 0xFF) { + + PciAddress.Bus = RegTable[Index++]; + PciAddress.Device = RegTable[Index++]; + PciAddress.Function = RegTable[Index++]; + PciAddress.Register = 0; + PciAddress.ExtendedRegister = 0; + + Data16 = MmioRead16 ( + MmPciAddress (0, + PciAddress.Bus, + PciAddress.Device, + PciAddress.Function, + PciAddress.Register + ) + ); + + if (Data16 == 0xFFFF) { + Index+=8; + continue; + } + + for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) { + + if (Mask == 0x00) { + Mask = 0x01; + } + + if (RegTable[Index + Offset/32] & Mask ) { + + PciAddress.Register = (UINT8) Offset; + Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)); + + // + // Save latest settings to runtime script table + // + S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint32, + *(UINT64 *) &PciAddress, + 1, + &Data32 + ); + } + } + + Index += 8; + + } + + // + // Save I/O ports to S3 script table + // + + // + // Selftest KBC + // + Data8 = 0xAA; + S3BootScriptSaveIoWrite ( + S3BootScriptWidthUint8, + 0x64, + (UINTN)1, + &Data8 + ); + + Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN); + + S3BootScriptSaveIoWrite ( + S3BootScriptWidthUint32, + (mAcpiBaseAddr + R_PCH_SMI_EN), + 1, + &Data32 + ); + + // + // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path. + // + Data16 = IoRead16 (mAcpiBaseAddr + R_PCH_TCO_CNT); + + S3BootScriptSaveIoWrite ( + S3BootScriptWidthUint16, + mAcpiBaseAddr + R_PCH_TCO_CNT, + 1, + &Data16 + ); + + return EFI_SUCCESS; +} -- cgit v1.2.3