947 lines
30 KiB
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;
|
|
}
|
|
|