alder_lake_bios/Intel/AlderLake/AlderLakeChipsetPkg/ChipsetSvcSmm/CsSvcIhisiFbts.c

947 lines
30 KiB
C

/** @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 <Uefi.h>
#include <H2OIhisi.h>
#include <ChipsetCmos.h>
#include <ChipsetAccess.h>
#include <Register/MeRegs.h>
#include <CsSvcIhisiFbts.h>
#include <Library/FdSupportLib.h>
#include <Library/IoLib.h>
#include <Library/CmosLib.h>
#include <Library/HobLib.h>
#include <Library/UefiLib.h>
#include <Library/DebugLib.h>
#include <Library/SpiAccessLib.h>
#include <Library/SmmChipsetSvcLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseOemSvcKernelLib.h>
#include <Library/SmmServicesTableLib.h>
#include <Library/TimerLib.h>
#include <Library/PerformanceLib.h>
//#include <Library/PchPlatformLib.h>
#include <Library/PchInfoLib.h>
#include <Library/PchCycleDecodingLib.h>
#include <Protocol/PlatformNvsArea.h>
#include <Protocol/SmmFwBlockService.h>
#include <Protocol/HeciProtocol.h>
#include <Protocol/Spi.h>
#include <Library/GpioLib.h>
#include <Library/MmPciLib.h>
#include <Library/SmmOemSvcChipsetLib.h>
#include <Register/MeRegs.h>
//[-start-190910-IB11270246-add]//
#include <Library/SmmHeciLib.h>
//[-end-190910-IB11270246-add]//
#include <Register/HeciRegs.h>
#include <MeState.h>
#include <SecureFlash.h>
#include <Library/VariableLib.h>
#include <Library/PmcLib.h>
#include <Library/ChipsetSignatureLib.h>
#include <Register/PmcRegs.h>
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;
}