Ryzen/AmiModulePkg/Ofbd/Ofbd.c
2022-12-23 15:14:44 +08:00

437 lines
13 KiB
C

//***********************************************************************
//* *
//* Copyright (c) 1985-2020, American Megatrends International LLC. *
//* *
//* All rights reserved. Subject to AMI licensing agreement. *
//* *
//***********************************************************************
/** @file
Ofbd.c
This is the main file of OFBD module. We setup OFBD SMI handler here.
Please also refer to Aptio SMM Module Porting guide.
*/
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include <Efi.h>
#include <Token.h>
#include <Ofbd.h>
#include <AmiLib.h>
#include <AmiDxeLib.h>
#include <Protocol/SmmCpu.h>
#include <Protocol/SmmBase2.h>
#include <Protocol/SmmSwDispatch2.h>
#include <Protocol/DevicePath.h>
#include <OfbdFuncInc.h> // Build directory
#include <OfbdFuncElinks.h> // Build directory
#if OFBD_FOR_ARM_SUPPORT == 1
#include <Protocol/AmiFri.h>
#include <Flash.h>
#else
#include <AmiSmm.h>
#include <Library/AmiBufferValidationLib.h>
#if OFBD_NEW_WSMT_SUPPORT == 1
#include <Protocol/AmiSmmCommunication.h>
#include <Library/PcdLib.h>
BOOLEAN gUseAmiNewComm;
AMI_SMM_COMMUNICATION_PROTOCOL *gAmiSmmCommunication;
#endif
//---------------------------------------------------------------------------
// Global Vars
//---------------------------------------------------------------------------
EFI_GUID gSwSmiCpuTriggerGuid = SW_SMI_CPU_TRIGGER_GUID;
EFI_GUID gEfiSmmCpuProtocolGuid = EFI_SMM_CPU_PROTOCOL_GUID;
#if OFBD_NEW_WSMT_SUPPORT == 1
EFI_GUID gAmiSmmCommunicationProtocolGuid = AMI_SMM_COMMUNICATION_PROTOCOL_GUID;
#endif
EFI_SMM_BASE2_PROTOCOL *gSmmBase2 = NULL;
EFI_SMM_CPU_PROTOCOL *gSmmCpu = NULL;
#endif
UINT64 gU64TempVPT = 0;
UINT16 gOFBD_Size = 0; ///< Ofbd buffer total size
//---------------------------------------------------------------------------
#define RETURN(status) {return status;}
#define OFBD_SIGNATURE SIGNATURE_32('O', 'F', 'B', 'D')
static OFBD_INIT_PARTS_FUNC * OFBDInitPartsTbl[] =
{
OFBD_INIT_FUNC_LIST
NULL
};
static OFBD_INIT_SMM_FUNC * OFBDInSMMFuncTbl[] =
{
OFBD_IN_SMM_FUNC_LIST
NULL
};
static OFBD_INIT_SMM_FUNC * OFBDNotInSMMFunc[] =
{
OFBD_NOT_SMM_FUNC_LIST
NULL
};
#if OFBD_FOR_ARM_SUPPORT == 1
//---------------------------------------------------------------------------
/**
Ofbd (Convert Buffer Pointer)
This function will to convert the unknown virtual address to runtime pointer
@param Buffer - Ofbd header.
@return VOID
*/
VOID OfbdConvertBufferPointer(
IN VOID *Buffer
)
{
OFBD_HDR * pOFBDHdr = 0;
OFBD_EXT_HDR * pOFBDExtHdr = 0;
UINT8 * pOFBDTblEnd = 0;
UINT64 * pTempVPT = 0;
OFBD_TC_54_STD_EC_STRUCT * pECStructPtr = 0;
pOFBDHdr = (OFBD_HDR *)Buffer;
pOFBDExtHdr = (OFBD_EXT_HDR *)((UINT8 *)Buffer + sizeof(OFBD_HDR));
pOFBDTblEnd = (UINT8 *)((UINT8 *)pOFBDHdr + gOFBD_Size);
pTempVPT = (UINT64 *)((UINT8 *)pOFBDTblEnd - sizeof(OFBD_END));
gU64TempVPT = *pTempVPT;
//TRACE((-1, "[OFBD] Buffer(%08X)\n", Buffer);)
//TRACE((-1, "[OFBD] gU64TempVPT(%08X)\n", gU64TempVPT);)
//TRACE((-1, "[OFBD] 0 pOFBDEnd->OFBD_END(%08X)\n", *pTempVPT);)
switch (pOFBDExtHdr->TypeCodeID)
{
case OFBD_EXT_TC_EC:
pECStructPtr = (OFBD_TC_54_STD_EC_STRUCT *)((UINT8 *)pOFBDExtHdr + sizeof(OFBD_EXT_HDR));
if (pECStructPtr->dbFlaSts & OFBD_TC_STD_EC_FLASH)
*pTempVPT = (UINT64)(VOID *)((UINT8 *)pOFBDTblEnd + 128); // Skip OEM string length, to avoid error message return function invalid.
break;
}
//TRACE((-1, "[OFBD] 1 pOFBDEnd->OFBD_END(%08X)\n", *pTempVPT);)
}
//---------------------------------------------------------------------------
/**
Ofbd (Virtual Notify Event)
This function will be invoked to convert runtime pointers to virtual address
@param EFI_EVENT - Not used.
@param VOID - Not used.
@return VOID
*/
VOID OfbdVirtualNotifyEvent (
EFI_EVENT Event,
VOID *Context
)
{
UINTN i = 0;
FlashVirtualFixup(pRS);
for (i = 0; OFBDInitPartsTbl[i] != NULL; i++)
{
pRS->ConvertPointer(0, (VOID **)&(OFBDInitPartsTbl[i]));
}
}
#endif
/**
Ofbd (Smi Handles)
The SMI handler of Ofbd services.
@param DispatchHandle - Dispatch Handle.
@param DispatchContext - Dispatch Context.
@return EFI_STATUS
@retval EFI_SUCCESS Function executed successfully
*/
EFI_STATUS
EFIAPI
OFBDSMIHandler (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *Context OPTIONAL,
IN OUT VOID *CommBuffer OPTIONAL,
IN OUT UINTN *CommBufferSize OPTIONAL
)
{
EFI_STATUS Status = EFI_SUCCESS;
UINTN i = 0;
OFBD_HDR *OFBDHeader = NULL;
UINT8 OFBDDataHandled = 0;
#if OFBD_FOR_ARM_SUPPORT == 0
UINTN Cpu = 0;
UINT8 Data = 0;
UINT64 BuffAddr = 0;
UINT32 HighBufferAddress = 0;
UINT32 LowBufferAddress = 0;
Cpu = ((EFI_SMM_SW_CONTEXT*)CommBuffer)->SwSmiCpuIndex;
Data = ((EFI_SMM_SW_CONTEXT*)CommBuffer)->CommandPort;
//
// Found Invalid CPU number, return
//
if(Cpu == (UINTN)-1)
RETURN(Status);
if(Data != OFBD_SW_SMI_VALUE)
RETURN(Status);
#if OFBD_NEW_WSMT_SUPPORT == 1
if( gUseAmiNewComm == TRUE )
{
AMI_SMM_COMM_BUFFER_X86_REGISTERS Registers;
Status = gAmiSmmCommunication->GetRegisterBlock(
gAmiSmmCommunication,
(UINT32)Data,
&Registers );
if( EFI_ERROR(Status) )
return Status;
LowBufferAddress = (UINT32)Registers.Rbx;
HighBufferAddress = (UINT32)Registers.Rcx;
}
else
#endif
{
gSmmCpu->ReadSaveState ( gSmmCpu, \
4, \
EFI_SMM_SAVE_STATE_REGISTER_RBX, \
Cpu, \
&LowBufferAddress );
gSmmCpu->ReadSaveState ( gSmmCpu, \
4, \
EFI_SMM_SAVE_STATE_REGISTER_RCX, \
Cpu, \
&HighBufferAddress );
}
//Data = ((EFI_SMM_SW_CONTEXT*)CommBuffer)->CommandPort;
BuffAddr = HighBufferAddress;
BuffAddr = Shl64(BuffAddr, 32);
BuffAddr += LowBufferAddress;
//TRACE((-1,"\nOFBD address is:%x ------\n",BuffAddr));
//if (Data != OFBD_SW_SMI_VALUE) RETURN(Status);
if (EFI_ERROR(AmiValidateMemoryBuffer ((UINT8*)(UINTN)BuffAddr, sizeof(OFBD_HDR)))) return EFI_ACCESS_DENIED;
OFBDHeader = (OFBD_HDR *)BuffAddr;
if (OFBDHeader->OFBD_SIG == OFBD_SIGNATURE)
{
OFBDHeader->OFBD_VER = OFBD_VERSION;
OFBDHeader->OFBD_RS |= OFBD_RS_SUPPORT;
gOFBD_Size = OFBDHeader->OFBD_Size;
if (gOFBD_Size > (sizeof(OFBD_HDR) + sizeof(OFBD_EXT_HDR) + sizeof(OFBD_END) + 0x1000)) return EFI_ACCESS_DENIED;
if (EFI_ERROR(AmiValidateMemoryBuffer ((UINT8*)(UINTN)BuffAddr, sizeof(OFBD_HDR) + sizeof(OFBD_EXT_HDR) + sizeof(OFBD_END) + 0x1000))) return EFI_ACCESS_DENIED;
for (i = 0; OFBDInitPartsTbl[i] != NULL; i++)
{
OFBDInitPartsTbl[i]((VOID *)BuffAddr, &OFBDDataHandled);
}
}
#else
AFRI_OFBD_BUFFER *pData = NULL;
if (CommBuffer != NULL)
{
pData = (AFRI_OFBD_BUFFER *)CommBuffer;
//TRACE((-1, "[OFBD] Command(%02X) Size(%08X)\n", pData->Command, *CommBufferSize);)
if (pData->Command == OFBD_SW_SMI_VALUE)
{
OFBDHeader = (OFBD_HDR *)((VOID *)pData->Data);
if (OFBDHeader->OFBD_SIG == OFBD_SIGNATURE) {
OFBDHeader->OFBD_VER = OFBD_VERSION;
OFBDHeader->OFBD_RS |= OFBD_RS_SUPPORT;
gOFBD_Size = OFBDHeader->OFBD_Size;
OfbdConvertBufferPointer((VOID *)pData->Data);
for (i = 0; OFBDInitPartsTbl[i] != NULL; i++)
{
OFBDInitPartsTbl[i]((VOID *)pData->Data, &OFBDDataHandled);
}
}
}
}
#endif
RETURN(Status);
}
#if OFBD_FOR_ARM_SUPPORT == 0
/**
Ofbd (In Smm Function)
This function registers OFBD SMI Handler.
@param ImageHandle - EFI Image Handle.
@param SystemTable - EFI System Table.
@retval EFI_STATUS, based on the result.
*/
EFI_STATUS
EFIAPI
InSmmFunction(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_HANDLE Handle = NULL;
UINT16 i = 0;
#if OFBD_NEW_WSMT_SUPPORT == 1
UINT32 Index;
#endif
EFI_SMM_SW_DISPATCH2_PROTOCOL *pSwDispatch = NULL;
EFI_SMM_SW_REGISTER_CONTEXT SwContext = {OFBD_SW_SMI_VALUE};
InitAmiSmmLib( ImageHandle, SystemTable );
Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&gSmmBase2);
if (EFI_ERROR(Status)) return EFI_SUCCESS;
Status = pSmmBase->GetSmstLocation (gSmmBase2, &pSmst);
if (EFI_ERROR(Status)) return EFI_SUCCESS;
Status = pSmst->SmmLocateProtocol( \
&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID **)&pSwDispatch);
if (EFI_ERROR(Status)) return EFI_SUCCESS;
#if OFBD_NEW_WSMT_SUPPORT == 1
Index = PcdGet32(AmiPcdSmmCommInterfaceProperties);
Index &= AMI_SMM_COMMUNICATION_PROPERTY_NEW_STYLE_INTERFACE_SUPPORT;
if( Index == AMI_SMM_COMMUNICATION_PROPERTY_NEW_STYLE_INTERFACE_SUPPORT )
{
gUseAmiNewComm = TRUE;
Status = pSmst->SmmLocateProtocol(
&gAmiSmmCommunicationProtocolGuid,
NULL,
(VOID**)&gAmiSmmCommunication );
}
else
{
gUseAmiNewComm = FALSE;
Status = pSmst->SmmLocateProtocol(&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&gSmmCpu);
}
#else
Status = pSmst->SmmLocateProtocol(&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&gSmmCpu);
#endif
if (EFI_ERROR(Status)) return EFI_SUCCESS;
Status = pSwDispatch->Register(pSwDispatch, OFBDSMIHandler, &SwContext, &Handle);
ASSERT_EFI_ERROR(Status);
for (i = 0; OFBDInSMMFuncTbl[i] != NULL; i++)
{
OFBDInSMMFuncTbl[i]();
}
return Status;
}
/**
Ofbd (Not In Smm Function)
This function will services OFBD Not In Smm Functions.
@param ImageHandle - EFI Image Handle.
@param SystemTable - EFI System Table.
@retval EFI_STATUS, based on the result.
*/
EFI_STATUS
EFIAPI
NotInSmmFunction(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
UINT8 i;
for (i = 0; OFBDNotInSMMFunc[i] != NULL; i++) OFBDNotInSMMFunc[i]();
return EFI_SUCCESS;
}
#endif
/**
Ofbd (Ami OFBD Entry Point)
The main entry point of OFBD module.
@param ImageHandle - EFI Image Handle.
@param SystemTable - EFI System Table.
@retval EFI_STATUS, based on the result.
*/
EFI_STATUS EFIAPI AmiOFBDEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable )
{
#if OFBD_FOR_ARM_SUPPORT == 0
// 1. Setup AMI library
InitAmiLib(ImageHandle, SystemTable);
// 2. Utilize EfiLib to init
return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NULL);
#else
EFI_STATUS status = EFI_SUCCESS;
EFI_HANDLE hOfbd = NULL;
EFI_GUID gEfiOfbdHandlerGuid = OFBD_HANDLER_GUID;
AMI_FRI_PROTOCOL *afriProtocol = NULL;
// Create event for address translation of Ofbd Library
InitAmiRuntimeLib(ImageHandle, SystemTable, NULL, OfbdVirtualNotifyEvent);
// Register Ofbd handler to AFRI Protocol
status = SystemTable->BootServices->LocateProtocol(
&gAmiFriProtocolGuid,
NULL,
(VOID**)&afriProtocol);
ASSERT_EFI_ERROR(status);
status = afriProtocol->RegisterAfriHandler( OFBDSMIHandler,
&gEfiOfbdHandlerGuid,
&hOfbd );
ASSERT_EFI_ERROR(status);
//TRACE((-1, "[OFBD Module] Initialized ...\n");)
return status;
#endif
}