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:
371
MdeModulePkg/Core/PiSmmCore/Dependency.c
Normal file
371
MdeModulePkg/Core/PiSmmCore/Dependency.c
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
/** @file
|
||||||
|
SMM Driver Dispatcher Dependency Evaluator
|
||||||
|
|
||||||
|
This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
|
||||||
|
if a driver can be scheduled for execution. The criteria for
|
||||||
|
schedulability is that the dependency expression is satisfied.
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
///
|
||||||
|
/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependecy expression
|
||||||
|
/// to save time. A EFI_DEP_PUSH is evauated one an
|
||||||
|
/// replaced with EFI_DEP_REPLACE_TRUE. If PI spec's Vol 2
|
||||||
|
/// Driver Execution Environment Core Interface use 0xff
|
||||||
|
/// as new DEPEX opcode. EFI_DEP_REPLACE_TRUE should be
|
||||||
|
/// defined to a new value that is not conflicting with PI spec.
|
||||||
|
///
|
||||||
|
#define EFI_DEP_REPLACE_TRUE 0xff
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Define the initial size of the dependency expression evaluation stack
|
||||||
|
///
|
||||||
|
#define DEPEX_STACK_SIZE_INCREMENT 0x1000
|
||||||
|
|
||||||
|
//
|
||||||
|
// Global stack used to evaluate dependency expressions
|
||||||
|
//
|
||||||
|
BOOLEAN *mDepexEvaluationStack = NULL;
|
||||||
|
BOOLEAN *mDepexEvaluationStackEnd = NULL;
|
||||||
|
BOOLEAN *mDepexEvaluationStackPointer = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grow size of the Depex stack
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Stack successfully growed.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GrowDepexStack (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BOOLEAN *NewStack;
|
||||||
|
UINTN Size;
|
||||||
|
|
||||||
|
Size = DEPEX_STACK_SIZE_INCREMENT;
|
||||||
|
if (mDepexEvaluationStack != NULL) {
|
||||||
|
Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
NewStack = AllocatePool (Size * sizeof (BOOLEAN));
|
||||||
|
if (NewStack == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDepexEvaluationStack != NULL) {
|
||||||
|
//
|
||||||
|
// Copy to Old Stack to the New Stack
|
||||||
|
//
|
||||||
|
CopyMem (
|
||||||
|
NewStack,
|
||||||
|
mDepexEvaluationStack,
|
||||||
|
(mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLEAN)
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free The Old Stack
|
||||||
|
//
|
||||||
|
FreePool (mDepexEvaluationStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make the Stack pointer point to the old data in the new stack
|
||||||
|
//
|
||||||
|
mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
|
||||||
|
mDepexEvaluationStack = NewStack;
|
||||||
|
mDepexEvaluationStackEnd = NewStack + Size;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Push an element onto the Boolean Stack.
|
||||||
|
|
||||||
|
@param Value BOOLEAN to push.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
PushBool (
|
||||||
|
IN BOOLEAN Value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check for a stack overflow condition
|
||||||
|
//
|
||||||
|
if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
|
||||||
|
//
|
||||||
|
// Grow the stack
|
||||||
|
//
|
||||||
|
Status = GrowDepexStack ();
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Push the item onto the stack
|
||||||
|
//
|
||||||
|
*mDepexEvaluationStackPointer = Value;
|
||||||
|
mDepexEvaluationStackPointer++;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Pop an element from the Boolean stack.
|
||||||
|
|
||||||
|
@param Value BOOLEAN to pop.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The value was popped onto the stack.
|
||||||
|
@retval EFI_ACCESS_DENIED The pop operation underflowed the stack.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
PopBool (
|
||||||
|
OUT BOOLEAN *Value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Check for a stack underflow condition
|
||||||
|
//
|
||||||
|
if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pop the item off the stack
|
||||||
|
//
|
||||||
|
mDepexEvaluationStackPointer--;
|
||||||
|
*Value = *mDepexEvaluationStackPointer;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is the POSTFIX version of the dependency evaluator. This code does
|
||||||
|
not need to handle Before or After, as it is not valid to call this
|
||||||
|
routine in this case. The SOR is just ignored and is a nop in the grammer.
|
||||||
|
POSTFIX means all the math is done on top of the stack.
|
||||||
|
|
||||||
|
@param DriverEntry DriverEntry element to update.
|
||||||
|
|
||||||
|
@retval TRUE If driver is ready to run.
|
||||||
|
@retval FALSE If driver is not ready to run or some fatal error
|
||||||
|
was found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
SmmIsSchedulable (
|
||||||
|
IN EFI_SMM_DRIVER_ENTRY *DriverEntry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT8 *Iterator;
|
||||||
|
BOOLEAN Operator;
|
||||||
|
BOOLEAN Operator2;
|
||||||
|
EFI_GUID DriverGuid;
|
||||||
|
VOID *Interface;
|
||||||
|
|
||||||
|
Operator = FALSE;
|
||||||
|
Operator2 = FALSE;
|
||||||
|
|
||||||
|
if (DriverEntry->After || DriverEntry->Before) {
|
||||||
|
//
|
||||||
|
// If Before or After Depex skip as SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter ()
|
||||||
|
// processes them.
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DriverEntry->Depex == NULL) {
|
||||||
|
//
|
||||||
|
// A NULL Depex means that the SMM driver is not built correctly.
|
||||||
|
// All SMM drivers must have a valid depex expressiion.
|
||||||
|
//
|
||||||
|
ASSERT (FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clean out memory leaks in Depex Boolean stack. Leaks are only caused by
|
||||||
|
// incorrectly formed DEPEX expressions
|
||||||
|
//
|
||||||
|
mDepexEvaluationStackPointer = mDepexEvaluationStack;
|
||||||
|
|
||||||
|
|
||||||
|
Iterator = DriverEntry->Depex;
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
//
|
||||||
|
// Check to see if we are attempting to fetch dependency expression instructions
|
||||||
|
// past the end of the dependency expression.
|
||||||
|
//
|
||||||
|
if (((UINTN)Iterator - (UINTN)DriverEntry->Depex) >= DriverEntry->DepexSize) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Look at the opcode of the dependency expression instruction.
|
||||||
|
//
|
||||||
|
switch (*Iterator) {
|
||||||
|
case EFI_DEP_BEFORE:
|
||||||
|
case EFI_DEP_AFTER:
|
||||||
|
//
|
||||||
|
// For a well-formed Dependency Expression, the code should never get here.
|
||||||
|
// The BEFORE and AFTER are processed prior to this routine's invocation.
|
||||||
|
// If the code flow arrives at this point, there was a BEFORE or AFTER
|
||||||
|
// that were not the first opcodes.
|
||||||
|
//
|
||||||
|
ASSERT (FALSE);
|
||||||
|
case EFI_DEP_SOR:
|
||||||
|
//
|
||||||
|
// These opcodes can only appear once as the first opcode. If it is found
|
||||||
|
// at any other location, then the dependency expression evaluates to FALSE
|
||||||
|
//
|
||||||
|
if (Iterator != DriverEntry->Depex) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Otherwise, it is the first opcode and should be treated as a NOP.
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_PUSH:
|
||||||
|
//
|
||||||
|
// Push operator is followed by a GUID. Test to see if the GUID protocol
|
||||||
|
// is installed and push the boolean result on the stack.
|
||||||
|
//
|
||||||
|
CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID));
|
||||||
|
|
||||||
|
Status = SmmLocateProtocol (&DriverGuid, NULL, &Interface);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// For SMM Driver, it may depend on uefi protocols
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (&DriverGuid, NULL, &Interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = PushBool (FALSE);
|
||||||
|
} else {
|
||||||
|
*Iterator = EFI_DEP_REPLACE_TRUE;
|
||||||
|
Status = PushBool (TRUE);
|
||||||
|
}
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator += sizeof (EFI_GUID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_AND:
|
||||||
|
Status = PopBool (&Operator);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PopBool (&Operator2);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PushBool ((BOOLEAN)(Operator && Operator2));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_OR:
|
||||||
|
Status = PopBool (&Operator);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PopBool (&Operator2);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PushBool ((BOOLEAN)(Operator || Operator2));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_NOT:
|
||||||
|
Status = PopBool (&Operator);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PushBool ((BOOLEAN)(!Operator));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_TRUE:
|
||||||
|
Status = PushBool (TRUE);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_FALSE:
|
||||||
|
Status = PushBool (FALSE);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_DEP_END:
|
||||||
|
Status = PopBool (&Operator);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return Operator;
|
||||||
|
|
||||||
|
case EFI_DEP_REPLACE_TRUE:
|
||||||
|
Status = PushBool (TRUE);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator += sizeof (EFI_GUID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Skip over the Dependency Op Code we just processed in the switch.
|
||||||
|
// The math is done out of order, but it should not matter. That is
|
||||||
|
// we may add in the sizeof (EFI_GUID) before we account for the OP Code.
|
||||||
|
// This is not an issue, since we just need the correct end result. You
|
||||||
|
// need to be careful using Iterator in the loop as it's intermediate value
|
||||||
|
// may be strange.
|
||||||
|
//
|
||||||
|
Iterator++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
return FALSE;
|
||||||
|
}
|
1174
MdeModulePkg/Core/PiSmmCore/Dispatcher.c
Normal file
1174
MdeModulePkg/Core/PiSmmCore/Dispatcher.c
Normal file
File diff suppressed because it is too large
Load Diff
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;
|
||||||
|
}
|
161
MdeModulePkg/Core/PiSmmCore/InstallConfigurationTable.c
Normal file
161
MdeModulePkg/Core/PiSmmCore/InstallConfigurationTable.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/** @file
|
||||||
|
System Management System Table Services SmmInstallConfigurationTable service
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#define CONFIG_TABLE_SIZE_INCREASED 0x10
|
||||||
|
|
||||||
|
UINTN mSmmSystemTableAllocateSize = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The SmmInstallConfigurationTable() function is used to maintain the list
|
||||||
|
of configuration tables that are stored in the System Management System
|
||||||
|
Table. The list is stored as an array of (GUID, Pointer) pairs. The list
|
||||||
|
must be allocated from pool memory with PoolType set to EfiRuntimeServicesData.
|
||||||
|
|
||||||
|
@param SystemTable A pointer to the SMM System Table (SMST).
|
||||||
|
@param Guid A pointer to the GUID for the entry to add, update, or remove.
|
||||||
|
@param Table A pointer to the buffer of the table to add.
|
||||||
|
@param TableSize The size of the table to install.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
|
||||||
|
@retval EFI_INVALID_PARAMETER Guid is not valid.
|
||||||
|
@retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmInstallConfigurationTable (
|
||||||
|
IN CONST EFI_SMM_SYSTEM_TABLE2 *SystemTable,
|
||||||
|
IN CONST EFI_GUID *Guid,
|
||||||
|
IN VOID *Table,
|
||||||
|
IN UINTN TableSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_CONFIGURATION_TABLE *ConfigurationTable;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If Guid is NULL, then this operation cannot be performed
|
||||||
|
//
|
||||||
|
if (Guid == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationTable = gSmmCoreSmst.SmmConfigurationTable;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search all the table for an entry that matches Guid
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < gSmmCoreSmst.NumberOfTableEntries; Index++) {
|
||||||
|
if (CompareGuid (Guid, &(ConfigurationTable[Index].VendorGuid))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index < gSmmCoreSmst.NumberOfTableEntries) {
|
||||||
|
//
|
||||||
|
// A match was found, so this is either a modify or a delete operation
|
||||||
|
//
|
||||||
|
if (Table != NULL) {
|
||||||
|
//
|
||||||
|
// If Table is not NULL, then this is a modify operation.
|
||||||
|
// Modify the table enty and return.
|
||||||
|
//
|
||||||
|
ConfigurationTable[Index].VendorTable = Table;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// A match was found and Table is NULL, so this is a delete operation.
|
||||||
|
//
|
||||||
|
gSmmCoreSmst.NumberOfTableEntries--;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Copy over deleted entry
|
||||||
|
//
|
||||||
|
CopyMem (
|
||||||
|
&(ConfigurationTable[Index]),
|
||||||
|
&(ConfigurationTable[Index + 1]),
|
||||||
|
(gSmmCoreSmst.NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// No matching GUIDs were found, so this is an add operation.
|
||||||
|
//
|
||||||
|
if (Table == NULL) {
|
||||||
|
//
|
||||||
|
// If Table is NULL on an add operation, then return an error.
|
||||||
|
//
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Assume that Index == gSmmCoreSmst.NumberOfTableEntries
|
||||||
|
//
|
||||||
|
if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSmmSystemTableAllocateSize) {
|
||||||
|
//
|
||||||
|
// Allocate a table with one additional entry.
|
||||||
|
//
|
||||||
|
mSmmSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
|
||||||
|
ConfigurationTable = AllocatePool (mSmmSystemTableAllocateSize);
|
||||||
|
if (ConfigurationTable == NULL) {
|
||||||
|
//
|
||||||
|
// If a new table could not be allocated, then return an error.
|
||||||
|
//
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gSmmCoreSmst.SmmConfigurationTable != NULL) {
|
||||||
|
//
|
||||||
|
// Copy the old table to the new table.
|
||||||
|
//
|
||||||
|
CopyMem (
|
||||||
|
ConfigurationTable,
|
||||||
|
gSmmCoreSmst.SmmConfigurationTable,
|
||||||
|
Index * sizeof (EFI_CONFIGURATION_TABLE)
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free Old Table
|
||||||
|
//
|
||||||
|
FreePool (gSmmCoreSmst.SmmConfigurationTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update System Table
|
||||||
|
//
|
||||||
|
gSmmCoreSmst.SmmConfigurationTable = ConfigurationTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill in the new entry
|
||||||
|
//
|
||||||
|
CopyGuid ((VOID *)&ConfigurationTable[Index].VendorGuid, Guid);
|
||||||
|
ConfigurationTable[Index].VendorTable = Table;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is an add operation, so increment the number of table entries
|
||||||
|
//
|
||||||
|
gSmmCoreSmst.NumberOfTableEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CRC-32 field is ignorable for SMM System Table and should be set to zero
|
||||||
|
//
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
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;
|
||||||
|
}
|
170
MdeModulePkg/Core/PiSmmCore/Notify.c
Normal file
170
MdeModulePkg/Core/PiSmmCore/Notify.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/** @file
|
||||||
|
Support functions for UEFI protocol notification infrastructure.
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Signal event for every protocol in protocol entry.
|
||||||
|
|
||||||
|
@param Prot Protocol interface
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmNotifyProtocol (
|
||||||
|
IN PROTOCOL_INTERFACE *Prot
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PROTOCOL_ENTRY *ProtEntry;
|
||||||
|
PROTOCOL_NOTIFY *ProtNotify;
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
|
||||||
|
ProtEntry = Prot->Protocol;
|
||||||
|
for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
|
||||||
|
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
|
||||||
|
ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes Protocol from the protocol list (but not the handle list).
|
||||||
|
|
||||||
|
@param Handle The handle to remove protocol on.
|
||||||
|
@param Protocol GUID of the protocol to be moved
|
||||||
|
@param Interface The interface of the protocol
|
||||||
|
|
||||||
|
@return Protocol Entry
|
||||||
|
|
||||||
|
**/
|
||||||
|
PROTOCOL_INTERFACE *
|
||||||
|
SmmRemoveInterfaceFromProtocol (
|
||||||
|
IN IHANDLE *Handle,
|
||||||
|
IN EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PROTOCOL_INTERFACE *Prot;
|
||||||
|
PROTOCOL_NOTIFY *ProtNotify;
|
||||||
|
PROTOCOL_ENTRY *ProtEntry;
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
|
||||||
|
Prot = SmmFindProtocolInterface (Handle, Protocol, Interface);
|
||||||
|
if (Prot != NULL) {
|
||||||
|
|
||||||
|
ProtEntry = Prot->Protocol;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If there's a protocol notify location pointing to this entry, back it up one
|
||||||
|
//
|
||||||
|
for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
|
||||||
|
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
|
||||||
|
|
||||||
|
if (ProtNotify->Position == &Prot->ByProtocol) {
|
||||||
|
ProtNotify->Position = Prot->ByProtocol.BackLink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Remove the protocol interface entry
|
||||||
|
//
|
||||||
|
RemoveEntryList (&Prot->ByProtocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Prot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add a new protocol notification record for the request protocol.
|
||||||
|
|
||||||
|
@param Protocol The requested protocol to add the notify
|
||||||
|
registration
|
||||||
|
@param Function Points to the notification function
|
||||||
|
@param Registration Returns the registration record
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||||
|
@retval EFI_SUCCESS Successfully returned the registration record
|
||||||
|
that has been added
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmRegisterProtocolNotify (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN EFI_SMM_NOTIFY_FN Function,
|
||||||
|
OUT VOID **Registration
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PROTOCOL_ENTRY *ProtEntry;
|
||||||
|
PROTOCOL_NOTIFY *ProtNotify;
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
if ((Protocol == NULL) || (Function == NULL) || (Registration == NULL)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtNotify = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the protocol entry to add the notification too
|
||||||
|
//
|
||||||
|
ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);
|
||||||
|
if (ProtEntry != NULL) {
|
||||||
|
//
|
||||||
|
// Find whether notification already exist
|
||||||
|
//
|
||||||
|
for (Link = ProtEntry->Notify.ForwardLink;
|
||||||
|
Link != &ProtEntry->Notify;
|
||||||
|
Link = Link->ForwardLink) {
|
||||||
|
|
||||||
|
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
|
||||||
|
if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
|
||||||
|
(ProtNotify->Function == Function)) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notification already exist
|
||||||
|
//
|
||||||
|
*Registration = ProtNotify;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate a new notification record
|
||||||
|
//
|
||||||
|
ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
|
||||||
|
if (ProtNotify != NULL) {
|
||||||
|
ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
|
||||||
|
ProtNotify->Protocol = ProtEntry;
|
||||||
|
ProtNotify->Function = Function;
|
||||||
|
//
|
||||||
|
// Start at the ending
|
||||||
|
//
|
||||||
|
ProtNotify->Position = ProtEntry->Protocols.BackLink;
|
||||||
|
|
||||||
|
InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Done. If we have a protocol notify entry, then return it.
|
||||||
|
// Otherwise, we must have run out of resources trying to add one
|
||||||
|
//
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
if (ProtNotify != NULL) {
|
||||||
|
*Registration = ProtNotify;
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
318
MdeModulePkg/Core/PiSmmCore/Page.c
Normal file
318
MdeModulePkg/Core/PiSmmCore/Page.c
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/** @file
|
||||||
|
SMM Memory page management 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"
|
||||||
|
|
||||||
|
#define TRUNCATE_TO_PAGES(a) ((a) >> EFI_PAGE_SHIFT)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
UINTN NumberOfPages;
|
||||||
|
} FREE_PAGE_LIST;
|
||||||
|
|
||||||
|
LIST_ENTRY mSmmMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal Function. Allocate n pages from given free page node.
|
||||||
|
|
||||||
|
@param Pages The free page node.
|
||||||
|
@param NumberOfPages Number of pages to be allocated.
|
||||||
|
@param MaxAddress Request to allocate memory below this address.
|
||||||
|
|
||||||
|
@return Memory address of allocated pages.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
InternalAllocPagesOnOneNode (
|
||||||
|
IN OUT FREE_PAGE_LIST *Pages,
|
||||||
|
IN UINTN NumberOfPages,
|
||||||
|
IN UINTN MaxAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Top;
|
||||||
|
UINTN Bottom;
|
||||||
|
FREE_PAGE_LIST *Node;
|
||||||
|
|
||||||
|
Top = TRUNCATE_TO_PAGES (MaxAddress + 1 - (UINTN)Pages);
|
||||||
|
if (Top > Pages->NumberOfPages) {
|
||||||
|
Top = Pages->NumberOfPages;
|
||||||
|
}
|
||||||
|
Bottom = Top - NumberOfPages;
|
||||||
|
|
||||||
|
if (Top < Pages->NumberOfPages) {
|
||||||
|
Node = (FREE_PAGE_LIST*)((UINTN)Pages + EFI_PAGES_TO_SIZE (Top));
|
||||||
|
Node->NumberOfPages = Pages->NumberOfPages - Top;
|
||||||
|
InsertHeadList (&Pages->Link, &Node->Link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bottom > 0) {
|
||||||
|
Pages->NumberOfPages = Bottom;
|
||||||
|
} else {
|
||||||
|
RemoveEntryList (&Pages->Link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (UINTN)Pages + EFI_PAGES_TO_SIZE (Bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal Function. Allocate n pages from free page list below MaxAddress.
|
||||||
|
|
||||||
|
@param FreePageList The free page node.
|
||||||
|
@param NumberOfPages Number of pages to be allocated.
|
||||||
|
@param MaxAddress Request to allocate memory below this address.
|
||||||
|
|
||||||
|
@return Memory address of allocated pages.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
InternalAllocMaxAddress (
|
||||||
|
IN OUT LIST_ENTRY *FreePageList,
|
||||||
|
IN UINTN NumberOfPages,
|
||||||
|
IN UINTN MaxAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LIST_ENTRY *Node;
|
||||||
|
FREE_PAGE_LIST *Pages;
|
||||||
|
|
||||||
|
for (Node = FreePageList->BackLink; Node != FreePageList; Node = Node->BackLink) {
|
||||||
|
Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
|
||||||
|
if (Pages->NumberOfPages >= NumberOfPages &&
|
||||||
|
(UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) {
|
||||||
|
return InternalAllocPagesOnOneNode (Pages, NumberOfPages, MaxAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (UINTN)(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal Function. Allocate n pages from free page list at given address.
|
||||||
|
|
||||||
|
@param FreePageList The free page node.
|
||||||
|
@param NumberOfPages Number of pages to be allocated.
|
||||||
|
@param MaxAddress Request to allocate memory below this address.
|
||||||
|
|
||||||
|
@return Memory address of allocated pages.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
InternalAllocAddress (
|
||||||
|
IN OUT LIST_ENTRY *FreePageList,
|
||||||
|
IN UINTN NumberOfPages,
|
||||||
|
IN UINTN Address
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN EndAddress;
|
||||||
|
LIST_ENTRY *Node;
|
||||||
|
FREE_PAGE_LIST *Pages;
|
||||||
|
|
||||||
|
if ((Address & EFI_PAGE_MASK) != 0) {
|
||||||
|
return ~Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndAddress = Address + EFI_PAGES_TO_SIZE (NumberOfPages);
|
||||||
|
for (Node = FreePageList->BackLink; Node!= FreePageList; Node = Node->BackLink) {
|
||||||
|
Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
|
||||||
|
if ((UINTN)Pages <= Address) {
|
||||||
|
if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) < EndAddress) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return InternalAllocPagesOnOneNode (Pages, NumberOfPages, EndAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ~Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocates pages from the memory map.
|
||||||
|
|
||||||
|
@param Type The type of allocation to perform.
|
||||||
|
@param MemoryType The type of memory to turn the allocated pages
|
||||||
|
into.
|
||||||
|
@param NumberOfPages The number of pages to allocate.
|
||||||
|
@param Memory A pointer to receive the base allocated memory
|
||||||
|
address.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
|
||||||
|
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
|
||||||
|
@retval EFI_SUCCESS Pages successfully allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmAllocatePages (
|
||||||
|
IN EFI_ALLOCATE_TYPE Type,
|
||||||
|
IN EFI_MEMORY_TYPE MemoryType,
|
||||||
|
IN UINTN NumberOfPages,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN RequestedAddress;
|
||||||
|
|
||||||
|
if (MemoryType != EfiRuntimeServicesCode &&
|
||||||
|
MemoryType != EfiRuntimeServicesData) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumberOfPages > TRUNCATE_TO_PAGES ((UINTN)-1) + 1) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We don't track memory type in SMM
|
||||||
|
//
|
||||||
|
RequestedAddress = (UINTN)*Memory;
|
||||||
|
switch (Type) {
|
||||||
|
case AllocateAnyPages:
|
||||||
|
RequestedAddress = (UINTN)(-1);
|
||||||
|
case AllocateMaxAddress:
|
||||||
|
*Memory = InternalAllocMaxAddress (
|
||||||
|
&mSmmMemoryMap,
|
||||||
|
NumberOfPages,
|
||||||
|
RequestedAddress
|
||||||
|
);
|
||||||
|
if (*Memory == (UINTN)-1) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AllocateAddress:
|
||||||
|
*Memory = InternalAllocAddress (
|
||||||
|
&mSmmMemoryMap,
|
||||||
|
NumberOfPages,
|
||||||
|
RequestedAddress
|
||||||
|
);
|
||||||
|
if (*Memory != RequestedAddress) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal Function. Merge two adjacent nodes.
|
||||||
|
|
||||||
|
@param First The first of two nodes to merge.
|
||||||
|
|
||||||
|
@return Pointer to node after merge (if success) or pointer to next node (if fail).
|
||||||
|
|
||||||
|
**/
|
||||||
|
FREE_PAGE_LIST *
|
||||||
|
InternalMergeNodes (
|
||||||
|
IN FREE_PAGE_LIST *First
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FREE_PAGE_LIST *Next;
|
||||||
|
|
||||||
|
Next = BASE_CR (First->Link.ForwardLink, FREE_PAGE_LIST, Link);
|
||||||
|
ASSERT (
|
||||||
|
TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) >= First->NumberOfPages);
|
||||||
|
|
||||||
|
if (TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) == First->NumberOfPages) {
|
||||||
|
First->NumberOfPages += Next->NumberOfPages;
|
||||||
|
RemoveEntryList (&Next->Link);
|
||||||
|
Next = First;
|
||||||
|
}
|
||||||
|
return Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees previous allocated pages.
|
||||||
|
|
||||||
|
@param Memory Base address of memory being freed.
|
||||||
|
@param NumberOfPages The number of pages to free.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND Could not find the entry that covers the range.
|
||||||
|
@retval EFI_INVALID_PARAMETER Address not aligned.
|
||||||
|
@return EFI_SUCCESS Pages successfully freed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmFreePages (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||||
|
IN UINTN NumberOfPages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LIST_ENTRY *Node;
|
||||||
|
FREE_PAGE_LIST *Pages;
|
||||||
|
|
||||||
|
if ((Memory & EFI_PAGE_MASK) != 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pages = NULL;
|
||||||
|
Node = mSmmMemoryMap.ForwardLink;
|
||||||
|
while (Node != &mSmmMemoryMap) {
|
||||||
|
Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
|
||||||
|
if (Memory < (UINTN)Pages) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Node = Node->ForwardLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Node != &mSmmMemoryMap &&
|
||||||
|
Memory + EFI_PAGES_TO_SIZE (NumberOfPages) > (UINTN)Pages) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Node->BackLink != &mSmmMemoryMap) {
|
||||||
|
Pages = BASE_CR (Node->BackLink, FREE_PAGE_LIST, Link);
|
||||||
|
if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) > Memory) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pages = (FREE_PAGE_LIST*)(UINTN)Memory;
|
||||||
|
Pages->NumberOfPages = NumberOfPages;
|
||||||
|
InsertTailList (Node, &Pages->Link);
|
||||||
|
|
||||||
|
if (Pages->Link.BackLink != &mSmmMemoryMap) {
|
||||||
|
Pages = InternalMergeNodes (
|
||||||
|
BASE_CR (Pages->Link.BackLink, FREE_PAGE_LIST, Link)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Node != &mSmmMemoryMap) {
|
||||||
|
InternalMergeNodes (Pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add free SMRAM region for use by memory service.
|
||||||
|
|
||||||
|
@param MemBase Base address of memory region.
|
||||||
|
@param MemLength Length of the memory region.
|
||||||
|
@param Type Memory type.
|
||||||
|
@param Attributes Memory region state.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmAddMemoryRegion (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS MemBase,
|
||||||
|
IN UINT64 MemLength,
|
||||||
|
IN EFI_MEMORY_TYPE Type,
|
||||||
|
IN UINT64 Attributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN AlignedMemBase;
|
||||||
|
|
||||||
|
AlignedMemBase = (UINTN)(MemBase + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
|
||||||
|
MemLength -= AlignedMemBase - MemBase;
|
||||||
|
SmmFreePages (AlignedMemBase, TRUNCATE_TO_PAGES ((UINTN)MemLength));
|
||||||
|
}
|
363
MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
Normal file
363
MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/** @file
|
||||||
|
SMM Core Main Entry Point
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Physical pointer to private structure shared between SMM IPL and the SMM Core
|
||||||
|
//
|
||||||
|
SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SMM Core global variable for SMM System Table. Only accessed as a physical structure in SMRAM.
|
||||||
|
//
|
||||||
|
EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst = {
|
||||||
|
{
|
||||||
|
SMM_SMST_SIGNATURE,
|
||||||
|
EFI_SMM_SYSTEM_TABLE2_REVISION,
|
||||||
|
sizeof (gSmmCoreSmst.Hdr)
|
||||||
|
},
|
||||||
|
NULL, // SmmFirmwareVendor
|
||||||
|
0, // SmmFirmwareRevision
|
||||||
|
SmmInstallConfigurationTable,
|
||||||
|
{
|
||||||
|
{
|
||||||
|
(EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmMemRead
|
||||||
|
(EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmMemWrite
|
||||||
|
},
|
||||||
|
{
|
||||||
|
(EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmIoRead
|
||||||
|
(EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmIoWrite
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SmmAllocatePool,
|
||||||
|
SmmFreePool,
|
||||||
|
SmmAllocatePages,
|
||||||
|
SmmFreePages,
|
||||||
|
NULL, // SmmStartupThisAp
|
||||||
|
0, // CurrentlyExecutingCpu
|
||||||
|
0, // NumberOfCpus
|
||||||
|
NULL, // CpuSaveStateSize
|
||||||
|
NULL, // CpuSaveState
|
||||||
|
0, // NumberOfTableEntries
|
||||||
|
NULL, // SmmConfigurationTable
|
||||||
|
SmmInstallProtocolInterface,
|
||||||
|
SmmUninstallProtocolInterface,
|
||||||
|
SmmHandleProtocol,
|
||||||
|
SmmRegisterProtocolNotify,
|
||||||
|
SmmLocateHandle,
|
||||||
|
SmmLocateProtocol,
|
||||||
|
SmiManage,
|
||||||
|
SmiHandlerRegister,
|
||||||
|
SmiHandlerUnRegister
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Flag to determine if the platform has performed a legacy boot.
|
||||||
|
// If this flag is TRUE, then the runtime code and runtime data associated with the
|
||||||
|
// SMM IPL are converted to free memory, so the SMM COre must guarantee that is
|
||||||
|
// does not touch of the code/data associated with the SMM IPL if this flag is TRUE.
|
||||||
|
//
|
||||||
|
BOOLEAN mInLegacyBoot = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Table of SMI Handlers that are registered by the SMM Core when it is initialized
|
||||||
|
//
|
||||||
|
SMM_CORE_SMI_HANDLERS mSmmCoreSmiHandlers[] = {
|
||||||
|
{ SmmDriverDispatchHandler, &gEfiEventDxeDispatchGuid, NULL, TRUE },
|
||||||
|
{ SmmReadyToLockHandler, &gEfiDxeSmmReadyToLockProtocolGuid, NULL, FALSE },
|
||||||
|
{ SmmLegacyBootHandler, &gEfiEventLegacyBootGuid, NULL, FALSE },
|
||||||
|
{ NULL, NULL, NULL, FALSE }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Place holder function until all the SMM System Table Service are available.
|
||||||
|
|
||||||
|
Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.
|
||||||
|
|
||||||
|
@param Arg1 Undefined
|
||||||
|
@param Arg2 Undefined
|
||||||
|
@param Arg3 Undefined
|
||||||
|
@param Arg4 Undefined
|
||||||
|
@param Arg5 Undefined
|
||||||
|
|
||||||
|
@return EFI_NOT_AVAILABLE_YET
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmEfiNotAvailableYetArg5 (
|
||||||
|
UINTN Arg1,
|
||||||
|
UINTN Arg2,
|
||||||
|
UINTN Arg3,
|
||||||
|
UINTN Arg4,
|
||||||
|
UINTN Arg5
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// This function should never be executed. If it does, then the architectural protocols
|
||||||
|
// have not been designed correctly.
|
||||||
|
//
|
||||||
|
return EFI_NOT_AVAILABLE_YET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Software SMI handler that is called when a Legacy Boot event is signalled. The SMM
|
||||||
|
Core uses this signal to know that a Legacy Boot has been performed and that
|
||||||
|
gSmmCorePrivate that is shared between the UEFI and SMM execution environments can
|
||||||
|
not be accessed from SMM anymore since that structure is considered free memory by
|
||||||
|
a legacy OS.
|
||||||
|
|
||||||
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||||
|
@param Context Points to an optional handler context which was specified when the handler was registered.
|
||||||
|
@param CommBuffer A pointer to a collection of data in memory that will
|
||||||
|
be conveyed from a non-SMM environment into an SMM environment.
|
||||||
|
@param CommBufferSize The size of the CommBuffer.
|
||||||
|
|
||||||
|
@return Status Code
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmLegacyBootHandler (
|
||||||
|
IN EFI_HANDLE DispatchHandle,
|
||||||
|
IN CONST VOID *Context, OPTIONAL
|
||||||
|
IN OUT VOID *CommBuffer, OPTIONAL
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mInLegacyBoot = TRUE;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Software SMI handler that is called when the DxeSmmReadyToLock protocol is added
|
||||||
|
or if gEfiEventReadyToBootGuid is signalled. This function unregisters the
|
||||||
|
Software SMIs that are nor required after SMRAM is locked and installs the
|
||||||
|
SMM Ready To Lock Protocol so SMM Drivers are informed that SMRAM is about
|
||||||
|
to be locked. It also verifies the the SMM CPU I/O 2 Protocol has been installed
|
||||||
|
and NULLs gBS and gST because they can not longer be used after SMRAM is locked.
|
||||||
|
|
||||||
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||||
|
@param Context Points to an optional handler context which was specified when the handler was registered.
|
||||||
|
@param CommBuffer A pointer to a collection of data in memory that will
|
||||||
|
be conveyed from a non-SMM environment into an SMM environment.
|
||||||
|
@param CommBufferSize The size of the CommBuffer.
|
||||||
|
|
||||||
|
@return Status Code
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmReadyToLockHandler (
|
||||||
|
IN EFI_HANDLE DispatchHandle,
|
||||||
|
IN CONST VOID *Context, OPTIONAL
|
||||||
|
IN OUT VOID *CommBuffer, OPTIONAL
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_HANDLE SmmHandle;
|
||||||
|
VOID *Interface;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Unregister SMI Handlers that are no required after the SMM driver dispatch is stopped
|
||||||
|
//
|
||||||
|
for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
|
||||||
|
if (mSmmCoreSmiHandlers[Index].UnRegister) {
|
||||||
|
SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install SMM Ready to lock protocol
|
||||||
|
//
|
||||||
|
SmmHandle = NULL;
|
||||||
|
Status = SmmInstallProtocolInterface (
|
||||||
|
&SmmHandle,
|
||||||
|
&gEfiSmmReadyToLockProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure SMM CPU I/O 2 Procol has been installed into the handle database
|
||||||
|
//
|
||||||
|
Status = SmmLocateProtocol (&gEfiSmmCpuIo2ProtocolGuid, NULL, &Interface);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print a message on a debug build if the SMM CPU I/O 2 Protocol is not installed
|
||||||
|
//
|
||||||
|
DEBUG_CODE_BEGIN ();
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));
|
||||||
|
}
|
||||||
|
DEBUG_CODE_END ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Assert if the CPU I/O 2 Protocol is not installed
|
||||||
|
//
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Display any drivers that were not dispatched because dependency expression
|
||||||
|
// evaluated to false if this is a debug build
|
||||||
|
//
|
||||||
|
DEBUG_CODE_BEGIN ();
|
||||||
|
SmmDisplayDiscoveredNotDispatched ();
|
||||||
|
DEBUG_CODE_END ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Not allowed to use gST or gBS after lock
|
||||||
|
//
|
||||||
|
gST = NULL;
|
||||||
|
gBS = NULL;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The main entry point to SMM Foundation.
|
||||||
|
|
||||||
|
Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.
|
||||||
|
|
||||||
|
@param SmmEntryContext Processor information and functionality
|
||||||
|
needed by SMM Foundation.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SmmEntryPoint (
|
||||||
|
IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
|
||||||
|
BOOLEAN OldInSmm;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update SMST using the context
|
||||||
|
//
|
||||||
|
CopyMem (&gSmmCoreSmst.SmmStartupThisAp, SmmEntryContext, sizeof (EFI_SMM_ENTRY_CONTEXT));
|
||||||
|
|
||||||
|
//
|
||||||
|
// If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed
|
||||||
|
//
|
||||||
|
if (mInLegacyBoot) {
|
||||||
|
//
|
||||||
|
// Asynchronous SMI
|
||||||
|
//
|
||||||
|
SmiManage (NULL, NULL, NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save current InSmm state and set InSmm state to TRUE, it will be used by SmmBase2 protocol
|
||||||
|
//
|
||||||
|
OldInSmm = gSmmCorePrivate->InSmm;
|
||||||
|
gSmmCorePrivate->InSmm = TRUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check to see if this is a Synchronous SMI sent through the SMM Communication
|
||||||
|
// Protocol or an Asynchronous SMI
|
||||||
|
//
|
||||||
|
if (gSmmCorePrivate->CommunicationBuffer != NULL) {
|
||||||
|
//
|
||||||
|
// Synchronous SMI for SMM Core or request from Communicate protocol
|
||||||
|
//
|
||||||
|
CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)gSmmCorePrivate->CommunicationBuffer;
|
||||||
|
*gSmmCorePrivate->BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
|
||||||
|
Status = SmiManage (
|
||||||
|
&CommunicateHeader->HeaderGuid,
|
||||||
|
NULL,
|
||||||
|
CommunicateHeader->Data,
|
||||||
|
gSmmCorePrivate->BufferSize
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update CommunicationBuffer, BufferSize and ReturnStatus
|
||||||
|
// Communicate service finished, reset the pointer to CommBuffer to NULL
|
||||||
|
//
|
||||||
|
*gSmmCorePrivate->BufferSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
|
||||||
|
gSmmCorePrivate->CommunicationBuffer = NULL;
|
||||||
|
gSmmCorePrivate->ReturnStatus = (Status == EFI_WARN_INTERRUPT_SOURCE_QUIESCED) ? EFI_SUCCESS : EFI_NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Asynchronous SMI
|
||||||
|
//
|
||||||
|
SmiManage (NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Restore original InSmm state as we are going to leave SMM
|
||||||
|
//
|
||||||
|
gSmmCorePrivate->InSmm = OldInSmm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The Entry Point for SMM Core
|
||||||
|
|
||||||
|
Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core
|
||||||
|
EntryPoint on the SMI vector.
|
||||||
|
|
||||||
|
Note: This function is called for both DXE invocation and SMRAM invocation.
|
||||||
|
|
||||||
|
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||||
|
@param SystemTable A pointer to the EFI System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||||
|
@retval Other Some error occurred when executing this entry point.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmMain (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get SMM Core Private context passed in from SMM IPL in ImageHandle.
|
||||||
|
//
|
||||||
|
gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.
|
||||||
|
//
|
||||||
|
gSmmCorePrivate->Smst = &gSmmCoreSmst;
|
||||||
|
gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize memory service using free SMRAM
|
||||||
|
//
|
||||||
|
SmmInitializeMemoryServices (gSmmCorePrivate->SmramRangeCount, gSmmCorePrivate->SmramRanges);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register all SMI Handlers required by the SMM Core
|
||||||
|
//
|
||||||
|
for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
|
||||||
|
Status = SmiHandlerRegister (
|
||||||
|
mSmmCoreSmiHandlers[Index].Handler,
|
||||||
|
mSmmCoreSmiHandlers[Index].HandlerType,
|
||||||
|
&mSmmCoreSmiHandlers[Index].DispatchHandle
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
718
MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
Normal file
718
MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
Normal file
@ -0,0 +1,718 @@
|
|||||||
|
/** @file
|
||||||
|
The internal header file includes the common header files, defines
|
||||||
|
internal structure and functions used by SmmCore module.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _SMM_CORE_H_
|
||||||
|
#define _SMM_CORE_H_
|
||||||
|
|
||||||
|
#include <PiSmm.h>
|
||||||
|
|
||||||
|
#include <Protocol/DxeSmmReadyToLock.h>
|
||||||
|
#include <Protocol/SmmReadyToLock.h>
|
||||||
|
#include <Protocol/CpuIo2.h>
|
||||||
|
#include <Protocol/SmmCommunication.h>
|
||||||
|
#include <Protocol/SmmAccess2.h>
|
||||||
|
#include <Protocol/FirmwareVolume2.h>
|
||||||
|
#include <Protocol/LoadedImage.h>
|
||||||
|
#include <Protocol/DevicePath.h>
|
||||||
|
#include <Protocol/Security.h>
|
||||||
|
|
||||||
|
#include <Guid/Apriori.h>
|
||||||
|
#include <Guid/EventGroup.h>
|
||||||
|
#include <Guid/EventLegacyBios.h>
|
||||||
|
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/PeCoffLib.h>
|
||||||
|
#include <Library/CacheMaintenanceLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/ReportStatusCodeLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/DevicePathLib.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
|
||||||
|
#include "PiSmmCorePrivateData.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Used to build a table of SMI Handlers that the SMM Core registers
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
EFI_SMM_HANDLER_ENTRY_POINT2 Handler;
|
||||||
|
EFI_GUID *HandlerType;
|
||||||
|
EFI_HANDLE DispatchHandle;
|
||||||
|
BOOLEAN UnRegister;
|
||||||
|
} SMM_CORE_SMI_HANDLERS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structure for recording the state of an SMM Driver
|
||||||
|
//
|
||||||
|
#define EFI_SMM_DRIVER_ENTRY_SIGNATURE SIGNATURE_32('s', 'd','r','v')
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
LIST_ENTRY Link; // mDriverList
|
||||||
|
|
||||||
|
LIST_ENTRY ScheduledLink; // mScheduledQueue
|
||||||
|
|
||||||
|
EFI_HANDLE FvHandle;
|
||||||
|
EFI_GUID FileName;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
|
||||||
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
||||||
|
|
||||||
|
VOID *Depex;
|
||||||
|
UINTN DepexSize;
|
||||||
|
|
||||||
|
BOOLEAN Before;
|
||||||
|
BOOLEAN After;
|
||||||
|
EFI_GUID BeforeAfterGuid;
|
||||||
|
|
||||||
|
BOOLEAN Dependent;
|
||||||
|
BOOLEAN Unrequested;
|
||||||
|
BOOLEAN Scheduled;
|
||||||
|
BOOLEAN Untrusted;
|
||||||
|
BOOLEAN Initialized;
|
||||||
|
BOOLEAN DepexProtocolError;
|
||||||
|
|
||||||
|
EFI_HANDLE ImageHandle;
|
||||||
|
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
||||||
|
//
|
||||||
|
// Image EntryPoint in SMRAM
|
||||||
|
//
|
||||||
|
PHYSICAL_ADDRESS ImageEntryPoint;
|
||||||
|
//
|
||||||
|
// Image Buffer in SMRAM
|
||||||
|
//
|
||||||
|
PHYSICAL_ADDRESS ImageBuffer;
|
||||||
|
//
|
||||||
|
// Image Page Number
|
||||||
|
//
|
||||||
|
UINTN NumberOfPage;
|
||||||
|
} EFI_SMM_DRIVER_ENTRY;
|
||||||
|
|
||||||
|
#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l')
|
||||||
|
|
||||||
|
///
|
||||||
|
/// IHANDLE - contains a list of protocol handles
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
/// All handles list of IHANDLE
|
||||||
|
LIST_ENTRY AllHandles;
|
||||||
|
/// List of PROTOCOL_INTERFACE's for this handle
|
||||||
|
LIST_ENTRY Protocols;
|
||||||
|
UINTN LocateRequest;
|
||||||
|
} IHANDLE;
|
||||||
|
|
||||||
|
#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
|
||||||
|
|
||||||
|
#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e')
|
||||||
|
|
||||||
|
///
|
||||||
|
/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
|
||||||
|
/// database. Each handler that supports this protocol is listed, along
|
||||||
|
/// with a list of registered notifies.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
/// Link Entry inserted to mProtocolDatabase
|
||||||
|
LIST_ENTRY AllEntries;
|
||||||
|
/// ID of the protocol
|
||||||
|
EFI_GUID ProtocolID;
|
||||||
|
/// All protocol interfaces
|
||||||
|
LIST_ENTRY Protocols;
|
||||||
|
/// Registerd notification handlers
|
||||||
|
LIST_ENTRY Notify;
|
||||||
|
} PROTOCOL_ENTRY;
|
||||||
|
|
||||||
|
#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c')
|
||||||
|
|
||||||
|
///
|
||||||
|
/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
|
||||||
|
/// with a protocol interface structure
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
/// Link on IHANDLE.Protocols
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
/// Back pointer
|
||||||
|
IHANDLE *Handle;
|
||||||
|
/// Link on PROTOCOL_ENTRY.Protocols
|
||||||
|
LIST_ENTRY ByProtocol;
|
||||||
|
/// The protocol ID
|
||||||
|
PROTOCOL_ENTRY *Protocol;
|
||||||
|
/// The interface value
|
||||||
|
VOID *Interface;
|
||||||
|
} PROTOCOL_INTERFACE;
|
||||||
|
|
||||||
|
#define PROTOCOL_NOTIFY_SIGNATURE SIGNATURE_32('p','r','t','n')
|
||||||
|
|
||||||
|
///
|
||||||
|
/// PROTOCOL_NOTIFY - used for each register notification for a protocol
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
PROTOCOL_ENTRY *Protocol;
|
||||||
|
/// All notifications for this protocol
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
/// Notification function
|
||||||
|
EFI_SMM_NOTIFY_FN Function;
|
||||||
|
/// Last position notified
|
||||||
|
LIST_ENTRY *Position;
|
||||||
|
} PROTOCOL_NOTIFY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SMM Core Global Variables
|
||||||
|
//
|
||||||
|
extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
|
||||||
|
extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst;
|
||||||
|
extern LIST_ENTRY gHandleList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called to initialize the memory service.
|
||||||
|
|
||||||
|
@param SmramRangeCount Number of SMRAM Regions
|
||||||
|
@param SmramRanges Pointer to SMRAM Descriptors
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmInitializeMemoryServices (
|
||||||
|
IN UINTN SmramRangeCount,
|
||||||
|
IN EFI_SMRAM_DESCRIPTOR *SmramRanges
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The SmmInstallConfigurationTable() function is used to maintain the list
|
||||||
|
of configuration tables that are stored in the System Management System
|
||||||
|
Table. The list is stored as an array of (GUID, Pointer) pairs. The list
|
||||||
|
must be allocated from pool memory with PoolType set to EfiRuntimeServicesData.
|
||||||
|
|
||||||
|
@param SystemTable A pointer to the SMM System Table (SMST).
|
||||||
|
@param Guid A pointer to the GUID for the entry to add, update, or remove.
|
||||||
|
@param Table A pointer to the buffer of the table to add.
|
||||||
|
@param TableSize The size of the table to install.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
|
||||||
|
@retval EFI_INVALID_PARAMETER Guid is not valid.
|
||||||
|
@retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmInstallConfigurationTable (
|
||||||
|
IN CONST EFI_SMM_SYSTEM_TABLE2 *SystemTable,
|
||||||
|
IN CONST EFI_GUID *Guid,
|
||||||
|
IN VOID *Table,
|
||||||
|
IN UINTN TableSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocates pages from the memory map.
|
||||||
|
|
||||||
|
@param Type The type of allocation to perform
|
||||||
|
@param MemoryType The type of memory to turn the allocated pages
|
||||||
|
into
|
||||||
|
@param NumberOfPages The number of pages to allocate
|
||||||
|
@param Memory A pointer to receive the base allocated memory
|
||||||
|
address
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
|
||||||
|
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
|
||||||
|
@retval EFI_SUCCESS Pages successfully allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmAllocatePages (
|
||||||
|
IN EFI_ALLOCATE_TYPE Type,
|
||||||
|
IN EFI_MEMORY_TYPE MemoryType,
|
||||||
|
IN UINTN NumberOfPages,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees previous allocated pages.
|
||||||
|
|
||||||
|
@param Memory Base address of memory being freed
|
||||||
|
@param NumberOfPages The number of pages to free
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND Could not find the entry that covers the range
|
||||||
|
@retval EFI_INVALID_PARAMETER Address not aligned
|
||||||
|
@return EFI_SUCCESS Pages successfully freed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmFreePages (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||||
|
IN UINTN NumberOfPages
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate pool of a particular type.
|
||||||
|
|
||||||
|
@param PoolType Type of pool to allocate
|
||||||
|
@param Size The amount of pool to allocate
|
||||||
|
@param Buffer The address to return a pointer to the allocated
|
||||||
|
pool
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER PoolType not valid
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
|
||||||
|
@retval EFI_SUCCESS Pool successfully allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmAllocatePool (
|
||||||
|
IN EFI_MEMORY_TYPE PoolType,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT VOID **Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees pool.
|
||||||
|
|
||||||
|
@param Buffer The allocated pool entry to free
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
|
||||||
|
@retval EFI_SUCCESS Pool successfully freed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmFreePool (
|
||||||
|
IN VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
|
||||||
|
@return The requested protocol interface for the handle
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmHandleProtocol (
|
||||||
|
IN EFI_HANDLE UserHandle,
|
||||||
|
IN EFI_GUID *Protocol,
|
||||||
|
OUT VOID **Interface
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add a new protocol notification record for the request protocol.
|
||||||
|
|
||||||
|
@param Protocol The requested protocol to add the notify
|
||||||
|
registration
|
||||||
|
@param Function Points to the notification function
|
||||||
|
@param Registration Returns the registration record
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||||
|
@retval EFI_SUCCESS Successfully returned the registration record
|
||||||
|
that has been added
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmRegisterProtocolNotify (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN EFI_SMM_NOTIFY_FN Function,
|
||||||
|
OUT VOID **Registration
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Manage SMI of a particular type.
|
||||||
|
|
||||||
|
@param HandlerType Points to the handler type or NULL for root SMI handlers.
|
||||||
|
@param Context Points to an optional context buffer.
|
||||||
|
@param CommBuffer Points to the optional communication buffer.
|
||||||
|
@param CommBufferSize Points to the size of the optional communication buffer.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Interrupt source was processed successfully but not quiesced.
|
||||||
|
@retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced.
|
||||||
|
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was not handled or quiesced.
|
||||||
|
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED Interrupt source was handled and quiesced.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmiManage (
|
||||||
|
IN CONST EFI_GUID *HandlerType,
|
||||||
|
IN CONST VOID *Context OPTIONAL,
|
||||||
|
IN OUT VOID *CommBuffer OPTIONAL,
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Registers a handler to execute within SMM.
|
||||||
|
|
||||||
|
@param Handler Handler service funtion pointer.
|
||||||
|
@param HandlerType Points to the handler type or NULL for root SMI handlers.
|
||||||
|
@param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Handler register success.
|
||||||
|
@retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmiHandlerRegister (
|
||||||
|
IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
|
||||||
|
IN CONST EFI_GUID *HandlerType OPTIONAL,
|
||||||
|
OUT EFI_HANDLE *DispatchHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Unregister a handler in SMM.
|
||||||
|
|
||||||
|
@param DispatchHandle The handle that was specified when the handler was registered.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Handler function was successfully unregistered.
|
||||||
|
@retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmiHandlerUnRegister (
|
||||||
|
IN EFI_HANDLE DispatchHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is the main entry point for an SMM handler dispatch
|
||||||
|
or communicate-based callback.
|
||||||
|
|
||||||
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||||
|
@param Context Points to an optional handler context which was specified when the handler was registered.
|
||||||
|
@param CommBuffer A pointer to a collection of data in memory that will
|
||||||
|
be conveyed from a non-SMM environment into an SMM environment.
|
||||||
|
@param CommBufferSize The size of the CommBuffer.
|
||||||
|
|
||||||
|
@return Status Code
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmDriverDispatchHandler (
|
||||||
|
IN EFI_HANDLE DispatchHandle,
|
||||||
|
IN CONST VOID *Context, OPTIONAL
|
||||||
|
IN OUT VOID *CommBuffer, OPTIONAL
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is the main entry point for an SMM handler dispatch
|
||||||
|
or communicate-based callback.
|
||||||
|
|
||||||
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||||
|
@param Context Points to an optional handler context which was specified when the handler was registered.
|
||||||
|
@param CommBuffer A pointer to a collection of data in memory that will
|
||||||
|
be conveyed from a non-SMM environment into an SMM environment.
|
||||||
|
@param CommBufferSize The size of the CommBuffer.
|
||||||
|
|
||||||
|
@return Status Code
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmLegacyBootHandler (
|
||||||
|
IN EFI_HANDLE DispatchHandle,
|
||||||
|
IN CONST VOID *Context, OPTIONAL
|
||||||
|
IN OUT VOID *CommBuffer, OPTIONAL
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is the main entry point for an SMM handler dispatch
|
||||||
|
or communicate-based callback.
|
||||||
|
|
||||||
|
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||||
|
@param Context Points to an optional handler context which was specified when the handler was registered.
|
||||||
|
@param CommBuffer A pointer to a collection of data in memory that will
|
||||||
|
be conveyed from a non-SMM environment into an SMM environment.
|
||||||
|
@param CommBufferSize The size of the CommBuffer.
|
||||||
|
|
||||||
|
@return Status Code
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmReadyToLockHandler (
|
||||||
|
IN EFI_HANDLE DispatchHandle,
|
||||||
|
IN CONST VOID *Context, OPTIONAL
|
||||||
|
IN OUT VOID *CommBuffer, OPTIONAL
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Place holder function until all the SMM System Table Service are available.
|
||||||
|
|
||||||
|
@param Arg1 Undefined
|
||||||
|
@param Arg2 Undefined
|
||||||
|
@param Arg3 Undefined
|
||||||
|
@param Arg4 Undefined
|
||||||
|
@param Arg5 Undefined
|
||||||
|
|
||||||
|
@return EFI_NOT_AVAILABLE_YET
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmEfiNotAvailableYetArg5 (
|
||||||
|
UINTN Arg1,
|
||||||
|
UINTN Arg2,
|
||||||
|
UINTN Arg3,
|
||||||
|
UINTN Arg4,
|
||||||
|
UINTN Arg5
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
//Functions used during debug buils
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
Traverse the discovered list for any drivers that were discovered but not loaded
|
||||||
|
because the dependency experessions evaluated to false.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmDisplayDiscoveredNotDispatched (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add free SMRAM region for use by memory service.
|
||||||
|
|
||||||
|
@param MemBase Base address of memory region.
|
||||||
|
@param MemLength Length of the memory region.
|
||||||
|
@param Type Memory type.
|
||||||
|
@param Attributes Memory region state.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmAddMemoryRegion (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS MemBase,
|
||||||
|
IN UINT64 MemLength,
|
||||||
|
IN EFI_MEMORY_TYPE Type,
|
||||||
|
IN UINT64 Attributes
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Signal event for every protocol in protocol entry.
|
||||||
|
|
||||||
|
@param Prot Protocol interface
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmNotifyProtocol (
|
||||||
|
IN PROTOCOL_INTERFACE *Prot
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes Protocol from the protocol list (but not the handle list).
|
||||||
|
|
||||||
|
@param Handle The handle to remove protocol on.
|
||||||
|
@param Protocol GUID of the protocol to be moved
|
||||||
|
@param Interface The interface of the protocol
|
||||||
|
|
||||||
|
@return Protocol Entry
|
||||||
|
|
||||||
|
**/
|
||||||
|
PROTOCOL_INTERFACE *
|
||||||
|
SmmRemoveInterfaceFromProtocol (
|
||||||
|
IN IHANDLE *Handle,
|
||||||
|
IN EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is the POSTFIX version of the dependency evaluator. This code does
|
||||||
|
not need to handle Before or After, as it is not valid to call this
|
||||||
|
routine in this case. The SOR is just ignored and is a nop in the grammer.
|
||||||
|
POSTFIX means all the math is done on top of the stack.
|
||||||
|
|
||||||
|
@param DriverEntry DriverEntry element to update.
|
||||||
|
|
||||||
|
@retval TRUE If driver is ready to run.
|
||||||
|
@retval FALSE If driver is not ready to run or some fatal error
|
||||||
|
was found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
SmmIsSchedulable (
|
||||||
|
IN EFI_SMM_DRIVER_ENTRY *DriverEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
68
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
Normal file
68
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
## @file
|
||||||
|
# This module provide an SMM CIS compliant implementation of SMM Core.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 - 2010, Intel Corporation
|
||||||
|
#
|
||||||
|
# All rights reserved. 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.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = PiSmmCore
|
||||||
|
FILE_GUID = E94F54CD-81EB-47ed-AEC3-856F5DC157A9
|
||||||
|
MODULE_TYPE = SMM_CORE
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||||
|
ENTRY_POINT = SmmMain
|
||||||
|
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
PiSmmCore.c
|
||||||
|
PiSmmCore.h
|
||||||
|
PiSmmCorePrivateData.h
|
||||||
|
Page.c
|
||||||
|
Pool.c
|
||||||
|
Handle.c
|
||||||
|
Locate.c
|
||||||
|
Notify.c
|
||||||
|
Dependency.c
|
||||||
|
Dispatcher.c
|
||||||
|
Smi.c
|
||||||
|
InstallConfigurationTable.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
PeCoffLib
|
||||||
|
CacheMaintenanceLib
|
||||||
|
DebugLib
|
||||||
|
ReportStatusCodeLib
|
||||||
|
DevicePathLib
|
||||||
|
UefiLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_PRODUCED
|
||||||
|
gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiSecurityArchProtocolGuid # PROTOCOL SIMETIMES_CONSUMED
|
||||||
|
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
|
||||||
|
gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gAprioriGuid # ALWAYS_CONSUMED
|
||||||
|
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED
|
||||||
|
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED
|
105
MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
Normal file
105
MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/** @file
|
||||||
|
The internal header file that declared a data structure that is shared
|
||||||
|
between the SMM IPL and the SMM Core.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _PI_SMM_CORE_PRIVATE_DATA_H_
|
||||||
|
#define _PI_SMM_CORE_PRIVATE_DATA_H_
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Signature for the private structure shared between the SMM IPL and the SMM Core
|
||||||
|
///
|
||||||
|
#define SMM_CORE_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('s', 'm', 'm', 'c')
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Private structure that is used to share information between the SMM IPL and
|
||||||
|
/// the SMM Core. This structure is allocated from memory of type EfiRuntimeServicesData.
|
||||||
|
/// Since runtime memory types are converted to available memory when a legacy boot
|
||||||
|
/// is performed, the SMM Core must access any fields of this structure if a legacy
|
||||||
|
/// boot is performed. As a result, the SMM IPL must create an event notification
|
||||||
|
/// for the Legacy Boot event and notify the SMM Core that a legacy boot is being
|
||||||
|
/// performed. The SMM Core can then use this information to filter accesses to
|
||||||
|
/// thos structure.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The ImageHandle passed into the entry point of the SMM IPL. This ImageHandle
|
||||||
|
/// is used by the SMM Core to fill in the ParentImageHandle field of the Loaded
|
||||||
|
/// Image Protocol for each SMM Driver that is dispatched by the SMM Core.
|
||||||
|
///
|
||||||
|
EFI_HANDLE SmmIplImageHandle;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The number of SMRAM ranges passed from the SMM IPL to the SMM Core. The SMM
|
||||||
|
/// Core uses these ranges of SMRAM to initialize the SMM Core memory manager.
|
||||||
|
///
|
||||||
|
UINTN SmramRangeCount;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// A table of SMRAM ranges passed from the SMM IPL to the SMM Core. The SMM
|
||||||
|
/// Core uses these ranges of SMRAM to initialize the SMM Core memory manager.
|
||||||
|
///
|
||||||
|
EFI_SMRAM_DESCRIPTOR *SmramRanges;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The SMM Foundation Entry Point. The SMM Core fills in this field when the
|
||||||
|
/// SMM Core is initialized. The SMM IPL is responsbile for registering this entry
|
||||||
|
/// point with the SMM Configuration Protocol. The SMM Configuration Protocol may
|
||||||
|
/// not be available at the time the SMM IPL and SMM Core are started, so the SMM IPL
|
||||||
|
/// sets up a protocol notification on the SMM Configuration Protocol and registers
|
||||||
|
/// the SMM Foundation Entry Point as soon as the SMM Configuration Protocol is
|
||||||
|
/// available.
|
||||||
|
///
|
||||||
|
EFI_SMM_ENTRY_POINT SmmEntryPoint;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Boolean flag set to TRUE while an SMI is being processed by the SMM Core.
|
||||||
|
///
|
||||||
|
BOOLEAN SmmEntryPointRegistered;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Boolean flag set to TRUE while an SMI is being processed by the SMM Core.
|
||||||
|
///
|
||||||
|
BOOLEAN InSmm;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This field is set by the SMM Core then the SMM Core is initialized. This field is
|
||||||
|
/// used by the SMM Base 2 Protocol and SMM Communication Protocol implementations in
|
||||||
|
/// the SMM IPL.
|
||||||
|
///
|
||||||
|
EFI_SMM_SYSTEM_TABLE2 *Smst;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This field is used by the SMM Communicatioon Protocol to pass a buffer into
|
||||||
|
/// a software SMI handler and for the software SMI handler to pass a buffer back to
|
||||||
|
/// the caller of the SMM Communication Protocol.
|
||||||
|
///
|
||||||
|
VOID *CommunicationBuffer;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This field is used by the SMM Communicatioon Protocol to pass the size of a buffer,
|
||||||
|
/// in bytes, into a software SMI handler and for the software SMI handler to pass the
|
||||||
|
/// size, in bytes, of a buffer back to the caller of the SMM Communication Protocol.
|
||||||
|
///
|
||||||
|
UINTN *BufferSize;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This field is used by the SMM Communication Protocol to pass the return status from
|
||||||
|
/// a software SMI handler back to the caller of the SMM Communication Protocol.
|
||||||
|
///
|
||||||
|
EFI_STATUS ReturnStatus;
|
||||||
|
} SMM_CORE_PRIVATE_DATA;
|
||||||
|
|
||||||
|
#endif
|
1041
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
Normal file
1041
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
Normal file
File diff suppressed because it is too large
Load Diff
66
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
Normal file
66
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
## @file
|
||||||
|
# This module provide an SMM CIS compliant implementation of SMM IPL.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 - 2010, Intel Corporation
|
||||||
|
#
|
||||||
|
# All rights reserved. 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.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = PiSmmIpl
|
||||||
|
FILE_GUID = 2FA2A6DA-11D5-4dc3-999A-749648B03C56
|
||||||
|
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||||
|
ENTRY_POINT = SmmIplEntry
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
PiSmmIpl.c
|
||||||
|
PiSmmCorePrivateData.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
PeCoffLib
|
||||||
|
CacheMaintenanceLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
DebugLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
UefiLib
|
||||||
|
UefiRuntimeLib
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSmmBase2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
|
||||||
|
gEfiSmmCommunicationProtocolGuid # PROTOCOL ALWAYS_PRODUCED
|
||||||
|
gEfiSmmAccess2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiSmmConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiSmmControl2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED
|
||||||
|
gEfiEventReadyToBootGuid # ALWAYS_CONSUMED
|
||||||
|
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED
|
||||||
|
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid
|
249
MdeModulePkg/Core/PiSmmCore/Pool.c
Normal file
249
MdeModulePkg/Core/PiSmmCore/Pool.c
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/** @file
|
||||||
|
SMM Memory pool management 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"
|
||||||
|
|
||||||
|
//
|
||||||
|
// MIN_POOL_SHIFT must not be less than 5
|
||||||
|
//
|
||||||
|
#define MIN_POOL_SHIFT 6
|
||||||
|
#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT)
|
||||||
|
|
||||||
|
//
|
||||||
|
// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1
|
||||||
|
//
|
||||||
|
#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1)
|
||||||
|
#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT)
|
||||||
|
|
||||||
|
//
|
||||||
|
// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes
|
||||||
|
//
|
||||||
|
#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN Size;
|
||||||
|
BOOLEAN Available;
|
||||||
|
} POOL_HEADER;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
POOL_HEADER Header;
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
} FREE_POOL_HEADER;
|
||||||
|
|
||||||
|
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called to initialize the memory service.
|
||||||
|
|
||||||
|
@param SmramRangeCount Number of SMRAM Regions
|
||||||
|
@param SmramRanges Pointer to SMRAM Descriptors
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SmmInitializeMemoryServices (
|
||||||
|
IN UINTN SmramRangeCount,
|
||||||
|
IN EFI_SMRAM_DESCRIPTOR *SmramRanges
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize Pool list
|
||||||
|
//
|
||||||
|
for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {
|
||||||
|
InitializeListHead (&mSmmPoolLists[--Index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize free SMRAM regions
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < SmramRangeCount; Index++) {
|
||||||
|
SmmAddMemoryRegion (
|
||||||
|
SmramRanges[Index].CpuStart,
|
||||||
|
SmramRanges[Index].PhysicalSize,
|
||||||
|
EfiConventionalMemory,
|
||||||
|
SmramRanges[Index].RegionState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal Function. Allocate a pool by specified PoolIndex.
|
||||||
|
|
||||||
|
@param PoolIndex Index which indicate the Pool size.
|
||||||
|
@param FreePoolHdr The returned Free pool.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Allocation failed.
|
||||||
|
@retval EFI_SUCCESS Pool successfully allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InternalAllocPoolByIndex (
|
||||||
|
IN UINTN PoolIndex,
|
||||||
|
OUT FREE_POOL_HEADER **FreePoolHdr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FREE_POOL_HEADER *Hdr;
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
if (PoolIndex == MAX_POOL_INDEX) {
|
||||||
|
Hdr = (FREE_POOL_HEADER *)AllocatePages (EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1));
|
||||||
|
if (Hdr == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
} else if (!IsListEmpty (&mSmmPoolLists[PoolIndex])) {
|
||||||
|
Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);
|
||||||
|
RemoveEntryList (&Hdr->Link);
|
||||||
|
} else {
|
||||||
|
Status = InternalAllocPoolByIndex (PoolIndex + 1, &Hdr);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Hdr->Header.Size >>= 1;
|
||||||
|
Hdr->Header.Available = TRUE;
|
||||||
|
InsertHeadList (&mSmmPoolLists[PoolIndex], &Hdr->Link);
|
||||||
|
Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
|
||||||
|
Hdr->Header.Available = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*FreePoolHdr = Hdr;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal Function. Free a pool by specified PoolIndex.
|
||||||
|
|
||||||
|
@param FreePoolHdr The pool to free.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Pool successfully freed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InternalFreePoolByIndex (
|
||||||
|
IN FREE_POOL_HEADER *FreePoolHdr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN PoolIndex;
|
||||||
|
|
||||||
|
ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);
|
||||||
|
ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);
|
||||||
|
ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);
|
||||||
|
|
||||||
|
PoolIndex = HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT;
|
||||||
|
FreePoolHdr->Header.Available = TRUE;
|
||||||
|
InsertHeadList (&mSmmPoolLists[PoolIndex], &FreePoolHdr->Link);
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate pool of a particular type.
|
||||||
|
|
||||||
|
@param PoolType Type of pool to allocate.
|
||||||
|
@param Size The amount of pool to allocate.
|
||||||
|
@param Buffer The address to return a pointer to the allocated
|
||||||
|
pool.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER PoolType not valid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
|
||||||
|
@retval EFI_SUCCESS Pool successfully allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmAllocatePool (
|
||||||
|
IN EFI_MEMORY_TYPE PoolType,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT VOID **Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
POOL_HEADER *PoolHdr;
|
||||||
|
FREE_POOL_HEADER *FreePoolHdr;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_PHYSICAL_ADDRESS Address;
|
||||||
|
UINTN PoolIndex;
|
||||||
|
|
||||||
|
if (PoolType != EfiRuntimeServicesCode &&
|
||||||
|
PoolType != EfiRuntimeServicesData) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Size == 0) {
|
||||||
|
*Buffer = NULL;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size += sizeof (*PoolHdr);
|
||||||
|
if (Size > MAX_POOL_SIZE) {
|
||||||
|
Size = EFI_SIZE_TO_PAGES (Size);
|
||||||
|
Status = SmmAllocatePages (AllocateAnyPages, PoolType, Size, &Address);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolHdr = (POOL_HEADER*)(UINTN)Address;
|
||||||
|
PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);
|
||||||
|
PoolHdr->Available = FALSE;
|
||||||
|
*Buffer = PoolHdr + 1;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
|
||||||
|
PoolIndex = HighBitSet32 ((UINT32)Size);
|
||||||
|
if ((Size & (Size - 1)) != 0) {
|
||||||
|
PoolIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);
|
||||||
|
*Buffer = &FreePoolHdr->Header + 1;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees pool.
|
||||||
|
|
||||||
|
@param Buffer The allocated pool entry to free.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
|
||||||
|
@retval EFI_SUCCESS Pool successfully freed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmFreePool (
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FREE_POOL_HEADER *FreePoolHdr;
|
||||||
|
|
||||||
|
if (Buffer == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);
|
||||||
|
ASSERT (!FreePoolHdr->Header.Available);
|
||||||
|
|
||||||
|
if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
|
||||||
|
ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
|
||||||
|
ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
|
||||||
|
return SmmFreePages (
|
||||||
|
(EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
|
||||||
|
EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return InternalFreePoolByIndex (FreePoolHdr);
|
||||||
|
}
|
333
MdeModulePkg/Core/PiSmmCore/Smi.c
Normal file
333
MdeModulePkg/Core/PiSmmCore/Smi.c
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/** @file
|
||||||
|
SMI management.
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
//
|
||||||
|
// SMM_HANDLER - used for each SMM handler
|
||||||
|
//
|
||||||
|
|
||||||
|
#define SMI_ENTRY_SIGNATURE SIGNATURE_32('s','m','i','e')
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
LIST_ENTRY AllEntries; // All entries
|
||||||
|
|
||||||
|
EFI_GUID HandlerType; // Type of interrupt
|
||||||
|
LIST_ENTRY SmiHandlers; // All handlers
|
||||||
|
} SMI_ENTRY;
|
||||||
|
|
||||||
|
#define SMI_HANDLER_SIGNATURE SIGNATURE_32('s','m','i','h')
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
LIST_ENTRY Link; // Link on SMI_ENTRY.SmiHandlers
|
||||||
|
EFI_SMM_HANDLER_ENTRY_POINT2 Handler; // The smm handler's entry point
|
||||||
|
SMI_ENTRY *SmiEntry;
|
||||||
|
} SMI_HANDLER;
|
||||||
|
|
||||||
|
LIST_ENTRY mRootSmiHandlerList = INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiHandlerList);
|
||||||
|
LIST_ENTRY mSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mSmiEntryList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Finds the SMI entry for the requested handler type.
|
||||||
|
|
||||||
|
@param HandlerType The type of the interrupt
|
||||||
|
@param Create Create a new entry if not found
|
||||||
|
|
||||||
|
@return SMI entry
|
||||||
|
|
||||||
|
**/
|
||||||
|
SMI_ENTRY *
|
||||||
|
EFIAPI
|
||||||
|
SmmCoreFindSmiEntry (
|
||||||
|
IN EFI_GUID *HandlerType,
|
||||||
|
IN BOOLEAN Create
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
SMI_ENTRY *Item;
|
||||||
|
SMI_ENTRY *SmiEntry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search the SMI entry list for the matching GUID
|
||||||
|
//
|
||||||
|
SmiEntry = NULL;
|
||||||
|
for (Link = mSmiEntryList.ForwardLink;
|
||||||
|
Link != &mSmiEntryList;
|
||||||
|
Link = Link->ForwardLink) {
|
||||||
|
|
||||||
|
Item = CR (Link, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
|
||||||
|
if (CompareGuid (&Item->HandlerType, HandlerType)) {
|
||||||
|
//
|
||||||
|
// This is the SMI entry
|
||||||
|
//
|
||||||
|
SmiEntry = Item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the protocol entry was not found and Create is TRUE, then
|
||||||
|
// allocate a new entry
|
||||||
|
//
|
||||||
|
if ((SmiEntry == NULL) && Create) {
|
||||||
|
SmiEntry = AllocatePool (sizeof(SMI_ENTRY));
|
||||||
|
if (SmiEntry != NULL) {
|
||||||
|
//
|
||||||
|
// Initialize new SMI entry structure
|
||||||
|
//
|
||||||
|
SmiEntry->Signature = SMI_ENTRY_SIGNATURE;
|
||||||
|
CopyGuid ((VOID *)&SmiEntry->HandlerType, HandlerType);
|
||||||
|
InitializeListHead (&SmiEntry->SmiHandlers);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add it to SMI entry list
|
||||||
|
//
|
||||||
|
InsertTailList (&mSmiEntryList, &SmiEntry->AllEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SmiEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Manage SMI of a particular type.
|
||||||
|
|
||||||
|
@param HandlerType Points to the handler type or NULL for root SMI handlers.
|
||||||
|
@param Context Points to an optional context buffer.
|
||||||
|
@param CommBuffer Points to the optional communication buffer.
|
||||||
|
@param CommBufferSize Points to the size of the optional communication buffer.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Interrupt source was processed successfully but not quiesced.
|
||||||
|
@retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced.
|
||||||
|
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was not handled or quiesced.
|
||||||
|
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED Interrupt source was handled and quiesced.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmiManage (
|
||||||
|
IN CONST EFI_GUID *HandlerType,
|
||||||
|
IN CONST VOID *Context OPTIONAL,
|
||||||
|
IN OUT VOID *CommBuffer OPTIONAL,
|
||||||
|
IN OUT UINTN *CommBufferSize OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
LIST_ENTRY *Head;
|
||||||
|
SMI_ENTRY *SmiEntry;
|
||||||
|
SMI_HANDLER *SmiHandler;
|
||||||
|
BOOLEAN InterruptQuiesced;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
if (HandlerType == NULL) {
|
||||||
|
//
|
||||||
|
// Root SMI handler
|
||||||
|
//
|
||||||
|
Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;
|
||||||
|
|
||||||
|
Head = &mRootSmiHandlerList;
|
||||||
|
for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
|
||||||
|
SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
|
||||||
|
|
||||||
|
Status = SmiHandler->Handler (
|
||||||
|
(EFI_HANDLE) SmiHandler,
|
||||||
|
Context,
|
||||||
|
CommBuffer,
|
||||||
|
CommBufferSize
|
||||||
|
);
|
||||||
|
if (Status == EFI_SUCCESS || Status == EFI_INTERRUPT_PENDING) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Non-root SMI handler
|
||||||
|
//
|
||||||
|
SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *) HandlerType, FALSE);
|
||||||
|
if (SmiEntry == NULL) {
|
||||||
|
//
|
||||||
|
// There is no handler registered for this interrupt source
|
||||||
|
//
|
||||||
|
return EFI_WARN_INTERRUPT_SOURCE_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
InterruptQuiesced = FALSE;
|
||||||
|
Head = &SmiEntry->SmiHandlers;
|
||||||
|
for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
|
||||||
|
SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
|
||||||
|
|
||||||
|
Status = SmiHandler->Handler (
|
||||||
|
(EFI_HANDLE) SmiHandler,
|
||||||
|
Context,
|
||||||
|
CommBuffer,
|
||||||
|
CommBufferSize
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (Status) {
|
||||||
|
case EFI_INTERRUPT_PENDING:
|
||||||
|
//
|
||||||
|
// If a handler returns EFI_INTERRUPT_PENDING, the interrupt could not be
|
||||||
|
// quiesced, then no additional handlers will be processed,
|
||||||
|
// and EFI_INTERRUPT_PENDING will be returned
|
||||||
|
//
|
||||||
|
return EFI_INTERRUPT_PENDING;
|
||||||
|
|
||||||
|
case EFI_SUCCESS:
|
||||||
|
//
|
||||||
|
// If handler return EFI_SUCCESS, the interrupt was handled and quiesced,
|
||||||
|
// no other handlers should still be called,
|
||||||
|
// and EFI_WARN_INTERRUPT_SOURCE_QUIESCED will be returned
|
||||||
|
//
|
||||||
|
return EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
|
||||||
|
|
||||||
|
case EFI_WARN_INTERRUPT_SOURCE_QUIESCED:
|
||||||
|
//
|
||||||
|
// If at least one of the handlers report EFI_WARN_INTERRUPT_SOURCE_QUIESCED,
|
||||||
|
// then this function will return EFI_WARN_INTERRUPT_SOURCE_QUIESCED
|
||||||
|
//
|
||||||
|
InterruptQuiesced = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InterruptQuiesced) {
|
||||||
|
Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// If no handler report EFI_WARN_INTERRUPT_SOURCE_QUIESCED, then this
|
||||||
|
// function will return EFI_INTERRUPT_PENDING
|
||||||
|
//
|
||||||
|
Status = EFI_INTERRUPT_PENDING;
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Registers a handler to execute within SMM.
|
||||||
|
|
||||||
|
@param Handler Handler service funtion pointer.
|
||||||
|
@param HandlerType Points to the handler type or NULL for root SMI handlers.
|
||||||
|
@param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Handler register success.
|
||||||
|
@retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmiHandlerRegister (
|
||||||
|
IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
|
||||||
|
IN CONST EFI_GUID *HandlerType OPTIONAL,
|
||||||
|
OUT EFI_HANDLE *DispatchHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SMI_HANDLER *SmiHandler;
|
||||||
|
SMI_ENTRY *SmiEntry;
|
||||||
|
LIST_ENTRY *List;
|
||||||
|
|
||||||
|
if (Handler == NULL || DispatchHandle == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmiHandler = AllocateZeroPool (sizeof (SMI_HANDLER));
|
||||||
|
if (SmiHandler == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmiHandler->Signature = SMI_HANDLER_SIGNATURE;
|
||||||
|
SmiHandler->Handler = Handler;
|
||||||
|
|
||||||
|
if (HandlerType == NULL) {
|
||||||
|
//
|
||||||
|
// This is root SMI handler
|
||||||
|
//
|
||||||
|
SmiEntry = NULL;
|
||||||
|
List = &mRootSmiHandlerList;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// None root SMI handler
|
||||||
|
//
|
||||||
|
SmiEntry = SmmCoreFindSmiEntry ((EFI_GUID *) HandlerType, TRUE);
|
||||||
|
if (SmiEntry == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
List = &SmiEntry->SmiHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmiHandler->SmiEntry = SmiEntry;
|
||||||
|
InsertTailList (List, &SmiHandler->Link);
|
||||||
|
|
||||||
|
*DispatchHandle = (EFI_HANDLE) SmiHandler;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Unregister a handler in SMM.
|
||||||
|
|
||||||
|
@param DispatchHandle The handle that was specified when the handler was registered.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Handler function was successfully unregistered.
|
||||||
|
@retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmiHandlerUnRegister (
|
||||||
|
IN EFI_HANDLE DispatchHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SMI_HANDLER *SmiHandler;
|
||||||
|
SMI_ENTRY *SmiEntry;
|
||||||
|
|
||||||
|
SmiHandler = (SMI_HANDLER *) DispatchHandle;
|
||||||
|
|
||||||
|
if (SmiHandler == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SmiHandler->Signature != SMI_HANDLER_SIGNATURE) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmiEntry = SmiHandler->SmiEntry;
|
||||||
|
|
||||||
|
RemoveEntryList (&SmiHandler->Link);
|
||||||
|
FreePool (SmiHandler);
|
||||||
|
|
||||||
|
if (SmiEntry == NULL) {
|
||||||
|
//
|
||||||
|
// This is root SMI handler
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsListEmpty (&SmiEntry->SmiHandlers)) {
|
||||||
|
//
|
||||||
|
// No handler registered for this interrupt now, remove the SMI_ENTRY
|
||||||
|
//
|
||||||
|
RemoveEntryList (&SmiEntry->AllEntries);
|
||||||
|
|
||||||
|
FreePool (SmiEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
Reference in New Issue
Block a user