/** @file Implement the Chipset Servcie IHISI FBTS subfunction for this driver. ;*************************************************************************** ;* Copyright (c) 2017 - 2020, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #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 //[-start-190910-IB11270246-add]// #include //[-end-190910-IB11270246-add]// #include #include #include #include #include #include #include BOOLEAN mFlashMEResetCommandDone = FALSE; UINT8 mFlashEnvironment = 0; // // Intel RC remove these define, so redefine value as below. // #define ME_STATE_STALL_1_SECOND 1000000 #define MSG_MAX_WAIT_TIMEOUT 5 #define B_PCH_SPI_FRAP_BMWAG_MASK 0xFF000000 ///< Master Write Access Grant MASK #define B_PCH_SPI_FRAP_BMRAG_MASK 0x00FF0000 ///< Master Read Access Grant MASK #define B_PCH_SPI_FREG0_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12] #define B_PCH_SPI_FREG0_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12] #define B_PCH_SPI_FREG1_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12] #define B_PCH_SPI_FREG1_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12] #define B_PCH_SPI_FREG2_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12] #define B_PCH_SPI_FREG2_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12] BOOLEAN mFlashME; UINT32 SmiEnSave; UINTN mWriteSize; UINTN mRomBaseAddress; UINT8 mReadLockPresent; UINT8 mWriteLockPresent; extern EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *mSmmFwBlockService; FBTS_PLATFORM_ROM_MAP mOemRomMap[] = { // {FbtsRomMapEc, FixedPcdGet32 (PcdFlashFvEcBase) , FixedPcdGet32 (PcdFlashFvEcSize) }, {FbtsRomMapDxe, FixedPcdGet32 (PcdFlashFvMainBase) , FixedPcdGet32 (PcdFlashFvMainSize) }, {FbtsRomMapNVRam, FixedPcdGet32 (PcdFlashNvStorageVariableBase) , FixedPcdGet32 (PcdFlashNvStorageVariableSize) }, {FbtsRomMapCpuMicrocode, FixedPcdGet32 (PcdFlashNvStorageMicrocodeBase) , FixedPcdGet32 (PcdFlashNvStorageMicrocodeSize) }, {FbtsRomMapFtwState, FixedPcdGet32 (PcdFlashNvStorageFtwWorkingBase), FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize)}, {FbtsRomMapFtwBackup, FixedPcdGet32 (PcdFlashNvStorageFtwSpareBase) , FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) }, {FbtsRomMapPei, FixedPcdGet32 (PcdFlashFvRecoveryBase) , FixedPcdGet32 (PcdFlashFvRecoverySize) }, {FbtsRomMapEos, 0, 0 } }; FLASH_BASE_MAP_TABLE mFlashBaseMapTable[] = {{FLASH_SIZE_1024K, ROM_1M_BASE }, {FLASH_SIZE_2048K, ROM_2M_BASE }, {FLASH_SIZE_4096K, ROM_4M_BASE }, {FLASH_SIZE_8192K, ROM_8M_BASE }, {FLASH_SIZE_16384K, ROM_16M_BASE }, {FLASH_SIZE_32768K, ROM_32M_BASE } }; // // Add OEM private rom map table, // FBTS_PLATFORM_PRIVATE_ROM mOemPrivateRomMap[] = { //[-start-210623-YUNLEI0104-modify]// #ifdef LCFC_SUPPORT {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, #ifdef L05_COMPUTRACE_ENABLE {0, 0}, #endif #else {FixedPcdGet32 (PcdFlashNvStorageMsdmDataBase), FixedPcdGet32 (PcdFlashNvStorageMsdmDataSize)}, #endif //[-end-210623-YUNLEI0104-modify]// {FbtsRomMapEos, 0} }; /** AH=10h(FbtsGetSupportVersion), Get FBTS supported version and FBTS permission. @param[in] VersionStr Flash tool version @param[in, out] Permission Permission **/ VOID EFIAPI IhisiFbtsGetPermission ( IN FBTS_TOOLS_VERSION_BUFFER *VersionPtr, IN OUT UINT16 *Permission ) { if (VersionPtr == NULL || Permission == NULL) { return; } // // Initialing permission to FBTS_PERMISSION_ALLOWED // *Permission = FBTS_PERMISSION_ALLOWED; // // Check version signature // if (VersionPtr->Signature != FBTS_VERSION_SIGNATURE) { *Permission = FBTS_PERMISSION_DENY; } //Tool environment //1 = Dos //2 = Windows //3 = Linux //4 = Shell mFlashEnvironment = VersionPtr->Environment; } /** AH=12h(FbtsGetPlatformRomMap), Get Oem define flash map. @param[in, out] RomMapBuffer Pointer to the returned platform's ROM map protection structure. After version 1.7.6, InsydeFlash will skip this structure if it found definition in BVDT @param[in, out] PrivateRomMapBuffer Pointer to the returned platform's private map structure. Flash utility will not flash these areas (even userenter /all in flashit or all=1 in platform.ini). @retval EFI_SUCCESS Get OEM flash map successful. @retval EFI_UNSUPPORTED FBTS_OEM_ROM_MAP_COUNT is 0 or module rom map buffer is full. **/ EFI_STATUS EFIAPI IhisiFbtsGetOemFlashMap ( IN OUT FBTS_PLATFORM_ROM_MAP **RomMapBuffer, IN OUT FBTS_PLATFORM_PRIVATE_ROM **PrivateRomMapBuffer ) { UINTN Media_mOemRomMapSize; UINTN Media_mOemPrivateRomMapSize; FBTS_PLATFORM_ROM_MAP *Media_mOemRomMap; FBTS_PLATFORM_PRIVATE_ROM *Media_mOemPrivateRomMap; UINTN Index; //[-start-210623-YUNLEI0104-add]// #ifdef LCFC_SUPPORT mOemPrivateRomMap[0].LinearAddress = PcdGet32 (PcdFlashFvSystemSupervisorPasswordBase); mOemPrivateRomMap[0].Size = PcdGet32 (PcdFlashFvSystemSupervisorPasswordSize); mOemPrivateRomMap[1].LinearAddress = PcdGet32 (PcdFlashFvSystemUserPasswordBase); mOemPrivateRomMap[1].Size = PcdGet32 (PcdFlashFvSystemUserPasswordSize); mOemPrivateRomMap[2].LinearAddress = PcdGet32 (PcdFlashFvLvarSub1Base); mOemPrivateRomMap[2].Size = PcdGet32 (PcdFlashFvLvarSub1Size); mOemPrivateRomMap[3].LinearAddress = PcdGet32 (PcdFlashFvLvarSub2Base); mOemPrivateRomMap[3].Size = PcdGet32 (PcdFlashFvLvarSub2Size); mOemPrivateRomMap[4].LinearAddress = PcdGet32 (PcdFlashFvLvarDebugBase); mOemPrivateRomMap[4].Size = PcdGet32 (PcdFlashFvLvarDebugSize); #ifdef L05_COMPUTRACE_ENABLE mOemPrivateRomMap[5].LinearAddress = PcdGet32 (PcdFlashFvL05ComputraceRegionBase); mOemPrivateRomMap[5].Size = PcdGet32 (PcdFlashFvL05ComputraceRegionSize); #endif #endif //[-end-210623-YUNLEI0104-add]// Media_mOemRomMapSize = (sizeof (mOemRomMap) / sizeof (mOemRomMap[0])); Media_mOemPrivateRomMapSize = (sizeof (mOemPrivateRomMap) / sizeof (mOemPrivateRomMap[0])); for (Index = 0; Index < (Media_mOemRomMapSize - 1); Index++) { mOemRomMap[Index].Address = mOemRomMap[Index].Address - PcdGet32 (PcdFlashAreaBaseAddress) + PcdGet32(PcdFlashPartBaseAddress); } for (Index = 0; Index < (Media_mOemPrivateRomMapSize - 1); Index++) { mOemPrivateRomMap[Index].LinearAddress = mOemPrivateRomMap[Index].LinearAddress - PcdGet32 (PcdFlashAreaBaseAddress) + PcdGet32(PcdFlashPartBaseAddress); } Media_mOemRomMap = mOemRomMap; Media_mOemPrivateRomMap = mOemPrivateRomMap; *RomMapBuffer = Media_mOemRomMap; *PrivateRomMapBuffer = Media_mOemPrivateRomMap; return EFI_SUCCESS; } /** Send End of Post Request Message through HECI. @param[out] RequestedActions Action request returned by EOP ACK 0x00 (HECI_EOP_STATUS_SUCCESS) - Continue to boot 0x01 (HECI_EOP_PERFORM_GLOBAL_RESET) - Global reset @retval EFI_UNSUPPORTED Current ME mode doesn't support this function @retval EFI_SUCCESS Command succeeded @retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally @retval EFI_TIMEOUT HECI does not return the buffer before timeout **/ EFI_STATUS HeciSendEndOfPostMessage ( OUT UINT32 *RequestedActions ) { EFI_STATUS Status; UINT32 Length; UINT32 RecvLength; END_OF_POST_BUFFER EndOfPost; EndOfPost.Request.MkhiHeader.Data = 0; EndOfPost.Request.MkhiHeader.Fields.Command = GEN_END_OF_POST_CMD; EndOfPost.Request.MkhiHeader.Fields.GroupId = MKHI_GEN_GROUP_ID; Length = sizeof (END_OF_POST); RecvLength = sizeof (END_OF_POST_ACK); PERF_START_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x3030); Status = SmmHeciSendwAck ( HECI1_DEVICE, (UINT32 *) &EndOfPost, Length, &RecvLength, BIOS_FIXED_HOST_ADDR, HECI_MKHI_MESSAGE_ADDR ); PERF_END_EX (NULL, "EventRec", NULL, AsmReadTsc (), 0x3031); if (!EFI_ERROR (Status)) { *RequestedActions = EndOfPost.Response.Data.RequestedActions; if (EndOfPost.Response.Data.RequestedActions == HeciEopPerformGlobalReset) { DEBUG ((DEBUG_INFO, "HeciSendEndOfPostMessage(): Global Reset requested by FW EOP ACK\n")); } } return Status; } EFI_STATUS HeciSetMeResetHalt ( VOID ) { EFI_STATUS Status; SET_ME_RESET_HALT_ACK SetMeResetAndHalt; UINT32 MeMode; HECI_FWS_REGISTER MeFirmwareStatus; UINT32 TimeOut; UINT32 HeciSendLength; TimeOut = 0; HeciSendLength = 0; Status = SmmHeciGetMeMode(&MeMode); if ((!EFI_ERROR(Status)) && (MeMode == ME_MODE_NORMAL)) { /// /// Check for Manufacturing Mode. /// MeFirmwareStatus.ul = MmioRead32 (MmPciBase(ME_BUS, ME_DEVICE_NUMBER, HECI_FUNCTION_NUMBER) + R_ME_HFS); if(MeFirmwareStatus.r.SpiProtectionMode) { /// /// Allocate MsgGenSetMeResetAndHalt data structure /// SetMeResetAndHalt.MkhiHeader.Data = 0; SetMeResetAndHalt.MkhiHeader.Fields.GroupId = MKHI_GEN_GROUP_ID; SetMeResetAndHalt.MkhiHeader.Fields.Command = GEN_SET_ME_RESET_HALT_CMD; SetMeResetAndHalt.MkhiHeader.Fields.IsResponse = 0; HeciSendLength = sizeof (SET_ME_RESET_HALT); Status = SmmHeciSend ( HECI1_DEVICE, (UINT32 *) &SetMeResetAndHalt, HeciSendLength, BIOS_FIXED_HOST_ADDR, HECI_MKHI_MESSAGE_ADDR ); if (EFI_ERROR(Status)) { return Status; } while (1) { /// /// Read ME status and check for operation mode /// Status = SmmHeciGetMeMode(&MeMode); if (MeMode == ME_OPERATION_MODE_SOFT_TEMP_DISABLE) { mFlashMEResetCommandDone = TRUE; break; } MicroSecondDelay (ME_STATE_STALL_1_SECOND); TimeOut++; if (TimeOut >= MSG_MAX_WAIT_TIMEOUT) { DEBUG ((DEBUG_ERROR, "Timeout occur, MeFirmwareStatus: %08x.\n", MeFirmwareStatus.ul)); return EFI_TIMEOUT; } } } } return Status; } VOID CheckInMERange( IN UINTN ROMOffset ){ EFI_STATUS Status; UINT8 Index; UINT8 *OutputDataBuffer; FLASH_REGION *FlashRegionPtr; Status = EFI_SUCCESS; Index = 0x0; Status = gSmst->SmmAllocatePool ( EfiRuntimeServicesData, (sizeof (FLASH_REGION) * (FlashRegionMax + 1)), (VOID **)&OutputDataBuffer ); if (!EFI_ERROR ( Status )) { Status = mSmmFwBlockService->GetFlashTable ( mSmmFwBlockService, OutputDataBuffer ); if (!EFI_ERROR (Status)) { FlashRegionPtr = (FLASH_REGION *) OutputDataBuffer; for (Index = FlashRegionDescriptor; Index < FlashRegionMax; Index = Index + 1, FlashRegionPtr++) { if (FlashRegionPtr->Type == FLASH_REGION_TYPE_OF_EOS){ break; } if (Index == ME_REGION) { if (!(((UINT32) (ROMOffset + mWriteSize - 1) < FlashRegionPtr->Offset) || ((FlashRegionPtr->Offset + FlashRegionPtr->Size - 1) < (UINT32) (ROMOffset)))) { mFlashME = TRUE; break; } } } } } if (EFI_ERROR( Status )) { DEBUG (( EFI_D_ERROR, "Get ROM Map Information Failure!\n")); } return; } VOID FlashMEAfterProcess( IN EFI_STATUS WriteStatus ) { UINT16 PmBase; PmBase = 0; if (mFlashME == TRUE) { PmBase = PmcGetAcpiBase (); gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &SmiEnSave); if (EFI_ERROR (WriteStatus)) { mFlashME = FALSE; DEBUG ((DEBUG_ERROR, "Write ME Failure!\n")); } } return; } VOID SetMeHalt( VOID ) { EFI_STATUS Status; UINT16 PmBase; UINT32 Data32; UINT32 RequestedActions; PmBase = 0; SmiEnSave = 0; Data32 = 0; mWriteLockPresent = 0; // // Only For DOS (1) and Shell (4) flash // if (!mFlashMEResetCommandDone && ((mFlashEnvironment == 1) || (mFlashEnvironment == 4))) { RequestedActions = HeciEopStatusSuccess; Status = HeciSendEndOfPostMessage (&RequestedActions); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (Status)) { if (RequestedActions == HeciEopStatusSuccess) { DEBUG ((DEBUG_INFO, "[HeciSendEndOfPostMessage Status = (%r)!]\n", Status)); Status = HeciSetMeResetHalt(); } else { DEBUG ((DEBUG_INFO, "[HeciSendEndOfPostMessage Status = (%r)!]\n", Status)); Status = EFI_UNSUPPORTED; } } } PmBase = PmcGetAcpiBase (); gSmst->SmmIo.Io.Read (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &SmiEnSave); Data32 = SmiEnSave & ~B_ACPI_IO_SMI_EN_GBL_SMI; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &Data32); // // Markup ME region will try to write. // mWriteLockPresent = 1; return; } //EFI_STATUS //Stall ( // IN UINTN Microseconds // ); /** AH=15h(FBTS write) : Hook function before Write process @param[in, out] WriteDataBufferPtr Pointer to data buffer for write. @param[in, out] WriteSizePtr Write size. @param[in, out] RomBaseAddressPtr Target linear address to write. @retval EFI_SUCCESS Function succeeded. @return Other Error occurred in this function. **/ EFI_STATUS EFIAPI IhisiFbtsDoBeforeWriteProcess ( IN OUT UINT8 *WriteDataBufferPtr, IN OUT UINTN *WriteSizePtr, IN OUT UINTN *RomBaseAddressPtr ) { EFI_STATUS Status; //[-start-210615-BAIN000011-remove]// #ifndef LCFC_SUPPORT UINT8 Index; #endif //[-end-210615-BAIN000011-remove]// UINTN ROMBase; UINTN ROMOffset; UINT8 SpiFlashNumber; UINT8 WholeROMSizeIndex; FLASH_DEVICE *Buffer; // EFI_BOOT_MODE BootMode; EFI_STATUS OemSvcStatus; // UINT32 MeMode=0; // HECI_FWS_REGISTER MeFirmwareStatus; // GEN_SET_ME_RESET_HALT_ACK MsgGenSetMeResetAndHalt; // UINT32 HeciSendLength=0; // UINT32 HeciRecvLength=0; // UINT32 TimeOut = 10; // Status=EFI_UNSUPPORTED; mWriteSize = *WriteSizePtr; mRomBaseAddress = *RomBaseAddressPtr; ROMBase = 0; ROMOffset = 0; SpiFlashNumber = 0; WholeROMSizeIndex = 0; // BootMode = GetBootModeHob(); if (*(mSmmFwBlockService->FlashMode) == SMM_FW_DEFAULT_MODE) { if (PcdGetBool (PcdEcSharedFlashSupported) && !PcdGetBool (PcdEcIdlePerWriteBlockSupported)) { // // Old Insyde Flash tool, which only supports above Ihisi spec 2.0.3, // doesn't support 1Fh function (FbtsApHookForBios), so need backward capability to do EcIdle here. // if (FeaturePcdGet (PcdIhisiToolBackwardSupport)) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (TRUE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); } } *(mSmmFwBlockService->FlashMode) = SMM_FW_FLASH_MODE; } if ( !mFlashME ) { Status = gSmst->SmmAllocatePool ( EfiRuntimeServicesData, sizeof (FLASH_DEVICE), (VOID **)&Buffer ); if (!EFI_ERROR ( Status ) ) { Status = mSmmFwBlockService->DetectDevice ( mSmmFwBlockService, (UINT8 *) Buffer ); } if (!EFI_ERROR (Status )) { Status = mSmmFwBlockService->GetSpiFlashNumber ( mSmmFwBlockService, (UINT8 *)&SpiFlashNumber ); } if ( EFI_ERROR ( Status ) ) { DEBUG ((DEBUG_ERROR, "Get ROM Information Failure!\n")); } if (!EFI_ERROR (Status)) { if (Buffer->DeviceInfo.Size == 0xFF) { ROMBase = (0x100000000 - (Buffer->DeviceInfo.BlockMap.Multiple * Buffer->DeviceInfo.BlockMap.BlockSize) * 0x100); ROMOffset = mRomBaseAddress - ROMBase; } else { //[-start-210615-BAIN000011-modify]// #ifdef LCFC_SUPPORT ROMBase = 0x100000000 - SpiGetTotalFlashSize (); ROMOffset = mRomBaseAddress - ROMBase; #else WholeROMSizeIndex = Buffer->DeviceInfo.Size; if ( SpiFlashNumber == 2 ) { WholeROMSizeIndex = WholeROMSizeIndex + 1; } for (Index = 0; Index < (sizeof (mFlashBaseMapTable) / sizeof (FLASH_BASE_MAP_TABLE)); Index = Index + 1) { if (mFlashBaseMapTable[Index].SizeIndex == WholeROMSizeIndex) { ROMBase = mFlashBaseMapTable[Index].Base; ROMOffset = mRomBaseAddress - ROMBase; break; } } #endif //[-end-210615-BAIN000011-modify]// } } CheckInMERange(ROMOffset); } if (mFlashME){ SetMeHalt(); } return EFI_SUCCESS; } /** AH=15h(FBTS write) : Hook function after Write process. @param[in] WriteStatus @retval EFI_SUCCESS Function returns successfully **/ EFI_STATUS EFIAPI IhisiFbtsDoAfterWriteProcess ( IN EFI_STATUS WriteStatus ) { EFI_STATUS Status; Status = (WriteStatus & 0x00000000000000FF); if ((Status == FbtsWriteFail) || (Status == FbtsEraseFail)) { if (mWriteLockPresent == 1) { // // Write region fall in Descriptor or ME // Status = FbtsSkipThisWriteBlock; } } FlashMEAfterProcess(Status); return Status; } /** AH=14h(FbtsRead) : Hook function before read process @param[in, out] ReadAddress Target linear address to read. @param[in, out] ReadSize Read size. @param[in, out] DataBuffer Pointer to returned data buffer. @retval EFI_SUCCESS Function succeeded. @return Other Error occurred in this function. **/ EFI_STATUS EFIAPI IhisiFbtsDoBeforeReadProcess ( IN OUT UINTN *ReadAddress, IN OUT UINTN *ReadSize, IN OUT UINT8 *DataBuffer ) { EFI_STATUS OemSvcStatus; mReadLockPresent = 0; if (*(mSmmFwBlockService->FlashMode) == SMM_FW_DEFAULT_MODE) { if (PcdGetBool (PcdEcSharedFlashSupported) && !PcdGetBool (PcdEcIdlePerWriteBlockSupported)) { // // Old Insyde Flash tool, which only supports above Ihisi spec 2.0.3, // doesn't support 1Fh function (FbtsApHookForBios), so need backward capability to do EcIdle here. // if (FeaturePcdGet (PcdIhisiToolBackwardSupport)) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (TRUE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); } } *(mSmmFwBlockService->FlashMode) = SMM_FW_FLASH_MODE; } return EFI_SUCCESS; } /** AH=14h(FbtsRead) : Hook function after read process @retval EFI_SUCCESS Function returns successfully **/ EFI_STATUS EFIAPI IhisiFbtsDoAfterReadProcess ( IN EFI_STATUS ReadStatus ) { EFI_STATUS Status; Status = (ReadStatus & 0x00000000000000FF); if (Status == FbtsReadFail) { // // According mReadLockPresent of status to update chipset of fail status. // } return Status; } /** Function to entry S3. @retval EFI_SUCCESS Successfully returns. **/ EFI_STATUS EFIAPI IhisiFbtsS3 ( VOID ) { UINT16 PmBase; UINT32 Data32; UINT32 GlobalSmiEn; UINT32 SleepStatus; UINTN Size; IMAGE_INFO ImageInfo; EFI_STATUS Status; AsmWbinvd(); Size = sizeof (IMAGE_INFO); Status = CommonGetVariable ( SECURE_FLASH_INFORMATION_NAME, &gSecureFlashInfoGuid, &Size, &ImageInfo); if ((Status == EFI_SUCCESS) && (ImageInfo.FlashMode)) { PmBase = PmcGetAcpiBase (); gSmst->SmmIo.Io.Read (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_PM1_CNT), 1, &SleepStatus); SleepStatus = (SleepStatus & ~(B_ACPI_IO_PM1_CNT_SLP_TYP + B_ACPI_IO_PM1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S3; // // Disable global SMI to avoid PCH generate any SMI# // gSmst->SmmIo.Io.Read (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &GlobalSmiEn); Data32 = GlobalSmiEn & ~B_ACPI_IO_SMI_EN_GBL_SMI; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &Data32); // // Enable S3 SLP_TYP and SLP_EN // gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_PM1_CNT), 1, &SleepStatus); SleepStatus |= B_ACPI_IO_PM1_CNT_SLP_EN; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_PM1_CNT), 1, &SleepStatus); // // Enable global SMI // gSmst->SmmIo.Io.Read (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &GlobalSmiEn); Data32 = GlobalSmiEn | B_ACPI_IO_SMI_EN_GBL_SMI; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (PmBase + R_ACPI_IO_SMI_EN), 1, &Data32); return EFI_SUCCESS; } return EFI_UNSUPPORTED; } /** AH=16h(Fbtscomplete), This function uses to execute Ap terminate. @retval EFI_SUCCESS Function succeeded. @return Other Error occurred in this function. **/ EFI_STATUS EFIAPI IhisiFbtsApTerminated ( VOID ) { return EFI_SUCCESS; } /** AH=16h(Fbtscomplete), This function uses to execute normal flash. (Update whole image or BIOS region by normal or secure flash.) @retval EFI_UNSUPPORTED Returns unsupported by default. @retval EFI_SUCCESS The service is customized in the project. **/ EFI_STATUS EFIAPI IhisiFbtsNormalFlash ( VOID ) { return EFI_UNSUPPORTED; } /** AH=16h(Fbtscomplete), This function uses to execute Partial flash. (Update specific address or update single firmware volume.) @retval EFI_SUCCESS Function succeeded. @return Other Error occurred in this function. **/ EFI_STATUS EFIAPI IhisiFbtsPartialFlash ( VOID ) { return EFI_SUCCESS; } /** AH=16h(Fbtscomplete), This function is a hook function berfore ApRequest execute. @retval EFI_UNSUPPORTED Returns unsupported by default. @retval EFI_SUCCESS The service is customized in the project. **/ EFI_STATUS EFIAPI IhisiFbtsOemComplete ( IN UINT8 ApRequest ) { EFI_STATUS Status; EFI_STATUS OemSvcStatus; Status = EFI_UNSUPPORTED; if (PcdGetBool (PcdEcSharedFlashSupported) && !PcdGetBool (PcdEcIdlePerWriteBlockSupported)) { // // Old Insyde Flash tool, which only supports above Ihisi spec 2.0.3, // doesn't support 1Fh function (FbtsApHookForBios), so need backward capability to do EcIdle here. // if (FeaturePcdGet (PcdIhisiToolBackwardSupport)) { DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcEcIdle \n")); OemSvcStatus = OemSvcEcIdle (FALSE); DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcEcIdle Status: %r\n", OemSvcStatus)); } } if (PcdGetBool (PcdAmtEnable) && !mFlashME) { WriteExtCmos8 (R_XCMOS_INDEX, R_XCMOS_DATA, MEFlashReset, V_ME_NEED_BIOS_SYNC); } if (RECOVERY_VALUE == ReadExtCmos8 ( R_XCMOS_INDEX, R_XCMOS_DATA, ChipsetRecoveryFlag)) { WriteExtCmos8 (R_XCMOS_INDEX, R_XCMOS_DATA, ChipsetRecoveryFlag, 0); } if ((ApRequest != FlashCompleteDoNothing) && IsDeviceFirmwareUpdateProcess()) { // // To avoid capsule file not deleted normally; // we should stop any reset behavior at this during device firmware capsule update. // Status = EFI_SUCCESS; } if (ApRequest == FlashCompleteS3) { // Status = IhisiFbtsS3 (); Status = IhisiFbtsReboot(); } return Status; } /** Function to do system shutdown. @retval EFI_SUCCESS Successfully returns. **/ EFI_STATUS EFIAPI IhisiFbtsShutDown ( VOID ) { UINT32 Buffer; UINT16 AcpiBaseAddr; UINT16 Data16; AcpiBaseAddr = PmcGetAcpiBase (); // //if S5LongRunTest is enable. // if(ReadExtCmos8 ( R_XCMOS_INDEX, R_XCMOS_DATA, S5LongRunTestFlag)) { // // Clear RTC PM1 status // gSmst->SmmIo.Io.Read ( &gSmst->SmmIo, SMM_IO_UINT16, AcpiBaseAddr + R_ACPI_IO_PM1_STS, 1, &Data16 ); Data16 = Data16 | B_ACPI_IO_PM1_STS_RTC; gSmst->SmmIo.Io.Write ( &gSmst->SmmIo, SMM_IO_UINT16, AcpiBaseAddr + R_ACPI_IO_PM1_STS, 1, &Data16 ); // // set RTC_EN bit in PM1_EN to wake up from the alarm // gSmst->SmmIo.Io.Read ( &gSmst->SmmIo, SMM_IO_UINT16, AcpiBaseAddr + R_ACPI_IO_PM1_EN, 1, &Data16 ); Data16 = Data16 | B_ACPI_IO_PM1_EN_RTC; gSmst->SmmIo.Io.Write ( &gSmst->SmmIo, SMM_IO_UINT16, AcpiBaseAddr + R_ACPI_IO_PM1_EN, 1, &Data16 ); } gSmst->SmmIo.Io.Read (&gSmst->SmmIo, SMM_IO_UINT32, (AcpiBaseAddr + R_ACPI_IO_SMI_EN), 1, &Buffer); Buffer = Buffer & ~B_ACPI_IO_SMI_EN_ON_SLP_EN; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (AcpiBaseAddr + R_ACPI_IO_SMI_EN), 1, &Buffer); gSmst->SmmIo.Io.Read (&gSmst->SmmIo, SMM_IO_UINT32, (AcpiBaseAddr + R_ACPI_IO_PM1_CNT), 1, &Buffer); Buffer = Buffer & ~(B_ACPI_IO_PM1_CNT_SLP_EN | B_ACPI_IO_PM1_CNT_SLP_TYP); Buffer |= V_ACPI_IO_PM1_CNT_S5; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (AcpiBaseAddr + R_ACPI_IO_PM1_CNT), 1, &Buffer); Buffer |= B_ACPI_IO_PM1_CNT_SLP_EN; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT32, (AcpiBaseAddr + R_ACPI_IO_PM1_CNT), 1, &Buffer); return EFI_SUCCESS; } /** Function to reboot system. @retval EFI_SUCCESS Successfully returns. **/ EFI_STATUS EFIAPI IhisiFbtsReboot ( VOID ) { UINT8 Buffer; UINT32 PchPwrmBase; AsmWbinvd(); PchPwrmBase = PmcGetPwrmBase (); if (mFlashME) { MmioOr32 (PchPwrmBase + R_PMC_PWRM_ETR3, (UINT32) (B_PMC_PWRM_ETR3_CF9GR)); } Buffer = 6; gSmst->SmmIo.Io.Write (&gSmst->SmmIo, SMM_IO_UINT8, 0xcf9, 1, &Buffer); return EFI_SUCCESS; } /** Function to flash complete do nothing. @retval EFI_SUCCESS Successfully returns. **/ EFI_STATUS EFIAPI IhisiFbtsApRequestDoNothing ( VOID ) { if (mFlashME) { WriteExtCmos8 (R_XCMOS_INDEX, R_XCMOS_DATA, MEFlashReset, V_ME_GLOBAL_RESET); mFlashME = FALSE; } return EFI_SUCCESS; }