Add PI SMM IPL and PI SMM Core
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10094 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
499
MdeModulePkg/Core/PiSmmCore/Locate.c
Normal file
499
MdeModulePkg/Core/PiSmmCore/Locate.c
Normal file
@@ -0,0 +1,499 @@
|
||||
/** @file
|
||||
Locate handle functions
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available
|
||||
under the terms and conditions of the BSD License which accompanies this
|
||||
distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCore.h"
|
||||
|
||||
//
|
||||
// ProtocolRequest - Last LocateHandle request ID
|
||||
//
|
||||
UINTN mEfiLocateHandleRequest = 0;
|
||||
|
||||
//
|
||||
// Internal prototypes
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID *Protocol;
|
||||
VOID *SearchKey;
|
||||
LIST_ENTRY *Position;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
} LOCATE_POSITION;
|
||||
|
||||
typedef
|
||||
IHANDLE *
|
||||
(* CORE_GET_NEXT) (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
);
|
||||
|
||||
/**
|
||||
Routine to get the next Handle, when you are searching for all handles.
|
||||
|
||||
@param Position Information about which Handle to seach for.
|
||||
@param Interface Return the interface structure for the matching
|
||||
protocol.
|
||||
|
||||
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
||||
Otherwise,NULL is returned.
|
||||
|
||||
**/
|
||||
IHANDLE *
|
||||
SmmGetNextLocateAllHandles (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
|
||||
//
|
||||
// Next handle
|
||||
//
|
||||
Position->Position = Position->Position->ForwardLink;
|
||||
|
||||
//
|
||||
// If not at the end of the list, get the handle
|
||||
//
|
||||
Handle = NULL;
|
||||
*Interface = NULL;
|
||||
if (Position->Position != &gHandleList) {
|
||||
Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
|
||||
}
|
||||
return Handle;
|
||||
}
|
||||
|
||||
/**
|
||||
Routine to get the next Handle, when you are searching for register protocol
|
||||
notifies.
|
||||
|
||||
@param Position Information about which Handle to seach for.
|
||||
@param Interface Return the interface structure for the matching
|
||||
protocol.
|
||||
|
||||
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
||||
Otherwise,NULL is returned.
|
||||
|
||||
**/
|
||||
IHANDLE *
|
||||
SmmGetNextLocateByRegisterNotify (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
LIST_ENTRY *Link;
|
||||
|
||||
Handle = NULL;
|
||||
*Interface = NULL;
|
||||
ProtNotify = Position->SearchKey;
|
||||
|
||||
//
|
||||
// If this is the first request, get the next handle
|
||||
//
|
||||
if (ProtNotify != NULL) {
|
||||
ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
|
||||
Position->SearchKey = NULL;
|
||||
|
||||
//
|
||||
// If not at the end of the list, get the next handle
|
||||
//
|
||||
Link = ProtNotify->Position->ForwardLink;
|
||||
if (Link != &ProtNotify->Protocol->Protocols) {
|
||||
Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
|
||||
Handle = Prot->Handle;
|
||||
*Interface = Prot->Interface;
|
||||
}
|
||||
}
|
||||
return Handle;
|
||||
}
|
||||
|
||||
/**
|
||||
Routine to get the next Handle, when you are searching for a given protocol.
|
||||
|
||||
@param Position Information about which Handle to seach for.
|
||||
@param Interface Return the interface structure for the matching
|
||||
protocol.
|
||||
|
||||
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
||||
Otherwise,NULL is returned.
|
||||
|
||||
**/
|
||||
IHANDLE *
|
||||
SmmGetNextLocateByProtocol (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
LIST_ENTRY *Link;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
|
||||
Handle = NULL;
|
||||
*Interface = NULL;
|
||||
for (; ;) {
|
||||
//
|
||||
// Next entry
|
||||
//
|
||||
Link = Position->Position->ForwardLink;
|
||||
Position->Position = Link;
|
||||
|
||||
//
|
||||
// If not at the end, return the handle
|
||||
//
|
||||
if (Link == &Position->ProtEntry->Protocols) {
|
||||
Handle = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the handle
|
||||
//
|
||||
Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
|
||||
Handle = Prot->Handle;
|
||||
*Interface = Prot->Interface;
|
||||
|
||||
//
|
||||
// If this handle has not been returned this request, then
|
||||
// return it now
|
||||
//
|
||||
if (Handle->LocateRequest != mEfiLocateHandleRequest) {
|
||||
Handle->LocateRequest = mEfiLocateHandleRequest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Handle;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the first Protocol Interface that matches the Protocol GUID. If
|
||||
Registration is pasased in return a Protocol Instance that was just add
|
||||
to the system. If Retistration is NULL return the first Protocol Interface
|
||||
you find.
|
||||
|
||||
@param Protocol The protocol to search for
|
||||
@param Registration Optional Registration Key returned from
|
||||
RegisterProtocolNotify()
|
||||
@param Interface Return the Protocol interface (instance).
|
||||
|
||||
@retval EFI_SUCCESS If a valid Interface is returned
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_NOT_FOUND Protocol interface not found
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmLocateProtocol (
|
||||
IN EFI_GUID *Protocol,
|
||||
IN VOID *Registration OPTIONAL,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LOCATE_POSITION Position;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
IHANDLE *Handle;
|
||||
|
||||
if (Interface == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Protocol == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
*Interface = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Set initial position
|
||||
//
|
||||
Position.Protocol = Protocol;
|
||||
Position.SearchKey = Registration;
|
||||
Position.Position = &gHandleList;
|
||||
|
||||
mEfiLocateHandleRequest += 1;
|
||||
|
||||
if (Registration == NULL) {
|
||||
//
|
||||
// Look up the protocol entry and set the head pointer
|
||||
//
|
||||
Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
|
||||
if (Position.ProtEntry == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
Position.Position = &Position.ProtEntry->Protocols;
|
||||
|
||||
Handle = SmmGetNextLocateByProtocol (&Position, Interface);
|
||||
} else {
|
||||
Handle = SmmGetNextLocateByRegisterNotify (&Position, Interface);
|
||||
}
|
||||
|
||||
if (Handle == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
} else if (Registration != NULL) {
|
||||
//
|
||||
// If this is a search by register notify and a handle was
|
||||
// returned, update the register notification position
|
||||
//
|
||||
ProtNotify = Registration;
|
||||
ProtNotify->Position = ProtNotify->Position->ForwardLink;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Locates the requested handle(s) and returns them in Buffer.
|
||||
|
||||
@param SearchType The type of search to perform to locate the
|
||||
handles
|
||||
@param Protocol The protocol to search for
|
||||
@param SearchKey Dependant on SearchType
|
||||
@param BufferSize On input the size of Buffer. On output the
|
||||
size of data returned.
|
||||
@param Buffer The buffer to return the results in
|
||||
|
||||
@retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
|
||||
returned in BufferSize.
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_SUCCESS Successfully found the requested handle(s) and
|
||||
returns them in Buffer.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmLocateHandle (
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol OPTIONAL,
|
||||
IN VOID *SearchKey OPTIONAL,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT EFI_HANDLE *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LOCATE_POSITION Position;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
CORE_GET_NEXT GetNext;
|
||||
UINTN ResultSize;
|
||||
IHANDLE *Handle;
|
||||
IHANDLE **ResultBuffer;
|
||||
VOID *Interface;
|
||||
|
||||
if (BufferSize == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((*BufferSize > 0) && (Buffer == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
GetNext = NULL;
|
||||
|
||||
//
|
||||
// Set initial position
|
||||
//
|
||||
Position.Protocol = Protocol;
|
||||
Position.SearchKey = SearchKey;
|
||||
Position.Position = &gHandleList;
|
||||
|
||||
ResultSize = 0;
|
||||
ResultBuffer = (IHANDLE **) Buffer;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Get the search function based on type
|
||||
//
|
||||
switch (SearchType) {
|
||||
case AllHandles:
|
||||
GetNext = SmmGetNextLocateAllHandles;
|
||||
break;
|
||||
|
||||
case ByRegisterNotify:
|
||||
//
|
||||
// Must have SearchKey for locate ByRegisterNotify
|
||||
//
|
||||
if (SearchKey == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
GetNext = SmmGetNextLocateByRegisterNotify;
|
||||
break;
|
||||
|
||||
case ByProtocol:
|
||||
GetNext = SmmGetNextLocateByProtocol;
|
||||
if (Protocol == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Look up the protocol entry and set the head pointer
|
||||
//
|
||||
Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
|
||||
if (Position.ProtEntry == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
Position.Position = &Position.ProtEntry->Protocols;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Enumerate out the matching handles
|
||||
//
|
||||
mEfiLocateHandleRequest += 1;
|
||||
for (; ;) {
|
||||
//
|
||||
// Get the next handle. If no more handles, stop
|
||||
//
|
||||
Handle = GetNext (&Position, &Interface);
|
||||
if (NULL == Handle) {
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Increase the resulting buffer size, and if this handle
|
||||
// fits return it
|
||||
//
|
||||
ResultSize += sizeof(Handle);
|
||||
if (ResultSize <= *BufferSize) {
|
||||
*ResultBuffer = Handle;
|
||||
ResultBuffer += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the result is a zero length buffer, then there were no
|
||||
// matching handles
|
||||
//
|
||||
if (ResultSize == 0) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
} else {
|
||||
//
|
||||
// Return the resulting buffer size. If it's larger than what
|
||||
// was passed, then set the error code
|
||||
//
|
||||
if (ResultSize > *BufferSize) {
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*BufferSize = ResultSize;
|
||||
|
||||
if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
|
||||
//
|
||||
// If this is a search by register notify and a handle was
|
||||
// returned, update the register notification position
|
||||
//
|
||||
ProtNotify = SearchKey;
|
||||
ProtNotify->Position = ProtNotify->Position->ForwardLink;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Function returns an array of handles that support the requested protocol
|
||||
in a buffer allocated from pool. This is a version of SmmLocateHandle()
|
||||
that allocates a buffer for the caller.
|
||||
|
||||
@param SearchType Specifies which handle(s) are to be returned.
|
||||
@param Protocol Provides the protocol to search by. This
|
||||
parameter is only valid for SearchType
|
||||
ByProtocol.
|
||||
@param SearchKey Supplies the search key depending on the
|
||||
SearchType.
|
||||
@param NumberHandles The number of handles returned in Buffer.
|
||||
@param Buffer A pointer to the buffer to return the requested
|
||||
array of handles that support Protocol.
|
||||
|
||||
@retval EFI_SUCCESS The result array of handles was returned.
|
||||
@retval EFI_NOT_FOUND No handles match the search.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
|
||||
matching results.
|
||||
@retval EFI_INVALID_PARAMETER One or more paramters are not valid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmLocateHandleBuffer (
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol OPTIONAL,
|
||||
IN VOID *SearchKey OPTIONAL,
|
||||
IN OUT UINTN *NumberHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BufferSize;
|
||||
|
||||
if (NumberHandles == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BufferSize = 0;
|
||||
*NumberHandles = 0;
|
||||
*Buffer = NULL;
|
||||
Status = SmmLocateHandle (
|
||||
SearchType,
|
||||
Protocol,
|
||||
SearchKey,
|
||||
&BufferSize,
|
||||
*Buffer
|
||||
);
|
||||
//
|
||||
// LocateHandleBuffer() returns incorrect status code if SearchType is
|
||||
// invalid.
|
||||
//
|
||||
// Add code to correctly handle expected errors from SmmLocateHandle().
|
||||
//
|
||||
if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
|
||||
if (Status != EFI_INVALID_PARAMETER) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Buffer = AllocatePool (BufferSize);
|
||||
if (*Buffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = SmmLocateHandle (
|
||||
SearchType,
|
||||
Protocol,
|
||||
SearchKey,
|
||||
&BufferSize,
|
||||
*Buffer
|
||||
);
|
||||
|
||||
*NumberHandles = BufferSize / sizeof(EFI_HANDLE);
|
||||
if (EFI_ERROR(Status)) {
|
||||
*NumberHandles = 0;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user