REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1420 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1420 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   SMI handler profile support.
 | |
| 
 | |
| Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <PiSmm.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/SmmServicesTableLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/PrintLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include <Library/DevicePathLib.h>
 | |
| #include <Library/PeCoffGetEntryPointLib.h>
 | |
| #include <Protocol/LoadedImage.h>
 | |
| #include <Protocol/SmmAccess2.h>
 | |
| #include <Protocol/SmmReadyToLock.h>
 | |
| #include <Protocol/SmmEndOfDxe.h>
 | |
| 
 | |
| #include <Guid/SmiHandlerProfile.h>
 | |
| 
 | |
| #include "PiSmmCore.h"
 | |
| 
 | |
| #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
 | |
|   ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
 | |
| 
 | |
| typedef struct {
 | |
|   EFI_GUID            FileGuid;
 | |
|   PHYSICAL_ADDRESS    EntryPoint;
 | |
|   PHYSICAL_ADDRESS    ImageBase;
 | |
|   UINT64              ImageSize;
 | |
|   UINT32              ImageRef;
 | |
|   UINT16              PdbStringSize;
 | |
|   CHAR8               *PdbString;
 | |
| } IMAGE_STRUCT;
 | |
| 
 | |
| /**
 | |
|   Register SMI handler profile handler.
 | |
| **/
 | |
| VOID
 | |
| RegisterSmiHandlerProfileHandler (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
 | |
|   into system memory with the PE/COFF Loader Library functions.
 | |
| 
 | |
|   Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
 | |
|   point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then
 | |
|   return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
 | |
|   If Pe32Data is NULL, then ASSERT().
 | |
|   If EntryPoint is NULL, then ASSERT().
 | |
| 
 | |
|   @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.
 | |
|   @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.
 | |
| 
 | |
|   @retval RETURN_SUCCESS            EntryPoint was returned.
 | |
|   @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| InternalPeCoffGetEntryPoint (
 | |
|   IN  VOID  *Pe32Data,
 | |
|   OUT VOID  **EntryPoint
 | |
|   );
 | |
| 
 | |
| extern LIST_ENTRY  mSmiEntryList;
 | |
| extern LIST_ENTRY  mHardwareSmiEntryList;
 | |
| extern SMI_ENTRY   mRootSmiEntry;
 | |
| 
 | |
| extern SMI_HANDLER_PROFILE_PROTOCOL  mSmiHandlerProfile;
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mHardwareSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mHardwareSmiEntryList);
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mRootSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntryList);
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  *mSmmCoreRootSmiEntryList     = &mRootSmiEntryList;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  *mSmmCoreSmiEntryList         = &mSmiEntryList;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  *mSmmCoreHardwareSmiEntryList = &mHardwareSmiEntryList;
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED IMAGE_STRUCT  *mImageStruct;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINT32        mImageStructCountMax;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINT32        mImageStructCount;
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED VOID   *mSmiHandlerProfileDatabase;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mSmiHandlerProfileDatabaseSize;
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mSmmImageDatabaseSize;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mSmmRootSmiDatabaseSize;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mSmmSmiDatabaseSize;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mSmmHardwareSmiDatabaseSize;
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN  mSmiHandlerProfileRecordingStatus;
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED SMI_HANDLER_PROFILE_PROTOCOL  mSmiHandlerProfile = {
 | |
|   SmiHandlerProfileRegisterHandler,
 | |
|   SmiHandlerProfileUnregisterHandler,
 | |
| };
 | |
| 
 | |
| /**
 | |
|   This function dump raw data.
 | |
| 
 | |
|   @param  Data  raw data
 | |
|   @param  Size  raw data size
 | |
| **/
 | |
| VOID
 | |
