2 SMI handler profile support.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/SmmServicesTableLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/PrintLib.h>
17 #include <Library/UefiLib.h>
18 #include <Library/DevicePathLib.h>
19 #include <Library/PeCoffGetEntryPointLib.h>
20 #include <Protocol/LoadedImage.h>
21 #include <Protocol/SmmAccess2.h>
22 #include <Protocol/SmmReadyToLock.h>
23 #include <Protocol/SmmEndOfDxe.h>
25 #include <Guid/SmiHandlerProfile.h>
27 #include "PiSmmCore.h"
29 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
30 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
34 PHYSICAL_ADDRESS EntryPoint
;
35 PHYSICAL_ADDRESS ImageBase
;
43 Register SMI handler profile handler.
46 RegisterSmiHandlerProfileHandler(
51 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
52 into system memory with the PE/COFF Loader Library functions.
54 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
55 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
56 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
57 If Pe32Data is NULL, then ASSERT().
58 If EntryPoint is NULL, then ASSERT().
60 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
61 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
63 @retval RETURN_SUCCESS EntryPoint was returned.
64 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
68 InternalPeCoffGetEntryPoint (
73 extern LIST_ENTRY mSmiEntryList
;
74 extern LIST_ENTRY mHardwareSmiEntryList
;
75 extern SMI_ENTRY mRootSmiEntry
;
77 extern SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile
;
79 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mHardwareSmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mHardwareSmiEntryList
);
81 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mRootSmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntryList
);
83 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreRootSmiEntryList
= &mRootSmiEntryList
;
84 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreSmiEntryList
= &mSmiEntryList
;
85 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreHardwareSmiEntryList
= &mHardwareSmiEntryList
;
87 GLOBAL_REMOVE_IF_UNREFERENCED IMAGE_STRUCT
*mImageStruct
;
88 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCountMax
;
89 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCount
;
91 GLOBAL_REMOVE_IF_UNREFERENCED VOID
*mSmiHandlerProfileDatabase
;
92 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmiHandlerProfileDatabaseSize
;
94 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmImageDatabaseSize
;
95 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmRootSmiDatabaseSize
;
96 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmSmiDatabaseSize
;
97 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmHardwareSmiDatabaseSize
;
99 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmiHandlerProfileRecordingStatus
;
101 GLOBAL_REMOVE_IF_UNREFERENCED SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile
= {
102 SmiHandlerProfileRegisterHandler
,
103 SmiHandlerProfileUnregisterHandler
,
107 This function dump raw data.
110 @param Size raw data size
119 for (Index
= 0; Index
< Size
; Index
++) {
120 DEBUG ((DEBUG_INFO
, "%02x ", (UINTN
)Data
[Index
]));
125 Get GUID name for an image.
127 @param[in] LoadedImage LoadedImage protocol.
128 @param[out] Guid Guid of the FFS
132 IN EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
,
139 if ((DevicePathType(LoadedImage
->FilePath
) == MEDIA_DEVICE_PATH
) &&
140 (DevicePathSubType(LoadedImage
->FilePath
) == MEDIA_PIWG_FW_FILE_DP
)) {
141 FileName
= &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)LoadedImage
->FilePath
)->FvFileName
;
143 if (FileName
!= NULL
) {
144 CopyGuid(Guid
, FileName
);
146 ZeroMem(Guid
, sizeof(EFI_GUID
));
153 @param ImageBase image base
154 @param ImageSize image size
155 @param EntryPoint image entry point
156 @param Guid FFS GUID of the image
157 @param PdbString image PDB string
161 IN PHYSICAL_ADDRESS ImageBase
,
163 IN PHYSICAL_ADDRESS EntryPoint
,
170 if (mImageStructCount
>= mImageStructCountMax
) {
175 CopyGuid(&mImageStruct
[mImageStructCount
].FileGuid
, Guid
);
176 mImageStruct
[mImageStructCount
].ImageRef
= mImageStructCount
;
177 mImageStruct
[mImageStructCount
].ImageBase
= ImageBase
;
178 mImageStruct
[mImageStructCount
].ImageSize
= ImageSize
;
179 mImageStruct
[mImageStructCount
].EntryPoint
= EntryPoint
;
180 if (PdbString
!= NULL
) {
181 PdbStringSize
= AsciiStrSize(PdbString
);
182 mImageStruct
[mImageStructCount
].PdbString
= AllocateCopyPool (PdbStringSize
, PdbString
);
183 if (mImageStruct
[mImageStructCount
].PdbString
!= NULL
) {
184 mImageStruct
[mImageStructCount
].PdbStringSize
= (UINT16
) PdbStringSize
;
192 return an image structure based upon image address.
194 @param Address image address
196 @return image structure
199 AddressToImageStruct(
205 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
206 if ((Address
>= mImageStruct
[Index
].ImageBase
) &&
207 (Address
< mImageStruct
[Index
].ImageBase
+ mImageStruct
[Index
].ImageSize
)) {
208 return &mImageStruct
[Index
];
215 return an image reference index based upon image address.
217 @param Address image address
219 @return image reference index
226 IMAGE_STRUCT
*ImageStruct
;
228 ImageStruct
= AddressToImageStruct(Address
);
229 if (ImageStruct
!= NULL
) {
230 return ImageStruct
->ImageRef
;
236 Collect SMM image information based upon loaded image protocol.
245 UINTN HandleBufferSize
;
246 EFI_HANDLE
*HandleBuffer
;
248 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
250 EFI_SMM_DRIVER_ENTRY
*LoadedImagePrivate
;
251 PHYSICAL_ADDRESS EntryPoint
;
252 VOID
*EntryPointInImage
;
255 PHYSICAL_ADDRESS RealImageBase
;
257 HandleBufferSize
= 0;
259 Status
= gSmst
->SmmLocateHandle(
261 &gEfiLoadedImageProtocolGuid
,
266 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
269 HandleBuffer
= AllocateZeroPool (HandleBufferSize
);
270 if (HandleBuffer
== NULL
) {
273 Status
= gSmst
->SmmLocateHandle(
275 &gEfiLoadedImageProtocolGuid
,
280 if (EFI_ERROR(Status
)) {
284 NoHandles
= HandleBufferSize
/sizeof(EFI_HANDLE
);
285 mImageStructCountMax
= (UINT32
) NoHandles
;
286 mImageStruct
= AllocateZeroPool(mImageStructCountMax
* sizeof(IMAGE_STRUCT
));
287 if (mImageStruct
== NULL
) {
291 for (Index
= 0; Index
< NoHandles
; Index
++) {
292 Status
= gSmst
->SmmHandleProtocol(
294 &gEfiLoadedImageProtocolGuid
,
295 (VOID
**)&LoadedImage
297 if (EFI_ERROR(Status
)) {
300 PathStr
= ConvertDevicePathToText(LoadedImage
->FilePath
, TRUE
, TRUE
);
301 GetDriverGuid(LoadedImage
, &Guid
);
302 DEBUG ((DEBUG_INFO
, "Image: %g ", &Guid
));
305 LoadedImagePrivate
= BASE_CR(LoadedImage
, EFI_SMM_DRIVER_ENTRY
, SmmLoadedImage
);
306 RealImageBase
= (UINTN
)LoadedImage
->ImageBase
;
307 if (LoadedImagePrivate
->Signature
== EFI_SMM_DRIVER_ENTRY_SIGNATURE
) {
308 EntryPoint
= LoadedImagePrivate
->ImageEntryPoint
;
309 if ((EntryPoint
!= 0) && ((EntryPoint
< (UINTN
)LoadedImage
->ImageBase
) || (EntryPoint
>= ((UINTN
)LoadedImage
->ImageBase
+ LoadedImage
->ImageSize
)))) {
311 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
312 // So patch ImageBuffer here to align the EntryPoint.
314 Status
= InternalPeCoffGetEntryPoint(LoadedImage
->ImageBase
, &EntryPointInImage
);
315 ASSERT_EFI_ERROR(Status
);
316 RealImageBase
= (UINTN
)LoadedImage
->ImageBase
+ EntryPoint
- (UINTN
)EntryPointInImage
;
319 DEBUG ((DEBUG_INFO
, "(0x%lx - 0x%lx", RealImageBase
, LoadedImage
->ImageSize
));
320 if (EntryPoint
!= 0) {
321 DEBUG ((DEBUG_INFO
, ", EntryPoint:0x%lx", EntryPoint
));
323 DEBUG ((DEBUG_INFO
, ")\n"));
325 if (RealImageBase
!= 0) {
326 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) RealImageBase
);
327 DEBUG ((DEBUG_INFO
, " pdb - %a\n", PdbString
));
331 DEBUG ((DEBUG_INFO
, " (%s)\n", PathStr
));
333 AddImageStruct(RealImageBase
, LoadedImage
->ImageSize
, EntryPoint
, &Guid
, PdbString
);
337 FreePool(HandleBuffer
);
342 Dump SMI child context.
344 @param HandlerType the handler type
345 @param Context the handler context
346 @param ContextSize the handler context size
349 DumpSmiChildContext (
350 IN EFI_GUID
*HandlerType
,
357 if (CompareGuid (HandlerType
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
358 DEBUG ((DEBUG_INFO
, " SwSmi - 0x%lx\n", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*)Context
)->SwSmiInputValue
));
359 } else if (CompareGuid (HandlerType
, &gEfiSmmSxDispatch2ProtocolGuid
)) {
360 DEBUG ((DEBUG_INFO
, " SxType - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT
*)Context
)->Type
));
361 DEBUG ((DEBUG_INFO
, " SxPhase - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT
*)Context
)->Phase
));
362 } else if (CompareGuid (HandlerType
, &gEfiSmmPowerButtonDispatch2ProtocolGuid
)) {
363 DEBUG ((DEBUG_INFO
, " PowerButtonPhase - 0x%x\n", ((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT
*)Context
)->Phase
));
364 } else if (CompareGuid (HandlerType
, &gEfiSmmStandbyButtonDispatch2ProtocolGuid
)) {
365 DEBUG ((DEBUG_INFO
, " StandbyButtonPhase - 0x%x\n", ((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT
*)Context
)->Phase
));
366 } else if (CompareGuid (HandlerType
, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid
)) {
367 DEBUG ((DEBUG_INFO
, " PeriodicTimerPeriod - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT
*)Context
)->Period
));
368 DEBUG ((DEBUG_INFO
, " PeriodicTimerSmiTickInterval - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT
*)Context
)->SmiTickInterval
));
369 } else if (CompareGuid (HandlerType
, &gEfiSmmGpiDispatch2ProtocolGuid
)) {
370 DEBUG ((DEBUG_INFO
, " GpiNum - 0x%lx\n", ((EFI_SMM_GPI_REGISTER_CONTEXT
*)Context
)->GpiNum
));
371 } else if (CompareGuid (HandlerType
, &gEfiSmmIoTrapDispatch2ProtocolGuid
)) {
372 DEBUG ((DEBUG_INFO
, " IoTrapAddress - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Address
));
373 DEBUG ((DEBUG_INFO
, " IoTrapLength - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Length
));
374 DEBUG ((DEBUG_INFO
, " IoTrapType - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Type
));
375 } else if (CompareGuid (HandlerType
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
376 DEBUG ((DEBUG_INFO
, " UsbType - 0x%x\n", ((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*)Context
)->Type
));
377 Str
= ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL
*)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*)Context
) + 1), TRUE
, TRUE
);
378 DEBUG ((DEBUG_INFO
, " UsbDevicePath - %s\n", Str
));
383 DEBUG ((DEBUG_INFO
, " Context - "));
384 InternalDumpData (Context
, ContextSize
);
385 DEBUG ((DEBUG_INFO
, "\n"));
390 Dump all SMI handlers associated with SmiEntry.
392 @param SmiEntry SMI entry.
395 DumpSmiHandlerOnSmiEntry(
396 IN SMI_ENTRY
*SmiEntry
399 LIST_ENTRY
*ListEntry
;
400 SMI_HANDLER
*SmiHandler
;
401 IMAGE_STRUCT
*ImageStruct
;
403 ListEntry
= &SmiEntry
->SmiHandlers
;
404 for (ListEntry
= ListEntry
->ForwardLink
;
405 ListEntry
!= &SmiEntry
->SmiHandlers
;
406 ListEntry
= ListEntry
->ForwardLink
) {
407 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
408 ImageStruct
= AddressToImageStruct((UINTN
)SmiHandler
->Handler
);
409 if (ImageStruct
!= NULL
) {
410 DEBUG ((DEBUG_INFO
, " Module - %g", &ImageStruct
->FileGuid
));
412 if ((ImageStruct
!= NULL
) && (ImageStruct
->PdbString
[0] != 0)) {
413 DEBUG ((DEBUG_INFO
, " (Pdb - %a)", ImageStruct
->PdbString
));
415 DEBUG ((DEBUG_INFO
, "\n"));
416 if (SmiHandler
->ContextSize
!= 0) {
417 DumpSmiChildContext (&SmiEntry
->HandlerType
, SmiHandler
->Context
, SmiHandler
->ContextSize
);
419 DEBUG ((DEBUG_INFO
, " Handler - 0x%x", SmiHandler
->Handler
));
420 if (ImageStruct
!= NULL
) {
421 DEBUG ((DEBUG_INFO
, " <== RVA - 0x%x", (UINTN
)SmiHandler
->Handler
- (UINTN
) ImageStruct
->ImageBase
));
423 DEBUG ((DEBUG_INFO
, "\n"));
424 DEBUG ((DEBUG_INFO
, " CallerAddr - 0x%x", SmiHandler
->CallerAddr
));
425 if (ImageStruct
!= NULL
) {
426 DEBUG ((DEBUG_INFO
, " <== RVA - 0x%x", SmiHandler
->CallerAddr
- (UINTN
) ImageStruct
->ImageBase
));
428 DEBUG ((DEBUG_INFO
, "\n"));
435 Dump all SMI entry on the list.
437 @param SmiEntryList a list of SMI entry.
441 IN LIST_ENTRY
*SmiEntryList
444 LIST_ENTRY
*ListEntry
;
447 ListEntry
= SmiEntryList
;
448 for (ListEntry
= ListEntry
->ForwardLink
;
449 ListEntry
!= SmiEntryList
;
450 ListEntry
= ListEntry
->ForwardLink
) {
451 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
452 DEBUG ((DEBUG_INFO
, "SmiEntry - %g\n", &SmiEntry
->HandlerType
));
453 DumpSmiHandlerOnSmiEntry(SmiEntry
);
460 SMM Ready To Lock event notification handler.
462 This function collects all SMM image information and build SmiHandleProfile database,
463 and register SmiHandlerProfile SMI handler.
465 @param[in] Protocol Points to the protocol's unique identifier.
466 @param[in] Interface Points to the interface instance.
467 @param[in] Handle The handle on which the interface was installed.
469 @retval EFI_SUCCESS Notification handler runs successfully.
473 SmmReadyToLockInSmiHandlerProfile (
474 IN CONST EFI_GUID
*Protocol
,
482 DEBUG ((DEBUG_INFO
, "##################\n"));
483 DEBUG ((DEBUG_INFO
, "# IMAGE DATABASE #\n"));
484 DEBUG ((DEBUG_INFO
, "##################\n"));
485 GetSmmLoadedImage ();
486 DEBUG ((DEBUG_INFO
, "\n"));
491 DEBUG ((DEBUG_INFO
, "########################\n"));
492 DEBUG ((DEBUG_INFO
, "# SMI Handler DATABASE #\n"));
493 DEBUG ((DEBUG_INFO
, "########################\n"));
495 DEBUG ((DEBUG_INFO
, "# 1. ROOT SMI Handler #\n"));
497 DumpSmiEntryList(mSmmCoreRootSmiEntryList
);
500 DEBUG ((DEBUG_INFO
, "# 2. GUID SMI Handler #\n"));
502 DumpSmiEntryList(mSmmCoreSmiEntryList
);
505 DEBUG ((DEBUG_INFO
, "# 3. Hardware SMI Handler #\n"));
507 DumpSmiEntryList(mSmmCoreHardwareSmiEntryList
);
510 DEBUG ((DEBUG_INFO
, "\n"));
512 RegisterSmiHandlerProfileHandler();
514 if (mImageStruct
!= NULL
) {
515 FreePool(mImageStruct
);
522 returns SMM image data base size.
524 @return SMM image data base size.
527 GetSmmImageDatabaseSize(
535 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
536 Size
+= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
));
542 returns all SMI handlers' size associated with SmiEntry.
544 @param SmiEntry SMI entry.
546 @return all SMI handlers' size associated with SmiEntry.
549 GetSmmSmiHandlerSizeOnSmiEntry(
550 IN SMI_ENTRY
*SmiEntry
553 LIST_ENTRY
*ListEntry
;
554 SMI_HANDLER
*SmiHandler
;
558 ListEntry
= &SmiEntry
->SmiHandlers
;
559 for (ListEntry
= ListEntry
->ForwardLink
;
560 ListEntry
!= &SmiEntry
->SmiHandlers
;
561 ListEntry
= ListEntry
->ForwardLink
) {
562 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
563 Size
+= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
));
570 return all SMI handler database size on the SMI entry list.
572 @param SmiEntryList a list of SMI entry.
574 @return all SMI handler database size on the SMI entry list.
577 GetSmmSmiDatabaseSize(
578 IN LIST_ENTRY
*SmiEntryList
581 LIST_ENTRY
*ListEntry
;
586 ListEntry
= SmiEntryList
;
587 for (ListEntry
= ListEntry
->ForwardLink
;
588 ListEntry
!= SmiEntryList
;
589 ListEntry
= ListEntry
->ForwardLink
) {
590 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
591 Size
+= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
592 Size
+= GetSmmSmiHandlerSizeOnSmiEntry(SmiEntry
);
598 return SMI handler profile database size.
600 @return SMI handler profile database size.
603 GetSmiHandlerProfileDatabaseSize (
607 mSmmImageDatabaseSize
= GetSmmImageDatabaseSize();
608 mSmmRootSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreRootSmiEntryList
);
609 mSmmSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreSmiEntryList
);
610 mSmmHardwareSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreHardwareSmiEntryList
);
612 return mSmmImageDatabaseSize
+ mSmmSmiDatabaseSize
+ mSmmRootSmiDatabaseSize
+ mSmmHardwareSmiDatabaseSize
;
616 get SMM image database.
618 @param Data The buffer to hold SMM image database
619 @param ExpectedSize The expected size of the SMM image database
621 @return SMM image data base size.
624 GetSmmImageDatabaseData (
626 IN UINTN ExpectedSize
629 SMM_CORE_IMAGE_DATABASE_STRUCTURE
*ImageStruct
;
635 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
636 if (Size
>= ExpectedSize
) {
639 if (sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
)) > ExpectedSize
- Size
) {
642 ImageStruct
->Header
.Signature
= SMM_CORE_IMAGE_DATABASE_SIGNATURE
;
643 ImageStruct
->Header
.Length
= (UINT32
)(sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
)));
644 ImageStruct
->Header
.Revision
= SMM_CORE_IMAGE_DATABASE_REVISION
;
645 CopyGuid(&ImageStruct
->FileGuid
, &mImageStruct
[Index
].FileGuid
);
646 ImageStruct
->ImageRef
= mImageStruct
[Index
].ImageRef
;
647 ImageStruct
->EntryPoint
= mImageStruct
[Index
].EntryPoint
;
648 ImageStruct
->ImageBase
= mImageStruct
[Index
].ImageBase
;
649 ImageStruct
->ImageSize
= mImageStruct
[Index
].ImageSize
;
650 if (mImageStruct
[Index
].PdbStringSize
!= 0) {
651 ImageStruct
->PdbStringOffset
= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
);
652 CopyMem ((VOID
*)((UINTN
)ImageStruct
+ ImageStruct
->PdbStringOffset
), mImageStruct
[Index
].PdbString
, mImageStruct
[Index
].PdbStringSize
);
654 ImageStruct
->PdbStringOffset
= 0;
656 ImageStruct
= (SMM_CORE_IMAGE_DATABASE_STRUCTURE
*)((UINTN
)ImageStruct
+ ImageStruct
->Header
.Length
);
657 Size
+= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
));
660 if (ExpectedSize
!= Size
) {
667 get all SMI handler data associated with SmiEntry.
669 @param SmiEntry SMI entry.
670 @param Data The buffer to hold all SMI handler data
671 @param MaxSize The max size of the SMM image database
672 @param Count The count of the SMI handler.
674 @return SMM image data base size.
677 GetSmmSmiHandlerDataOnSmiEntry(
678 IN SMI_ENTRY
*SmiEntry
,
684 SMM_CORE_SMI_HANDLER_STRUCTURE
*SmiHandlerStruct
;
685 LIST_ENTRY
*ListEntry
;
686 SMI_HANDLER
*SmiHandler
;
689 SmiHandlerStruct
= Data
;
692 ListEntry
= &SmiEntry
->SmiHandlers
;
693 for (ListEntry
= ListEntry
->ForwardLink
;
694 ListEntry
!= &SmiEntry
->SmiHandlers
;
695 ListEntry
= ListEntry
->ForwardLink
) {
696 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
697 if (Size
>= MaxSize
) {
701 if (sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
)) > MaxSize
- Size
) {
705 SmiHandlerStruct
->Length
= (UINT32
)(sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
)));
706 SmiHandlerStruct
->CallerAddr
= (UINTN
)SmiHandler
->CallerAddr
;
707 SmiHandlerStruct
->Handler
= (UINTN
)SmiHandler
->Handler
;
708 SmiHandlerStruct
->ImageRef
= AddressToImageRef((UINTN
)SmiHandler
->Handler
);
709 SmiHandlerStruct
->ContextBufferSize
= (UINT32
)SmiHandler
->ContextSize
;
710 if (SmiHandler
->ContextSize
!= 0) {
711 SmiHandlerStruct
->ContextBufferOffset
= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
);
712 CopyMem ((UINT8
*)SmiHandlerStruct
+ SmiHandlerStruct
->ContextBufferOffset
, SmiHandler
->Context
, SmiHandler
->ContextSize
);
714 SmiHandlerStruct
->ContextBufferOffset
= 0;
716 Size
+= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
));
717 SmiHandlerStruct
= (SMM_CORE_SMI_HANDLER_STRUCTURE
*)((UINTN
)SmiHandlerStruct
+ SmiHandlerStruct
->Length
);
725 get all SMI handler database on the SMI entry list.
727 @param SmiEntryList a list of SMI entry.
728 @param HandlerCategory The handler category
729 @param Data The buffer to hold all SMI handler database
730 @param ExpectedSize The expected size of the SMM image database
732 @return all SMI database size on the SMI entry list.
735 GetSmmSmiDatabaseData(
736 IN LIST_ENTRY
*SmiEntryList
,
737 IN UINT32 HandlerCategory
,
739 IN UINTN ExpectedSize
742 SMM_CORE_SMI_DATABASE_STRUCTURE
*SmiStruct
;
743 LIST_ENTRY
*ListEntry
;
746 UINTN SmiHandlerSize
;
747 UINT32 SmiHandlerCount
;
751 ListEntry
= SmiEntryList
;
752 for (ListEntry
= ListEntry
->ForwardLink
;
753 ListEntry
!= SmiEntryList
;
754 ListEntry
= ListEntry
->ForwardLink
) {
755 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
756 if (Size
>= ExpectedSize
) {
759 if (sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
) > ExpectedSize
- Size
) {
763 SmiStruct
->Header
.Signature
= SMM_CORE_SMI_DATABASE_SIGNATURE
;
764 SmiStruct
->Header
.Length
= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
765 SmiStruct
->Header
.Revision
= SMM_CORE_SMI_DATABASE_REVISION
;
766 SmiStruct
->HandlerCategory
= HandlerCategory
;
767 CopyGuid(&SmiStruct
->HandlerType
, &SmiEntry
->HandlerType
);
768 Size
+= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
769 SmiHandlerSize
= GetSmmSmiHandlerDataOnSmiEntry(SmiEntry
, (UINT8
*)SmiStruct
+ SmiStruct
->Header
.Length
, ExpectedSize
- Size
, &SmiHandlerCount
);
770 SmiStruct
->HandlerCount
= SmiHandlerCount
;
771 Size
+= SmiHandlerSize
;
772 SmiStruct
->Header
.Length
+= (UINT32
)SmiHandlerSize
;
773 SmiStruct
= (VOID
*)((UINTN
)SmiStruct
+ SmiStruct
->Header
.Length
);
775 if (ExpectedSize
!= Size
) {
782 Get SMI handler profile database.
784 @param Data the buffer to hold SMI handler profile database
786 @retval EFI_SUCCESS the database is got.
787 @retval EFI_INVALID_PARAMETER the database size mismatch.
790 GetSmiHandlerProfileDatabaseData(
794 UINTN SmmImageDatabaseSize
;
795 UINTN SmmSmiDatabaseSize
;
796 UINTN SmmRootSmiDatabaseSize
;
797 UINTN SmmHardwareSmiDatabaseSize
;
799 DEBUG((DEBUG_VERBOSE
, "GetSmiHandlerProfileDatabaseData\n"));
800 SmmImageDatabaseSize
= GetSmmImageDatabaseData(Data
, mSmmImageDatabaseSize
);
801 if (SmmImageDatabaseSize
!= mSmmImageDatabaseSize
) {
802 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmImageDatabaseSize mismatch!\n"));
803 return EFI_INVALID_PARAMETER
;
805 SmmRootSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreRootSmiEntryList
, SmmCoreSmiHandlerCategoryRootHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
, mSmmRootSmiDatabaseSize
);
806 if (SmmRootSmiDatabaseSize
!= mSmmRootSmiDatabaseSize
) {
807 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmRootSmiDatabaseSize mismatch!\n"));
808 return EFI_INVALID_PARAMETER
;
810 SmmSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreSmiEntryList
, SmmCoreSmiHandlerCategoryGuidHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
+ mSmmRootSmiDatabaseSize
, mSmmSmiDatabaseSize
);
811 if (SmmSmiDatabaseSize
!= mSmmSmiDatabaseSize
) {
812 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmSmiDatabaseSize mismatch!\n"));
813 return EFI_INVALID_PARAMETER
;
815 SmmHardwareSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreHardwareSmiEntryList
, SmmCoreSmiHandlerCategoryHardwareHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
+ SmmRootSmiDatabaseSize
+ SmmSmiDatabaseSize
, mSmmHardwareSmiDatabaseSize
);
816 if (SmmHardwareSmiDatabaseSize
!= mSmmHardwareSmiDatabaseSize
) {
817 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmHardwareSmiDatabaseSize mismatch!\n"));
818 return EFI_INVALID_PARAMETER
;
825 build SMI handler profile database.
828 BuildSmiHandlerProfileDatabase(
833 mSmiHandlerProfileDatabaseSize
= GetSmiHandlerProfileDatabaseSize();
834 mSmiHandlerProfileDatabase
= AllocatePool(mSmiHandlerProfileDatabaseSize
);
835 if (mSmiHandlerProfileDatabase
== NULL
) {
838 Status
= GetSmiHandlerProfileDatabaseData(mSmiHandlerProfileDatabase
);
839 if (EFI_ERROR(Status
)) {
840 FreePool(mSmiHandlerProfileDatabase
);
841 mSmiHandlerProfileDatabase
= NULL
;
846 Copy SMI handler profile data.
848 @param DataBuffer The buffer to hold SMI handler profile data.
849 @param DataSize On input, data buffer size.
850 On output, actual data buffer size copied.
851 @param DataOffset On input, data buffer offset to copy.
852 On output, next time data buffer offset to copy.
856 SmiHandlerProfileCopyData(
857 OUT VOID
*DataBuffer
,
858 IN OUT UINT64
*DataSize
,
859 IN OUT UINT64
*DataOffset
862 if (*DataOffset
>= mSmiHandlerProfileDatabaseSize
) {
863 *DataOffset
= mSmiHandlerProfileDatabaseSize
;
866 if (mSmiHandlerProfileDatabaseSize
- *DataOffset
< *DataSize
) {
867 *DataSize
= mSmiHandlerProfileDatabaseSize
- *DataOffset
;
872 (UINT8
*)mSmiHandlerProfileDatabase
+ *DataOffset
,
875 *DataOffset
= *DataOffset
+ *DataSize
;
879 SMI handler profile handler to get info.
881 @param SmiHandlerProfileParameterGetInfo The parameter of SMI handler profile get info.
885 SmiHandlerProfileHandlerGetInfo(
886 IN SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
*SmiHandlerProfileParameterGetInfo
889 BOOLEAN SmiHandlerProfileRecordingStatus
;
891 SmiHandlerProfileRecordingStatus
= mSmiHandlerProfileRecordingStatus
;
892 mSmiHandlerProfileRecordingStatus
= FALSE
;
894 SmiHandlerProfileParameterGetInfo
->DataSize
= mSmiHandlerProfileDatabaseSize
;
895 SmiHandlerProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
897 mSmiHandlerProfileRecordingStatus
= SmiHandlerProfileRecordingStatus
;
901 SMI handler profile handler to get data by offset.
903 @param SmiHandlerProfileParameterGetDataByOffset The parameter of SMI handler profile get data by offset.
907 SmiHandlerProfileHandlerGetDataByOffset(
908 IN SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
*SmiHandlerProfileParameterGetDataByOffset
911 SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET SmiHandlerProfileGetDataByOffset
;
912 BOOLEAN SmiHandlerProfileRecordingStatus
;
914 SmiHandlerProfileRecordingStatus
= mSmiHandlerProfileRecordingStatus
;
915 mSmiHandlerProfileRecordingStatus
= FALSE
;
917 CopyMem(&SmiHandlerProfileGetDataByOffset
, SmiHandlerProfileParameterGetDataByOffset
, sizeof(SmiHandlerProfileGetDataByOffset
));
922 if (!SmmIsBufferOutsideSmmValid((UINTN
)SmiHandlerProfileGetDataByOffset
.DataBuffer
, (UINTN
)SmiHandlerProfileGetDataByOffset
.DataSize
)) {
923 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetDataByOffset: SMI handler profile get data in SMRAM or overflow!\n"));
924 SmiHandlerProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_ACCESS_DENIED
;
928 SmiHandlerProfileCopyData((VOID
*)(UINTN
)SmiHandlerProfileGetDataByOffset
.DataBuffer
, &SmiHandlerProfileGetDataByOffset
.DataSize
, &SmiHandlerProfileGetDataByOffset
.DataOffset
);
929 CopyMem(SmiHandlerProfileParameterGetDataByOffset
, &SmiHandlerProfileGetDataByOffset
, sizeof(SmiHandlerProfileGetDataByOffset
));
930 SmiHandlerProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
933 mSmiHandlerProfileRecordingStatus
= SmiHandlerProfileRecordingStatus
;
937 Dispatch function for a Software SMI handler.
939 Caution: This function may receive untrusted input.
940 Communicate buffer and buffer size are external input, so this function will do basic validation.
942 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
943 @param Context Points to an optional handler context which was specified when the
944 handler was registered.
945 @param CommBuffer A pointer to a collection of data in memory that will
946 be conveyed from a non-SMM environment into an SMM environment.
947 @param CommBufferSize The size of the CommBuffer.
949 @retval EFI_SUCCESS Command is handled successfully.
953 SmiHandlerProfileHandler(
954 IN EFI_HANDLE DispatchHandle
,
955 IN CONST VOID
*Context OPTIONAL
,
956 IN OUT VOID
*CommBuffer OPTIONAL
,
957 IN OUT UINTN
*CommBufferSize OPTIONAL
960 SMI_HANDLER_PROFILE_PARAMETER_HEADER
*SmiHandlerProfileParameterHeader
;
961 UINTN TempCommBufferSize
;
963 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler Enter\n"));
965 if (mSmiHandlerProfileDatabase
== NULL
) {
970 // If input is invalid, stop processing this SMI
972 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
976 TempCommBufferSize
= *CommBufferSize
;
978 if (TempCommBufferSize
< sizeof(SMI_HANDLER_PROFILE_PARAMETER_HEADER
)) {
979 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
983 if (!SmmIsBufferOutsideSmmValid((UINTN
)CommBuffer
, TempCommBufferSize
)) {
984 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
988 SmiHandlerProfileParameterHeader
= (SMI_HANDLER_PROFILE_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
989 SmiHandlerProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
991 switch (SmiHandlerProfileParameterHeader
->Command
) {
992 case SMI_HANDLER_PROFILE_COMMAND_GET_INFO
:
993 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetInfo\n"));
994 if (TempCommBufferSize
!= sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
)) {
995 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
998 SmiHandlerProfileHandlerGetInfo((SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
*)(UINTN
)CommBuffer
);
1000 case SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET
:
1001 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetDataByOffset\n"));
1002 if (TempCommBufferSize
!= sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
)) {
1003 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
1006 SmiHandlerProfileHandlerGetDataByOffset((SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
*)(UINTN
)CommBuffer
);
1012 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler Exit\n"));
1018 Register SMI handler profile handler.
1021 RegisterSmiHandlerProfileHandler (
1026 EFI_HANDLE DispatchHandle
;
1028 Status
= gSmst
->SmiHandlerRegister (
1029 SmiHandlerProfileHandler
,
1030 &gSmiHandlerProfileGuid
,
1033 ASSERT_EFI_ERROR (Status
);
1035 BuildSmiHandlerProfileDatabase();
1039 Finds the SMI entry for the requested handler type.
1041 @param HandlerType The type of the interrupt
1042 @param Create Create a new entry if not found
1047 SmmCoreFindHardwareSmiEntry (
1048 IN EFI_GUID
*HandlerType
,
1054 SMI_ENTRY
*SmiEntry
;
1057 // Search the SMI entry list for the matching GUID
1060 for (Link
= mHardwareSmiEntryList
.ForwardLink
;
1061 Link
!= &mHardwareSmiEntryList
;
1062 Link
= Link
->ForwardLink
) {
1064 Item
= CR (Link
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
1065 if (CompareGuid (&Item
->HandlerType
, HandlerType
)) {
1067 // This is the SMI entry
1075 // If the protocol entry was not found and Create is TRUE, then
1076 // allocate a new entry
1078 if ((SmiEntry
== NULL
) && Create
) {
1079 SmiEntry
= AllocatePool (sizeof(SMI_ENTRY
));
1080 if (SmiEntry
!= NULL
) {
1082 // Initialize new SMI entry structure
1084 SmiEntry
->Signature
= SMI_ENTRY_SIGNATURE
;
1085 CopyGuid ((VOID
*)&SmiEntry
->HandlerType
, HandlerType
);
1086 InitializeListHead (&SmiEntry
->SmiHandlers
);
1089 // Add it to SMI entry list
1091 InsertTailList (&mHardwareSmiEntryList
, &SmiEntry
->AllEntries
);
1098 Convert EFI_SMM_USB_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT.
1100 @param UsbContext A pointer to EFI_SMM_USB_REGISTER_CONTEXT
1101 @param UsbContextSize The size of EFI_SMM_USB_REGISTER_CONTEXT in bytes
1102 @param SmiHandlerUsbContextSize The size of SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT in bytes
1104 @return SmiHandlerUsbContext A pointer to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
1106 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*
1107 ConvertSmiHandlerUsbContext (
1108 IN EFI_SMM_USB_REGISTER_CONTEXT
*UsbContext
,
1109 IN UINTN UsbContextSize
,
1110 OUT UINTN
*SmiHandlerUsbContextSize
1113 UINTN DevicePathSize
;
1114 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*SmiHandlerUsbContext
;
1116 ASSERT (UsbContextSize
== sizeof(EFI_SMM_USB_REGISTER_CONTEXT
));
1118 DevicePathSize
= GetDevicePathSize (UsbContext
->Device
);
1119 SmiHandlerUsbContext
= AllocatePool (sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
) + DevicePathSize
);
1120 if (SmiHandlerUsbContext
== NULL
) {
1121 *SmiHandlerUsbContextSize
= 0;
1124 SmiHandlerUsbContext
->Type
= UsbContext
->Type
;
1125 SmiHandlerUsbContext
->DevicePathSize
= (UINT32
)DevicePathSize
;
1126 CopyMem (SmiHandlerUsbContext
+ 1, UsbContext
->Device
, DevicePathSize
);
1127 *SmiHandlerUsbContextSize
= sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
) + DevicePathSize
;
1128 return SmiHandlerUsbContext
;
1132 Convert EFI_SMM_SW_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT.
1134 @param SwContext A pointer to EFI_SMM_SW_REGISTER_CONTEXT
1135 @param SwContextSize The size of EFI_SMM_SW_REGISTER_CONTEXT in bytes
1136 @param SmiHandlerSwContextSize The size of SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT in bytes
1138 @return SmiHandlerSwContext A pointer to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
1140 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*
1141 ConvertSmiHandlerSwContext (
1142 IN EFI_SMM_SW_REGISTER_CONTEXT
*SwContext
,
1143 IN UINTN SwContextSize
,
1144 OUT UINTN
*SmiHandlerSwContextSize
1147 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*SmiHandlerSwContext
;
1149 ASSERT (SwContextSize
== sizeof(EFI_SMM_SW_REGISTER_CONTEXT
));
1151 SmiHandlerSwContext
= AllocatePool (sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
));
1152 if (SmiHandlerSwContext
== NULL
) {
1153 *SmiHandlerSwContextSize
= 0;
1156 SmiHandlerSwContext
->SwSmiInputValue
= SwContext
->SwSmiInputValue
;
1157 *SmiHandlerSwContextSize
= sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
);
1158 return SmiHandlerSwContext
;
1162 This function is called by SmmChildDispatcher module to report
1163 a new SMI handler is registered, to SmmCore.
1165 @param This The protocol instance
1166 @param HandlerGuid The GUID to identify the type of the handler.
1167 For the SmmChildDispatch protocol, the HandlerGuid
1168 must be the GUID of SmmChildDispatch protocol.
1169 @param Handler The SMI handler.
1170 @param CallerAddress The address of the module who registers the SMI handler.
1171 @param Context The context of the SMI handler.
1172 For the SmmChildDispatch protocol, the Context
1173 must match the one defined for SmmChildDispatch protocol.
1174 @param ContextSize The size of the context in bytes.
1175 For the SmmChildDispatch protocol, the Context
1176 must match the one defined for SmmChildDispatch protocol.
1178 @retval EFI_SUCCESS The information is recorded.
1179 @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.
1183 SmiHandlerProfileRegisterHandler (
1184 IN SMI_HANDLER_PROFILE_PROTOCOL
*This
,
1185 IN EFI_GUID
*HandlerGuid
,
1186 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler
,
1187 IN PHYSICAL_ADDRESS CallerAddress
,
1188 IN VOID
*Context OPTIONAL
,
1189 IN UINTN ContextSize OPTIONAL
1192 SMI_HANDLER
*SmiHandler
;
1193 SMI_ENTRY
*SmiEntry
;
1196 if (((ContextSize
== 0) && (Context
!= NULL
)) ||
1197 ((ContextSize
!= 0) && (Context
== NULL
))) {
1198 return EFI_INVALID_PARAMETER
;
1201 SmiHandler
= AllocateZeroPool (sizeof (SMI_HANDLER
));
1202 if (SmiHandler
== NULL
) {
1203 return EFI_OUT_OF_RESOURCES
;
1206 SmiHandler
->Signature
= SMI_HANDLER_SIGNATURE
;
1207 SmiHandler
->Handler
= Handler
;
1208 SmiHandler
->CallerAddr
= (UINTN
)CallerAddress
;
1209 SmiHandler
->Context
= Context
;
1210 SmiHandler
->ContextSize
= ContextSize
;
1212 if (Context
!= NULL
) {
1213 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1214 SmiHandler
->Context
= ConvertSmiHandlerUsbContext (Context
, ContextSize
, &SmiHandler
->ContextSize
);
1215 } else if (CompareGuid (HandlerGuid
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
1216 SmiHandler
->Context
= ConvertSmiHandlerSwContext (Context
, ContextSize
, &SmiHandler
->ContextSize
);
1218 SmiHandler
->Context
= AllocateCopyPool (ContextSize
, Context
);
1221 if (SmiHandler
->Context
== NULL
) {
1222 SmiHandler
->ContextSize
= 0;
1225 SmiEntry
= SmmCoreFindHardwareSmiEntry (HandlerGuid
, TRUE
);
1226 if (SmiEntry
== NULL
) {
1227 if (SmiHandler
->Context
!= NULL
) {
1228 FreePool (SmiHandler
->Context
);
1230 FreePool (SmiHandler
);
1231 return EFI_OUT_OF_RESOURCES
;
1234 List
= &SmiEntry
->SmiHandlers
;
1236 SmiHandler
->SmiEntry
= SmiEntry
;
1237 InsertTailList (List
, &SmiHandler
->Link
);
1243 This function is called by SmmChildDispatcher module to report
1244 an existing SMI handler is unregistered, to SmmCore.
1246 @param This The protocol instance
1247 @param HandlerGuid The GUID to identify the type of the handler.
1248 For the SmmChildDispatch protocol, the HandlerGuid
1249 must be the GUID of SmmChildDispatch protocol.
1250 @param Handler The SMI handler.
1251 @param Context The context of the SMI handler.
1252 If it is NOT NULL, it will be used to check what is registered.
1253 @param ContextSize The size of the context in bytes.
1254 If Context is NOT NULL, it will be used to check what is registered.
1256 @retval EFI_SUCCESS The original record is removed.
1257 @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.
1261 SmiHandlerProfileUnregisterHandler (
1262 IN SMI_HANDLER_PROFILE_PROTOCOL
*This
,
1263 IN EFI_GUID
*HandlerGuid
,
1264 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler
,
1265 IN VOID
*Context OPTIONAL
,
1266 IN UINTN ContextSize OPTIONAL
1271 SMI_HANDLER
*SmiHandler
;
1272 SMI_ENTRY
*SmiEntry
;
1273 SMI_HANDLER
*TargetSmiHandler
;
1274 VOID
*SearchContext
;
1275 UINTN SearchContextSize
;
1277 if (((ContextSize
== 0) && (Context
!= NULL
)) ||
1278 ((ContextSize
!= 0) && (Context
== NULL
))) {
1279 return EFI_INVALID_PARAMETER
;
1282 SmiEntry
= SmmCoreFindHardwareSmiEntry (HandlerGuid
, FALSE
);
1283 if (SmiEntry
== NULL
) {
1284 return EFI_NOT_FOUND
;
1287 SearchContext
= Context
;
1288 SearchContextSize
= ContextSize
;
1289 if (Context
!= NULL
) {
1290 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1291 SearchContext
= ConvertSmiHandlerUsbContext (Context
, ContextSize
, &SearchContextSize
);
1292 } else if (CompareGuid (HandlerGuid
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
1293 SearchContext
= ConvertSmiHandlerSwContext (Context
, ContextSize
, &SearchContextSize
);
1297 TargetSmiHandler
= NULL
;
1298 Head
= &SmiEntry
->SmiHandlers
;
1299 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
1300 SmiHandler
= CR (Link
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
1301 if (SmiHandler
->Handler
== Handler
) {
1302 if ((SearchContext
== NULL
) ||
1303 ((SearchContextSize
== SmiHandler
->ContextSize
) && (CompareMem (SearchContext
, SmiHandler
->Context
, SearchContextSize
) == 0))) {
1304 TargetSmiHandler
= SmiHandler
;
1310 if (SearchContext
!= NULL
) {
1311 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1312 FreePool (SearchContext
);
1316 if (TargetSmiHandler
== NULL
) {
1317 return EFI_NOT_FOUND
;
1319 SmiHandler
= TargetSmiHandler
;
1321 RemoveEntryList (&SmiHandler
->Link
);
1322 if (SmiHandler
->Context
!= NULL
) {
1323 FreePool (SmiHandler
->Context
);
1325 FreePool (SmiHandler
);
1327 if (IsListEmpty (&SmiEntry
->SmiHandlers
)) {
1328 RemoveEntryList (&SmiEntry
->AllEntries
);
1329 FreePool (SmiEntry
);
1336 Initialize SmiHandler profile feature.
1339 SmmCoreInitializeSmiHandlerProfile (
1347 if ((PcdGet8 (PcdSmiHandlerProfilePropertyMask
) & 0x1) != 0) {
1348 InsertTailList (&mRootSmiEntryList
, &mRootSmiEntry
.AllEntries
);
1350 Status
= gSmst
->SmmRegisterProtocolNotify (
1351 &gEfiSmmReadyToLockProtocolGuid
,
1352 SmmReadyToLockInSmiHandlerProfile
,
1355 ASSERT_EFI_ERROR (Status
);
1358 Status
= gSmst
->SmmInstallProtocolInterface (
1360 &gSmiHandlerProfileGuid
,
1361 EFI_NATIVE_INTERFACE
,
1364 ASSERT_EFI_ERROR (Status
);