/** @file The PEIM implements the SA PEI Initialization. @copyright INTEL CONFIDENTIAL Copyright 1999 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains an 'Intel Peripheral Driver' and is uniquely identified as "Intel Reference Module" and is licensed for Intel CPUs and chipsets under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to additional terms of the license agreement. @par Specification **/ #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 #include #include #include #include #include #include typedef struct { UINT8 DeviceNumber; UINT8 FunctionNumber; UINT8 SvidRegOffset; } SA_SVID_SID_INIT_ENTRY; /** Function to handle SA at end of PEI @retval None **/ EFI_STATUS EFIAPI SaOnEndOfPei ( VOID ) { UINTN McD2BaseAddress; EFI_BOOT_MODE BootMode; EFI_STATUS Status; SaS3ResumeAtEndOfPei (); Status = PeiServicesGetBootMode (&BootMode); if ((Status == EFI_SUCCESS) && (BootMode != BOOT_ON_S3_RESUME)) { /// /// Clear IGD GttMmAdr, Aperture BAR and disable Bus Initiator and Memory Access for 0/2/0 /// DEBUG ((DEBUG_INFO, "Clear Temp Gfx BARs at End Of PEI.\n")); McD2BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, 0); PciSegmentWrite32 (McD2BaseAddress + PCI_COMMAND_OFFSET, 0x0); PciSegmentWrite32 (McD2BaseAddress + R_SA_IGD_GTTMMADR, 0x0); PciSegmentWrite32 (McD2BaseAddress + R_SA_IGD_GTTMMADR + 0x4, 0x0); PciSegmentWrite32 (McD2BaseAddress + GetIgfxApertureOffset (), 0x0); PciSegmentWrite32 (McD2BaseAddress + GetIgfxApertureOffset () + 4, 0x0); } return EFI_SUCCESS; } /// /// Functions /// /** This function handles SA S3 resume task @retval EFI_STATUS - Always return EFI_SUCCESS **/ EFI_STATUS SaS3ResumeAtEndOfPei ( VOID ) { EFI_BOOT_MODE BootMode; EFI_STATUS Status; #if FixedPcdGetBool(PcdFspBinaryEnable) == 0 SI_POLICY_PPI *SiPolicyPpi; HOST_BRIDGE_PEI_CONFIG *HostBridgePeiConfig; BOOLEAN SkipPamLock; #endif Status = PeiServicesGetBootMode (&BootMode); DEBUG ((DEBUG_INFO, "[SA] BootMode = %X\n", BootMode)); if ((Status != EFI_SUCCESS) || (BootMode != BOOT_ON_S3_RESUME)) { return EFI_SUCCESS; } DEBUG ((DEBUG_INFO, "SaS3ResumeAtEndOfPei Callback Entry\n")); PostCode (0xA70); // // SA S3 tasks that must be done after S3 Boot Script Restore finished. // #if FixedPcdGetBool(PcdFspBinaryEnable) == 0 // // In FSP S3 resume path, PAM lock is took care by Notify Phase API, so skipped it here. // SiPolicyPpi = NULL; HostBridgePeiConfig = NULL; SkipPamLock = FALSE; Status = PeiServicesLocatePpi ( &gSiPolicyPpiGuid, 0, NULL, (VOID **) &SiPolicyPpi ); if ((Status == EFI_SUCCESS) && (SiPolicyPpi != NULL)) { Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHostBridgePeiConfigGuid, (VOID *) &HostBridgePeiConfig); ASSERT_EFI_ERROR (Status); if (Status == EFI_SUCCESS) { SkipPamLock = (BOOLEAN) (UINTN) HostBridgePeiConfig->SkipPamLock; } } if (SkipPamLock == FALSE) { DEBUG ((DEBUG_INFO, "S3 PAM_LOCK!!\n")); PciSegmentOr32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, 0, 0, 0, R_SA_PAM0), BIT0); } #endif DEBUG ((DEBUG_INFO, "SaS3ResumeAtEndOfPei Callback Exit\n")); PostCode (0xA7F); return EFI_SUCCESS; } /** Print SA PCI space in Debug log. @retval None **/ VOID SaPciPrint ( VOID ) { UINT64 PciBase; UINT8 Device; UINT8 i; UINT8 j; for (Device = 0; Device <= 8; Device++) { if ((PcdGetBool (PcdSaPciPrint)) || (Device == 0) || (Device == 2)) { PciBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, 0, Device, 0, 0); if (PciSegmentRead16 (PciBase) != 0xFFFF) { DEBUG ((DEBUG_INFO, "\nPrinting PCI space for device %x\n ", Device)); for (i = 0; i <= 0xF ; i++) { DEBUG ((DEBUG_INFO," %2X",i)); } for (i = 0; i <= 0xF; i++) { DEBUG ((DEBUG_INFO, "\n%2X", (i * 0x10))); for (j = 0; j <= 0xF; j++) { DEBUG ((DEBUG_INFO, " %2X", PciSegmentRead8 (PciBase + (i * 0x10) + j))); } } } } } DEBUG ((DEBUG_INFO, "\n")); } /** Set SAPMCTL Register. @retval None **/ VOID SetSaPmCtlReg ( VOID ) { EFI_STATUS Status; UINT64_STRUCT MchBar; UINT32 Data32And; UINT32 Data32Or; SI_POLICY_PPI *SiPolicyPpi; HOST_BRIDGE_PEI_CONFIG *HostBridgePeiConfig; SiPolicyPpi = NULL; /// /// Get policy settings through the SaPolicy PPI /// Status = PeiServicesLocatePpi (&gSiPolicyPpiGuid, 0, NULL, (VOID **) &SiPolicyPpi); ASSERT_EFI_ERROR (Status); Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gHostBridgePeiConfigGuid, (VOID *) &HostBridgePeiConfig); ASSERT_EFI_ERROR (Status); MchBar.Data32.High = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR + 4)); MchBar.Data32.Low = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR)); MchBar.Data &= (UINT64) ~BIT0; Data32And = (UINT32) ~(BIT10 | BIT9); Data32Or = 0x3 << 9; MmioAndThenOr32 ((UINTN) MchBar.Data + R_SA_MCHBAR_SAPMCTL_OFFSET, Data32And, Data32Or); } /** This function is to Set BIOS_RESET_CPL bits. @retval None **/ VOID SetBiosResetCpl ( VOID ) { UINT64_STRUCT MchBar; MchBar.Data32.High = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR + 4)); MchBar.Data32.Low = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR)); MchBar.Data &= (UINT64) ~BIT0; DEBUG ((DEBUG_INFO, "Set BIOS_RESET_CPL to indicate all configurations complete\n")); PostCode (0xA61); MmioOr8 ((UINTN) MchBar.Data + R_SA_MCHBAR_BIOS_RESET_CPL_OFFSET, BIT0 | BIT1); }