/** @file This driver provides IHISI interface in SMM mode ;****************************************************************************** ;* Copyright (c) 2016 - 2020, Insyde Software Corporation. 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 "MeCapsuleSmm.h" #include #include #include #include #include #define MAX_RECOVERY_RETRY 3 H2O_IHISI_PROTOCOL *mH2OIhisi = NULL; EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *mSmmFwBlockService = NULL; STATIC CONST BOOLEAN mPcdIhisiRegisterTableValid = (BOOLEAN)(FixedPcdGetPtrSize (PcdIhisiRegisterTable) % sizeof (PCD_IHISI_REGISTER_TABLE) == 0); /** Ihisi driver entry point to initialize all of IHISI relative services @param[in] ImageHandle The firmware allocated handle for the UEFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The operation completed successfully. @retval Others An unexpected error occurred. */ EFI_STATUS EFIAPI IfwuSmmEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; Status = gSmst->SmmLocateProtocol ( &gH2OIhisiProtocolGuid, NULL, (VOID **) &mH2OIhisi ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); } if (mSmmFwBlockService == NULL) { Status = gSmst->SmmLocateProtocol ( &gEfiSmmFwBlockServiceProtocolGuid, NULL, (VOID **) &mSmmFwBlockService ); if (EFI_ERROR (Status)) { return Status; } } Status = FmtsUseIntelLibInit (); if (EFI_ERROR (Status)) { return Status; } return EFI_SUCCESS; } /** Register IHISI sub function if SubFuncTable CmdNumber/AsciiFuncGuid define in PcdIhisiRegisterTable list. @param[out] SubFuncTable Pointer to ihisi register table. @param[out] TableCount SubFuncTable count @retval EFI_SUCCESS Function succeeded. @return Other Error occurred in this function. **/ EFI_STATUS RegisterIhisiSubFunction ( IHISI_REGISTER_TABLE *SubFuncTable, UINT16 TableCount ) { EFI_STATUS Status; UINT8 *PcdTable; UINT8 PcdPriority; UINT8 EndChar; UINTN Index; UINTN PcdCount; UINTN PcdMaxCount; UINTN SignatureSize; BOOLEAN PcdFoundRegistered; Status = EFI_SUCCESS; EndChar = 0; PcdFoundRegistered = FALSE; PcdTable = (UINT8 *)PcdGetPtr (PcdIhisiRegisterTable); PcdMaxCount = FixedPcdGetPtrSize (PcdIhisiRegisterTable) / sizeof (UINT8); if (!mPcdIhisiRegisterTableValid) { DEBUG ((DEBUG_ERROR, "PcdIhisiRegisterTable of description not follow PCD_IHISI_REGISTER_TABLE definition, \ it may cause some of IHISI function register fail \n")); } for (Index = 0; Index < TableCount; Index ++) { PcdCount = 0; PcdPriority = 0x80; PcdFoundRegistered = FALSE; SignatureSize = AsciiStrLen (SubFuncTable[Index].FuncSignature); // // Caculate PCD of address to find 1. CmdNumber 2. FuncSignature 3. Priority // do { if (SubFuncTable[Index].CmdNumber == *(PcdTable + PcdCount)) { PcdCount++; if (AsciiStrnCmp (SubFuncTable[Index].FuncSignature, (CHAR8 *) (PcdTable + PcdCount), SignatureSize) == 0) { if (EndChar == *(PcdTable + PcdCount + SignatureSize)) { PcdPriority = *(PcdTable + PcdCount + SignatureSize + 1); PcdFoundRegistered = TRUE; break; } } } PcdCount++; } while (PcdCount < PcdMaxCount); if (PcdFoundRegistered) { Status = mH2OIhisi->RegisterCommand (SubFuncTable[Index].CmdNumber, SubFuncTable[Index].IhisiFunction, PcdPriority); if (EFI_ERROR(Status)) { DEBUG ((DEBUG_ERROR, "IHISI command :0x%X, priority : 0x%X, that already has a registered function\n", SubFuncTable[Index].CmdNumber, PcdPriority)); ASSERT (FALSE); } } } return Status; } #if 1 UINTN CheckAndFixHeciForAccess ( IN HECI_DEVICE HeciDev ); /** Determine whether ME state is in recovery mode. @retval TRUE Is in Recovery mode. @retval FALSE Not in Recovery mode. **/ BOOLEAN EFIAPI IsMeStateRecovery ( VOID ) { HECI_FWS_REGISTER MeFirmwareStatus; MeFirmwareStatus.ul = 0; if (CheckAndFixHeciForAccess (HECI1_DEVICE) != 0) { MeFirmwareStatus.ul = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (ME_SEGMENT, ME_BUS, ME_DEVICE_NUMBER, HECI_FUNCTION_NUMBER, R_ME_HFS)); if (MeFirmwareStatus.r.CurrentState == ME_STATE_RECOVERY) { return TRUE; } } return FALSE; } /** Determine whether is up to maximum try of ME recovery. @param[in] Recorder If TRUE, set the variable to record the times of recovery try. @retval TRUE Is up to maximum try. @retval FALSE Not up to maximum try. **/ BOOLEAN EFIAPI IsMaxRecoveryTry ( IN BOOLEAN Recorder ) { EFI_STATUS Status; UINTN Size; UINT8 MaxRecoveryRetryCounter; Size = sizeof (MaxRecoveryRetryCounter); Status = CommonGetVariable ( L"MeRecoveryRetry", &gMeUpdCountGuid, &Size, &MaxRecoveryRetryCounter ); if (EFI_ERROR (Status)) { MaxRecoveryRetryCounter = 1; } MaxRecoveryRetryCounter++; if (MaxRecoveryRetryCounter > MAX_RECOVERY_RETRY) { return TRUE; } if (Recorder) { // // Set recovery retry counter // Size = sizeof (MaxRecoveryRetryCounter); Status = CommonSetVariable ( L"MeRecoveryRetry", &gMeUpdCountGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, Size, &MaxRecoveryRetryCounter ); } return FALSE; } #endif