| InternalDumpData (
 | |
|   IN UINT8  *Data,
 | |
|   IN UINTN  Size
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
| 
 | |
|   for (Index = 0; Index < Size; Index++) {
 | |
|     DEBUG ((DEBUG_INFO, "%02x ", (UINTN)Data[Index]));
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get GUID name for an image.
 | |
| 
 | |
|   @param[in]  LoadedImage LoadedImage protocol.
 | |
|   @param[out] Guid        Guid of the FFS
 | |
| **/
 | |
| VOID
 | |
| GetDriverGuid (
 | |
|   IN  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage,
 | |
|   OUT EFI_GUID                   *Guid
 | |
|   )
 | |
| {
 | |
|   EFI_GUID  *FileName;
 | |
| 
 | |
|   FileName = NULL;
 | |
|   if ((DevicePathType (LoadedImage->FilePath) == MEDIA_DEVICE_PATH) &&
 | |
|       (DevicePathSubType (LoadedImage->FilePath) == MEDIA_PIWG_FW_FILE_DP))
 | |
|   {
 | |
|     FileName = &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath)->FvFileName;
 | |
|   }
 | |
| 
 | |
|   if (FileName != NULL) {
 | |
|     CopyGuid (Guid, FileName);
 | |
|   } else {
 | |
|     ZeroMem (Guid, sizeof (EFI_GUID));
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Add image structure.
 | |
| 
 | |
|   @param  ImageBase         image base
 | |
|   @param  ImageSize         image size
 | |
|   @param  EntryPoint        image entry point
 | |
|   @param  Guid              FFS GUID of the image
 | |
|   @param  PdbString         image PDB string
 | |
| **/
 | |
| VOID
 | |
| AddImageStruct (
 | |
|   IN PHYSICAL_ADDRESS  ImageBase,
 | |
|   IN UINT64            ImageSize,
 | |
|   IN PHYSICAL_ADDRESS  EntryPoint,
 | |
|   IN EFI_GUID          *Guid,
 | |
|   IN CHAR8             *PdbString
 | |
|   )
 | |
| {
 | |
|   UINTN  PdbStringSize;
 | |
| 
 | |
|   if (mImageStructCount >= mImageStructCountMax) {
 | |
|     ASSERT (FALSE);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   CopyGuid (&mImageStruct[mImageStructCount].FileGuid, Guid);
 | |
|   mImageStruct[mImageStructCount].ImageRef   = mImageStructCount;
 | |
|   mImageStruct[mImageStructCount].ImageBase  = ImageBase;
 | |
|   mImageStruct[mImageStructCount].ImageSize  = ImageSize;
 | |
|   mImageStruct[mImageStructCount].EntryPoint = EntryPoint;
 | |
|   if (PdbString != NULL) {
 | |
|     PdbStringSize                             = AsciiStrSize (PdbString);
 | |
|     mImageStruct[mImageStructCount].PdbString = AllocateCopyPool (PdbStringSize, PdbString);
 | |
|     if (mImageStruct[mImageStructCount].PdbString != NULL) {
 | |
|       mImageStruct[mImageStructCount].PdbStringSize = (UINT16)PdbStringSize;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   mImageStructCount++;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   return an image structure based upon image address.
 | |
| 
 | |
|   @param  Address  image address
 | |
| 
 | |
|   @return image structure
 | |
| **/
 | |
| IMAGE_STRUCT *
 | |
| AddressToImageStruct (
 | |
|   IN UINTN  Address
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
| 
 | |
|   for (Index = 0; Index < mImageStructCount; Index++) {
 | |
|     if ((Address >= mImageStruct[Index].ImageBase) &&
 | |
|         (Address < mImageStruct[Index].ImageBase + mImageStruct[Index].ImageSize))
 | |
|     {
 | |
|       return &mImageStruct[Index];
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   return an image reference index based upon image address.
 | |
| 
 | |
|   @param  Address  image address
 | |
| 
 | |
|   @return image reference index
 | |
| **/
 | |
| UINT32
 | |
| AddressToImageRef (
 | |
|   IN UINTN  Address
 | |
|   )
 | |
| {
 | |
|   IMAGE_STRUCT  *ImageStruct;
 | |
| 
 | |
|   ImageStruct = AddressToImageStruct (Address);
 | |
|   if (ImageStruct != NULL) {
 | |
|     return ImageStruct->ImageRef;
 | |
|   }
 | |
| 
 | |
|   return (UINT32)-1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Collect SMM image information based upon loaded image protocol.
 | |
| **/
 | |
| VOID
 | |
| GetSmmLoadedImage (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   UINTN                      NoHandles;
 | |
|   UINTN                      HandleBufferSize;
 | |
|   EFI_HANDLE                 *HandleBuffer;
 | |
|   UINTN                      Index;
 | |
|   EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
 | |
|   CHAR16                     *PathStr;
 | |
|   EFI_SMM_DRIVER_ENTRY       *LoadedImagePrivate;
 | |
|   PHYSICAL_ADDRESS           EntryPoint;
 | |
|   VOID                       *EntryPointInImage;
 | |
|   EFI_GUID                   Guid;
 | |
|   CHAR8                      *PdbString;
 | |
|   PHYSICAL_ADDRESS           RealImageBase;
 | |
| 
 | |
|   HandleBufferSize = 0;
 | |
|   HandleBuffer     = NULL;
 | |
|   Status           = gSmst->SmmLocateHandle (
 | |
|                               ByProtocol,
 | |
|                               &gEfiLoadedImageProtocolGuid,
 | |
|                               NULL,
 | |
|                               &HandleBufferSize,
 | |
|                               HandleBuffer
 | |
|                               );
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   HandleBuffer = AllocateZeroPool (HandleBufferSize);
 | |
|   if (HandleBuffer == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Status = gSmst->SmmLocateHandle (
 | |
|                     ByProtocol,
 | |
|                     &gEfiLoadedImageProtocolGuid,
 | |
|                     NULL,
 | |
|                     &HandleBufferSize,
 | |
|                     HandleBuffer
 | |
|                     );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   NoHandles            = HandleBufferSize/sizeof (EFI_HANDLE);
 | |
|   mImageStructCountMax = (UINT32)NoHandles;
 | |
|   mImageStruct         = AllocateZeroPool (mImageStructCountMax * sizeof (IMAGE_STRUCT));
 | |
|   if (mImageStruct == NULL) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < NoHandles; Index++) {
 | |
|     Status = gSmst->SmmHandleProtocol (
 | |
|                       HandleBuffer[Index],
 | |
|                       &gEfiLoadedImageProtocolGuid,
 | |
|                       (VOID **)&LoadedImage
 | |
|                       );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     PathStr = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE);
 | |
|     GetDriverGuid (LoadedImage, &Guid);
 | |
|     DEBUG ((DEBUG_INFO, "Image: %g ", &Guid));
 | |
| 
 | |
|     EntryPoint         = 0;
 | |
|     LoadedImagePrivate = BASE_CR (LoadedImage, EFI_SMM_DRIVER_ENTRY, SmmLoadedImage);
 | |
|     RealImageBase      = (UINTN)LoadedImage->ImageBase;
 | |
|     if (LoadedImagePrivate->Signature == EFI_SMM_DRIVER_ENTRY_SIGNATURE) {
 | |
|       EntryPoint = LoadedImagePrivate->ImageEntryPoint;
 | |
|       if ((EntryPoint != 0) && ((EntryPoint < (UINTN)LoadedImage->ImageBase) || (EntryPoint >= ((UINTN)LoadedImage->ImageBase + LoadedImage->ImageSize)))) {
 | |
|         //
 | |
|         // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
 | |
|         // So patch ImageBuffer here to align the EntryPoint.
 | |
|         //
 | |
|         Status = InternalPeCoffGetEntryPoint (LoadedImage->ImageBase, &EntryPointInImage);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
|         RealImageBase = (UINTN)LoadedImage->ImageBase + EntryPoint - (UINTN)EntryPointInImage;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "(0x%lx - 0x%lx", RealImageBase, LoadedImage->ImageSize));
 | |
|     if (EntryPoint != 0) {
 | |
|       DEBUG ((DEBUG_INFO, ", EntryPoint:0x%lx", EntryPoint));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, ")\n"));
 | |
| 
 | |
|     if (RealImageBase != 0) {
 | |
|       PdbString = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)RealImageBase);
 | |
|       DEBUG ((DEBUG_INFO, "       pdb - %a\n", PdbString));
 | |
|     } else {
 | |
|       PdbString = NULL;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "       (%s)\n", PathStr));
 | |
| 
 | |
|     AddImageStruct (RealImageBase, LoadedImage->ImageSize, EntryPoint, &Guid, PdbString);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   FreePool (HandleBuffer);
 | |
|   return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump SMI child context.
 | |
| 
 | |
|   @param HandlerType  the handler type
 | |
|   @param Context      the handler context
 | |
|   @param ContextSize  the handler context size
 | |
| **/
 | |
| VOID
 | |
| DumpSmiChildContext (
 | |
|   IN EFI_GUID  *HandlerType,
 | |
|   IN VOID      *Context,
 | |
|   IN UINTN     ContextSize
 | |
|   )
 | |
| {
 | |
|   CHAR16  *Str;
 | |
| 
 | |
|   if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  SwSmi - 0x%lx\n", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *)Context)->SwSmiInputValue));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmSxDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  SxType - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Type));
 | |
|     DEBUG ((DEBUG_INFO, "  SxPhase - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Phase));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmPowerButtonDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  PowerButtonPhase - 0x%x\n", ((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT *)Context)->Phase));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmStandbyButtonDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  StandbyButtonPhase - 0x%x\n", ((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT *)Context)->Phase));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  PeriodicTimerPeriod - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->Period));
 | |
|     DEBUG ((DEBUG_INFO, "  PeriodicTimerSmiTickInterval - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->SmiTickInterval));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmGpiDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  GpiNum - 0x%lx\n", ((EFI_SMM_GPI_REGISTER_CONTEXT *)Context)->GpiNum));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmIoTrapDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  IoTrapAddress - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Address));
 | |
|     DEBUG ((DEBUG_INFO, "  IoTrapLength - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Length));
 | |
|     DEBUG ((DEBUG_INFO, "  IoTrapType - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Type));
 | |
|   } else if (CompareGuid (HandlerType, &gEfiSmmUsbDispatch2ProtocolGuid)) {
 | |
|     DEBUG ((DEBUG_INFO, "  UsbType - 0x%x\n", ((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context)->Type));
 | |
|     Str = ConvertDevicePathToText ((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE);
 | |
|     DEBUG ((DEBUG_INFO, "  UsbDevicePath - %s\n", Str));
 | |
|     if (Str != NULL) {
 | |
|       FreePool (Str);
 | |
|     }
 | |
|   } else {
 | |
|     DEBUG ((DEBUG_INFO, "  Context - "));
 | |
|     InternalDumpData (Context, ContextSize);
 | |
|     DEBUG ((DEBUG_INFO, "\n"));
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump all SMI handlers associated with SmiEntry.
 | |
| 
 | |
|   @param SmiEntry  SMI entry.
 | |
| **/
 | |
| VOID
 | |
| DumpSmiHandlerOnSmiEntry (
 | |
|   IN SMI_ENTRY  *SmiEntry
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY    *ListEntry;
 | |
|   SMI_HANDLER   *SmiHandler;
 | |
|   IMAGE_STRUCT  *ImageStruct;
 | |
| 
 | |
|   ListEntry = &SmiEntry->SmiHandlers;
 | |
|   for (ListEntry = ListEntry->ForwardLink;
 | |
|        ListEntry != &SmiEntry->SmiHandlers;
 | |
|        ListEntry = ListEntry->ForwardLink)
 | |
|   {
 | |
|     SmiHandler  = CR (ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
 | |
|     ImageStruct = AddressToImageStruct ((UINTN)SmiHandler->Handler);
 | |
|     if (ImageStruct != NULL) {
 | |
|       DEBUG ((DEBUG_INFO, " Module - %g", &ImageStruct->FileGuid));
 | |
|     }
 | |
| 
 | |
|     if ((ImageStruct != NULL) && (ImageStruct->PdbString[0] != 0)) {
 | |
|       DEBUG ((DEBUG_INFO, " (Pdb - %a)", ImageStruct->PdbString));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "\n"));
 | |
|     if (SmiHandler->ContextSize != 0) {
 | |
|       DumpSmiChildContext (&SmiEntry->HandlerType, SmiHandler->Context, SmiHandler->ContextSize);
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "  Handler - 0x%x", SmiHandler->Handler));
 | |
|     if (ImageStruct != NULL) {
 | |
|       DEBUG ((DEBUG_INFO, " <== RVA - 0x%x", (UINTN)SmiHandler->Handler - (UINTN)ImageStruct->ImageBase));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "\n"));
 | |
|     DEBUG ((DEBUG_INFO, "  CallerAddr - 0x%x", SmiHandler->CallerAddr));
 | |
|     if (ImageStruct != NULL) {
 | |
|       DEBUG ((DEBUG_INFO, " <== RVA - 0x%x", SmiHandler->CallerAddr - (UINTN)ImageStruct->ImageBase));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "\n"));
 | |
|   }
 | |
| 
 | |
|   return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump all SMI entry on the list.
 | |
| 
 | |
|   @param SmiEntryList a list of SMI entry.
 | |
| **/
 | |
| VOID
 | |
| DumpSmiEntryList (
 | |
|   IN LIST_ENTRY  *SmiEntryList
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY  *ListEntry;
 | |
|   SMI_ENTRY   *SmiEntry;
 | |
| 
 | |
|   ListEntry = SmiEntryList;
 | |
|   for (ListEntry = ListEntry->ForwardLink;
 | |
|        ListEntry != SmiEntryList;
 | |
|        ListEntry = ListEntry->ForwardLink)
 | |
|   {
 | |
|     SmiEntry = CR (ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
 | |
|     DEBUG ((DEBUG_INFO, "SmiEntry - %g\n", &SmiEntry->HandlerType));
 | |
|     DumpSmiHandlerOnSmiEntry (SmiEntry);
 | |
|   }
 | |
| 
 | |
|   return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   SMM Ready To Lock event notification handler.
 | |
| 
 | |
|   This function collects all SMM image information and build SmiHandleProfile database,
 | |
|   and register SmiHandlerProfile SMI handler.
 | |
| 
 | |
|   @param[in] Protocol   Points to the protocol's unique identifier.
 | |
|   @param[in] Interface  Points to the interface instance.
 | |
|   @param[in] Handle     The handle on which the interface was installed.
 | |
| 
 | |
|   @retval EFI_SUCCESS   Notification handler runs successfully.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmReadyToLockInSmiHandlerProfile (
 | |
|   IN CONST EFI_GUID  *Protocol,
 | |
|   IN VOID            *Interface,
 | |
|   IN EFI_HANDLE      Handle
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Dump all image
 | |
|   //
 | |
|   DEBUG ((DEBUG_INFO, "##################\n"));
 | |
|   DEBUG ((DEBUG_INFO, "# IMAGE DATABASE #\n"));
 | |
|   DEBUG ((DEBUG_INFO, "##################\n"));
 | |
|   GetSmmLoadedImage ();
 | |
|   DEBUG ((DEBUG_INFO, "\n"));
 | |
| 
 | |
|   //
 | |
|   // Dump SMI Handler
 | |
|   //
 | |
|   DEBUG ((DEBUG_INFO, "########################\n"));
 | |
|   DEBUG ((DEBUG_INFO, "# SMI Handler DATABASE #\n"));
 | |
|   DEBUG ((DEBUG_INFO, "########################\n"));
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "# 1. ROOT SMI Handler #\n"));
 | |
|   DEBUG_CODE (
 | |
|     DumpSmiEntryList (mSmmCoreRootSmiEntryList);
 | |
|     );
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "# 2. GUID SMI Handler #\n"));
 | |
|   DEBUG_CODE (
 | |
|     DumpSmiEntryList (mSmmCoreSmiEntryList);
 | |
|     );
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "# 3. Hardware SMI Handler #\n"));
 | |
|   DEBUG_CODE (
 | |
|     DumpSmiEntryList (mSmmCoreHardwareSmiEntryList);
 | |
|     );
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "\n"));
 | |
| 
 | |
|   RegisterSmiHandlerProfileHandler ();
 | |
| 
 | |
|   if (mImageStruct != NULL) {
 | |
|     FreePool (mImageStruct);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   returns SMM image data base size.
 | |
| 
 | |
|   @return SMM image data base size.
 | |
| **/
 | |
| UINTN
 | |
| GetSmmImageDatabaseSize (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINTN   Size;
 | |
|   UINT32  Index;
 | |
| 
 | |
|   Size = 0;
 | |
|   for (Index = 0; Index < mImageStructCount; Index++) {
 | |
|     Size += sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64));
 | |
|   }
 | |
| 
 | |
|   return Size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   returns all SMI handlers' size associated with SmiEntry.
 | |
| 
 | |
|   @param SmiEntry  SMI entry.
 | |
| 
 | |
|   @return all SMI handlers' size associated with SmiEntry.
 | |
| **/
 | |
| UINTN
 | |
| GetSmmSmiHandlerSizeOnSmiEntry (
 | |
|   IN SMI_ENTRY  *SmiEntry
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY   *ListEntry;
 | |
|   SMI_HANDLER  *SmiHandler;
 | |
|   UINTN        Size;
 | |
| 
 | |
|   Size      = 0;
 | |
|   ListEntry = &SmiEntry->SmiHandlers;
 | |
|   for (ListEntry = ListEntry->ForwardLink;
 | |
|        ListEntry != &SmiEntry->SmiHandlers;
 | |
|        ListEntry = ListEntry->ForwardLink)
 | |
|   {
 | |
|     SmiHandler = CR (ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
 | |
|     Size      += sizeof (SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64));
 | |
|   }
 | |
| 
 | |
|   return Size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   return all SMI handler database size on the SMI entry list.
 | |
| 
 | |
|   @param SmiEntryList a list of SMI entry.
 | |
| 
 | |
|   @return all SMI handler database size on the SMI entry list.
 | |
| **/
 | |
| UINTN
 | |
| GetSmmSmiDatabaseSize (
 | |
|   IN LIST_ENTRY  *SmiEntryList
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY  *ListEntry;
 | |
|   SMI_ENTRY   *SmiEntry;
 | |
|   UINTN       Size;
 | |
| 
 | |
|   Size      = 0;
 | |
|   ListEntry = SmiEntryList;
 | |
|   for (ListEntry = ListEntry->ForwardLink;
 | |
|        ListEntry != SmiEntryList;
 | |
|        ListEntry = ListEntry->ForwardLink)
 | |
|   {
 | |
|     SmiEntry = CR (ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
 | |
|     Size    += sizeof (SMM_CORE_SMI_DATABASE_STRUCTURE);
 | |
|     Size    += GetSmmSmiHandlerSizeOnSmiEntry (SmiEntry);
 | |
|   }
 | |
| 
 | |
|   return Size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   return SMI handler profile database size.
 | |
| 
 | |
|   @return SMI handler profile database size.
 | |
| **/
 | |
| UINTN
 | |
| GetSmiHandlerProfileDatabaseSize (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   mSmmImageDatabaseSize       = GetSmmImageDatabaseSize ();
 | |
|   mSmmRootSmiDatabaseSize     = GetSmmSmiDatabaseSize (mSmmCoreRootSmiEntryList);
 | |
|   mSmmSmiDatabaseSize         = GetSmmSmiDatabaseSize (mSmmCoreSmiEntryList);
 | |
|   mSmmHardwareSmiDatabaseSize = GetSmmSmiDatabaseSize (mSmmCoreHardwareSmiEntryList);
 | |
| 
 | |
|   return mSmmImageDatabaseSize + mSmmSmiDatabaseSize + mSmmRootSmiDatabaseSize + mSmmHardwareSmiDatabaseSize;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   get SMM image database.
 | |
| 
 | |
|   @param Data           The buffer to hold SMM image database
 | |
|   @param ExpectedSize   The expected size of the SMM image database
 | |
| 
 | |
|   @return SMM image data base size.
 | |
| **/
 | |
| UINTN
 | |
| GetSmmImageDatabaseData (
 | |
|   IN OUT VOID   *Data,
 | |
|   IN     UINTN  ExpectedSize
 | |
|   )
 | |
| {
 | |
|   SMM_CORE_IMAGE_DATABASE_STRUCTURE  *ImageStruct;
 | |
|   UINTN                              Size;
 | |
|   UINTN                              Index;
 | |
| 
 | |
|   ImageStruct = Data;
 | |
|   Size        = 0;
 | |
|   for (Index = 0; Index < mImageStructCount; Index++) {
 | |
|     if (Size >= ExpectedSize) {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     if (sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64)) > ExpectedSize - Size) {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     ImageStruct->Header.Signature = SMM_CORE_IMAGE_DATABASE_SIGNATURE;
 | |
|     ImageStruct->Header.Length    = (UINT32)(sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64)));
 | |
|     ImageStruct->Header.Revision  = SMM_CORE_IMAGE_DATABASE_REVISION;
 | |
|     CopyGuid (&ImageStruct->FileGuid, &mImageStruct[Index].FileGuid);
 | |
|     ImageStruct->ImageRef   = mImageStruct[Index].ImageRef;
 | |
|     ImageStruct->EntryPoint = mImageStruct[Index].EntryPoint;
 | |
|     ImageStruct->ImageBase  = mImageStruct[Index].ImageBase;
 | |
|     ImageStruct->ImageSize  = mImageStruct[Index].ImageSize;
 | |
|     if (mImageStruct[Index].PdbStringSize != 0) {
 | |
|       ImageStruct->PdbStringOffset = sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE);
 | |
|       CopyMem ((VOID *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset), mImageStruct[Index].PdbString, mImageStruct[Index].PdbStringSize);
 | |
|     } else {
 | |
|       ImageStruct->PdbStringOffset = 0;
 | |
|     }
 | |
| 
 | |
|     ImageStruct = (SMM_CORE_IMAGE_DATABASE_STRUCTURE *)((UINTN)ImageStruct + ImageStruct->Header.Length);
 | |
|     Size       += sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64));
 | |
|   }
 | |
| 
 | |
|   if (ExpectedSize != Size) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return Size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   get all SMI handler data associated with SmiEntry.
 | |
| 
 | |
|   @param SmiEntry       SMI entry.
 | |
|   @param Data           The buffer to hold all SMI handler data
 | |
|   @param MaxSize        The max size of the SMM image database
 | |
|   @param Count          The count of the SMI handler.
 | |
| 
 | |
|   @return SMM image data base size.
 | |
| **/
 | |
| UINTN
 | |
| GetSmmSmiHandlerDataOnSmiEntry (
 | |
|   IN     SMI_ENTRY  *SmiEntry,
 | |
|   IN OUT VOID       *Data,
 | |
|   IN     UINTN      MaxSize,
 | |
|   OUT UINT32        *Count
 | |
|   )
 | |
| {
 | |
|   SMM_CORE_SMI_HANDLER_STRUCTURE  *SmiHandlerStruct;
 | |
|   LIST_ENTRY                      *ListEntry;
 | |
|   SMI_HANDLER                     *SmiHandler;
 | |
|   UINTN                           Size;
 | |
| 
 | |
|   SmiHandlerStruct = Data;
 | |
|   Size             = 0;
 | |
|   *Count           = 0;
 | |
|   ListEntry        = &SmiEntry->SmiHandlers;
 | |
|   for (ListEntry = ListEntry->ForwardLink;
 | |
|        ListEntry != &SmiEntry->SmiHandlers;
 | |
|        ListEntry = ListEntry->ForwardLink)
 | |
|   {
 | |
|     SmiHandler = CR (ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
 | |
|     if (Size >= MaxSize) {
 | |
|       *Count = 0;
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     if (sizeof (SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64)) > MaxSize - Size) {
 | |
|       *Count = 0;
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     SmiHandlerStruct->Length            = (UINT32)(sizeof (SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64)));
 | |
|     SmiHandlerStruct->CallerAddr        = (UINTN)SmiHandler->CallerAddr;
 | |
|     SmiHandlerStruct->Handler           = (UINTN)SmiHandler->Handler;
 | |
|     SmiHandlerStruct->ImageRef          = AddressToImageRef ((UINTN)SmiHandler->Handler);
 | |
|     SmiHandlerStruct->ContextBufferSize = (UINT32)SmiHandler->ContextSize;
 | |
|     if (SmiHandler->ContextSize != 0) {
 | |
|       SmiHandlerStruct->ContextBufferOffset = sizeof (SMM_CORE_SMI_HANDLER_STRUCTURE);
 | |
|       CopyMem ((UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandler->Context, SmiHandler->ContextSize);
 | |
|     } else {
 | |
|       SmiHandlerStruct->ContextBufferOffset = 0;
 | |
|     }
 | |
| 
 | |
|     Size            += sizeof (SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64));
 | |
|     SmiHandlerStruct = (SMM_CORE_SMI_HANDLER_STRUCTURE *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length);
 | |
|     *Count           = *Count + 1;
 | |
|   }
 | |
| 
 | |
|   return Size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   get all SMI handler database on the SMI entry list.
 | |
| 
 | |
|   @param SmiEntryList     a list of SMI entry.
 | |
|   @param HandlerCategory  The handler category
 | |
|   @param Data             The buffer to hold all SMI handler database
 | |
|   @param ExpectedSize     The expected size of the SMM image database
 | |
| 
 | |
|   @return all SMI database size on the SMI entry list.
 | |
| **/
 | |
| UINTN
 | |
| GetSmmSmiDatabaseData (
 | |
|   IN     LIST_ENTRY  *SmiEntryList,
 | |
|   IN     UINT32      HandlerCategory,
 | |
|   IN OUT VOID        *Data,
 | |
|   IN     UINTN       ExpectedSize
 | |
|   )
 | |
| {
 | |
|   SMM_CORE_SMI_DATABASE_STRUCTURE  *SmiStruct;
 | |
|   LIST_ENTRY                       *ListEntry;
 | |
|   SMI_ENTRY                        *SmiEntry;
 | |
|   UINTN                            Size;
 | |
|   UINTN                            SmiHandlerSize;
 | |
|   UINT32                           SmiHandlerCount;
 | |
| 
 | |
|   SmiStruct = Data;
 | |
|   Size      = 0;
 | |
|   ListEntry = SmiEntryList;
 | |
|   for (ListEntry = ListEntry->ForwardLink;
 | |
|        ListEntry != SmiEntryList;
 | |
|        ListEntry = ListEntry->ForwardLink)
 | |
|   {
 | |
|     SmiEntry = CR (ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);
 | |
|     if (Size >= ExpectedSize) {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     if (sizeof (SMM_CORE_SMI_DATABASE_STRUCTURE) > ExpectedSize - Size) {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     SmiStruct->Header.Signature = SMM_CORE_SMI_DATABASE_SIGNATURE;
 | |
|     SmiStruct->Header.Length    = sizeof (SMM_CORE_SMI_DATABASE_STRUCTURE);
 | |
|     SmiStruct->Header.Revision  = SMM_CORE_SMI_DATABASE_REVISION;
 | |
|     SmiStruct->HandlerCategory  = HandlerCategory;
 | |
|     CopyGuid (&SmiStruct->HandlerType, &SmiEntry->HandlerType);
 | |
|     Size                     += sizeof (SMM_CORE_SMI_DATABASE_STRUCTURE);
 | |
|     SmiHandlerSize            = GetSmmSmiHandlerDataOnSmiEntry (SmiEntry, (UINT8 *)SmiStruct + SmiStruct->Header.Length, ExpectedSize - Size, &SmiHandlerCount);
 | |
|     SmiStruct->HandlerCount   = SmiHandlerCount;
 | |
|     Size                     += SmiHandlerSize;
 | |
|     SmiStruct->Header.Length += (UINT32)SmiHandlerSize;
 | |
|     SmiStruct                 = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length);
 | |
|   }
 | |
| 
 | |
|   if (ExpectedSize != Size) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return Size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get SMI handler profile database.
 | |
| 
 | |
|   @param Data the buffer to hold SMI handler profile database
 | |
| 
 | |
|   @retval EFI_SUCCESS            the database is got.
 | |
|   @retval EFI_INVALID_PARAMETER  the database size mismatch.
 | |
| **/
 | |
| EFI_STATUS
 | |
| GetSmiHandlerProfileDatabaseData (
 | |
|   IN OUT VOID  *Data
 | |
|   )
 | |
| {
 | |
|   UINTN  SmmImageDatabaseSize;
 | |
|   UINTN  SmmSmiDatabaseSize;
 | |
|   UINTN  SmmRootSmiDatabaseSize;
 | |
|   UINTN  SmmHardwareSmiDatabaseSize;
 | |
| 
 | |
|   DEBUG ((DEBUG_VERBOSE, "GetSmiHandlerProfileDatabaseData\n"));
 | |
|   SmmImageDatabaseSize = GetSmmImageDatabaseData (Data, mSmmImageDatabaseSize);
 | |
|   if (SmmImageDatabaseSize != mSmmImageDatabaseSize) {
 | |
|     DEBUG ((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmImageDatabaseSize mismatch!\n"));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SmmRootSmiDatabaseSize = GetSmmSmiDatabaseData (mSmmCoreRootSmiEntryList, SmmCoreSmiHandlerCategoryRootHandler, (UINT8 *)Data + SmmImageDatabaseSize, mSmmRootSmiDatabaseSize);
 | |
|   if (SmmRootSmiDatabaseSize != mSmmRootSmiDatabaseSize) {
 | |
|     DEBUG ((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmRootSmiDatabaseSize mismatch!\n"));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SmmSmiDatabaseSize = GetSmmSmiDatabaseData (mSmmCoreSmiEntryList, SmmCoreSmiHandlerCategoryGuidHandler, (UINT8 *)Data + SmmImageDatabaseSize + mSmmRootSmiDatabaseSize, mSmmSmiDatabaseSize);
 | |
|   if (SmmSmiDatabaseSize != mSmmSmiDatabaseSize) {
 | |
|     DEBUG ((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmSmiDatabaseSize mismatch!\n"));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SmmHardwareSmiDatabaseSize = GetSmmSmiDatabaseData (mSmmCoreHardwareSmiEntryList, SmmCoreSmiHandlerCategoryHardwareHandler, (UINT8 *)Data + SmmImageDatabaseSize + SmmRootSmiDatabaseSize + SmmSmiDatabaseSize, mSmmHardwareSmiDatabaseSize);
 | |
|   if (SmmHardwareSmiDatabaseSize != mSmmHardwareSmiDatabaseSize) {
 | |
|     DEBUG ((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmHardwareSmiDatabaseSize mismatch!\n"));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   build SMI handler profile database.
 | |
| **/
 | |
| VOID
 | |
| BuildSmiHandlerProfileDatabase (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   mSmiHandlerProfileDatabaseSize = GetSmiHandlerProfileDatabaseSize ();
 | |
|   mSmiHandlerProfileDatabase     = AllocatePool (mSmiHandlerProfileDatabaseSize);
 | |
|   if (mSmiHandlerProfileDatabase == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Status = GetSmiHandlerProfileDatabaseData (mSmiHandlerProfileDatabase);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (mSmiHandlerProfileDatabase);
 | |
|     mSmiHandlerProfileDatabase = NULL;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Copy SMI handler profile data.
 | |
| 
 | |
|   @param DataBuffer  The buffer to hold SMI handler profile data.
 | |
|   @param DataSize    On input, data buffer size.
 | |
|                      On output, actual data buffer size copied.
 | |
|   @param DataOffset  On input, data buffer offset to copy.
 | |
|                      On output, next time data buffer offset to copy.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SmiHandlerProfileCopyData (
 | |
|   OUT VOID       *DataBuffer,
 | |
|   IN OUT UINT64  *DataSize,
 | |
|   IN OUT UINT64  *DataOffset
 | |
|   )
 | |
| {
 | |
|   if (*DataOffset >= mSmiHandlerProfileDatabaseSize) {
 | |
|     *DataOffset = mSmiHandlerProfileDatabaseSize;
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (mSmiHandlerProfileDatabaseSize - *DataOffset < *DataSize) {
 | |
|     *DataSize = mSmiHandlerProfileDatabaseSize - *DataOffset;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     DataBuffer,
 | |
|     (UINT8 *)mSmiHandlerProfileDatabase + *DataOffset,
 | |
|     (UINTN)*DataSize
 | |
|     );
 | |
|   *DataOffset = *DataOffset + *DataSize;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   SMI handler profile handler to get info.
 | |
| 
 | |
|   @param SmiHandlerProfileParameterGetInfo The parameter of SMI handler profile get info.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SmiHandlerProfileHandlerGetInfo (
 | |
|   IN SMI_HANDLER_PROFILE_PARAMETER_GET_INFO  *SmiHandlerProfileParameterGetInfo
 | |
|   )
 | |
| {
 | |
|   BOOLEAN  SmiHandlerProfileRecordingStatus;
 | |
| 
 | |
|   SmiHandlerProfileRecordingStatus  = mSmiHandlerProfileRecordingStatus;
 | |
|   mSmiHandlerProfileRecordingStatus = FALSE;
 | |
| 
 | |
|   SmiHandlerProfileParameterGetInfo->DataSize            = mSmiHandlerProfileDatabaseSize;
 | |
|   SmiHandlerProfileParameterGetInfo->Header.ReturnStatus = 0;
 | |
| 
 | |
|   mSmiHandlerProfileRecordingStatus = SmiHandlerProfileRecordingStatus;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   SMI handler profile handler to get data by offset.
 | |
| 
 | |
|   @param SmiHandlerProfileParameterGetDataByOffset   The parameter of SMI handler profile get data by offset.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SmiHandlerProfileHandlerGetDataByOffset (
 | |
|   IN SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET  *SmiHandlerProfileParameterGetDataByOffset
 | |
|   )
 | |
| {
 | |
|   SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET  SmiHandlerProfileGetDataByOffset;
 | |
|   BOOLEAN                                           SmiHandlerProfileRecordingStatus;
 | |
| 
 | |
|   SmiHandlerProfileRecordingStatus  = mSmiHandlerProfileRecordingStatus;
 | |
|   mSmiHandlerProfileRecordingStatus = FALSE;
 | |
| 
 | |
|   CopyMem (&SmiHandlerProfileGetDataByOffset, SmiHandlerProfileParameterGetDataByOffset, sizeof (SmiHandlerProfileGetDataByOffset));
 | |
| 
 | |
|   //
 | |
|   // Sanity check
 | |
|   //
 | |
|   if (!SmmIsBufferOutsideSmmValid ((UINTN)SmiHandlerProfileGetDataByOffset.DataBuffer, (UINTN)SmiHandlerProfileGetDataByOffset.DataSize)) {
 | |
|     DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandlerGetDataByOffset: SMI handler profile get data in SMRAM or overflow!\n"));
 | |
|     SmiHandlerProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64)(INT64)(INTN)EFI_ACCESS_DENIED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   SmiHandlerProfileCopyData ((VOID *)(UINTN)SmiHandlerProfileGetDataByOffset.DataBuffer, &SmiHandlerProfileGetDataByOffset.DataSize, &SmiHandlerProfileGetDataByOffset.DataOffset);
 | |
|   CopyMem (SmiHandlerProfileParameterGetDataByOffset, &SmiHandlerProfileGetDataByOffset, sizeof (SmiHandlerProfileGetDataByOffset));
 | |
|   SmiHandlerProfileParameterGetDataByOffset->Header.ReturnStatus = 0;
 | |
| 
 | |
| Done:
 | |
|   mSmiHandlerProfileRecordingStatus = SmiHandlerProfileRecordingStatus;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dispatch function for a Software SMI handler.
 | |
| 
 | |
|   Caution: This function may receive untrusted input.
 | |
|   Communicate buffer and buffer size are external input, so this function will do basic validation.
 | |
| 
 | |
|   @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.
 | |
| 
 | |
|   @retval EFI_SUCCESS Command is handled successfully.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmiHandlerProfileHandler (
 | |
|   IN EFI_HANDLE  DispatchHandle,
 | |
|   IN CONST VOID  *Context         OPTIONAL,
 | |
|   IN OUT VOID    *CommBuffer      OPTIONAL,
 | |
|   IN OUT UINTN   *CommBufferSize  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   SMI_HANDLER_PROFILE_PARAMETER_HEADER  *SmiHandlerProfileParameterHeader;
 | |
|   UINTN                                 TempCommBufferSize;
 | |
| 
 | |
|   DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandler Enter\n"));
 | |
| 
 | |
|   if (mSmiHandlerProfileDatabase == NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If input is invalid, stop processing this SMI
 | |
|   //
 | |
|   if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   TempCommBufferSize = *CommBufferSize;
 | |
| 
 | |
|   if (TempCommBufferSize < sizeof (SMI_HANDLER_PROFILE_PARAMETER_HEADER)) {
 | |
|     DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
 | |
|     DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   SmiHandlerProfileParameterHeader               = (SMI_HANDLER_PROFILE_PARAMETER_HEADER *)((UINTN)CommBuffer);
 | |
|   SmiHandlerProfileParameterHeader->ReturnStatus = (UINT64)-1;
 | |
| 
 | |
|   switch (SmiHandlerProfileParameterHeader->Command) {
 | |
|     case SMI_HANDLER_PROFILE_COMMAND_GET_INFO:
 | |
|       DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandlerGetInfo\n"));
 | |
|       if (TempCommBufferSize != sizeof (SMI_HANDLER_PROFILE_PARAMETER_GET_INFO)) {
 | |
|         DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       SmiHandlerProfileHandlerGetInfo ((SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)(UINTN)CommBuffer);
 | |
|       break;
 | |
|     case SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET:
 | |
|       DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandlerGetDataByOffset\n"));
 | |
|       if (TempCommBufferSize != sizeof (SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET)) {
 | |
|         DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       SmiHandlerProfileHandlerGetDataByOffset ((SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)(UINTN)CommBuffer);
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_ERROR, "SmiHandlerProfileHandler Exit\n"));
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Register SMI handler profile handler.
 | |
| **/
 | |
| VOID
 | |
| RegisterSmiHandlerProfileHandler (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_HANDLE  DispatchHandle;
 | |
| 
 | |
|   Status = gSmst->SmiHandlerRegister (
 | |
|                     SmiHandlerProfileHandler,
 | |
|                     &gSmiHandlerProfileGuid,
 | |
|                     &DispatchHandle
 | |
|                     );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   BuildSmiHandlerProfileDatabase ();
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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  *
 | |
| SmmCoreFindHardwareSmiEntry (
 | |
|   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 = mHardwareSmiEntryList.ForwardLink;
 | |
|        Link != &mHardwareSmiEntryList;
 | |
|        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 (&mHardwareSmiEntryList, &SmiEntry->AllEntries);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return SmiEntry;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert EFI_SMM_USB_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT.
 | |
| 
 | |
|   @param UsbContext                   A pointer to EFI_SMM_USB_REGISTER_CONTEXT
 | |
|   @param UsbContextSize               The size of EFI_SMM_USB_REGISTER_CONTEXT in bytes
 | |
|   @param SmiHandlerUsbContextSize     The size of SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT in bytes
 | |
| 
 | |
|   @return SmiHandlerUsbContext  A pointer to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
 | |
| **/
 | |
| SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *
 | |
| ConvertSmiHandlerUsbContext (
 | |
|   IN EFI_SMM_USB_REGISTER_CONTEXT  *UsbContext,
 | |
|   IN UINTN                         UsbContextSize,
 | |
|   OUT UINTN                        *SmiHandlerUsbContextSize
 | |
|   )
 | |
| {
 | |
|   UINTN                                     DevicePathSize;
 | |
|   SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT  *SmiHandlerUsbContext;
 | |
| 
 | |
|   ASSERT (UsbContextSize == sizeof (EFI_SMM_USB_REGISTER_CONTEXT));
 | |
| 
 | |
|   DevicePathSize       = GetDevicePathSize (UsbContext->Device);
 | |
|   SmiHandlerUsbContext = AllocatePool (sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT) + DevicePathSize);
 | |
|   if (SmiHandlerUsbContext == NULL) {
 | |
|     *SmiHandlerUsbContextSize = 0;
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   SmiHandlerUsbContext->Type           = UsbContext->Type;
 | |
|   SmiHandlerUsbContext->DevicePathSize = (UINT32)DevicePathSize;
 | |
|   CopyMem (SmiHandlerUsbContext + 1, UsbContext->Device, DevicePathSize);
 | |
|   *SmiHandlerUsbContextSize = sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT) + DevicePathSize;
 | |
|   return SmiHandlerUsbContext;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert EFI_SMM_SW_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT.
 | |
| 
 | |
|   @param SwContext                    A pointer to EFI_SMM_SW_REGISTER_CONTEXT
 | |
|   @param SwContextSize                The size of EFI_SMM_SW_REGISTER_CONTEXT in bytes
 | |
|   @param SmiHandlerSwContextSize      The size of SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT in bytes
 | |
| 
 | |
|   @return SmiHandlerSwContext   A pointer to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
 | |
| **/
 | |
| SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *
 | |
| ConvertSmiHandlerSwContext (
 | |
|   IN EFI_SMM_SW_REGISTER_CONTEXT  *SwContext,
 | |
|   IN UINTN                        SwContextSize,
 | |
|   OUT UINTN                       *SmiHandlerSwContextSize
 | |
|   )
 | |
| {
 | |
|   SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT  *SmiHandlerSwContext;
 | |
| 
 | |
|   ASSERT (SwContextSize == sizeof (EFI_SMM_SW_REGISTER_CONTEXT));
 | |
| 
 | |
|   SmiHandlerSwContext = AllocatePool (sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT));
 | |
|   if (SmiHandlerSwContext == NULL) {
 | |
|     *SmiHandlerSwContextSize = 0;
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   SmiHandlerSwContext->SwSmiInputValue = SwContext->SwSmiInputValue;
 | |
|   *SmiHandlerSwContextSize             = sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT);
 | |
|   return SmiHandlerSwContext;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function is called by SmmChildDispatcher module to report
 | |
|   a new SMI handler is registered, to SmmCore.
 | |
| 
 | |
|   @param This            The protocol instance
 | |
|   @param HandlerGuid     The GUID to identify the type of the handler.
 | |
|                          For the SmmChildDispatch protocol, the HandlerGuid
 | |
|                          must be the GUID of SmmChildDispatch protocol.
 | |
|   @param Handler         The SMI handler.
 | |
|   @param CallerAddress   The address of the module who registers the SMI handler.
 | |
|   @param Context         The context of the SMI handler.
 | |
|                          For the SmmChildDispatch protocol, the Context
 | |
|                          must match the one defined for SmmChildDispatch protocol.
 | |
|   @param ContextSize     The size of the context in bytes.
 | |
|                          For the SmmChildDispatch protocol, the Context
 | |
|                          must match the one defined for SmmChildDispatch protocol.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The information is recorded.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There is no enough resource to record the information.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmiHandlerProfileRegisterHandler (
 | |
|   IN SMI_HANDLER_PROFILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID                      *HandlerGuid,
 | |
|   IN EFI_SMM_HANDLER_ENTRY_POINT2  Handler,
 | |
|   IN PHYSICAL_ADDRESS              CallerAddress,
 | |
|   IN VOID                          *Context  OPTIONAL,
 | |
|   IN UINTN                         ContextSize OPTIONAL
 | |
|   )
 | |
| {
 | |
|   SMI_HANDLER  *SmiHandler;
 | |
|   SMI_ENTRY    *SmiEntry;
 | |
|   LIST_ENTRY   *List;
 | |
| 
 | |
|   if (((ContextSize == 0) && (Context != NULL)) ||
 | |
|       ((ContextSize != 0) && (Context == 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;
 | |
|   SmiHandler->CallerAddr  = (UINTN)CallerAddress;
 | |
|   SmiHandler->Context     = Context;
 | |
|   SmiHandler->ContextSize = ContextSize;
 | |
| 
 | |
|   if (Context != NULL) {
 | |
|     if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {
 | |
|       SmiHandler->Context = ConvertSmiHandlerUsbContext (Context, ContextSize, &SmiHandler->ContextSize);
 | |
|     } else if (CompareGuid (HandlerGuid, &gEfiSmmSwDispatch2ProtocolGuid)) {
 | |
|       SmiHandler->Context = ConvertSmiHandlerSwContext (Context, ContextSize, &SmiHandler->ContextSize);
 | |
|     } else {
 | |
|       SmiHandler->Context = AllocateCopyPool (ContextSize, Context);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (SmiHandler->Context == NULL) {
 | |
|     SmiHandler->ContextSize = 0;
 | |
|   }
 | |
| 
 | |
|   SmiEntry = SmmCoreFindHardwareSmiEntry (HandlerGuid, TRUE);
 | |
|   if (SmiEntry == NULL) {
 | |
|     if (SmiHandler->Context != NULL) {
 | |
|       FreePool (SmiHandler->Context);
 | |
|     }
 | |
| 
 | |
|     FreePool (SmiHandler);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   List = &SmiEntry->SmiHandlers;
 | |
| 
 | |
|   SmiHandler->SmiEntry = SmiEntry;
 | |
|   InsertTailList (List, &SmiHandler->Link);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function is called by SmmChildDispatcher module to report
 | |
|   an existing SMI handler is unregistered, to SmmCore.
 | |
| 
 | |
|   @param This            The protocol instance
 | |
|   @param HandlerGuid     The GUID to identify the type of the handler.
 | |
|                          For the SmmChildDispatch protocol, the HandlerGuid
 | |
|                          must be the GUID of SmmChildDispatch protocol.
 | |
|   @param Handler         The SMI handler.
 | |
|   @param Context         The context of the SMI handler.
 | |
|                          If it is NOT NULL, it will be used to check what is registered.
 | |
|   @param ContextSize     The size of the context in bytes.
 | |
|                          If Context is NOT NULL, it will be used to check what is registered.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The original record is removed.
 | |
|   @retval EFI_NOT_FOUND         There is no record for the HandlerGuid and handler.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmiHandlerProfileUnregisterHandler (
 | |
|   IN SMI_HANDLER_PROFILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID                      *HandlerGuid,
 | |
|   IN EFI_SMM_HANDLER_ENTRY_POINT2  Handler,
 | |
|   IN VOID                          *Context  OPTIONAL,
 | |
|   IN UINTN                         ContextSize OPTIONAL
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY   *Link;
 | |
|   LIST_ENTRY   *Head;
 | |
|   SMI_HANDLER  *SmiHandler;
 | |
|   SMI_ENTRY    *SmiEntry;
 | |
|   SMI_HANDLER  *TargetSmiHandler;
 | |
|   VOID         *SearchContext;
 | |
|   UINTN        SearchContextSize;
 | |
| 
 | |
|   if (((ContextSize == 0) && (Context != NULL)) ||
 | |
|       ((ContextSize != 0) && (Context == NULL)))
 | |
|   {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SmiEntry = SmmCoreFindHardwareSmiEntry (HandlerGuid, FALSE);
 | |
|   if (SmiEntry == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   SearchContext     = Context;
 | |
|   SearchContextSize = ContextSize;
 | |
|   if (Context != NULL) {
 | |
|     if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {
 | |
|       SearchContext = ConvertSmiHandlerUsbContext (Context, ContextSize, &SearchContextSize);
 | |
|     } else if (CompareGuid (HandlerGuid, &gEfiSmmSwDispatch2ProtocolGuid)) {
 | |
|       SearchContext = ConvertSmiHandlerSwContext (Context, ContextSize, &SearchContextSize);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TargetSmiHandler = NULL;
 | |
|   Head             = &SmiEntry->SmiHandlers;
 | |
|   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
 | |
|     SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
 | |
|     if (SmiHandler->Handler == Handler) {
 | |
|       if ((SearchContext == NULL) ||
 | |
|           ((SearchContextSize == SmiHandler->ContextSize) && (CompareMem (SearchContext, SmiHandler->Context, SearchContextSize) == 0)))
 | |
|       {
 | |
|         TargetSmiHandler = SmiHandler;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (SearchContext != NULL) {
 | |
|     if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {
 | |
|       FreePool (SearchContext);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (TargetSmiHandler == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   SmiHandler = TargetSmiHandler;
 | |
| 
 | |
|   RemoveEntryList (&SmiHandler->Link);
 | |
|   if (SmiHandler->Context != NULL) {
 | |
|     FreePool (SmiHandler->Context);
 | |
|   }
 | |
| 
 | |
|   FreePool (SmiHandler);
 | |
| 
 | |
|   if (IsListEmpty (&SmiEntry->SmiHandlers)) {
 | |
|     RemoveEntryList (&SmiEntry->AllEntries);
 | |
|     FreePool (SmiEntry);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize SmiHandler profile feature.
 | |
| **/
 | |
| VOID
 | |
| SmmCoreInitializeSmiHandlerProfile (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   VOID        *Registration;
 | |
|   EFI_HANDLE  Handle;
 | |
| 
 | |
|   if ((PcdGet8 (PcdSmiHandlerProfilePropertyMask) & 0x1) != 0) {
 | |
|     InsertTailList (&mRootSmiEntryList, &mRootSmiEntry.AllEntries);
 | |
| 
 | |
|     Status = gSmst->SmmRegisterProtocolNotify (
 | |
|                       &gEfiSmmReadyToLockProtocolGuid,
 | |
|                       SmmReadyToLockInSmiHandlerProfile,
 | |
|                       &Registration
 | |
|                       );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     Handle = NULL;
 | |
|     Status = gSmst->SmmInstallProtocolInterface (
 | |
|                       &Handle,
 | |
|                       &gSmiHandlerProfileGuid,
 | |
|                       EFI_NATIVE_INTERFACE,
 | |
|                       &mSmiHandlerProfile
 | |
|                       );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| }
 |