2 SMI handler profile support.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/SmmServicesTableLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/PrintLib.h>
23 #include <Library/UefiLib.h>
24 #include <Library/DevicePathLib.h>
25 #include <Library/PeCoffGetEntryPointLib.h>
26 #include <Library/DxeServicesLib.h>
27 #include <Protocol/LoadedImage.h>
28 #include <Protocol/SmmAccess2.h>
29 #include <Protocol/SmmReadyToLock.h>
30 #include <Protocol/SmmEndOfDxe.h>
32 #include <Guid/SmiHandlerProfile.h>
34 #include "PiSmmCore.h"
36 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
37 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
41 PHYSICAL_ADDRESS EntryPoint
;
42 PHYSICAL_ADDRESS ImageBase
;
50 Register SMI handler profile handler.
53 RegisterSmiHandlerProfileHandler(
58 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
59 into system memory with the PE/COFF Loader Library functions.
61 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
62 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
63 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
64 If Pe32Data is NULL, then ASSERT().
65 If EntryPoint is NULL, then ASSERT().
67 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
68 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
70 @retval RETURN_SUCCESS EntryPoint was returned.
71 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
75 InternalPeCoffGetEntryPoint (
80 extern LIST_ENTRY mSmiEntryList
;
81 extern LIST_ENTRY mHardwareSmiEntryList
;
82 extern SMI_ENTRY mRootSmiEntry
;
84 extern SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile
;
86 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mHardwareSmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mHardwareSmiEntryList
);
88 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mRootSmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntryList
);
90 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreRootSmiEntryList
= &mRootSmiEntryList
;
91 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreSmiEntryList
= &mSmiEntryList
;
92 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreHardwareSmiEntryList
= &mHardwareSmiEntryList
;
94 GLOBAL_REMOVE_IF_UNREFERENCED IMAGE_STRUCT
*mImageStruct
;
95 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCountMax
;
96 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCount
;
98 GLOBAL_REMOVE_IF_UNREFERENCED VOID
*mSmiHandlerProfileDatabase
;
99 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmiHandlerProfileDatabaseSize
;
101 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmImageDatabaseSize
;
102 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmRootSmiDatabaseSize
;
103 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmSmiDatabaseSize
;
104 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmHardwareSmiDatabaseSize
;
106 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmiHandlerProfileRecordingStatus
;
108 GLOBAL_REMOVE_IF_UNREFERENCED SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile
= {
109 SmiHandlerProfileRegisterHandler
,
110 SmiHandlerProfileUnregisterHandler
,
114 This function dump raw data.
117 @param Size raw data size
126 for (Index
= 0; Index
< Size
; Index
++) {
127 DEBUG ((DEBUG_INFO
, "%02x ", (UINTN
)Data
[Index
]));
132 Get GUID name for an image.
134 @param[in] LoadedImage LoadedImage protocol.
135 @param[out] Guid Guid of the FFS
139 IN EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
,
146 if ((DevicePathType(LoadedImage
->FilePath
) == MEDIA_DEVICE_PATH
) &&
147 (DevicePathSubType(LoadedImage
->FilePath
) == MEDIA_PIWG_FW_FILE_DP
)) {
148 FileName
= &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)LoadedImage
->FilePath
)->FvFileName
;
150 if (FileName
!= NULL
) {
151 CopyGuid(Guid
, FileName
);
153 ZeroMem(Guid
, sizeof(EFI_GUID
));
160 @param ImageBase image base
161 @param ImageSize image size
162 @param EntryPoint image entry point
163 @param Guid FFS GUID of the image
164 @param PdbString image PDB string
168 IN PHYSICAL_ADDRESS ImageBase
,
170 IN PHYSICAL_ADDRESS EntryPoint
,
177 if (mImageStructCount
>= mImageStructCountMax
) {
182 CopyGuid(&mImageStruct
[mImageStructCount
].FileGuid
, Guid
);
183 mImageStruct
[mImageStructCount
].ImageRef
= mImageStructCount
;
184 mImageStruct
[mImageStructCount
].ImageBase
= ImageBase
;
185 mImageStruct
[mImageStructCount
].ImageSize
= ImageSize
;
186 mImageStruct
[mImageStructCount
].EntryPoint
= EntryPoint
;
187 if (PdbString
!= NULL
) {
188 PdbStringSize
= AsciiStrSize(PdbString
);
189 mImageStruct
[mImageStructCount
].PdbString
= AllocateCopyPool (PdbStringSize
, PdbString
);
190 if (mImageStruct
[mImageStructCount
].PdbString
!= NULL
) {
191 mImageStruct
[mImageStructCount
].PdbStringSize
= (UINT16
) PdbStringSize
;
199 return an image structure based upon image address.
201 @param Address image address
203 @return image structure
206 AddressToImageStruct(
212 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
213 if ((Address
>= mImageStruct
[Index
].ImageBase
) &&
214 (Address
< mImageStruct
[Index
].ImageBase
+ mImageStruct
[Index
].ImageSize
)) {
215 return &mImageStruct
[Index
];
222 return an image reference index based upon image address.
224 @param Address image address
226 @return image reference index
233 IMAGE_STRUCT
*ImageStruct
;
235 ImageStruct
= AddressToImageStruct(Address
);
236 if (ImageStruct
!= NULL
) {
237 return ImageStruct
->ImageRef
;
243 Collect SMM image information based upon loaded image protocol.
252 UINTN HandleBufferSize
;
253 EFI_HANDLE
*HandleBuffer
;
255 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
257 EFI_SMM_DRIVER_ENTRY
*LoadedImagePrivate
;
258 PHYSICAL_ADDRESS EntryPoint
;
259 VOID
*EntryPointInImage
;
262 PHYSICAL_ADDRESS RealImageBase
;
264 HandleBufferSize
= 0;
266 Status
= gSmst
->SmmLocateHandle(
268 &gEfiLoadedImageProtocolGuid
,
273 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
276 HandleBuffer
= AllocateZeroPool (HandleBufferSize
);
277 if (HandleBuffer
== NULL
) {
280 Status
= gSmst
->SmmLocateHandle(
282 &gEfiLoadedImageProtocolGuid
,
287 if (EFI_ERROR(Status
)) {
291 NoHandles
= HandleBufferSize
/sizeof(EFI_HANDLE
);
292 mImageStructCountMax
= (UINT32
) NoHandles
;
293 mImageStruct
= AllocateZeroPool(mImageStructCountMax
* sizeof(IMAGE_STRUCT
));
294 if (mImageStruct
== NULL
) {
298 for (Index
= 0; Index
< NoHandles
; Index
++) {
299 Status
= gSmst
->SmmHandleProtocol(
301 &gEfiLoadedImageProtocolGuid
,
302 (VOID
**)&LoadedImage
304 if (EFI_ERROR(Status
)) {
307 PathStr
= ConvertDevicePathToText(LoadedImage
->FilePath
, TRUE
, TRUE
);
308 GetDriverGuid(LoadedImage
, &Guid
);
309 DEBUG ((DEBUG_INFO
, "Image: %g ", &Guid
));
312 LoadedImagePrivate
= BASE_CR(LoadedImage
, EFI_SMM_DRIVER_ENTRY
, SmmLoadedImage
);
313 RealImageBase
= (UINTN
)LoadedImage
->ImageBase
;
314 if (LoadedImagePrivate
->Signature
== EFI_SMM_DRIVER_ENTRY_SIGNATURE
) {
315 EntryPoint
= LoadedImagePrivate
->ImageEntryPoint
;
316 if ((EntryPoint
!= 0) && ((EntryPoint
< (UINTN
)LoadedImage
->ImageBase
) || (EntryPoint
>= ((UINTN
)LoadedImage
->ImageBase
+ LoadedImage
->ImageSize
)))) {
318 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
319 // So patch ImageBuffer here to align the EntryPoint.
321 Status
= InternalPeCoffGetEntryPoint(LoadedImage
->ImageBase
, &EntryPointInImage
);
322 ASSERT_EFI_ERROR(Status
);
323 RealImageBase
= (UINTN
)LoadedImage
->ImageBase
+ EntryPoint
- (UINTN
)EntryPointInImage
;
326 DEBUG ((DEBUG_INFO
, "(0x%lx - 0x%lx", RealImageBase
, LoadedImage
->ImageSize
));
327 if (EntryPoint
!= 0) {
328 DEBUG ((DEBUG_INFO
, ", EntryPoint:0x%lx", EntryPoint
));
330 DEBUG ((DEBUG_INFO
, ")\n"));
332 if (RealImageBase
!= 0) {
333 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) RealImageBase
);
334 DEBUG ((DEBUG_INFO
, " pdb - %a\n", PdbString
));
338 DEBUG ((DEBUG_INFO
, " (%s)\n", PathStr
));
340 AddImageStruct(RealImageBase
, LoadedImage
->ImageSize
, EntryPoint
, &Guid
, PdbString
);
344 FreePool(HandleBuffer
);
349 Dump SMI child context.
351 @param HandlerType the handler type
352 @param Context the handler context
353 @param ContextSize the handler context size
356 DumpSmiChildContext (
357 IN EFI_GUID
*HandlerType
,
364 if (CompareGuid (HandlerType
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
365 DEBUG ((DEBUG_INFO
, " SwSmi - 0x%lx\n", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*)Context
)->SwSmiInputValue
));
366 } else if (CompareGuid (HandlerType
, &gEfiSmmSxDispatch2ProtocolGuid
)) {
367 DEBUG ((DEBUG_INFO
, " SxType - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT
*)Context
)->Type
));
368 DEBUG ((DEBUG_INFO
, " SxPhase - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT
*)Context
)->Phase
));
369 } else if (CompareGuid (HandlerType
, &gEfiSmmPowerButtonDispatch2ProtocolGuid
)) {
370 DEBUG ((DEBUG_INFO
, " PowerButtonPhase - 0x%x\n", ((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT
*)Context
)->Phase
));
371 } else if (CompareGuid (HandlerType
, &gEfiSmmStandbyButtonDispatch2ProtocolGuid
)) {
372 DEBUG ((DEBUG_INFO
, " StandbyButtonPhase - 0x%x\n", ((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT
*)Context
)->Phase
));
373 } else if (CompareGuid (HandlerType
, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid
)) {
374 DEBUG ((DEBUG_INFO
, " PeriodicTimerPeriod - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT
*)Context
)->Period
));
375 DEBUG ((DEBUG_INFO
, " PeriodicTimerSmiTickInterval - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT
*)Context
)->SmiTickInterval
));
376 } else if (CompareGuid (HandlerType
, &gEfiSmmGpiDispatch2ProtocolGuid
)) {
377 DEBUG ((DEBUG_INFO
, " GpiNum - 0x%lx\n", ((EFI_SMM_GPI_REGISTER_CONTEXT
*)Context
)->GpiNum
));
378 } else if (CompareGuid (HandlerType
, &gEfiSmmIoTrapDispatch2ProtocolGuid
)) {
379 DEBUG ((DEBUG_INFO
, " IoTrapAddress - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Address
));
380 DEBUG ((DEBUG_INFO
, " IoTrapLength - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Length
));
381 DEBUG ((DEBUG_INFO
, " IoTrapType - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Type
));
382 } else if (CompareGuid (HandlerType
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
383 DEBUG ((DEBUG_INFO
, " UsbType - 0x%x\n", ((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*)Context
)->Type
));
384 Str
= ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL
*)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*)Context
) + 1), TRUE
, TRUE
);
385 DEBUG ((DEBUG_INFO
, " UsbDevicePath - %s\n", Str
));
390 DEBUG ((DEBUG_INFO
, " Context - "));
391 InternalDumpData (Context
, ContextSize
);
392 DEBUG ((DEBUG_INFO
, "\n"));
397 Dump all SMI handlers associated with SmiEntry.
399 @param SmiEntry SMI entry.
402 DumpSmiHandlerOnSmiEntry(
403 IN SMI_ENTRY
*SmiEntry
406 LIST_ENTRY
*ListEntry
;
407 SMI_HANDLER
*SmiHandler
;
408 IMAGE_STRUCT
*ImageStruct
;
410 ListEntry
= &SmiEntry
->SmiHandlers
;
411 for (ListEntry
= ListEntry
->ForwardLink
;
412 ListEntry
!= &SmiEntry
->SmiHandlers
;
413 ListEntry
= ListEntry
->ForwardLink
) {
414 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
415 ImageStruct
= AddressToImageStruct((UINTN
)SmiHandler
->Handler
);
416 if (ImageStruct
!= NULL
) {
417 DEBUG ((DEBUG_INFO
, " Module - %g", &ImageStruct
->FileGuid
));
419 if ((ImageStruct
!= NULL
) && (ImageStruct
->PdbString
[0] != 0)) {
420 DEBUG ((DEBUG_INFO
, " (Pdb - %a)", ImageStruct
->PdbString
));
422 DEBUG ((DEBUG_INFO
, "\n"));
423 if (SmiHandler
->ContextSize
!= 0) {
424 DumpSmiChildContext (&SmiEntry
->HandlerType
, SmiHandler
->Context
, SmiHandler
->ContextSize
);
426 DEBUG ((DEBUG_INFO
, " Handler - 0x%x", SmiHandler
->Handler
));
427 if (ImageStruct
!= NULL
) {
428 DEBUG ((DEBUG_INFO
, " <== RVA - 0x%x", (UINTN
)SmiHandler
->Handler
- (UINTN
) ImageStruct
->ImageBase
));
430 DEBUG ((DEBUG_INFO
, "\n"));
431 DEBUG ((DEBUG_INFO
, " CallerAddr - 0x%x", SmiHandler
->CallerAddr
));
432 if (ImageStruct
!= NULL
) {
433 DEBUG ((DEBUG_INFO
, " <== RVA - 0x%x", SmiHandler
->CallerAddr
- (UINTN
) ImageStruct
->ImageBase
));
435 DEBUG ((DEBUG_INFO
, "\n"));
442 Dump all SMI entry on the list.
444 @param SmiEntryList a list of SMI entry.
448 IN LIST_ENTRY
*SmiEntryList
451 LIST_ENTRY
*ListEntry
;
454 ListEntry
= SmiEntryList
;
455 for (ListEntry
= ListEntry
->ForwardLink
;
456 ListEntry
!= SmiEntryList
;
457 ListEntry
= ListEntry
->ForwardLink
) {
458 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
459 DEBUG ((DEBUG_INFO
, "SmiEntry - %g\n", &SmiEntry
->HandlerType
));
460 DumpSmiHandlerOnSmiEntry(SmiEntry
);
467 SMM Ready To Lock event notification handler.
469 This function collects all SMM image information and build SmiHandleProfile database,
470 and register SmiHandlerProfile SMI handler.
472 @param[in] Protocol Points to the protocol's unique identifier.
473 @param[in] Interface Points to the interface instance.
474 @param[in] Handle The handle on which the interface was installed.
476 @retval EFI_SUCCESS Notification handler runs successfully.
480 SmmReadyToLockInSmiHandlerProfile (
481 IN CONST EFI_GUID
*Protocol
,
489 DEBUG ((DEBUG_INFO
, "##################\n"));
490 DEBUG ((DEBUG_INFO
, "# IMAGE DATABASE #\n"));
491 DEBUG ((DEBUG_INFO
, "##################\n"));
492 GetSmmLoadedImage ();
493 DEBUG ((DEBUG_INFO
, "\n"));
498 DEBUG ((DEBUG_INFO
, "########################\n"));
499 DEBUG ((DEBUG_INFO
, "# SMI Handler DATABASE #\n"));
500 DEBUG ((DEBUG_INFO
, "########################\n"));
502 DEBUG ((DEBUG_INFO
, "# 1. ROOT SMI Handler #\n"));
504 DumpSmiEntryList(mSmmCoreRootSmiEntryList
);
507 DEBUG ((DEBUG_INFO
, "# 2. GUID SMI Handler #\n"));
509 DumpSmiEntryList(mSmmCoreSmiEntryList
);
512 DEBUG ((DEBUG_INFO
, "# 3. Hardware SMI Handler #\n"));
514 DumpSmiEntryList(mSmmCoreHardwareSmiEntryList
);
517 DEBUG ((DEBUG_INFO
, "\n"));
519 RegisterSmiHandlerProfileHandler();
521 if (mImageStruct
!= NULL
) {
522 FreePool(mImageStruct
);
529 returns SMM image data base size.
531 @return SMM image data base size.
534 GetSmmImageDatabaseSize(
542 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
543 Size
+= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
));
549 returns all SMI handlers' size associated with SmiEntry.
551 @param SmiEntry SMI entry.
553 @return all SMI handlers' size associated with SmiEntry.
556 GetSmmSmiHandlerSizeOnSmiEntry(
557 IN SMI_ENTRY
*SmiEntry
560 LIST_ENTRY
*ListEntry
;
561 SMI_HANDLER
*SmiHandler
;
565 ListEntry
= &SmiEntry
->SmiHandlers
;
566 for (ListEntry
= ListEntry
->ForwardLink
;
567 ListEntry
!= &SmiEntry
->SmiHandlers
;
568 ListEntry
= ListEntry
->ForwardLink
) {
569 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
570 Size
+= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
));
577 return all SMI handler database size on the SMI entry list.
579 @param SmiEntryList a list of SMI entry.
581 @return all SMI handler database size on the SMI entry list.
584 GetSmmSmiDatabaseSize(
585 IN LIST_ENTRY
*SmiEntryList
588 LIST_ENTRY
*ListEntry
;
593 ListEntry
= SmiEntryList
;
594 for (ListEntry
= ListEntry
->ForwardLink
;
595 ListEntry
!= SmiEntryList
;
596 ListEntry
= ListEntry
->ForwardLink
) {
597 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
598 Size
+= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
599 Size
+= GetSmmSmiHandlerSizeOnSmiEntry(SmiEntry
);
605 return SMI handler profile database size.
607 @return SMI handler profile database size.
610 GetSmiHandlerProfileDatabaseSize (
614 mSmmImageDatabaseSize
= GetSmmImageDatabaseSize();
615 mSmmRootSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreRootSmiEntryList
);
616 mSmmSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreSmiEntryList
);
617 mSmmHardwareSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreHardwareSmiEntryList
);
619 return mSmmImageDatabaseSize
+ mSmmSmiDatabaseSize
+ mSmmRootSmiDatabaseSize
+ mSmmHardwareSmiDatabaseSize
;
623 get SMM image database.
625 @param Data The buffer to hold SMM image database
626 @param ExpectedSize The expected size of the SMM image database
628 @return SMM image data base size.
631 GetSmmImageDatabaseData (
633 IN UINTN ExpectedSize
636 SMM_CORE_IMAGE_DATABASE_STRUCTURE
*ImageStruct
;
642 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
643 if (Size
>= ExpectedSize
) {
646 if (sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
)) > ExpectedSize
- Size
) {
649 ImageStruct
->Header
.Signature
= SMM_CORE_IMAGE_DATABASE_SIGNATURE
;
650 ImageStruct
->Header
.Length
= (UINT32
)(sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
)));
651 ImageStruct
->Header
.Revision
= SMM_CORE_IMAGE_DATABASE_REVISION
;
652 CopyGuid(&ImageStruct
->FileGuid
, &mImageStruct
[Index
].FileGuid
);
653 ImageStruct
->ImageRef
= mImageStruct
[Index
].ImageRef
;
654 ImageStruct
->EntryPoint
= mImageStruct
[Index
].EntryPoint
;
655 ImageStruct
->ImageBase
= mImageStruct
[Index
].ImageBase
;
656 ImageStruct
->ImageSize
= mImageStruct
[Index
].ImageSize
;
657 if (mImageStruct
[Index
].PdbStringSize
!= 0) {
658 ImageStruct
->PdbStringOffset
= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
);
659 CopyMem ((VOID
*)((UINTN
)ImageStruct
+ ImageStruct
->PdbStringOffset
), mImageStruct
[Index
].PdbString
, mImageStruct
[Index
].PdbStringSize
);
661 ImageStruct
->PdbStringOffset
= 0;
663 ImageStruct
= (SMM_CORE_IMAGE_DATABASE_STRUCTURE
*)((UINTN
)ImageStruct
+ ImageStruct
->Header
.Length
);
664 Size
+= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
));
667 if (ExpectedSize
!= Size
) {
674 get all SMI handler data associated with SmiEntry.
676 @param SmiEntry SMI entry.
677 @param Data The buffer to hold all SMI handler data
678 @param MaxSize The max size of the SMM image database
679 @param Count The count of the SMI handler.
681 @return SMM image data base size.
684 GetSmmSmiHandlerDataOnSmiEntry(
685 IN SMI_ENTRY
*SmiEntry
,
691 SMM_CORE_SMI_HANDLER_STRUCTURE
*SmiHandlerStruct
;
692 LIST_ENTRY
*ListEntry
;
693 SMI_HANDLER
*SmiHandler
;
696 SmiHandlerStruct
= Data
;
699 ListEntry
= &SmiEntry
->SmiHandlers
;
700 for (ListEntry
= ListEntry
->ForwardLink
;
701 ListEntry
!= &SmiEntry
->SmiHandlers
;
702 ListEntry
= ListEntry
->ForwardLink
) {
703 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
704 if (Size
>= MaxSize
) {
708 if (sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
)) > MaxSize
- Size
) {
712 SmiHandlerStruct
->Length
= (UINT32
)(sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
)));
713 SmiHandlerStruct
->CallerAddr
= (UINTN
)SmiHandler
->CallerAddr
;
714 SmiHandlerStruct
->Handler
= (UINTN
)SmiHandler
->Handler
;
715 SmiHandlerStruct
->ImageRef
= AddressToImageRef((UINTN
)SmiHandler
->Handler
);
716 SmiHandlerStruct
->ContextBufferSize
= (UINT32
)SmiHandler
->ContextSize
;
717 if (SmiHandler
->ContextSize
!= 0) {
718 SmiHandlerStruct
->ContextBufferOffset
= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
);
719 CopyMem ((UINT8
*)SmiHandlerStruct
+ SmiHandlerStruct
->ContextBufferOffset
, SmiHandler
->Context
, SmiHandler
->ContextSize
);
721 SmiHandlerStruct
->ContextBufferOffset
= 0;
723 Size
+= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
));
724 SmiHandlerStruct
= (SMM_CORE_SMI_HANDLER_STRUCTURE
*)((UINTN
)SmiHandlerStruct
+ SmiHandlerStruct
->Length
);
732 get all SMI handler database on the SMI entry list.
734 @param SmiEntryList a list of SMI entry.
735 @param HandlerCategory The handler category
736 @param Data The buffer to hold all SMI handler database
737 @param ExpectedSize The expected size of the SMM image database
739 @return all SMI database size on the SMI entry list.
742 GetSmmSmiDatabaseData(
743 IN LIST_ENTRY
*SmiEntryList
,
744 IN UINT32 HandlerCategory
,
746 IN UINTN ExpectedSize
749 SMM_CORE_SMI_DATABASE_STRUCTURE
*SmiStruct
;
750 LIST_ENTRY
*ListEntry
;
753 UINTN SmiHandlerSize
;
754 UINT32 SmiHandlerCount
;
758 ListEntry
= SmiEntryList
;
759 for (ListEntry
= ListEntry
->ForwardLink
;
760 ListEntry
!= SmiEntryList
;
761 ListEntry
= ListEntry
->ForwardLink
) {
762 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
763 if (Size
>= ExpectedSize
) {
766 if (sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
) > ExpectedSize
- Size
) {
770 SmiStruct
->Header
.Signature
= SMM_CORE_SMI_DATABASE_SIGNATURE
;
771 SmiStruct
->Header
.Length
= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
772 SmiStruct
->Header
.Revision
= SMM_CORE_SMI_DATABASE_REVISION
;
773 SmiStruct
->HandlerCategory
= HandlerCategory
;
774 CopyGuid(&SmiStruct
->HandlerType
, &SmiEntry
->HandlerType
);
775 Size
+= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
776 SmiHandlerSize
= GetSmmSmiHandlerDataOnSmiEntry(SmiEntry
, (UINT8
*)SmiStruct
+ SmiStruct
->Header
.Length
, ExpectedSize
- Size
, &SmiHandlerCount
);
777 SmiStruct
->HandlerCount
= SmiHandlerCount
;
778 Size
+= SmiHandlerSize
;
779 SmiStruct
->Header
.Length
+= (UINT32
)SmiHandlerSize
;
780 SmiStruct
= (VOID
*)((UINTN
)SmiStruct
+ SmiStruct
->Header
.Length
);
782 if (ExpectedSize
!= Size
) {
789 Get SMI handler profile database.
791 @param Data the buffer to hold SMI handler profile database
793 @retval EFI_SUCCESS the database is got.
794 @retval EFI_INVALID_PARAMETER the database size mismatch.
797 GetSmiHandlerProfileDatabaseData(
801 UINTN SmmImageDatabaseSize
;
802 UINTN SmmSmiDatabaseSize
;
803 UINTN SmmRootSmiDatabaseSize
;
804 UINTN SmmHardwareSmiDatabaseSize
;
806 DEBUG((DEBUG_VERBOSE
, "GetSmiHandlerProfileDatabaseData\n"));
807 SmmImageDatabaseSize
= GetSmmImageDatabaseData(Data
, mSmmImageDatabaseSize
);
808 if (SmmImageDatabaseSize
!= mSmmImageDatabaseSize
) {
809 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmImageDatabaseSize mismatch!\n"));
810 return EFI_INVALID_PARAMETER
;
812 SmmRootSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreRootSmiEntryList
, SmmCoreSmiHandlerCategoryRootHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
, mSmmRootSmiDatabaseSize
);
813 if (SmmRootSmiDatabaseSize
!= mSmmRootSmiDatabaseSize
) {
814 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmRootSmiDatabaseSize mismatch!\n"));
815 return EFI_INVALID_PARAMETER
;
817 SmmSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreSmiEntryList
, SmmCoreSmiHandlerCategoryGuidHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
+ mSmmRootSmiDatabaseSize
, mSmmSmiDatabaseSize
);
818 if (SmmSmiDatabaseSize
!= mSmmSmiDatabaseSize
) {
819 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmSmiDatabaseSize mismatch!\n"));
820 return EFI_INVALID_PARAMETER
;
822 SmmHardwareSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreHardwareSmiEntryList
, SmmCoreSmiHandlerCategoryHardwareHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
+ SmmRootSmiDatabaseSize
+ SmmSmiDatabaseSize
, mSmmHardwareSmiDatabaseSize
);
823 if (SmmHardwareSmiDatabaseSize
!= mSmmHardwareSmiDatabaseSize
) {
824 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmHardwareSmiDatabaseSize mismatch!\n"));
825 return EFI_INVALID_PARAMETER
;
832 build SMI handler profile database.
835 BuildSmiHandlerProfileDatabase(
840 mSmiHandlerProfileDatabaseSize
= GetSmiHandlerProfileDatabaseSize();
841 mSmiHandlerProfileDatabase
= AllocatePool(mSmiHandlerProfileDatabaseSize
);
842 if (mSmiHandlerProfileDatabase
== NULL
) {
845 Status
= GetSmiHandlerProfileDatabaseData(mSmiHandlerProfileDatabase
);
846 if (EFI_ERROR(Status
)) {
847 FreePool(mSmiHandlerProfileDatabase
);
848 mSmiHandlerProfileDatabase
= NULL
;
853 Copy SMI handler profile data.
855 @param DataBuffer The buffer to hold SMI handler profile data.
856 @param DataSize On input, data buffer size.
857 On output, actual data buffer size copied.
858 @param DataOffset On input, data buffer offset to copy.
859 On output, next time data buffer offset to copy.
863 SmiHandlerProfileCopyData(
864 OUT VOID
*DataBuffer
,
865 IN OUT UINT64
*DataSize
,
866 IN OUT UINT64
*DataOffset
869 if (*DataOffset
>= mSmiHandlerProfileDatabaseSize
) {
870 *DataOffset
= mSmiHandlerProfileDatabaseSize
;
873 if (mSmiHandlerProfileDatabaseSize
- *DataOffset
< *DataSize
) {
874 *DataSize
= mSmiHandlerProfileDatabaseSize
- *DataOffset
;
879 (UINT8
*)mSmiHandlerProfileDatabase
+ *DataOffset
,
882 *DataOffset
= *DataOffset
+ *DataSize
;
886 SMI handler profile handler to get info.
888 @param SmiHandlerProfileParameterGetInfo The parameter of SMI handler profile get info.
892 SmiHandlerProfileHandlerGetInfo(
893 IN SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
*SmiHandlerProfileParameterGetInfo
896 BOOLEAN SmiHandlerProfileRecordingStatus
;
898 SmiHandlerProfileRecordingStatus
= mSmiHandlerProfileRecordingStatus
;
899 mSmiHandlerProfileRecordingStatus
= FALSE
;
901 SmiHandlerProfileParameterGetInfo
->DataSize
= mSmiHandlerProfileDatabaseSize
;
902 SmiHandlerProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
904 mSmiHandlerProfileRecordingStatus
= SmiHandlerProfileRecordingStatus
;
908 SMI handler profile handler to get data by offset.
910 @param SmiHandlerProfileParameterGetDataByOffset The parameter of SMI handler profile get data by offset.
914 SmiHandlerProfileHandlerGetDataByOffset(
915 IN SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
*SmiHandlerProfileParameterGetDataByOffset
918 SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET SmiHandlerProfileGetDataByOffset
;
919 BOOLEAN SmiHandlerProfileRecordingStatus
;
921 SmiHandlerProfileRecordingStatus
= mSmiHandlerProfileRecordingStatus
;
922 mSmiHandlerProfileRecordingStatus
= FALSE
;
924 CopyMem(&SmiHandlerProfileGetDataByOffset
, SmiHandlerProfileParameterGetDataByOffset
, sizeof(SmiHandlerProfileGetDataByOffset
));
929 if (!SmmIsBufferOutsideSmmValid((UINTN
)SmiHandlerProfileGetDataByOffset
.DataBuffer
, (UINTN
)SmiHandlerProfileGetDataByOffset
.DataSize
)) {
930 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetDataByOffset: SMI handler profile get data in SMRAM or overflow!\n"));
931 SmiHandlerProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_ACCESS_DENIED
;
935 SmiHandlerProfileCopyData((VOID
*)(UINTN
)SmiHandlerProfileGetDataByOffset
.DataBuffer
, &SmiHandlerProfileGetDataByOffset
.DataSize
, &SmiHandlerProfileGetDataByOffset
.DataOffset
);
936 CopyMem(SmiHandlerProfileParameterGetDataByOffset
, &SmiHandlerProfileGetDataByOffset
, sizeof(SmiHandlerProfileGetDataByOffset
));
937 SmiHandlerProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
940 mSmiHandlerProfileRecordingStatus
= SmiHandlerProfileRecordingStatus
;
944 Dispatch function for a Software SMI handler.
946 Caution: This function may receive untrusted input.
947 Communicate buffer and buffer size are external input, so this function will do basic validation.
949 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
950 @param Context Points to an optional handler context which was specified when the
951 handler was registered.
952 @param CommBuffer A pointer to a collection of data in memory that will
953 be conveyed from a non-SMM environment into an SMM environment.
954 @param CommBufferSize The size of the CommBuffer.
956 @retval EFI_SUCCESS Command is handled successfully.
960 SmiHandlerProfileHandler(
961 IN EFI_HANDLE DispatchHandle
,
962 IN CONST VOID
*Context OPTIONAL
,
963 IN OUT VOID
*CommBuffer OPTIONAL
,
964 IN OUT UINTN
*CommBufferSize OPTIONAL
967 SMI_HANDLER_PROFILE_PARAMETER_HEADER
*SmiHandlerProfileParameterHeader
;
968 UINTN TempCommBufferSize
;
970 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler Enter\n"));
972 if (mSmiHandlerProfileDatabase
== NULL
) {
977 // If input is invalid, stop processing this SMI
979 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
983 TempCommBufferSize
= *CommBufferSize
;
985 if (TempCommBufferSize
< sizeof(SMI_HANDLER_PROFILE_PARAMETER_HEADER
)) {
986 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
990 if (!SmmIsBufferOutsideSmmValid((UINTN
)CommBuffer
, TempCommBufferSize
)) {
991 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
995 SmiHandlerProfileParameterHeader
= (SMI_HANDLER_PROFILE_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
996 SmiHandlerProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
998 switch (SmiHandlerProfileParameterHeader
->Command
) {
999 case SMI_HANDLER_PROFILE_COMMAND_GET_INFO
:
1000 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetInfo\n"));
1001 if (TempCommBufferSize
!= sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
)) {
1002 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
1005 SmiHandlerProfileHandlerGetInfo((SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
*)(UINTN
)CommBuffer
);
1007 case SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET
:
1008 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetDataByOffset\n"));
1009 if (TempCommBufferSize
!= sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
)) {
1010 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
1013 SmiHandlerProfileHandlerGetDataByOffset((SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
*)(UINTN
)CommBuffer
);
1019 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler Exit\n"));
1025 Register SMI handler profile handler.
1028 RegisterSmiHandlerProfileHandler (
1033 EFI_HANDLE DispatchHandle
;
1035 Status
= gSmst
->SmiHandlerRegister (
1036 SmiHandlerProfileHandler
,
1037 &gSmiHandlerProfileGuid
,
1040 ASSERT_EFI_ERROR (Status
);
1042 BuildSmiHandlerProfileDatabase();
1046 Finds the SMI entry for the requested handler type.
1048 @param HandlerType The type of the interrupt
1049 @param Create Create a new entry if not found
1054 SmmCoreFindHardwareSmiEntry (
1055 IN EFI_GUID
*HandlerType
,
1061 SMI_ENTRY
*SmiEntry
;
1064 // Search the SMI entry list for the matching GUID
1067 for (Link
= mHardwareSmiEntryList
.ForwardLink
;
1068 Link
!= &mHardwareSmiEntryList
;
1069 Link
= Link
->ForwardLink
) {
1071 Item
= CR (Link
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
1072 if (CompareGuid (&Item
->HandlerType
, HandlerType
)) {
1074 // This is the SMI entry
1082 // If the protocol entry was not found and Create is TRUE, then
1083 // allocate a new entry
1085 if ((SmiEntry
== NULL
) && Create
) {
1086 SmiEntry
= AllocatePool (sizeof(SMI_ENTRY
));
1087 if (SmiEntry
!= NULL
) {
1089 // Initialize new SMI entry structure
1091 SmiEntry
->Signature
= SMI_ENTRY_SIGNATURE
;
1092 CopyGuid ((VOID
*)&SmiEntry
->HandlerType
, HandlerType
);
1093 InitializeListHead (&SmiEntry
->SmiHandlers
);
1096 // Add it to SMI entry list
1098 InsertTailList (&mHardwareSmiEntryList
, &SmiEntry
->AllEntries
);
1105 Convert EFI_SMM_USB_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT.
1107 @param UsbContext A pointer to EFI_SMM_USB_REGISTER_CONTEXT
1108 @param UsbContextSize The size of EFI_SMM_USB_REGISTER_CONTEXT in bytes
1109 @param SmiHandlerUsbContextSize The size of SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT in bytes
1111 @return SmiHandlerUsbContext A pointer to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
1113 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*
1114 ConvertSmiHandlerUsbContext (
1115 IN EFI_SMM_USB_REGISTER_CONTEXT
*UsbContext
,
1116 IN UINTN UsbContextSize
,
1117 OUT UINTN
*SmiHandlerUsbContextSize
1120 UINTN DevicePathSize
;
1121 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*SmiHandlerUsbContext
;
1123 ASSERT (UsbContextSize
== sizeof(EFI_SMM_USB_REGISTER_CONTEXT
));
1125 DevicePathSize
= GetDevicePathSize (UsbContext
->Device
);
1126 SmiHandlerUsbContext
= AllocatePool (sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
) + DevicePathSize
);
1127 if (SmiHandlerUsbContext
== NULL
) {
1128 *SmiHandlerUsbContextSize
= 0;
1131 SmiHandlerUsbContext
->Type
= UsbContext
->Type
;
1132 SmiHandlerUsbContext
->DevicePathSize
= (UINT32
)DevicePathSize
;
1133 CopyMem (SmiHandlerUsbContext
+ 1, UsbContext
->Device
, DevicePathSize
);
1134 *SmiHandlerUsbContextSize
= sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
) + DevicePathSize
;
1135 return SmiHandlerUsbContext
;
1139 Convert EFI_SMM_SW_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT.
1141 @param SwContext A pointer to EFI_SMM_SW_REGISTER_CONTEXT
1142 @param SwContextSize The size of EFI_SMM_SW_REGISTER_CONTEXT in bytes
1143 @param SmiHandlerSwContextSize The size of SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT in bytes
1145 @return SmiHandlerSwContext A pointer to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
1147 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*
1148 ConvertSmiHandlerSwContext (
1149 IN EFI_SMM_SW_REGISTER_CONTEXT
*SwContext
,
1150 IN UINTN SwContextSize
,
1151 OUT UINTN
*SmiHandlerSwContextSize
1154 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*SmiHandlerSwContext
;
1156 ASSERT (SwContextSize
== sizeof(EFI_SMM_SW_REGISTER_CONTEXT
));
1158 SmiHandlerSwContext
= AllocatePool (sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
));
1159 if (SmiHandlerSwContext
== NULL
) {
1160 *SmiHandlerSwContextSize
= 0;
1163 SmiHandlerSwContext
->SwSmiInputValue
= SwContext
->SwSmiInputValue
;
1164 *SmiHandlerSwContextSize
= sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
);
1165 return SmiHandlerSwContext
;
1169 This function is called by SmmChildDispatcher module to report
1170 a new SMI handler is registered, to SmmCore.
1172 @param This The protocol instance
1173 @param HandlerGuid The GUID to identify the type of the handler.
1174 For the SmmChildDispatch protocol, the HandlerGuid
1175 must be the GUID of SmmChildDispatch protocol.
1176 @param Handler The SMI handler.
1177 @param CallerAddress The address of the module who registers the SMI handler.
1178 @param Context The context of the SMI handler.
1179 For the SmmChildDispatch protocol, the Context
1180 must match the one defined for SmmChildDispatch protocol.
1181 @param ContextSize The size of the context in bytes.
1182 For the SmmChildDispatch protocol, the Context
1183 must match the one defined for SmmChildDispatch protocol.
1185 @retval EFI_SUCCESS The information is recorded.
1186 @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.
1190 SmiHandlerProfileRegisterHandler (
1191 IN SMI_HANDLER_PROFILE_PROTOCOL
*This
,
1192 IN EFI_GUID
*HandlerGuid
,
1193 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler
,
1194 IN PHYSICAL_ADDRESS CallerAddress
,
1195 IN VOID
*Context
, OPTIONAL
1196 IN UINTN ContextSize OPTIONAL
1199 SMI_HANDLER
*SmiHandler
;
1200 SMI_ENTRY
*SmiEntry
;
1203 if (((ContextSize
== 0) && (Context
!= NULL
)) ||
1204 ((ContextSize
!= 0) && (Context
== NULL
))) {
1205 return EFI_INVALID_PARAMETER
;
1208 SmiHandler
= AllocateZeroPool (sizeof (SMI_HANDLER
));
1209 if (SmiHandler
== NULL
) {
1210 return EFI_OUT_OF_RESOURCES
;
1213 SmiHandler
->Signature
= SMI_HANDLER_SIGNATURE
;
1214 SmiHandler
->Handler
= Handler
;
1215 SmiHandler
->CallerAddr
= (UINTN
)CallerAddress
;
1216 SmiHandler
->Context
= Context
;
1217 SmiHandler
->ContextSize
= ContextSize
;
1219 if (Context
!= NULL
) {
1220 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1221 SmiHandler
->Context
= ConvertSmiHandlerUsbContext (Context
, ContextSize
, &SmiHandler
->ContextSize
);
1222 } else if (CompareGuid (HandlerGuid
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
1223 SmiHandler
->Context
= ConvertSmiHandlerSwContext (Context
, ContextSize
, &SmiHandler
->ContextSize
);
1225 SmiHandler
->Context
= AllocateCopyPool (ContextSize
, Context
);
1228 if (SmiHandler
->Context
== NULL
) {
1229 SmiHandler
->ContextSize
= 0;
1232 SmiEntry
= SmmCoreFindHardwareSmiEntry (HandlerGuid
, TRUE
);
1233 if (SmiEntry
== NULL
) {
1234 if (SmiHandler
->Context
!= NULL
) {
1235 FreePool (SmiHandler
->Context
);
1237 FreePool (SmiHandler
);
1238 return EFI_OUT_OF_RESOURCES
;
1241 List
= &SmiEntry
->SmiHandlers
;
1243 SmiHandler
->SmiEntry
= SmiEntry
;
1244 InsertTailList (List
, &SmiHandler
->Link
);
1250 This function is called by SmmChildDispatcher module to report
1251 an existing SMI handler is unregistered, to SmmCore.
1253 @param This The protocol instance
1254 @param HandlerGuid The GUID to identify the type of the handler.
1255 For the SmmChildDispatch protocol, the HandlerGuid
1256 must be the GUID of SmmChildDispatch protocol.
1257 @param Handler The SMI handler.
1258 @param Context The context of the SMI handler.
1259 If it is NOT NULL, it will be used to check what is registered.
1260 @param ContextSize The size of the context in bytes.
1261 If Context is NOT NULL, it will be used to check what is registered.
1263 @retval EFI_SUCCESS The original record is removed.
1264 @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.
1268 SmiHandlerProfileUnregisterHandler (
1269 IN SMI_HANDLER_PROFILE_PROTOCOL
*This
,
1270 IN EFI_GUID
*HandlerGuid
,
1271 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler
,
1272 IN VOID
*Context
, OPTIONAL
1273 IN UINTN ContextSize OPTIONAL
1278 SMI_HANDLER
*SmiHandler
;
1279 SMI_ENTRY
*SmiEntry
;
1280 SMI_HANDLER
*TargetSmiHandler
;
1281 VOID
*SearchContext
;
1282 UINTN SearchContextSize
;
1284 if (((ContextSize
== 0) && (Context
!= NULL
)) ||
1285 ((ContextSize
!= 0) && (Context
== NULL
))) {
1286 return EFI_INVALID_PARAMETER
;
1289 SmiEntry
= SmmCoreFindHardwareSmiEntry (HandlerGuid
, FALSE
);
1290 if (SmiEntry
== NULL
) {
1291 return EFI_NOT_FOUND
;
1294 SearchContext
= Context
;
1295 SearchContextSize
= ContextSize
;
1296 if (Context
!= NULL
) {
1297 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1298 SearchContext
= ConvertSmiHandlerUsbContext (Context
, ContextSize
, &SearchContextSize
);
1299 } else if (CompareGuid (HandlerGuid
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
1300 SearchContext
= ConvertSmiHandlerSwContext (Context
, ContextSize
, &SearchContextSize
);
1304 TargetSmiHandler
= NULL
;
1305 Head
= &SmiEntry
->SmiHandlers
;
1306 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
1307 SmiHandler
= CR (Link
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
1308 if (SmiHandler
->Handler
== Handler
) {
1309 if ((SearchContext
== NULL
) ||
1310 ((SearchContextSize
== SmiHandler
->ContextSize
) && (CompareMem (SearchContext
, SmiHandler
->Context
, SearchContextSize
) == 0))) {
1311 TargetSmiHandler
= SmiHandler
;
1317 if (SearchContext
!= NULL
) {
1318 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1319 FreePool (SearchContext
);
1323 if (TargetSmiHandler
== NULL
) {
1324 return EFI_NOT_FOUND
;
1326 SmiHandler
= TargetSmiHandler
;
1328 RemoveEntryList (&SmiHandler
->Link
);
1329 if (SmiHandler
->Context
!= NULL
) {
1330 FreePool (SmiHandler
->Context
);
1332 FreePool (SmiHandler
);
1334 if (IsListEmpty (&SmiEntry
->SmiHandlers
)) {
1335 RemoveEntryList (&SmiEntry
->AllEntries
);
1336 FreePool (SmiEntry
);
1343 Initialize SmiHandler profile feature.
1346 SmmCoreInitializeSmiHandlerProfile (
1354 if ((PcdGet8 (PcdSmiHandlerProfilePropertyMask
) & 0x1) != 0) {
1355 InsertTailList (&mRootSmiEntryList
, &mRootSmiEntry
.AllEntries
);
1357 Status
= gSmst
->SmmRegisterProtocolNotify (
1358 &gEfiSmmReadyToLockProtocolGuid
,
1359 SmmReadyToLockInSmiHandlerProfile
,
1362 ASSERT_EFI_ERROR (Status
);
1365 Status
= gSmst
->SmmInstallProtocolInterface (
1367 &gSmiHandlerProfileGuid
,
1368 EFI_NATIVE_INTERFACE
,
1371 ASSERT_EFI_ERROR (Status
);