alder_lake_bios/Insyde/InsydeModulePkg/Library/Irsi/IrsiRegistrationLib/IrsiRegistrationLib.c

390 lines
10 KiB
C

/** @file
Helper functions for registering new IRSI functions
;******************************************************************************
;* Copyright (c) 2012 - 2014, 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 <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeLib.h>
#include <Library/DebugLib.h>
#include <Guid/EventGroup.h>
#include <Library/IrsiRegistrationLib.h>
#include <Protocol/SmmBase2.h>
#include <Protocol/LoadedImage.h>
//
// The RuntimeServiceEntry contains virtually converted pointer of runtime services entry
//
typedef struct {
UINT64 RuntimeServicesEntry;
} RUNTIME_SERVICES_CONFIG_TABLE;
IRSI_REGISTRATION_PROTOCOL *mIrsiReg = NULL;
EFI_EVENT mIrsiRegEvent;
BOOLEAN mIsRuntimeCode;
/**
Irsi AddVirtualPointer function
This routine adds pointer to the virtual conversion list
@param Pointer pointer to be converted
@retval EFI_SUCCESS: Pointer successfully added to virtual conversion list
@retval EFI_ABORTED Failed to add virtual pointer conversion list
**/
EFI_STATUS
EFIAPI
IrsiAddVirtualPointer (
VOID **Pointer
)
{
if (mIrsiReg == NULL || !mIsRuntimeCode) {
return EFI_ABORTED;
} else {
return mIrsiReg->AddVirtualPointer(Pointer);
}
}
/**
Irsi RemoveVirtualPointer function
This routine removes pointer from the virtual conversion list
@param[in] Pointer pointer to be removed
@retval EFI_SUCCESS Pointer successfully removed from virtual conversion list.
@retval EFI_NOT_FOUND pointer isn't in the conversion list.
@retval EFI_ABORTED Failed to remove virtual pointer conversion list.
**/
EFI_STATUS
EFIAPI
IrsiRemoveVirtualPointer (
VOID **Pointer
)
{
if (mIrsiReg == NULL || !mIsRuntimeCode) {
return EFI_ABORTED;
} else {
return mIrsiReg->RemoveVirtualPointer(Pointer);
}
}
/**
Irsi Registerfunction
This routine provides Irsi function registration
@param FunctionName Name of the IRSI function
@param Guid IRSI function GUID
@param IrsiFunction The IRSI function pointer
@retval EFI_SUCCESS IRSI function successfully registered
@retval EFI_ABORTED System aborted in OS runtime
**/
EFI_STATUS
EFIAPI
IrsiRegisterFunction (
EFI_GUID *Guid,
UINT32 FunctionNumber,
IRSI_FUNCTION IrsiFunction
)
{
if (mIrsiReg == NULL ) {
return EFI_ABORTED;
} else {
return mIrsiReg->RegisterFunction(Guid, FunctionNumber, IrsiFunction);
}
}
/**
Execute IRSI function
@param Guid IRSI Service Type GUID
@param FunctionNumber Command code of IRSI function
@param CommBuf Communication Buffer
@param BufSize Buffer size
@retval EFI_SUCCESS IRSI function successfully executed
@retval EFI_ABORT Abort without executing IRSI function
@return others IRSI function executed with error
**/
EFI_STATUS
EFIAPI
IrsiExecuteFunction (
EFI_GUID *Guid,
UINT32 FunctionNumber,
VOID *CommBuf,
UINT32 BufSize
)
{
if (mIrsiReg == NULL) {
return EFI_ABORTED;
} else {
return mIrsiReg->ExecuteFunction(Guid, FunctionNumber, CommBuf, BufSize);
}
}
/**
IRSI Get Runtime Buffer
During runtime, the memory cannot be allocated by AllocatePool()
This routine provides the pre-allocated IRSI runtime buffer for use at runtime
@param IrsiBuffer Pointer to the pre-allocated runtime buffer pointer
@param BufferSize Pointer to the IRSI runtime buffer size
@retval EFI_SUCCESS Function returns successfully
@retval EFI_INVALID_PARAMETER Invalid parameter list with NULL IrsiBuffer or BufferSize pointer
@retval EFI_ABORTED Function aborted, IRSI Registration protocol not installed
**/
EFI_STATUS
EFIAPI
IrsiGetRuntimeBuffer (
VOID **IrsiBuffer,
UINTN *BufferSize
)
{
if (IrsiBuffer == NULL || BufferSize == NULL) {
return EFI_INVALID_PARAMETER;
} else if (mIrsiReg == NULL) {
return EFI_ABORTED;
} else {
return mIrsiReg->GetRuntimeBuffer(IrsiBuffer, BufferSize);
}
}
/**
Install IRSI Runtime Services
@param RuntimeServicesGuid IRSI Service Type GUID
@param BufSize Buffer size
@retval EFI_SUCCESS IRSI function successfully executed
@retval RuntimeServicesEntry Runtime Services Entrypoint
@retval EFI_SUCCESS Runtime Services successfully installed
@retval EFI_INVALID_PARAMETER NULL services GUID or NULL services entry given
@retval EFI_DEVICE_ERROR Memory allocation failed
@return others Runtime services Configuration table installation failed
**/
EFI_STATUS
EFIAPI
IrsiInstallRuntimeServices (
EFI_GUID *RuntimeServicesGuid,
IRSI_RUNTIME_SERVICES_ENTRY RuntimeServicesEntry
)
{
EFI_STATUS Status;
RUNTIME_SERVICES_CONFIG_TABLE *ServicesTable;
if (RuntimeServicesGuid == NULL || RuntimeServicesEntry == NULL) {
return EFI_INVALID_PARAMETER;
}
ServicesTable = AllocateRuntimePool(sizeof(RUNTIME_SERVICES_CONFIG_TABLE));
ASSERT (ServicesTable != NULL);
if (ServicesTable == NULL) {
return EFI_DEVICE_ERROR;
}
ServicesTable->RuntimeServicesEntry = (UINT64)(UINTN)RuntimeServicesEntry;
Status = gBS->InstallConfigurationTable (RuntimeServicesGuid, (VOID *)ServicesTable);
if (Status == EFI_SUCCESS) {
IrsiAddVirtualPointer ((VOID **)&ServicesTable->RuntimeServicesEntry);
}
return Status;
}
/**
Notification function for Irsi Registration Protocol
This routine is the notification function for Irsi Registration Protocol
@param EFI_EVENT Event of the notification
@param Context not used in this function
@retval none
**/
STATIC
VOID
EFIAPI
IrsiRegEventCallBack (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
Status = gBS->LocateProtocol (&gIrsiRegistrationProtocolGuid, NULL, (VOID **)&mIrsiReg);
if (EFI_ERROR (Status)) {
return;
}
if (mIsRuntimeCode) {
IrsiAddVirtualPointer ((VOID **)&mIrsiReg);
}
gBS->CloseEvent(Event);
}
/**
Detect whether the system is at SMM mode.
@retval TRUE System is at SMM mode.
@retval FALSE System is not at SMM mode.
**/
STATIC
BOOLEAN
IsInSmm (
VOID
)
{
EFI_STATUS Status;
EFI_SMM_BASE2_PROTOCOL *SmmBase;
BOOLEAN InSmm;
Status = gBS->LocateProtocol (
&gEfiSmmBase2ProtocolGuid,
NULL,
(VOID **)&SmmBase
);
if (EFI_ERROR (Status)) {
return FALSE;
}
InSmm = FALSE;
SmmBase->InSmm (SmmBase, &InSmm);
return InSmm;
}
/**
Function uses image handle to check image is whther EfiRuntimeServicesCode image code type.
@param[in] ImageHandle Input Image handle.
@retval TRUE This is a EfiRuntimeServicesCode image code type iamge
@retval FALSE This isn't a EfiRuntimeServicesCode image code type iamge
**/
STATIC
BOOLEAN
IsRuntimeCodeImageType (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
Status = gBS->HandleProtocol (
ImageHandle,
&gEfiLoadedImageProtocolGuid,
(VOID **)&LoadedImage
);
if (!EFI_ERROR (Status) && LoadedImage->ImageCodeType == EfiRuntimeServicesCode) {
return TRUE;
}
return FALSE;
}
/**
IrsiRegistrationLib LibraryClass constructor
This routine is a LibraryClass constructor for IrsiRegistrationLib, it will
initialize IrsiRegistrationProtocol
@param ImageHandle A handle for the image that is initializing this driver
@param SystemTable A pointer to the EFI system table
@retval EFI_SUCCESS Module initialized successfully
@return others Failed to install IrsiRegistrationLib
**/
EFI_STATUS
EFIAPI
IrsiRegistrationLibInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *Registration;
//
// System doesn't support Irsi related functions in SMM mode, so just return
// EFI_SUCCESS and doesn't do any initialization.
//
if (IsInSmm ()) {
return EFI_SUCCESS;
}
mIsRuntimeCode = IsRuntimeCodeImageType (ImageHandle);
Status = gBS->LocateProtocol (&gIrsiRegistrationProtocolGuid, NULL, (VOID **)&mIrsiReg);
if (EFI_ERROR(Status)) {
mIrsiRegEvent = EfiCreateProtocolNotifyEvent (
&gIrsiRegistrationProtocolGuid,
TPL_CALLBACK,
IrsiRegEventCallBack,
NULL,
&Registration
);
ASSERT (mIrsiRegEvent != NULL);
} else {
if (mIsRuntimeCode) {
IrsiAddVirtualPointer ((VOID **)&mIrsiReg);
}
}
return EFI_SUCCESS;
}
/**
If a runtime driver exits with an error, it must call this routine
to free the allocated resource before the exiting.
It will ASSERT() if gBS is NULL.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The Runtime Driver Lib shutdown successfully.
**/
EFI_STATUS
EFIAPI
IrsiRegistrationLibDestruct (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
ASSERT (gBS != NULL);
if (mIrsiRegEvent != NULL) {
Status = gBS->CloseEvent (mIrsiRegEvent);
ASSERT_EFI_ERROR (Status);
} else if (mIrsiReg != NULL && mIsRuntimeCode) {
IrsiRemoveVirtualPointer ((VOID **)&mIrsiReg);
}
return EFI_SUCCESS;
}