diff options
Diffstat (limited to 'Board/EM/RapidStartWrapper/Library/RapidStartPlatformLib/Pei/RapidStartPeiLib.c')
-rw-r--r-- | Board/EM/RapidStartWrapper/Library/RapidStartPlatformLib/Pei/RapidStartPeiLib.c | 970 |
1 files changed, 970 insertions, 0 deletions
diff --git a/Board/EM/RapidStartWrapper/Library/RapidStartPlatformLib/Pei/RapidStartPeiLib.c b/Board/EM/RapidStartWrapper/Library/RapidStartPlatformLib/Pei/RapidStartPeiLib.c new file mode 100644 index 0000000..61d7f52 --- /dev/null +++ b/Board/EM/RapidStartWrapper/Library/RapidStartPlatformLib/Pei/RapidStartPeiLib.c @@ -0,0 +1,970 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/Intel Fast Flash Standby/iRST_SharkBay/RapidStartWrapper/RapidStartPeiLib/RapidStartPeiLib.c 5 7/15/13 6:32a Joshchou $ +// +// $Revision: 5 $ +// +// $Date: 7/15/13 6:32a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/Intel Fast Flash Standby/iRST_SharkBay/RapidStartWrapper/RapidStartPeiLib/RapidStartPeiLib.c $ +// +// 5 7/15/13 6:32a Joshchou +// [TAG] EIP129090 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Platform automatically wakes itself after entering S4 when +// doing Rapid Start flow +// [RootCause] The Update of PCH RC 1.6.0 in PchSmmSx.c will put XHCI +// into incorrect state on ULT platfrom. +// [Solution] Added code in the Rapid Start Entry phase, to put XHCI +// into the correct state i.e. D3 to fix the auto wake-up issue. +// +// 4 6/21/13 6:03a Joshchou +// [TAG] EIP126792 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Can't do AMI capsule when Intel Rapid Start eanble +// [RootCause] CMOS RapidStartFlag does not clear. +// [Solution] Clear RapidStartFlag when cold boot. +// +// 3 3/14/13 11:41p Bensonlai +// [TAG] EIP118122 +// [Category] Spec Update +// [Severity] Normal +// [Description] [SBY] Intel Rapid Start Technology Framework Reference +// Code Production Version 1.3.0 +// [Files] RapidStartPeiLib.c +// +// 2 12/18/12 12:19a Bensonlai +// [TAG] EIP109701 +// [Category] Spec Update +// [Severity] Normal +// [Description] Updated to Shark Bay Rapid Start Reference Code +// Version 0.8.1 +// [Files] RapidStartPeiLib.c, RapidStartPeiLib.h +// +// 1 10/15/12 4:41a Bensonlai +// [TAG] EIPNone +// [Category] Improvement +// [Description] [Category] Improvement +// [Severity] Important +// [Description] Rename all IFFS sting to Rapid Start. +// [Files] Board\EM\RapidStartWrapper\*.*, ReferenceCode\RapidStart\*.* +// [Files] RapidStartPeiLib.cif +// RapidStartPeiLib.sdl +// RapidStartPeiLib.mak +// RapidStartPeiLib.c +// RapidStartPeiLib.h +// RapidStartPeiLib.inf +// RapidStartPeiLib.lib +// PeiCryptLib.lib +// OpensslLib.lib +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: RapidStartPeiLib.c +// +// Description: RapidStart Platform PEI library. +// +//<AMI_FHDR_END> +//********************************************************************** + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include "RapidStartConfig.h" +#include "RapidStartPeiLib.h" +#include "RapidStartCommonLib.h" +#include <SaAccess.h> +#include <PchRegs.h> +#include <PchPlatformLib.h> +#endif +#ifndef SW_SMI_IO_ADDRESS +#define SW_SMI_IO_ADDRESS 0xB2 +#endif + +#ifndef SW_SMI_ACPI_ENABLE +#define SW_SMI_ACPI_ENABLE 0xA0 +#endif + +//AMI_OVERRIDE_FOR_RAPID_START +#ifndef FFS_NV_CONFIG_REG +#define FFS_NV_CONFIG_REG 0x47 +#endif +//AMI_OVERRIDE_FOR_RAPID_START + +#define HDD_PWD_ENCRYPTION_KEY "H?p1mA*k920_84o3d^!z@L.x4$kY64" + +#pragma pack(1) +typedef struct _HDDSECDATA +{ + UINT16 UserMaster; + UINT32 PasswordLength; + UINT8 HddUserPassword[ATA_PASSWORD_LEN]; + UINT8 HddMasterPassword[ATA_PASSWORD_LEN]; +} HDDSECDATA; +#pragma pack() + +#define DEFAULT_PCI_BUS_NUMBER_PCH 0 +#define PCI_DEVICE_NUMBER_PCH_SATA 31 +#define PCI_FUNCTION_NUMBER_PCH_SATA 2 + +#define IDE_SECURITY_PWNV_GUID \ +{ 0x69967a8c, 0x1159, 0x4522, 0xaa, 0x89, 0x74, 0xcd, 0xc6, 0xe5, 0x99, 0xa0} + +/** + Enables ACPI mode after RapidStart resume. + + @param[in] PeiServices - Pointer to PEI Services Table. + + @retval EFI_SUCCESS - enabled ACPI mode +**/ +EFI_STATUS +RapidStartEnableAcpi ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ +#ifdef RAPID_START_WHOLE_MEMORY_CHECK + DEBUG ((EFI_D_INFO, "[RapidStart] SMI port=%X, RapidStart SWSMI cmd=%X\n", SW_SMI_IO_ADDRESS, SW_SMI_WHOLE_MEMORY_CHECK)); + IoWrite8 (SW_SMI_IO_ADDRESS, SW_SMI_WHOLE_MEMORY_CHECK); +#endif + DEBUG ((EFI_D_INFO, "[RapidStart] SMI port=%X, ACPI_ENABLE cmd=%X\n", SW_SMI_IO_ADDRESS, SW_SMI_ACPI_ENABLE)); + IoWrite8 (SW_SMI_IO_ADDRESS, SW_SMI_ACPI_ENABLE); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: ConvertHddDataIdToString +// +// Description: Converts Integer HDD Data Id to String. +// +// Input: +// IN UINT32 DataId, +// OUT CHAR16 *String +// Output: +// None +// +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ConvertHddDataIdToString( + IN UINT32 DataId, + OUT CHAR16 *String ) +{ + UINTN Num, i; + Num = EfiValueToString (String, DataId, 0, 0); + + for ( i = 0; i < Num; i++ ) + { + DEBUG((EFI_D_ERROR, "HDD Passowrd: String[%x] = %x. \n", i, String[i])); + } + + return; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: EncodeDecodePassword +// +// Description: Encodes/Decodes Password. +// +// Input: +// IN UINT8 *InputString, +// OUT UINT8 *OutputString, +// IN UINT32 StringLen +// Output: +// None +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID EncodeDecodePassword( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 *InputString, + OUT UINT8 *OutputString, + IN UINT32 StringLength ) +{ + UINT8 *Key; + UINT32 i; + UINT32 KeyIndex; + UINT32 KeyLength; + + if ((InputString == NULL) || (StringLength == 0)) + { + return; + } + + KeyLength = (UINT32)(EfiAsciiStrLen( HDD_PWD_ENCRYPTION_KEY)); + + Key = AllocateZeroPool (KeyLength); + CopyMem ((VOID *) Key, (VOID *) HDD_PWD_ENCRYPTION_KEY, (UINTN) KeyLength); + ASSERT (Key != NULL); + + for ( i = 0, KeyIndex = 0; i < StringLength; i++, KeyIndex++ ) + { + if ( KeyIndex == (KeyLength - 1)) + { + KeyIndex = 0; + } + OutputString[i] = (UINT8) ( InputString[i] ^ Key[KeyIndex] ); + } + + return; +} + +/** + This callback is provided to support drive password locking interoperability with RapidStart. + It is called before RapidStart transition is to occur. If SSD partiotion is located on password + locked drive this function must copy the password to the output buffer. + Size of the buffer equals ATA_PASSWORD_LEN. + + Normally the drive password is kept in SMRAM so it can be used to unlock the drive at S3 resume, + thus during RapidStartEntry the password from SMRAM shall be returned. However at RapidStartExit the content + of SMRAM is not yet available so the password has to be preserved in a non-volatile memory + during RapidStartEntry (in RapidStartAfterTransition callback) and retrieved by this function. + + For security reasons the password must be scrubbed from non-volatile memory on RapidStartExit before + returning from this function. On RapidStartEntry the password must not be stored to non-volatile memory + sooner than RapidStartAfterTransition is called (that is after RapidStart non-volatile flag is set). + + @param[in] PeiServices - Pointer to PEI Services Table + @param[in] Transition - RapidStart transition being performed + @param[in] SataPort - locked SATA port + @param[out] Password - output buffer to place the password in + @param[out] FreezeLock - set to TRUE to freeze drive lock, set to FALSE otherwise + + @retval EFI_SUCCESS - Unlock password copied to the buffer + @retval EFI_NOT_FOUND - No password provided (will break the transition) +**/ +EFI_STATUS +RapidStartGetDriveUnlockPassword ( + IN EFI_PEI_SERVICES **PeiServices, + IN RAPID_START_TRANSITION Transition, + IN UINT8 SataPort, + OUT UINT8 *Password, + OUT BOOLEAN *FreezeLock + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariable; + UINT16 wBDF; + UINT16 wPortPMModeFlag; + UINT8 DeviceorPMPort = 0xff; + BOOLEAN ModeFlag = TRUE; //TRUE is AHCI mode, FALSE is IDE mode. + UINT32 HddDataId; + CHAR16 *HddSecutiyData = NULL; + UINTN HddSecDataSize = sizeof (HDDSECDATA); + HDDSECDATA *HddSecData; + UINT16 Control; + UINTN i; + UINT8 CryptBuffer[ATA_PASSWORD_LEN]; + EFI_GUID gIdeSecurityPwNvguid = IDE_SECURITY_PWNV_GUID; + + Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, &ReadOnlyVariable); + ASSERT_EFI_ERROR (Status); + + wBDF = (UINT16)((DEFAULT_PCI_BUS_NUMBER_PCH << 8) \ + | (PCI_DEVICE_NUMBER_PCH_SATA << 3) \ + | PCI_FUNCTION_NUMBER_PCH_SATA ); + wPortPMModeFlag = (UINT16)((SataPort << 12) \ + | (DeviceorPMPort << 4) \ + | ((UINT8)ModeFlag)); + + HddDataId = (UINT32)(((UINT16)wBDF << 16) + ((UINT16)wPortPMModeFlag)); + DEBUG ((EFI_D_ERROR, "[RapidStart] HddDataId=%X\n", HddDataId)); + + HddSecutiyData = AllocateZeroPool(ATA_PASSWORD_LEN); + + ConvertHddDataIdToString (HddDataId, HddSecutiyData); + + HddSecData = AllocateZeroPool(HddSecDataSize); + + Status = ReadOnlyVariable->PeiGetVariable ( + GetPeiServicesTablePointer (), + HddSecutiyData, + &gIdeSecurityPwNvguid, + NULL, + &HddSecDataSize, + HddSecData + ); + DEBUG ((EFI_D_ERROR, "[RapidStart] PeiGetVariable Status=%r\n", Status)); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Control = HddSecData->UserMaster; + + DEBUG ((EFI_D_ERROR, "[RapidStart] Control=%x\n", Control)); + + if ( Control & 0x01 ) + { + for ( i = 0; i < sizeof (HddSecData->HddMasterPassword); i++ ) + { + CryptBuffer[i] = HddSecData->HddMasterPassword[i]; + } + + EncodeDecodePassword (PeiServices, CryptBuffer, Password, HddSecData->PasswordLength); + } + else { + for ( i = 0; i < sizeof (HddSecData->HddUserPassword); i++ ) + { + DEBUG ((EFI_D_ERROR, "[RapidStart] HddSecData->HddUserPassword[%x]= %x.\n", i, HddSecData->HddUserPassword[i])); + CryptBuffer[i] = HddSecData->HddUserPassword[i]; + } + + EncodeDecodePassword (PeiServices, CryptBuffer, Password, HddSecData->PasswordLength); + } + + *FreezeLock = TRUE; + + return EFI_SUCCESS; +} + +/** + This callback is executed before RapidStart transition is performed, but after RapidStart transition conditions has been met. + + @param[in] PeiServices - Pointer to PEI Services Table + @param[in] Transition - RapidStart transition being performed + @param[in] SataPort - SATA port of RapidStart storage drive + + @retval EFI_SUCCESS - RapidStart transition will follow + @retval EFI_ABORTED - RapidStart transition will not be performed +**/ +EFI_STATUS +RapidStartBeforeTransition ( + IN EFI_PEI_SERVICES **PeiServices, + IN RAPID_START_TRANSITION Transition, + IN UINT8 SataPort + ) +{ + return EFI_SUCCESS; +} + +/** + This callback is executed at the end of RapidStart transition whether succesfull ot not. + + If RapidStart partition is located on password locked drive the drive password must be + copied to non-volatile memory during RapidStartEntry in this function, so it is available + on RapidStartExit (see RapidStartGetDriveUnlockPassword). + + @param[in] PeiServices - Pointer to PEI Services Table + @param[in] Transition - RapidStart transition being performed + @param[in] TransitionStatus - Status of the RapidStart transition + @param[in] SataPort - SATA port of RapidStart storage drive +**/ +VOID +RapidStartAfterTransition ( + IN EFI_PEI_SERVICES **PeiServices, + IN RAPID_START_TRANSITION Transition, + IN EFI_STATUS TransitionStatus, + IN UINT8 SataPort + ) +{ + //AMI_OVERRIDE_FOR_RAPID_START + //Clear CMOS RapidStartFlag in PEI + RtcWrite (FFS_NV_CONFIG_REG, 0); + //AMI_OVERRIDE_FOR_RAPID_START +} + +#ifndef RAPID_START_NO_SMRAM_INTEGRITY_CHECK +/** + Saves SMRAM Secure Hash to non-volatile secure location. + + @param[in] Hash[] - hash value + + @retval EFI_SUCCESS - Hash value saved successfully + @retval EFI_NOT_FOUND - Hash value not found +**/ +EFI_STATUS +RapidStartSaveSecureHash ( + IN UINT8 Hash[RAPID_START_SECURE_HASH_LENGTH] + ) +{ + UINT8 Index; + + DEBUG ((EFI_D_ERROR, "RapidStartSaveSecureHash()\n")); + + for (Index = 0; Index < RAPID_START_SECURE_HASH_LENGTH; Index++) { + // Save SMRAM hash value + RtcWrite (FFS_SMRAM_HASH_DATA_REG + Index, Hash[Index]); + } + + return EFI_SUCCESS; +} + +/** + Retrieves and removes SMRAM hash from non-volatile memory + + @param[out] Hash[] - hash value + + @retval EFI_SUCCESS - Hash value has been restored and cleared successfully + @retval EFI_NOT_FOUND - Hash value not found +**/ +EFI_STATUS +RapidStartRestoreAndClearSecureHash ( + OUT UINT8 Hash[RAPID_START_SECURE_HASH_LENGTH] + ) +{ + UINT8 Index; + + DEBUG ((EFI_D_ERROR, "RapidStartRestoreAndClearSecureHash()\n")); + + for (Index = 0; Index < RAPID_START_SECURE_HASH_LENGTH; Index++) { + // Retrieve SMRAM hash value + Hash[Index] = RtcRead (FFS_SMRAM_HASH_DATA_REG + Index); + // Remove SMRAM value + RtcWrite (FFS_SMRAM_HASH_DATA_REG + Index, 0); + } + return EFI_SUCCESS; +} + +#endif + +/** + Provide a hook for OEM to cancel RapidStart flow. + This function may impact RapidStart Entry performance since it's polled frequently. + + @retval FALSE - Do not cancel RapidStart flow + @retval TRUE - The RapidStart Entry flow should be canceled and do S3 resume back to OS +**/ +BOOLEAN +RapidStartShouldCancelEntry ( + VOID + ) +{ + return FALSE; +} + +/// +/// Device IDs for WLAN RSR Workaround +/// +UINT16 mWlanSkusDeviceIdsTable[] = { + 0x422B, 0x4238, // 6300 - Puma Peak 3 + 0x0082, 0x0085, // 6205 - Taylor Peak + 0x0890, 0x0891, // 2200 - Marble Peak + 0x0887, 0x0888, // 2230 - Jackson Peak 1 + 0x088F, 0x088E, // 6235 - Jackson Peak 2 + 0x008A, 0x008B, // 1030 - Rainbow Peak 1 + 0x0091, 0x0090, // 6230 - Rainbow Peak 2 + 0x0885, 0x0886, // 6150 - Kelsey Peak + 0x0087, 0x0089, // 6250 - Kilmer Peak +}; + +/// +/// Device IDs for WLAN D3 Workaround +/// +UINT16 mWlanSkusDeviceIdsTable2[] = { + 0x08B3, 0x08B4, // 3160 - Wilkins Peak 1 + 0x08B1, 0x08B2, // 7260 - Wilkins Peak 2 +}; + +/** + This function is work around for NetDetect and WakeOnLan when RapidStart enabled. + + @retval EFI_SUCCESS - Operation successfully performed +**/ +EFI_STATUS +RapidStartWANetDetect ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT32 WlanMmioSpace + ) +{ + UINT8 RpFunction; + UINTN RpBase; + UINT8 SecBusNum; + UINT8 SecSubBusNum; + UINT8 EpBusNum; + UINTN EpBase; + UINTN WlanSkusDeviceIdIndex; + UINT8 CapPtr; + UINT8 NxtPtr; + UINT8 CapID; + UINT8 PMCreg; + UINT8 PMCSR; + UINT32 Timeout; + PEI_STALL_PPI *StallPpi; + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect Start\n")); + + Status = PeiServicesLocatePpi (&gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_EFI_ERROR (Status); + + // + // Scan PCH PCI-EX slots (Root Port) : Device 28 Function 0~7 + // + for (RpFunction = 0; RpFunction < GetPchMaxPciePortNum (); RpFunction ++) { + RpBase = MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, RpFunction, 0); + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: PCI-EX slot %x ...\n", RpFunction)); + + if ((MmioRead16 (RpBase + R_PCH_PCIE_SLSTS) & B_PCH_PCIE_SLSTS_PDS) != 0 && MmioRead16 (RpBase + R_PCH_PCIE_VENDOR_ID) == V_PCH_PCIE_VENDOR_ID) { + + /// + /// Set WLAN PortBus = 1 to Read Endpoint. + /// + MmioAndThenOr32(RpBase + R_PCH_PCIE_BNUM, 0xFF0000FF, 0x00010100); + + // + // Get the downstream Bus number + // + SecBusNum = (UINT8) (MmioRead32 (RpBase + R_PCH_PCIE_BNUM) >> 8); + SecSubBusNum = (UINT8) (MmioRead32 (RpBase + R_PCH_PCIE_BNUM) >> 16); + + for (EpBusNum = SecBusNum; EpBusNum <= SecSubBusNum; EpBusNum++) { + EpBase = MmPciAddress (0, EpBusNum, 0, 0, 0); + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: downstream Bus %x\n", EpBusNum)); + + /// + /// A config write is required in order for the device to re-capture the Bus number, + /// according to PCI Express Base Specification, 2.2.6.2 + /// Write to a read-only register VendorID to not cause any side effects. + /// + MmioWrite16 (EpBase + R_PCH_PCIE_VENDOR_ID, 0); + + // + // WLAN RSR Workaround + // + for (WlanSkusDeviceIdIndex = 0; WlanSkusDeviceIdIndex < sizeof (mWlanSkusDeviceIdsTable) / sizeof (mWlanSkusDeviceIdsTable[0]); WlanSkusDeviceIdIndex++) { + if (mWlanSkusDeviceIdsTable[WlanSkusDeviceIdIndex] == MmioRead16 (EpBase + R_PCH_PCIE_DEVICE_ID)) { + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: Found a device to support RSR and device ID is %x\n", MmioRead16 (EpBase + R_PCH_PCIE_DEVICE_ID))); + + // + // Find out PMCSR register + // + CapPtr = MmioRead8 (EpBase + R_PCH_PCIE_CAPP); + CapID = MmioRead8 (EpBase + CapPtr); + NxtPtr = (UINT8) (MmioRead16 (EpBase + CapPtr) >> 8); + PMCreg = CapPtr; + + while (CapID != 0x01) { + CapID = MmioRead8 (EpBase + NxtPtr); + if (CapID == 0x01) { + PMCreg = NxtPtr; + break; + } + NxtPtr = (UINT8) (MmioRead16 (EpBase + NxtPtr) >> 8); + + if (NxtPtr == 0){ + PMCreg = 0; + break; + } + } + + if (PMCreg != 0) { + PMCSR = PMCreg + 0x04; + + // + // Check whether PME enabled + // + if (MmioRead16 (EpBase + PMCSR) & BIT8) { + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: This device PME has been enabled\n")); + + // + // Disabled PME + // + MmioAnd16 ((UINTN) (EpBase + PMCSR), (UINT16) (~BIT8)); + + // + // Set the WLAN device to D0 + // + MmioAnd8 ((UINTN) (EpBase + PMCSR), (UINT8)(~(BIT0 + BIT1))); + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MICROSECONDS * 30); + + // + // Disable PCIE memory map access + // + MmioAnd16 ((UINTN) (RpBase + R_PCH_PCIE_PCICMD), (UINT16) (~B_PCH_PCIE_PCICMD_MSE)); + + // + // Define PCIE MMIO BAR contains a valid address value + // + MmioWrite32 (RpBase + R_PCH_PCIE_MBL, (WlanMmioSpace & B_PCH_PCIE_MBL_ML) + ((WlanMmioSpace & B_PCH_PCIE_MBL_ML) >> 16)); + MmioWrite32 (RpBase + R_PCH_PCIE_PMBL, 0x0001FF1); + + // + // Enable PCIE memory map access + // + MmioOr16 ((UINTN) (RpBase + R_PCH_PCIE_PCICMD), (UINT16) B_PCH_PCIE_PCICMD_MSE); + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: Enabled PCIE memory map and MMIO Bar is %x\n", MmioRead32 (RpBase + R_PCH_PCIE_MBL))); + + // + // Disable WLAN memory map access + // + MmioAnd16 ((UINTN) (EpBase + R_PCH_LAN_CMD), (UINT16) (~B_PCH_LAN_CMD_MSE)); + + // + // Define WLAN MMIO BAR contains a valid address value + // + MmioWrite32 (EpBase + R_PCH_LAN_MEM_BASE_A, WlanMmioSpace); + + // + // Enable WLAN memory map access + // + MmioOr16 ((UINTN) (EpBase + R_PCH_LAN_CMD), (UINT16) B_PCH_LAN_CMD_MSE); + + WlanMmioSpace = MmioRead32 (EpBase + R_PCH_LAN_MEM_BASE_A) & B_PCH_LAN_MBARA_BA; + + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: Enabled memory map and MMIO Bar is %x\n", WlanMmioSpace)); + // + // BIOS notify the uCode that RSR flow is needed + // + MmioWrite32 ((WlanMmioSpace + 0x58), 0x40); + // + // BIOS waiting for uCode to do the all necessary preparation and set a timer of 100 ms. + // + Timeout = 0; + while ((MmioRead32 (WlanMmioSpace + 0x54) & BIT7) == 0 && Timeout < MAX_UCODE_TIMEOUT) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MICROSECONDS); + Timeout++; + } + + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: The Timeout value is %x and Register 0x54 is %x\n", Timeout, MmioRead32 (WlanMmioSpace + 0x54))); + if (Timeout < MAX_UCODE_TIMEOUT) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MICROSECONDS * 100); + // + // Perform WLAN Shared HW reset + // + MmioWrite32 ((WlanMmioSpace + 0x20), BIT7); + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MICROSECONDS * 50); + // + // Re-Enable MAC Clock + // + MmioWrite32 ((WlanMmioSpace + 0x24), BIT2); + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MICROSECONDS * 50000); + // + // De-Reset the MAC + // + MmioAnd32 ((UINTN) (WlanMmioSpace + 0x20), (UINT32) (~BIT0)); + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MICROSECONDS * 50); + + // + // Enabled PME again + // + MmioOr16 ((EpBase + PMCSR), BIT8); + // + // Persistence ON + // + MmioOr32 ((WlanMmioSpace + 0x00), BIT30); + + // + // Set the WLAN device to D3 + // + MmioOr8 ((UINTN) (EpBase + PMCSR), BIT0 + BIT1); + + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: RSR is successfully\n")); + } + } + } + } + } + + // + // WLAN D3 Workaround + // + for (WlanSkusDeviceIdIndex = 0; WlanSkusDeviceIdIndex < sizeof (mWlanSkusDeviceIdsTable2) / sizeof (mWlanSkusDeviceIdsTable2[0]); WlanSkusDeviceIdIndex++) { + if (mWlanSkusDeviceIdsTable2[WlanSkusDeviceIdIndex] == MmioRead16 (EpBase + R_PCH_PCIE_DEVICE_ID)) { + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: Found a device to support D3 and device ID is %x\n", MmioRead16 (EpBase + R_PCH_PCIE_DEVICE_ID))); + + // + // Find out PMCSR register + // + CapPtr = MmioRead8 (EpBase + R_PCH_PCIE_CAPP); + CapID = MmioRead8 (EpBase + CapPtr); + NxtPtr = (UINT8) (MmioRead16 (EpBase + CapPtr) >> 8); + PMCreg = CapPtr; + + while (CapID != 0x01) { + CapID = MmioRead8 (EpBase + NxtPtr); + if (CapID == 0x01) { + PMCreg = NxtPtr; + break; + } + NxtPtr = (UINT8) (MmioRead16 (EpBase + NxtPtr) >> 8); + + if (NxtPtr == 0){ + PMCreg = 0; + break; + } + } + + if (PMCreg != 0) { + PMCSR = PMCreg + 0x04; + + // + // Check whether PME enabled + // + if (MmioRead16 (EpBase + PMCSR) & BIT8) { + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: This device PME has been enabled\n")); + + // + // Set the WLAN device to D3 + // + MmioOr8 ((UINTN) (EpBase + PMCSR), BIT0 + BIT1); + + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect: D3 is successfully\n")); + } + } + } + } + + /// + /// Restore bus numbers on the WLAN bridge. + /// + MmioAnd32(RpBase + R_PCH_PCIE_BNUM, 0xFF0000FF); + } + } + } + DEBUG ((EFI_D_INFO, "RapidStartWANetDetect End\n")); + + return EFI_SUCCESS; +} + +/** + This callback is executed to clear all PEM events before Rapid Start enter S4. + + @retval EFI_SUCCESS - Operation successfully performed +**/ +EFI_STATUS +RapidStartClearOemPmeEvent ( + VOID + ) +{ + UINT16 EhciPme, Ehci2Pme, xHciPme; + UINT8 Index; + UINT16 PCIePme[8]; + UINT16 GigaLanPme; + + DEBUG ((EFI_D_INFO, "RapidStartClearOemPmeEvent Start\n")); + + // + // Save Ehci, Ehci2 and xHci Power Control Status register + // + EhciPme = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI, + R_PCH_EHCI_PWR_CNTL_STS) + ); + Ehci2Pme = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2, + R_PCH_EHCI_PWR_CNTL_STS) + ); + xHciPme = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + R_PCH_XHCI_PWR_CNTL_STS) + ); + // + // Disabled Ehci, Ehcu2 and xHci PME & Clear PME status + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI, + R_PCH_EHCI_PWR_CNTL_STS), + ((EhciPme & ~B_PCH_EHCI_PWR_CNTL_STS_PME_EN) | B_PCH_EHCI_PWR_CNTL_STS_PME_STS) + ); + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2, + R_PCH_EHCI_PWR_CNTL_STS), + ((Ehci2Pme & ~B_PCH_EHCI_PWR_CNTL_STS_PME_EN) | B_PCH_EHCI_PWR_CNTL_STS_PME_STS) + ); + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + R_PCH_XHCI_PWR_CNTL_STS), + ((xHciPme & ~B_PCH_XHCI_PWR_CNTL_STS_PME_EN) | B_PCH_XHCI_PWR_CNTL_STS_PME_STS) + ); + + for (Index = 0; Index <= PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8; Index++) { + // + // Save PCIEs Power Control Status register + // + PCIePme[Index] = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 + Index), + R_PCH_PCIE_PMCS) + ); + // + // Disabled PCIEs PME & Clear PME status + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 + Index), + R_PCH_PCIE_PMCS), + ((PCIePme[Index] & ~B_PCH_PCIE_PMCS_PMEE) | B_PCH_PCIE_PMCS_PMES) + ); + } + + // + // Save Giga Lan Power Control Status register + // + GigaLanPme = MmioRead16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LAN, + PCI_FUNCTION_NUMBER_PCH_LAN, + R_PCH_LAN_PMCS) + ); + // + // Disabled Giga Lan PME & Clear PME status + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LAN, + PCI_FUNCTION_NUMBER_PCH_LAN, + R_PCH_LAN_PMCS), + ((GigaLanPme & ~B_PCH_LAN_PMCS_PMEE) | B_PCH_LAN_PMCS_PMES) + ); + + // + // Restore Ehci, Ehci2 and xHci Power Control Status register + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI, + R_PCH_EHCI_PWR_CNTL_STS), + EhciPme + ); + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2, + R_PCH_EHCI_PWR_CNTL_STS), + Ehci2Pme + ); + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + R_PCH_XHCI_PWR_CNTL_STS), + xHciPme + ); + + // + // XHCI's previous state is D3(this is woken from S3). In the RapidStartEntry, + // when preparing to enter into S4, put XHCI into D3(fix the auto wake-up issue). + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + R_PCH_XHCI_PWR_CNTL_STS), + (xHciPme | V_PCH_XHCI_PWR_CNTL_STS_PWR_STS_D3) + ); + + // + // Restore PCIEs Power Control Status register + // + + for (Index = 0; Index <= PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8; Index++) { + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + (PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 + Index), + R_PCH_PCIE_PMCS), + PCIePme[Index] + ); + } + + // + // Restore Giga Lan Power Control Status register + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LAN, + PCI_FUNCTION_NUMBER_PCH_LAN, + R_PCH_LAN_PMCS), + GigaLanPme + ); + + DEBUG ((EFI_D_INFO, "RapidStartClearOemPmeEvent End\n")); + + return EFI_SUCCESS; +} + +/** + Provide a hook for OEM to cancel RapidStart Instant-On function. + This function may impact RapidStart Resume performance since it's polled frequently. + + @retval FALSE - Do not cancel RapidStart Instant-On + @retval TRUE - The RapidStart Resume will have no Instant-On function +**/ +BOOLEAN +RapidStartUnattendedWake ( + VOID + ) +{ + + return FALSE; +} +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |