mirror of https://github.com/acidanthera/audk.git
Update SMM Core to use SMM Mode as soon as SMM Mode is available
Signed-off-by: mdkinney Reviewed-by: rsun3 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12190 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
ad9aa87b56
commit
5657b268e7
|
@ -743,13 +743,15 @@ SmmGetDepexSectionAndPreProccess (
|
|||
drivers to run. Drain the mScheduledQueue and load and start a PE
|
||||
image for each driver. Search the mDiscoveredList to see if any driver can
|
||||
be placed on the mScheduledQueue. If no drivers are placed on the
|
||||
mScheduledQueue exit the function. On exit it is assumed the Bds()
|
||||
will be called, and when the Bds() exits the Dispatcher will be called
|
||||
again.
|
||||
mScheduledQueue exit the function.
|
||||
|
||||
@retval EFI_SUCCESS All of the SMM Drivers that could be dispatched
|
||||
have been run and the SMM Entry Point has been
|
||||
registered.
|
||||
@retval EFI_NOT_READY The SMM Driver that registered the SMM Entry Point
|
||||
was just dispatched.
|
||||
@retval EFI_NOT_FOUND There are no SMM Drivers available to be dispatched.
|
||||
@retval EFI_ALREADY_STARTED The SMM Dispatcher is already running
|
||||
@retval EFI_NOT_FOUND No SMM Drivers were dispatched
|
||||
@retval EFI_SUCCESS One or more SMM Drivers were dispatched
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -758,10 +760,10 @@ SmmDispatcher (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS ReturnStatus;
|
||||
LIST_ENTRY *Link;
|
||||
EFI_SMM_DRIVER_ENTRY *DriverEntry;
|
||||
BOOLEAN ReadyToRun;
|
||||
BOOLEAN PreviousSmmEntryPointRegistered;
|
||||
|
||||
if (!gRequestDispatch) {
|
||||
return EFI_NOT_FOUND;
|
||||
|
@ -776,7 +778,6 @@ SmmDispatcher (
|
|||
|
||||
gDispatcherRunning = TRUE;
|
||||
|
||||
ReturnStatus = EFI_NOT_FOUND;
|
||||
do {
|
||||
//
|
||||
// Drain the Scheduled Queue
|
||||
|
@ -827,6 +828,11 @@ SmmDispatcher (
|
|||
sizeof (DriverEntry->ImageHandle)
|
||||
);
|
||||
|
||||
//
|
||||
// Cache state of SmmEntryPointRegistered before calling entry point
|
||||
//
|
||||
PreviousSmmEntryPointRegistered = gSmmCorePrivate->SmmEntryPointRegistered;
|
||||
|
||||
//
|
||||
// For each SMM driver, pass NULL as ImageHandle
|
||||
//
|
||||
|
@ -842,7 +848,19 @@ SmmDispatcher (
|
|||
sizeof (DriverEntry->ImageHandle)
|
||||
);
|
||||
|
||||
ReturnStatus = EFI_SUCCESS;
|
||||
if (!PreviousSmmEntryPointRegistered && gSmmCorePrivate->SmmEntryPointRegistered) {
|
||||
//
|
||||
// Return immediately if the SMM Entry Point was registered by the SMM
|
||||
// Driver that was just dispatched. The SMM IPL will reinvoke the SMM
|
||||
// Core Dispatcher. This is required so SMM Mode may be enabled as soon
|
||||
// as all the dependent SMM Drivers for SMM Mode have been dispatched.
|
||||
// Once the SMM Entry Point has been registered, then SMM Mode will be
|
||||
// used.
|
||||
//
|
||||
gRequestDispatch = TRUE;
|
||||
gDispatcherRunning = FALSE;
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -886,7 +904,7 @@ SmmDispatcher (
|
|||
|
||||
gDispatcherRunning = FALSE;
|
||||
|
||||
return ReturnStatus;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1309,7 +1327,34 @@ SmmDriverDispatchHandler (
|
|||
// Execute the SMM Dispatcher on any newly discovered FVs and previously
|
||||
// discovered SMM drivers that have been discovered but not dispatched.
|
||||
//
|
||||
return SmmDispatcher ();
|
||||
Status = SmmDispatcher ();
|
||||
|
||||
//
|
||||
// Check to see if CommBuffer and CommBufferSize are valid
|
||||
//
|
||||
if (CommBuffer != NULL && CommBufferSize != NULL) {
|
||||
if (*CommBufferSize > 0) {
|
||||
if (Status == EFI_NOT_READY) {
|
||||
//
|
||||
// If a the SMM Core Entry Point was just registered, then set flag to
|
||||
// request the SMM Dispatcher to be restarted.
|
||||
//
|
||||
*(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_RESTART;
|
||||
} else if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Set the flag to show that the SMM Dispatcher executed without errors
|
||||
//
|
||||
*(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_SUCCESS;
|
||||
} else {
|
||||
//
|
||||
// Set the flag to show that the SMM Dispatcher encountered an error
|
||||
//
|
||||
*(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
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>
|
||||
Copyright (c) 2009 - 2011, 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
|
||||
|
@ -16,6 +16,22 @@
|
|||
#ifndef _PI_SMM_CORE_PRIVATE_DATA_H_
|
||||
#define _PI_SMM_CORE_PRIVATE_DATA_H_
|
||||
|
||||
///
|
||||
/// Define values for the communications buffer used when gEfiEventDxeDispatchGuid is
|
||||
/// event signaled. This event is signaled by the DXE Core each time the DXE Core
|
||||
/// dispatcher has completed its work. When this event is signaled, the SMM Core
|
||||
/// if notified, so the SMM Core can dispatch SMM drivers. If COMM_BUFFER_SMM_DISPATCH_ERROR
|
||||
/// is returned in the communication buffer, then an error occurred dispatching SMM
|
||||
/// Drivers. If COMM_BUFFER_SMM_DISPATCH_SUCCESS is returned, then the SMM Core
|
||||
/// dispatched all the drivers it could. If COMM_BUFFER_SMM_DISPATCH_RESTART is
|
||||
/// returned, then the SMM Core just dispatched the SMM Driver that registered
|
||||
/// the SMM Entry Point enabling the use of SMM Mode. In this case, the SMM Core
|
||||
/// should be notified again to dispatch more SMM Drivers using SMM Mode.
|
||||
///
|
||||
#define COMM_BUFFER_SMM_DISPATCH_ERROR 0x00
|
||||
#define COMM_BUFFER_SMM_DISPATCH_SUCCESS 0x01
|
||||
#define COMM_BUFFER_SMM_DISPATCH_RESTART 0x02
|
||||
|
||||
///
|
||||
/// Signature for the private structure shared between the SMM IPL and the SMM Core
|
||||
///
|
||||
|
|
|
@ -140,6 +140,20 @@ SmmIplReadyToLockEventNotify (
|
|||
@param Event The Event that is being processed, not used.
|
||||
@param Context Event Context, not used.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmIplDxeDispatchEventNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Event notification that is fired when a GUIDed Event Group is signaled.
|
||||
|
||||
@param Event The Event that is being processed, not used.
|
||||
@param Context Event Context, not used.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
|
@ -175,6 +189,7 @@ typedef struct {
|
|||
EFI_GUID *Guid;
|
||||
EFI_EVENT_NOTIFY NotifyFunction;
|
||||
VOID *NotifyContext;
|
||||
EFI_TPL NotifyTpl;
|
||||
EFI_EVENT Event;
|
||||
} SMM_IPL_EVENT_NOTIFICATION;
|
||||
|
||||
|
@ -240,39 +255,39 @@ SMM_IPL_EVENT_NOTIFICATION mSmmIplEvents[] = {
|
|||
// the associated event is immediately signalled, so the notification function will be executed and the
|
||||
// SMM Configuration Protocol will be found if it is already in the handle database.
|
||||
//
|
||||
{ TRUE, FALSE, &gEfiSmmConfigurationProtocolGuid, SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid, NULL },
|
||||
{ TRUE, FALSE, &gEfiSmmConfigurationProtocolGuid, SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid, TPL_NOTIFY, NULL },
|
||||
//
|
||||
// Declare protocl notification on DxeSmmReadyToLock protocols. When this notification is etablished,
|
||||
// the associated event is immediately signalled, so the notification function will be executed and the
|
||||
// DXE SMM Ready To Lock Protocol will be found if it is already in the handle database.
|
||||
//
|
||||
{ TRUE, TRUE, &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify, &gEfiDxeSmmReadyToLockProtocolGuid, NULL },
|
||||
{ TRUE, TRUE, &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify, &gEfiDxeSmmReadyToLockProtocolGuid, TPL_CALLBACK, NULL },
|
||||
//
|
||||
// Declare event notification on the DXE Dispatch Event Group. This event is signaled by the DXE Core
|
||||
// each time the DXE Core dispatcher has completed its work. When this event is signalled, the SMM Core
|
||||
// if notified, so the SMM Core can dispatch SMM drivers.
|
||||
//
|
||||
{ FALSE, TRUE, &gEfiEventDxeDispatchGuid, SmmIplGuidedEventNotify, &gEfiEventDxeDispatchGuid, NULL },
|
||||
{ FALSE, TRUE, &gEfiEventDxeDispatchGuid, SmmIplDxeDispatchEventNotify, &gEfiEventDxeDispatchGuid, TPL_CALLBACK, NULL },
|
||||
//
|
||||
// Declare event notification on Ready To Boot Event Group. This is an extra event notification that is
|
||||
// used to make sure SMRAM is locked before any boot options are processed.
|
||||
//
|
||||
{ FALSE, TRUE, &gEfiEventReadyToBootGuid, SmmIplReadyToLockEventNotify, &gEfiEventReadyToBootGuid, NULL },
|
||||
{ FALSE, TRUE, &gEfiEventReadyToBootGuid, SmmIplReadyToLockEventNotify, &gEfiEventReadyToBootGuid, TPL_CALLBACK, NULL },
|
||||
//
|
||||
// Declare event notification on Legacy Boot Event Group. This is used to inform the SMM Core that the platform
|
||||
// is performing a legacy boot operation, and that the UEFI environment is no longer available and the SMM Core
|
||||
// must guarantee that it does not access any UEFI related structures outside of SMRAM.
|
||||
//
|
||||
{ FALSE, FALSE, &gEfiEventLegacyBootGuid, SmmIplGuidedEventNotify, &gEfiEventLegacyBootGuid, NULL },
|
||||
{ FALSE, FALSE, &gEfiEventLegacyBootGuid, SmmIplGuidedEventNotify, &gEfiEventLegacyBootGuid, TPL_CALLBACK, NULL },
|
||||
//
|
||||
// Declare event notification on SetVirtualAddressMap() Event Group. This is used to convert gSmmCorePrivate
|
||||
// and mSmmControl2 from physical addresses to virtual addresses.
|
||||
//
|
||||
{ FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify, NULL, NULL },
|
||||
{ FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify, NULL, TPL_CALLBACK, NULL },
|
||||
//
|
||||
// Terminate the table of event notifications
|
||||
//
|
||||
{ FALSE, FALSE, NULL, NULL, NULL, NULL }
|
||||
{ FALSE, FALSE, NULL, NULL, NULL, TPL_CALLBACK, NULL }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -493,7 +508,7 @@ SmmCommunicationCommunicate (
|
|||
}
|
||||
|
||||
/**
|
||||
Event notification that is fired when DxeDispatch Event Group is signaled.
|
||||
Event notification that is fired when GUIDed Event Group is signaled.
|
||||
|
||||
@param Event The Event that is being processed, not used.
|
||||
@param Context Event Context, not used.
|
||||
|
@ -523,6 +538,86 @@ SmmIplGuidedEventNotify (
|
|||
SmmCommunicationCommunicate (&mSmmCommunication, &CommunicateHeader, &Size);
|
||||
}
|
||||
|
||||
/**
|
||||
Event notification that is fired when DxeDispatch Event Group is signaled.
|
||||
|
||||
@param Event The Event that is being processed, not used.
|
||||
@param Context Event Context, not used.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmIplDxeDispatchEventNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_SMM_COMMUNICATE_HEADER CommunicateHeader;
|
||||
UINTN Size;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Keep calling the SMM Core Dispatcher until there is no request to restart it.
|
||||
//
|
||||
while (TRUE) {
|
||||
//
|
||||
// Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure
|
||||
// Clear the buffer passed into the Software SMI. This buffer will return
|
||||
// the status of the SMM Core Dispatcher.
|
||||
//
|
||||
CopyGuid (&CommunicateHeader.HeaderGuid, (EFI_GUID *)Context);
|
||||
CommunicateHeader.MessageLength = 1;
|
||||
CommunicateHeader.Data[0] = 0;
|
||||
|
||||
//
|
||||
// Generate the Software SMI and return the result
|
||||
//
|
||||
Size = sizeof (CommunicateHeader);
|
||||
SmmCommunicationCommunicate (&mSmmCommunication, &CommunicateHeader, &Size);
|
||||
|
||||
//
|
||||
// Return if there is no request to restart the SMM Core Dispatcher
|
||||
//
|
||||
if (CommunicateHeader.Data[0] != COMM_BUFFER_SMM_DISPATCH_RESTART) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to reset SMRAM cacheability to UC
|
||||
// Assume CPU AP is available at this time
|
||||
//
|
||||
Status = gDS->SetMemorySpaceAttributes(
|
||||
mSmramCacheBase,
|
||||
mSmramCacheSize,
|
||||
EFI_MEMORY_UC
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));
|
||||
}
|
||||
|
||||
//
|
||||
// Close all SMRAM ranges to protect SMRAM
|
||||
//
|
||||
Status = mSmmAccess->Close (mSmmAccess);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Print debug message that the SMRAM window is now closed.
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));
|
||||
|
||||
//
|
||||
// Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)
|
||||
//
|
||||
mSmmAccess->Lock (mSmmAccess);
|
||||
|
||||
//
|
||||
// Print debug message that the SMRAM window is now locked
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "SMM IPL locked SMRAM window\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.
|
||||
|
||||
|
@ -555,7 +650,7 @@ SmmIplSmmConfigurationEventNotify (
|
|||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Set flag to indicate that the SM< Entry Point has been registered which
|
||||
// Set flag to indicate that the SMM Entry Point has been registered which
|
||||
// means that SMIs are now fully operational.
|
||||
//
|
||||
gSmmCorePrivate->SmmEntryPointRegistered = TRUE;
|
||||
|
@ -564,30 +659,6 @@ SmmIplSmmConfigurationEventNotify (
|
|||
// Print debug message showing SMM Core entry point address.
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "SMM IPL registered SMM Entry Point address %p\n", (VOID *)(UINTN)gSmmCorePrivate->SmmEntryPoint));
|
||||
|
||||
//
|
||||
// Attempt to reset SMRAM cacheability to UC
|
||||
// Assume CPU AP is available at this time
|
||||
//
|
||||
Status = gDS->SetMemorySpaceAttributes(
|
||||
mSmramCacheBase,
|
||||
mSmramCacheSize,
|
||||
EFI_MEMORY_UC
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));
|
||||
}
|
||||
|
||||
//
|
||||
// Close all SMRAM ranges to protect SMRAM
|
||||
//
|
||||
Status = mSmmAccess->Close (mSmmAccess);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Print debug message that the SMRAM window is now closed.
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1190,7 +1261,7 @@ SmmIplEntry (
|
|||
if (mSmmIplEvents[Index].Protocol) {
|
||||
mSmmIplEvents[Index].Event = EfiCreateProtocolNotifyEvent (
|
||||
mSmmIplEvents[Index].Guid,
|
||||
TPL_CALLBACK,
|
||||
mSmmIplEvents[Index].NotifyTpl,
|
||||
mSmmIplEvents[Index].NotifyFunction,
|
||||
mSmmIplEvents[Index].NotifyContext,
|
||||
&Registration
|
||||
|
@ -1198,7 +1269,7 @@ SmmIplEntry (
|
|||
} else {
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
mSmmIplEvents[Index].NotifyTpl,
|
||||
mSmmIplEvents[Index].NotifyFunction,
|
||||
mSmmIplEvents[Index].NotifyContext,
|
||||
mSmmIplEvents[Index].Guid,
|
||||
|
|
Loading…
Reference in New Issue