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:
532
MdeModulePkg/Core/PiSmmCore/Handle.c
Normal file
532
MdeModulePkg/Core/PiSmmCore/Handle.c
Normal file
@@ -0,0 +1,532 @@
|
||||
/** @file
|
||||
SMM handle & protocol handling.
|
||||
|
||||
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"
|
||||
|
||||
//
|
||||
// mProtocolDatabase - A list of all protocols in the system. (simple list for now)
|
||||
// gHandleList - A list of all the handles in the system
|
||||
//
|
||||
LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
|
||||
LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
|
||||
|
||||
/**
|
||||
Check whether a handle is a valid EFI_HANDLE
|
||||
|
||||
@param UserHandle The handle to check
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
|
||||
@retval EFI_SUCCESS The handle is valid EFI_HANDLE.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SmmValidateHandle (
|
||||
IN EFI_HANDLE UserHandle
|
||||
)
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
|
||||
Handle = (IHANDLE *)UserHandle;
|
||||
if (Handle == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the protocol entry for the requested protocol.
|
||||
|
||||
@param Protocol The ID of the protocol
|
||||
@param Create Create a new entry if not found
|
||||
|
||||
@return Protocol entry
|
||||
|
||||
**/
|
||||
PROTOCOL_ENTRY *
|
||||
SmmFindProtocolEntry (
|
||||
IN EFI_GUID *Protocol,
|
||||
IN BOOLEAN Create
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Link;
|
||||
PROTOCOL_ENTRY *Item;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
|
||||
//
|
||||
// Search the database for the matching GUID
|
||||
//
|
||||
|
||||
ProtEntry = NULL;
|
||||
for (Link = mProtocolDatabase.ForwardLink;
|
||||
Link != &mProtocolDatabase;
|
||||
Link = Link->ForwardLink) {
|
||||
|
||||
Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
|
||||
if (CompareGuid (&Item->ProtocolID, Protocol)) {
|
||||
//
|
||||
// This is the protocol entry
|
||||
//
|
||||
ProtEntry = Item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the protocol entry was not found and Create is TRUE, then
|
||||
// allocate a new entry
|
||||
//
|
||||
if ((ProtEntry == NULL) && Create) {
|
||||
ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));
|
||||
if (ProtEntry != NULL) {
|
||||
//
|
||||
// Initialize new protocol entry structure
|
||||
//
|
||||
ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
|
||||
CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
|
||||
InitializeListHead (&ProtEntry->Protocols);
|
||||
InitializeListHead (&ProtEntry->Notify);
|
||||
|
||||
//
|
||||
// Add it to protocol database
|
||||
//
|
||||
InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
|
||||
}
|
||||
}
|
||||
return ProtEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the protocol instance for the requested handle and protocol.
|
||||
Note: This function doesn't do parameters checking, it's caller's responsibility
|
||||
to pass in valid parameters.
|
||||
|
||||
@param Handle The handle to search the protocol on
|
||||
@param Protocol GUID of the protocol
|
||||
@param Interface The interface for the protocol being searched
|
||||
|
||||
@return Protocol instance (NULL: Not found)
|
||||
|
||||
**/
|
||||
PROTOCOL_INTERFACE *
|
||||
SmmFindProtocolInterface (
|
||||
IN IHANDLE *Handle,
|
||||
IN EFI_GUID *Protocol,
|
||||
IN VOID *Interface
|
||||
)
|
||||
{
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
LIST_ENTRY *Link;
|
||||
|
||||
Prot = NULL;
|
||||
|
||||
//
|
||||
// Lookup the protocol entry for this protocol ID
|
||||
//
|
||||
ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
|
||||
if (ProtEntry != NULL) {
|
||||
//
|
||||
// Look at each protocol interface for any matches
|
||||
//
|
||||
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
|
||||
//
|
||||
// If this protocol interface matches, remove it
|
||||
//
|
||||
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
|
||||
if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
|
||||
break;
|
||||
}
|
||||
Prot = NULL;
|
||||
}
|
||||
}
|
||||
return Prot;
|
||||
}
|
||||
|
||||
/**
|
||||
Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which
|
||||
Calls the private one which contains a BOOLEAN parameter for notifications
|
||||
|
||||
@param UserHandle The handle to install the protocol handler on,
|
||||
or NULL if a new handle is to be allocated
|
||||
@param Protocol The protocol to add to the handle
|
||||
@param InterfaceType Indicates whether Interface is supplied in
|
||||
native form.
|
||||
@param Interface The interface for the protocol being added
|
||||
|
||||
@return Status code
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmInstallProtocolInterface (
|
||||
IN OUT EFI_HANDLE *UserHandle,
|
||||
IN EFI_GUID *Protocol,
|
||||
IN EFI_INTERFACE_TYPE InterfaceType,
|
||||
IN VOID *Interface
|
||||
)
|
||||
{
|
||||
return SmmInstallProtocolInterfaceNotify (
|
||||
UserHandle,
|
||||
Protocol,
|
||||
InterfaceType,
|
||||
Interface,
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Installs a protocol interface into the boot services environment.
|
||||
|
||||
@param UserHandle The handle to install the protocol handler on,
|
||||
or NULL if a new handle is to be allocated
|
||||
@param Protocol The protocol to add to the handle
|
||||
@param InterfaceType Indicates whether Interface is supplied in
|
||||
native form.
|
||||
@param Interface The interface for the protocol being added
|
||||
@param Notify indicates whether notify the notification list
|
||||
for this protocol
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||
@retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
|
||||
@retval EFI_SUCCESS Protocol interface successfully installed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SmmInstallProtocolInterfaceNotify (
|
||||
IN OUT EFI_HANDLE *UserHandle,
|
||||
IN EFI_GUID *Protocol,
|
||||
IN EFI_INTERFACE_TYPE InterfaceType,
|
||||
IN VOID *Interface,
|
||||
IN BOOLEAN Notify
|
||||
)
|
||||
{
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
IHANDLE *Handle;
|
||||
EFI_STATUS Status;
|
||||
VOID *ExistingInterface;
|
||||
|
||||
//
|
||||
// returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
|
||||
// Also added check for invalid UserHandle and Protocol pointers.
|
||||
//
|
||||
if (UserHandle == NULL || Protocol == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (InterfaceType != EFI_NATIVE_INTERFACE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Print debug message
|
||||
//
|
||||
DEBUG((DEBUG_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface));
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
Prot = NULL;
|
||||
Handle = NULL;
|
||||
|
||||
if (*UserHandle != NULL) {
|
||||
Status = SmmHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Lookup the Protocol Entry for the requested protocol
|
||||
//
|
||||
ProtEntry = SmmFindProtocolEntry (Protocol, TRUE);
|
||||
if (ProtEntry == NULL) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate a new protocol interface structure
|
||||
//
|
||||
Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));
|
||||
if (Prot == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// If caller didn't supply a handle, allocate a new one
|
||||
//
|
||||
Handle = (IHANDLE *)*UserHandle;
|
||||
if (Handle == NULL) {
|
||||
Handle = AllocateZeroPool (sizeof(IHANDLE));
|
||||
if (Handle == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize new handler structure
|
||||
//
|
||||
Handle->Signature = EFI_HANDLE_SIGNATURE;
|
||||
InitializeListHead (&Handle->Protocols);
|
||||
|
||||
//
|
||||
// Add this handle to the list global list of all handles
|
||||
// in the system
|
||||
//
|
||||
InsertTailList (&gHandleList, &Handle->AllHandles);
|
||||
}
|
||||
|
||||
Status = SmmValidateHandle (Handle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Each interface that is added must be unique
|
||||
//
|
||||
ASSERT (SmmFindProtocolInterface (Handle, Protocol, Interface) == NULL);
|
||||
|
||||
//
|
||||
// Initialize the protocol interface structure
|
||||
//
|
||||
Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
|
||||
Prot->Handle = Handle;
|
||||
Prot->Protocol = ProtEntry;
|
||||
Prot->Interface = Interface;
|
||||
|
||||
//
|
||||
// Add this protocol interface to the head of the supported
|
||||
// protocol list for this handle
|
||||
//
|
||||
InsertHeadList (&Handle->Protocols, &Prot->Link);
|
||||
|
||||
//
|
||||
// Add this protocol interface to the tail of the
|
||||
// protocol entry
|
||||
//
|
||||
InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
|
||||
|
||||
//
|
||||
// Notify the notification list for this protocol
|
||||
//
|
||||
if (Notify) {
|
||||
SmmNotifyProtocol (Prot);
|
||||
}
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Done:
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Return the new handle back to the caller
|
||||
//
|
||||
*UserHandle = Handle;
|
||||
} else {
|
||||
//
|
||||
// There was an error, clean up
|
||||
//
|
||||
if (Prot != NULL) {
|
||||
FreePool (Prot);
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Uninstalls all instances of a protocol:interfacer from a handle.
|
||||
If the last protocol interface is remove from the handle, the
|
||||
handle is freed.
|
||||
|
||||
@param UserHandle The handle to remove the protocol handler from
|
||||
@param Protocol The protocol, of protocol:interface, to remove
|
||||
@param Interface The interface, of protocol:interface, to remove
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Protocol is NULL.
|
||||
@retval EFI_SUCCESS Protocol interface successfully uninstalled.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmUninstallProtocolInterface (
|
||||
IN EFI_HANDLE UserHandle,
|
||||
IN EFI_GUID *Protocol,
|
||||
IN VOID *Interface
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IHANDLE *Handle;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
|
||||
//
|
||||
// Check that Protocol is valid
|
||||
//
|
||||
if (Protocol == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check that UserHandle is a valid handle
|
||||
//
|
||||
Status = SmmValidateHandle (UserHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Check that Protocol exists on UserHandle, and Interface matches the interface in the database
|
||||
//
|
||||
Prot = SmmFindProtocolInterface (UserHandle, Protocol, Interface);
|
||||
if (Prot == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the protocol interface from the protocol
|
||||
//
|
||||
Status = EFI_NOT_FOUND;
|
||||
Handle = (IHANDLE *)UserHandle;
|
||||
Prot = SmmRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
|
||||
|
||||
if (Prot != NULL) {
|
||||
//
|
||||
// Remove the protocol interface from the handle
|
||||
//
|
||||
RemoveEntryList (&Prot->Link);
|
||||
|
||||
//
|
||||
// Free the memory
|
||||
//
|
||||
Prot->Signature = 0;
|
||||
FreePool (Prot);
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// If there are no more handlers for the handle, free the handle
|
||||
//
|
||||
if (IsListEmpty (&Handle->Protocols)) {
|
||||
Handle->Signature = 0;
|
||||
RemoveEntryList (&Handle->AllHandles);
|
||||
FreePool (Handle);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Locate a certain GUID protocol interface in a Handle's protocols.
|
||||
|
||||
@param UserHandle The handle to obtain the protocol interface on
|
||||
@param Protocol The GUID of the protocol
|
||||
|
||||
@return The requested protocol interface for the handle
|
||||
|
||||
**/
|
||||
PROTOCOL_INTERFACE *
|
||||
SmmGetProtocolInterface (
|
||||
IN EFI_HANDLE UserHandle,
|
||||
IN EFI_GUID *Protocol
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
IHANDLE *Handle;
|
||||
LIST_ENTRY *Link;
|
||||
|
||||
Status = SmmValidateHandle (UserHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Handle = (IHANDLE *)UserHandle;
|
||||
|
||||
//
|
||||
// Look at each protocol interface for a match
|
||||
//
|
||||
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
|
||||
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
|
||||
ProtEntry = Prot->Protocol;
|
||||
if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
|
||||
return Prot;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Queries a handle to determine if it supports a specified protocol.
|
||||
|
||||
@param UserHandle The handle being queried.
|
||||
@param Protocol The published unique identifier of the protocol.
|
||||
@param Interface Supplies the address where a pointer to the
|
||||
corresponding Protocol Interface is returned.
|
||||
|
||||
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||
@retval EFI_UNSUPPORTED The device does not support the specified protocol.
|
||||
@retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
|
||||
@retval EFI_INVALID_PARAMETER Protocol is NULL.
|
||||
@retval EFI_INVALID_PARAMETER Interface is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmHandleProtocol (
|
||||
IN EFI_HANDLE UserHandle,
|
||||
IN EFI_GUID *Protocol,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
|
||||
//
|
||||
// Check for invalid Protocol
|
||||
//
|
||||
if (Protocol == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for invalid Interface
|
||||
//
|
||||
if (Interface == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
} else {
|
||||
*Interface = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for invalid UserHandle
|
||||
//
|
||||
Status = SmmValidateHandle (UserHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Look at each protocol interface for a match
|
||||
//
|
||||
Prot = SmmGetProtocolInterface (UserHandle, Protocol);
|
||||
if (Prot == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// This is the protocol interface entry for this protocol
|
||||
//
|
||||
*Interface = Prot->Interface;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user