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 <Protocol/LoadedImage.h>
27 #include <Protocol/SmmAccess2.h>
28 #include <Protocol/SmmReadyToLock.h>
29 #include <Protocol/SmmEndOfDxe.h>
31 #include <Guid/SmiHandlerProfile.h>
33 #include "PiSmmCore.h"
35 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
36 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
40 PHYSICAL_ADDRESS EntryPoint
;
41 PHYSICAL_ADDRESS ImageBase
;
49 Register SMI handler profile handler.
52 RegisterSmiHandlerProfileHandler(
57 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
58 into system memory with the PE/COFF Loader Library functions.
60 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
61 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
62 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
63 If Pe32Data is NULL, then ASSERT().
64 If EntryPoint is NULL, then ASSERT().
66 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
67 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
69 @retval RETURN_SUCCESS EntryPoint was returned.
70 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
74 InternalPeCoffGetEntryPoint (
79 extern LIST_ENTRY mSmiEntryList
;
80 extern LIST_ENTRY mHardwareSmiEntryList
;
81 extern SMI_ENTRY mRootSmiEntry
;
83 extern SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile
;
85 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mHardwareSmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mHardwareSmiEntryList
);
87 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mRootSmiEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntryList
);
89 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreRootSmiEntryList
= &mRootSmiEntryList
;
90 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreSmiEntryList
= &mSmiEntryList
;
91 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY
*mSmmCoreHardwareSmiEntryList
= &mHardwareSmiEntryList
;
93 GLOBAL_REMOVE_IF_UNREFERENCED IMAGE_STRUCT
*mImageStruct
;
94 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCountMax
;
95 GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCount
;
97 GLOBAL_REMOVE_IF_UNREFERENCED VOID
*mSmiHandlerProfileDatabase
;
98 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmiHandlerProfileDatabaseSize
;
100 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmImageDatabaseSize
;
101 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmRootSmiDatabaseSize
;
102 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmSmiDatabaseSize
;
103 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmHardwareSmiDatabaseSize
;
105 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmiHandlerProfileRecordingStatus
;
107 GLOBAL_REMOVE_IF_UNREFERENCED SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile
= {
108 SmiHandlerProfileRegisterHandler
,
109 SmiHandlerProfileUnregisterHandler
,
113 This function dump raw data.
116 @param Size raw data size
125 for (Index
= 0; Index
< Size
; Index
++) {
126 DEBUG ((DEBUG_INFO
, "%02x ", (UINTN
)Data
[Index
]));
131 Get GUID name for an image.
133 @param[in] LoadedImage LoadedImage protocol.
134 @param[out] Guid Guid of the FFS
138 IN EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
,
145 if ((DevicePathType(LoadedImage
->FilePath
) == MEDIA_DEVICE_PATH
) &&
146 (DevicePathSubType(LoadedImage
->FilePath
) == MEDIA_PIWG_FW_FILE_DP
)) {
147 FileName
= &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)LoadedImage
->FilePath
)->FvFileName
;
149 if (FileName
!= NULL
) {
150 CopyGuid(Guid
, FileName
);
152 ZeroMem(Guid
, sizeof(EFI_GUID
));
159 @param ImageBase image base
160 @param ImageSize image size
161 @param EntryPoint image entry point
162 @param Guid FFS GUID of the image
163 @param PdbString image PDB string
167 IN PHYSICAL_ADDRESS ImageBase
,
169 IN PHYSICAL_ADDRESS EntryPoint
,
176 if (mImageStructCount
>= mImageStructCountMax
) {
181 CopyGuid(&mImageStruct
[mImageStructCount
].FileGuid
, Guid
);
182 mImageStruct
[mImageStructCount
].ImageRef
= mImageStructCount
;
183 mImageStruct
[mImageStructCount
].ImageBase
= ImageBase
;
184 mImageStruct
[mImageStructCount
].ImageSize
= ImageSize
;
185 mImageStruct
[mImageStructCount
].EntryPoint
= EntryPoint
;
186 if (PdbString
!= NULL
) {
187 PdbStringSize
= AsciiStrSize(PdbString
);
188 mImageStruct
[mImageStructCount
].PdbString
= AllocateCopyPool (PdbStringSize
, PdbString
);
189 if (mImageStruct
[mImageStructCount
].PdbString
!= NULL
) {
190 mImageStruct
[mImageStructCount
].PdbStringSize
= (UINT16
) PdbStringSize
;
198 return an image structure based upon image address.
200 @param Address image address
202 @return image structure
205 AddressToImageStruct(
211 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
212 if ((Address
>= mImageStruct
[Index
].ImageBase
) &&
213 (Address
< mImageStruct
[Index
].ImageBase
+ mImageStruct
[Index
].ImageSize
)) {
214 return &mImageStruct
[Index
];
221 return an image reference index based upon image address.
223 @param Address image address
225 @return image reference index
232 IMAGE_STRUCT
*ImageStruct
;
234 ImageStruct
= AddressToImageStruct(Address
);
235 if (ImageStruct
!= NULL
) {
236 return ImageStruct
->ImageRef
;
242 Collect SMM image information based upon loaded image protocol.
251 UINTN HandleBufferSize
;
252 EFI_HANDLE
*HandleBuffer
;
254 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
256 EFI_SMM_DRIVER_ENTRY
*LoadedImagePrivate
;
257 PHYSICAL_ADDRESS EntryPoint
;
258 VOID
*EntryPointInImage
;
261 PHYSICAL_ADDRESS RealImageBase
;
263 HandleBufferSize
= 0;
265 Status
= gSmst
->SmmLocateHandle(
267 &gEfiLoadedImageProtocolGuid
,
272 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
275 HandleBuffer
= AllocateZeroPool (HandleBufferSize
);
276 if (HandleBuffer
== NULL
) {
279 Status
= gSmst
->SmmLocateHandle(
281 &gEfiLoadedImageProtocolGuid
,
286 if (EFI_ERROR(Status
)) {
290 NoHandles
= HandleBufferSize
/sizeof(EFI_HANDLE
);
291 mImageStructCountMax
= (UINT32
) NoHandles
;
292 mImageStruct
= AllocateZeroPool(mImageStructCountMax
* sizeof(IMAGE_STRUCT
));
293 if (mImageStruct
== NULL
) {
297 for (Index
= 0; Index
< NoHandles
; Index
++) {
298 Status
= gSmst
->SmmHandleProtocol(
300 &gEfiLoadedImageProtocolGuid
,
301 (VOID
**)&LoadedImage
303 if (EFI_ERROR(Status
)) {
306 PathStr
= ConvertDevicePathToText(LoadedImage
->FilePath
, TRUE
, TRUE
);
307 GetDriverGuid(LoadedImage
, &Guid
);
308 DEBUG ((DEBUG_INFO
, "Image: %g ", &Guid
));
311 LoadedImagePrivate
= BASE_CR(LoadedImage
, EFI_SMM_DRIVER_ENTRY
, SmmLoadedImage
);
312 RealImageBase
= (UINTN
)LoadedImage
->ImageBase
;
313 if (LoadedImagePrivate
->Signature
== EFI_SMM_DRIVER_ENTRY_SIGNATURE
) {
314 EntryPoint
= LoadedImagePrivate
->ImageEntryPoint
;
315 if ((EntryPoint
!= 0) && ((EntryPoint
< (UINTN
)LoadedImage
->ImageBase
) || (EntryPoint
>= ((UINTN
)LoadedImage
->ImageBase
+ LoadedImage
->ImageSize
)))) {
317 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
318 // So patch ImageBuffer here to align the EntryPoint.
320 Status
= InternalPeCoffGetEntryPoint(LoadedImage
->ImageBase
, &EntryPointInImage
);
321 ASSERT_EFI_ERROR(Status
);
322 RealImageBase
= (UINTN
)LoadedImage
->ImageBase
+ EntryPoint
- (UINTN
)EntryPointInImage
;
325 DEBUG ((DEBUG_INFO
, "(0x%lx - 0x%lx", RealImageBase
, LoadedImage
->ImageSize
));
326 if (EntryPoint
!= 0) {
327 DEBUG ((DEBUG_INFO
, ", EntryPoint:0x%lx", EntryPoint
));
329 DEBUG ((DEBUG_INFO
, ")\n"));
331 if (RealImageBase
!= 0) {
332 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) RealImageBase
);
333 DEBUG ((DEBUG_INFO
, " pdb - %a\n", PdbString
));
337 DEBUG ((DEBUG_INFO
, " (%s)\n", PathStr
));
339 AddImageStruct(RealImageBase
, LoadedImage
->ImageSize
, EntryPoint
, &Guid
, PdbString
);
343 FreePool(HandleBuffer
);
348 Dump SMI child context.
350 @param HandlerType the handler type
351 @param Context the handler context
352 @param ContextSize the handler context size
355 DumpSmiChildContext (
356 IN EFI_GUID
*HandlerType
,
363 if (CompareGuid (HandlerType
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
364 DEBUG ((DEBUG_INFO
, " SwSmi - 0x%lx\n", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*)Context
)->SwSmiInputValue
));
365 } else if (CompareGuid (HandlerType
, &gEfiSmmSxDispatch2ProtocolGuid
)) {
366 DEBUG ((DEBUG_INFO
, " SxType - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT
*)Context
)->Type
));
367 DEBUG ((DEBUG_INFO
, " SxPhase - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT
*)Context
)->Phase
));
368 } else if (CompareGuid (HandlerType
, &gEfiSmmPowerButtonDispatch2ProtocolGuid
)) {
369 DEBUG ((DEBUG_INFO
, " PowerButtonPhase - 0x%x\n", ((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT
*)Context
)->Phase
));
370 } else if (CompareGuid (HandlerType
, &gEfiSmmStandbyButtonDispatch2ProtocolGuid
)) {
371 DEBUG ((DEBUG_INFO
, " StandbyButtonPhase - 0x%x\n", ((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT
*)Context
)->Phase
));
372 } else if (CompareGuid (HandlerType
, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid
)) {
373 DEBUG ((DEBUG_INFO
, " PeriodicTimerPeriod - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT
*)Context
)->Period
));
374 DEBUG ((DEBUG_INFO
, " PeriodicTimerSmiTickInterval - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT
*)Context
)->SmiTickInterval
));
375 } else if (CompareGuid (HandlerType
, &gEfiSmmGpiDispatch2ProtocolGuid
)) {
376 DEBUG ((DEBUG_INFO
, " GpiNum - 0x%lx\n", ((EFI_SMM_GPI_REGISTER_CONTEXT
*)Context
)->GpiNum
));
377 } else if (CompareGuid (HandlerType
, &gEfiSmmIoTrapDispatch2ProtocolGuid
)) {
378 DEBUG ((DEBUG_INFO
, " IoTrapAddress - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Address
));
379 DEBUG ((DEBUG_INFO
, " IoTrapLength - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Length
));
380 DEBUG ((DEBUG_INFO
, " IoTrapType - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT
*)Context
)->Type
));
381 } else if (CompareGuid (HandlerType
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
382 DEBUG ((DEBUG_INFO
, " UsbType - 0x%x\n", ((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*)Context
)->Type
));
383 Str
= ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL
*)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*)Context
) + 1), TRUE
, TRUE
);
384 DEBUG ((DEBUG_INFO
, " UsbDevicePath - %s\n", Str
));
389 DEBUG ((DEBUG_INFO
, " Context - "));
390 InternalDumpData (Context
, ContextSize
);
391 DEBUG ((DEBUG_INFO
, "\n"));
396 Dump all SMI handlers associated with SmiEntry.
398 @param SmiEntry SMI entry.
401 DumpSmiHandlerOnSmiEntry(
402 IN SMI_ENTRY
*SmiEntry
405 LIST_ENTRY
*ListEntry
;
406 SMI_HANDLER
*SmiHandler
;
407 IMAGE_STRUCT
*ImageStruct
;
409 ListEntry
= &SmiEntry
->SmiHandlers
;
410 for (ListEntry
= ListEntry
->ForwardLink
;
411 ListEntry
!= &SmiEntry
->SmiHandlers
;
412 ListEntry
= ListEntry
->ForwardLink
) {
413 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
414 ImageStruct
= AddressToImageStruct((UINTN
)SmiHandler
->Handler
);
415 if (ImageStruct
!= NULL
) {
416 DEBUG ((DEBUG_INFO
, " Module - %g", &ImageStruct
->FileGuid
));
418 if ((ImageStruct
!= NULL
) && (ImageStruct
->PdbString
[0] != 0)) {
419 DEBUG ((DEBUG_INFO
, " (Pdb - %a)", ImageStruct
->PdbString
));
421 DEBUG ((DEBUG_INFO
, "\n"));
422 if (SmiHandler
->ContextSize
!= 0) {
423 DumpSmiChildContext (&SmiEntry
->HandlerType
, SmiHandler
->Context
, SmiHandler
->ContextSize
);
425 DEBUG ((DEBUG_INFO
, " Handler - 0x%x", SmiHandler
->Handler
));
426 if (ImageStruct
!= NULL
) {
427 DEBUG ((DEBUG_INFO
, " <== RVA - 0x%x", (UINTN
)SmiHandler
->Handler
- (UINTN
) ImageStruct
->ImageBase
));
429 DEBUG ((DEBUG_INFO
, "\n"));
430 DEBUG ((DEBUG_INFO
, " CallerAddr - 0x%x", SmiHandler
->CallerAddr
));
431 if (ImageStruct
!= NULL
) {
432 DEBUG ((DEBUG_INFO
, " <== RVA - 0x%x", SmiHandler
->CallerAddr
- (UINTN
) ImageStruct
->ImageBase
));
434 DEBUG ((DEBUG_INFO
, "\n"));
441 Dump all SMI entry on the list.
443 @param SmiEntryList a list of SMI entry.
447 IN LIST_ENTRY
*SmiEntryList
450 LIST_ENTRY
*ListEntry
;
453 ListEntry
= SmiEntryList
;
454 for (ListEntry
= ListEntry
->ForwardLink
;
455 ListEntry
!= SmiEntryList
;
456 ListEntry
= ListEntry
->ForwardLink
) {
457 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
458 DEBUG ((DEBUG_INFO
, "SmiEntry - %g\n", &SmiEntry
->HandlerType
));
459 DumpSmiHandlerOnSmiEntry(SmiEntry
);
466 SMM Ready To Lock event notification handler.
468 This function collects all SMM image information and build SmiHandleProfile database,
469 and register SmiHandlerProfile SMI handler.
471 @param[in] Protocol Points to the protocol's unique identifier.
472 @param[in] Interface Points to the interface instance.
473 @param[in] Handle The handle on which the interface was installed.
475 @retval EFI_SUCCESS Notification handler runs successfully.
479 SmmReadyToLockInSmiHandlerProfile (
480 IN CONST EFI_GUID
*Protocol
,
488 DEBUG ((DEBUG_INFO
, "##################\n"));
489 DEBUG ((DEBUG_INFO
, "# IMAGE DATABASE #\n"));
490 DEBUG ((DEBUG_INFO
, "##################\n"));
491 GetSmmLoadedImage ();
492 DEBUG ((DEBUG_INFO
, "\n"));
497 DEBUG ((DEBUG_INFO
, "########################\n"));
498 DEBUG ((DEBUG_INFO
, "# SMI Handler DATABASE #\n"));
499 DEBUG ((DEBUG_INFO
, "########################\n"));
501 DEBUG ((DEBUG_INFO
, "# 1. ROOT SMI Handler #\n"));
503 DumpSmiEntryList(mSmmCoreRootSmiEntryList
);
506 DEBUG ((DEBUG_INFO
, "# 2. GUID SMI Handler #\n"));
508 DumpSmiEntryList(mSmmCoreSmiEntryList
);
511 DEBUG ((DEBUG_INFO
, "# 3. Hardware SMI Handler #\n"));
513 DumpSmiEntryList(mSmmCoreHardwareSmiEntryList
);
516 DEBUG ((DEBUG_INFO
, "\n"));
518 RegisterSmiHandlerProfileHandler();
520 if (mImageStruct
!= NULL
) {
521 FreePool(mImageStruct
);
528 returns SMM image data base size.
530 @return SMM image data base size.
533 GetSmmImageDatabaseSize(
541 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
542 Size
+= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
));
548 returns all SMI handlers' size associated with SmiEntry.
550 @param SmiEntry SMI entry.
552 @return all SMI handlers' size associated with SmiEntry.
555 GetSmmSmiHandlerSizeOnSmiEntry(
556 IN SMI_ENTRY
*SmiEntry
559 LIST_ENTRY
*ListEntry
;
560 SMI_HANDLER
*SmiHandler
;
564 ListEntry
= &SmiEntry
->SmiHandlers
;
565 for (ListEntry
= ListEntry
->ForwardLink
;
566 ListEntry
!= &SmiEntry
->SmiHandlers
;
567 ListEntry
= ListEntry
->ForwardLink
) {
568 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
569 Size
+= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
));
576 return all SMI handler database size on the SMI entry list.
578 @param SmiEntryList a list of SMI entry.
580 @return all SMI handler database size on the SMI entry list.
583 GetSmmSmiDatabaseSize(
584 IN LIST_ENTRY
*SmiEntryList
587 LIST_ENTRY
*ListEntry
;
592 ListEntry
= SmiEntryList
;
593 for (ListEntry
= ListEntry
->ForwardLink
;
594 ListEntry
!= SmiEntryList
;
595 ListEntry
= ListEntry
->ForwardLink
) {
596 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
597 Size
+= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
598 Size
+= GetSmmSmiHandlerSizeOnSmiEntry(SmiEntry
);
604 return SMI handler profile database size.
606 @return SMI handler profile database size.
609 GetSmiHandlerProfileDatabaseSize (
613 mSmmImageDatabaseSize
= GetSmmImageDatabaseSize();
614 mSmmRootSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreRootSmiEntryList
);
615 mSmmSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreSmiEntryList
);
616 mSmmHardwareSmiDatabaseSize
= GetSmmSmiDatabaseSize(mSmmCoreHardwareSmiEntryList
);
618 return mSmmImageDatabaseSize
+ mSmmSmiDatabaseSize
+ mSmmRootSmiDatabaseSize
+ mSmmHardwareSmiDatabaseSize
;
622 get SMM image database.
624 @param Data The buffer to hold SMM image database
625 @param ExpectedSize The expected size of the SMM image database
627 @return SMM image data base size.
630 GetSmmImageDatabaseData (
632 IN UINTN ExpectedSize
635 SMM_CORE_IMAGE_DATABASE_STRUCTURE
*ImageStruct
;
641 for (Index
= 0; Index
< mImageStructCount
; Index
++) {
642 if (Size
>= ExpectedSize
) {
645 if (sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
)) > ExpectedSize
- Size
) {
648 ImageStruct
->Header
.Signature
= SMM_CORE_IMAGE_DATABASE_SIGNATURE
;
649 ImageStruct
->Header
.Length
= (UINT32
)(sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
)));
650 ImageStruct
->Header
.Revision
= SMM_CORE_IMAGE_DATABASE_REVISION
;
651 CopyGuid(&ImageStruct
->FileGuid
, &mImageStruct
[Index
].FileGuid
);
652 ImageStruct
->ImageRef
= mImageStruct
[Index
].ImageRef
;
653 ImageStruct
->EntryPoint
= mImageStruct
[Index
].EntryPoint
;
654 ImageStruct
->ImageBase
= mImageStruct
[Index
].ImageBase
;
655 ImageStruct
->ImageSize
= mImageStruct
[Index
].ImageSize
;
656 if (mImageStruct
[Index
].PdbStringSize
!= 0) {
657 ImageStruct
->PdbStringOffset
= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
);
658 CopyMem ((VOID
*)((UINTN
)ImageStruct
+ ImageStruct
->PdbStringOffset
), mImageStruct
[Index
].PdbString
, mImageStruct
[Index
].PdbStringSize
);
660 ImageStruct
->PdbStringOffset
= 0;
662 ImageStruct
= (SMM_CORE_IMAGE_DATABASE_STRUCTURE
*)((UINTN
)ImageStruct
+ ImageStruct
->Header
.Length
);
663 Size
+= sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE
) + GET_OCCUPIED_SIZE (mImageStruct
[Index
].PdbStringSize
, sizeof (UINT64
));
666 if (ExpectedSize
!= Size
) {
673 get all SMI handler data associated with SmiEntry.
675 @param SmiEntry SMI entry.
676 @param Data The buffer to hold all SMI handler data
677 @param MaxSize The max size of the SMM image database
678 @param Count The count of the SMI handler.
680 @return SMM image data base size.
683 GetSmmSmiHandlerDataOnSmiEntry(
684 IN SMI_ENTRY
*SmiEntry
,
690 SMM_CORE_SMI_HANDLER_STRUCTURE
*SmiHandlerStruct
;
691 LIST_ENTRY
*ListEntry
;
692 SMI_HANDLER
*SmiHandler
;
695 SmiHandlerStruct
= Data
;
698 ListEntry
= &SmiEntry
->SmiHandlers
;
699 for (ListEntry
= ListEntry
->ForwardLink
;
700 ListEntry
!= &SmiEntry
->SmiHandlers
;
701 ListEntry
= ListEntry
->ForwardLink
) {
702 SmiHandler
= CR(ListEntry
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
703 if (Size
>= MaxSize
) {
707 if (sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
)) > MaxSize
- Size
) {
711 SmiHandlerStruct
->Length
= (UINT32
)(sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
)));
712 SmiHandlerStruct
->CallerAddr
= (UINTN
)SmiHandler
->CallerAddr
;
713 SmiHandlerStruct
->Handler
= (UINTN
)SmiHandler
->Handler
;
714 SmiHandlerStruct
->ImageRef
= AddressToImageRef((UINTN
)SmiHandler
->Handler
);
715 SmiHandlerStruct
->ContextBufferSize
= (UINT32
)SmiHandler
->ContextSize
;
716 if (SmiHandler
->ContextSize
!= 0) {
717 SmiHandlerStruct
->ContextBufferOffset
= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
);
718 CopyMem ((UINT8
*)SmiHandlerStruct
+ SmiHandlerStruct
->ContextBufferOffset
, SmiHandler
->Context
, SmiHandler
->ContextSize
);
720 SmiHandlerStruct
->ContextBufferOffset
= 0;
722 Size
+= sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE
) + GET_OCCUPIED_SIZE (SmiHandler
->ContextSize
, sizeof (UINT64
));
723 SmiHandlerStruct
= (SMM_CORE_SMI_HANDLER_STRUCTURE
*)((UINTN
)SmiHandlerStruct
+ SmiHandlerStruct
->Length
);
731 get all SMI handler database on the SMI entry list.
733 @param SmiEntryList a list of SMI entry.
734 @param HandlerCategory The handler category
735 @param Data The buffer to hold all SMI handler database
736 @param ExpectedSize The expected size of the SMM image database
738 @return all SMI database size on the SMI entry list.
741 GetSmmSmiDatabaseData(
742 IN LIST_ENTRY
*SmiEntryList
,
743 IN UINT32 HandlerCategory
,
745 IN UINTN ExpectedSize
748 SMM_CORE_SMI_DATABASE_STRUCTURE
*SmiStruct
;
749 LIST_ENTRY
*ListEntry
;
752 UINTN SmiHandlerSize
;
753 UINT32 SmiHandlerCount
;
757 ListEntry
= SmiEntryList
;
758 for (ListEntry
= ListEntry
->ForwardLink
;
759 ListEntry
!= SmiEntryList
;
760 ListEntry
= ListEntry
->ForwardLink
) {
761 SmiEntry
= CR(ListEntry
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
762 if (Size
>= ExpectedSize
) {
765 if (sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
) > ExpectedSize
- Size
) {
769 SmiStruct
->Header
.Signature
= SMM_CORE_SMI_DATABASE_SIGNATURE
;
770 SmiStruct
->Header
.Length
= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
771 SmiStruct
->Header
.Revision
= SMM_CORE_SMI_DATABASE_REVISION
;
772 SmiStruct
->HandlerCategory
= HandlerCategory
;
773 CopyGuid(&SmiStruct
->HandlerType
, &SmiEntry
->HandlerType
);
774 Size
+= sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE
);
775 SmiHandlerSize
= GetSmmSmiHandlerDataOnSmiEntry(SmiEntry
, (UINT8
*)SmiStruct
+ SmiStruct
->Header
.Length
, ExpectedSize
- Size
, &SmiHandlerCount
);
776 SmiStruct
->HandlerCount
= SmiHandlerCount
;
777 Size
+= SmiHandlerSize
;
778 SmiStruct
->Header
.Length
+= (UINT32
)SmiHandlerSize
;
779 SmiStruct
= (VOID
*)((UINTN
)SmiStruct
+ SmiStruct
->Header
.Length
);
781 if (ExpectedSize
!= Size
) {
788 Get SMI handler profile database.
790 @param Data the buffer to hold SMI handler profile database
792 @retval EFI_SUCCESS the database is got.
793 @retval EFI_INVALID_PARAMETER the database size mismatch.
796 GetSmiHandlerProfileDatabaseData(
800 UINTN SmmImageDatabaseSize
;
801 UINTN SmmSmiDatabaseSize
;
802 UINTN SmmRootSmiDatabaseSize
;
803 UINTN SmmHardwareSmiDatabaseSize
;
805 DEBUG((DEBUG_VERBOSE
, "GetSmiHandlerProfileDatabaseData\n"));
806 SmmImageDatabaseSize
= GetSmmImageDatabaseData(Data
, mSmmImageDatabaseSize
);
807 if (SmmImageDatabaseSize
!= mSmmImageDatabaseSize
) {
808 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmImageDatabaseSize mismatch!\n"));
809 return EFI_INVALID_PARAMETER
;
811 SmmRootSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreRootSmiEntryList
, SmmCoreSmiHandlerCategoryRootHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
, mSmmRootSmiDatabaseSize
);
812 if (SmmRootSmiDatabaseSize
!= mSmmRootSmiDatabaseSize
) {
813 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmRootSmiDatabaseSize mismatch!\n"));
814 return EFI_INVALID_PARAMETER
;
816 SmmSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreSmiEntryList
, SmmCoreSmiHandlerCategoryGuidHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
+ mSmmRootSmiDatabaseSize
, mSmmSmiDatabaseSize
);
817 if (SmmSmiDatabaseSize
!= mSmmSmiDatabaseSize
) {
818 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmSmiDatabaseSize mismatch!\n"));
819 return EFI_INVALID_PARAMETER
;
821 SmmHardwareSmiDatabaseSize
= GetSmmSmiDatabaseData(mSmmCoreHardwareSmiEntryList
, SmmCoreSmiHandlerCategoryHardwareHandler
, (UINT8
*)Data
+ SmmImageDatabaseSize
+ SmmRootSmiDatabaseSize
+ SmmSmiDatabaseSize
, mSmmHardwareSmiDatabaseSize
);
822 if (SmmHardwareSmiDatabaseSize
!= mSmmHardwareSmiDatabaseSize
) {
823 DEBUG((DEBUG_ERROR
, "GetSmiHandlerProfileDatabaseData - SmmHardwareSmiDatabaseSize mismatch!\n"));
824 return EFI_INVALID_PARAMETER
;
831 build SMI handler profile database.
834 BuildSmiHandlerProfileDatabase(
839 mSmiHandlerProfileDatabaseSize
= GetSmiHandlerProfileDatabaseSize();
840 mSmiHandlerProfileDatabase
= AllocatePool(mSmiHandlerProfileDatabaseSize
);
841 if (mSmiHandlerProfileDatabase
== NULL
) {
844 Status
= GetSmiHandlerProfileDatabaseData(mSmiHandlerProfileDatabase
);
845 if (EFI_ERROR(Status
)) {
846 FreePool(mSmiHandlerProfileDatabase
);
847 mSmiHandlerProfileDatabase
= NULL
;
852 Copy SMI handler profile data.
854 @param DataBuffer The buffer to hold SMI handler profile data.
855 @param DataSize On input, data buffer size.
856 On output, actual data buffer size copied.
857 @param DataOffset On input, data buffer offset to copy.
858 On output, next time data buffer offset to copy.
862 SmiHandlerProfileCopyData(
863 OUT VOID
*DataBuffer
,
864 IN OUT UINT64
*DataSize
,
865 IN OUT UINT64
*DataOffset
868 if (*DataOffset
>= mSmiHandlerProfileDatabaseSize
) {
869 *DataOffset
= mSmiHandlerProfileDatabaseSize
;
872 if (mSmiHandlerProfileDatabaseSize
- *DataOffset
< *DataSize
) {
873 *DataSize
= mSmiHandlerProfileDatabaseSize
- *DataOffset
;
878 (UINT8
*)mSmiHandlerProfileDatabase
+ *DataOffset
,
881 *DataOffset
= *DataOffset
+ *DataSize
;
885 SMI handler profile handler to get info.
887 @param SmiHandlerProfileParameterGetInfo The parameter of SMI handler profile get info.
891 SmiHandlerProfileHandlerGetInfo(
892 IN SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
*SmiHandlerProfileParameterGetInfo
895 BOOLEAN SmiHandlerProfileRecordingStatus
;
897 SmiHandlerProfileRecordingStatus
= mSmiHandlerProfileRecordingStatus
;
898 mSmiHandlerProfileRecordingStatus
= FALSE
;
900 SmiHandlerProfileParameterGetInfo
->DataSize
= mSmiHandlerProfileDatabaseSize
;
901 SmiHandlerProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
903 mSmiHandlerProfileRecordingStatus
= SmiHandlerProfileRecordingStatus
;
907 SMI handler profile handler to get data by offset.
909 @param SmiHandlerProfileParameterGetDataByOffset The parameter of SMI handler profile get data by offset.
913 SmiHandlerProfileHandlerGetDataByOffset(
914 IN SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
*SmiHandlerProfileParameterGetDataByOffset
917 SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET SmiHandlerProfileGetDataByOffset
;
918 BOOLEAN SmiHandlerProfileRecordingStatus
;
920 SmiHandlerProfileRecordingStatus
= mSmiHandlerProfileRecordingStatus
;
921 mSmiHandlerProfileRecordingStatus
= FALSE
;
923 CopyMem(&SmiHandlerProfileGetDataByOffset
, SmiHandlerProfileParameterGetDataByOffset
, sizeof(SmiHandlerProfileGetDataByOffset
));
928 if (!SmmIsBufferOutsideSmmValid((UINTN
)SmiHandlerProfileGetDataByOffset
.DataBuffer
, (UINTN
)SmiHandlerProfileGetDataByOffset
.DataSize
)) {
929 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetDataByOffset: SMI handler profile get data in SMRAM or overflow!\n"));
930 SmiHandlerProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_ACCESS_DENIED
;
934 SmiHandlerProfileCopyData((VOID
*)(UINTN
)SmiHandlerProfileGetDataByOffset
.DataBuffer
, &SmiHandlerProfileGetDataByOffset
.DataSize
, &SmiHandlerProfileGetDataByOffset
.DataOffset
);
935 CopyMem(SmiHandlerProfileParameterGetDataByOffset
, &SmiHandlerProfileGetDataByOffset
, sizeof(SmiHandlerProfileGetDataByOffset
));
936 SmiHandlerProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
939 mSmiHandlerProfileRecordingStatus
= SmiHandlerProfileRecordingStatus
;
943 Dispatch function for a Software SMI handler.
945 Caution: This function may receive untrusted input.
946 Communicate buffer and buffer size are external input, so this function will do basic validation.
948 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
949 @param Context Points to an optional handler context which was specified when the
950 handler was registered.
951 @param CommBuffer A pointer to a collection of data in memory that will
952 be conveyed from a non-SMM environment into an SMM environment.
953 @param CommBufferSize The size of the CommBuffer.
955 @retval EFI_SUCCESS Command is handled successfully.
959 SmiHandlerProfileHandler(
960 IN EFI_HANDLE DispatchHandle
,
961 IN CONST VOID
*Context OPTIONAL
,
962 IN OUT VOID
*CommBuffer OPTIONAL
,
963 IN OUT UINTN
*CommBufferSize OPTIONAL
966 SMI_HANDLER_PROFILE_PARAMETER_HEADER
*SmiHandlerProfileParameterHeader
;
967 UINTN TempCommBufferSize
;
969 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler Enter\n"));
971 if (mSmiHandlerProfileDatabase
== NULL
) {
976 // If input is invalid, stop processing this SMI
978 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
982 TempCommBufferSize
= *CommBufferSize
;
984 if (TempCommBufferSize
< sizeof(SMI_HANDLER_PROFILE_PARAMETER_HEADER
)) {
985 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
989 if (!SmmIsBufferOutsideSmmValid((UINTN
)CommBuffer
, TempCommBufferSize
)) {
990 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
994 SmiHandlerProfileParameterHeader
= (SMI_HANDLER_PROFILE_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
995 SmiHandlerProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
997 switch (SmiHandlerProfileParameterHeader
->Command
) {
998 case SMI_HANDLER_PROFILE_COMMAND_GET_INFO
:
999 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetInfo\n"));
1000 if (TempCommBufferSize
!= sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
)) {
1001 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
1004 SmiHandlerProfileHandlerGetInfo((SMI_HANDLER_PROFILE_PARAMETER_GET_INFO
*)(UINTN
)CommBuffer
);
1006 case SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET
:
1007 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandlerGetDataByOffset\n"));
1008 if (TempCommBufferSize
!= sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
)) {
1009 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));
1012 SmiHandlerProfileHandlerGetDataByOffset((SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET
*)(UINTN
)CommBuffer
);
1018 DEBUG((DEBUG_ERROR
, "SmiHandlerProfileHandler Exit\n"));
1024 Register SMI handler profile handler.
1027 RegisterSmiHandlerProfileHandler (
1032 EFI_HANDLE DispatchHandle
;
1034 Status
= gSmst
->SmiHandlerRegister (
1035 SmiHandlerProfileHandler
,
1036 &gSmiHandlerProfileGuid
,
1039 ASSERT_EFI_ERROR (Status
);
1041 BuildSmiHandlerProfileDatabase();
1045 Finds the SMI entry for the requested handler type.
1047 @param HandlerType The type of the interrupt
1048 @param Create Create a new entry if not found
1053 SmmCoreFindHardwareSmiEntry (
1054 IN EFI_GUID
*HandlerType
,
1060 SMI_ENTRY
*SmiEntry
;
1063 // Search the SMI entry list for the matching GUID
1066 for (Link
= mHardwareSmiEntryList
.ForwardLink
;
1067 Link
!= &mHardwareSmiEntryList
;
1068 Link
= Link
->ForwardLink
) {
1070 Item
= CR (Link
, SMI_ENTRY
, AllEntries
, SMI_ENTRY_SIGNATURE
);
1071 if (CompareGuid (&Item
->HandlerType
, HandlerType
)) {
1073 // This is the SMI entry
1081 // If the protocol entry was not found and Create is TRUE, then
1082 // allocate a new entry
1084 if ((SmiEntry
== NULL
) && Create
) {
1085 SmiEntry
= AllocatePool (sizeof(SMI_ENTRY
));
1086 if (SmiEntry
!= NULL
) {
1088 // Initialize new SMI entry structure
1090 SmiEntry
->Signature
= SMI_ENTRY_SIGNATURE
;
1091 CopyGuid ((VOID
*)&SmiEntry
->HandlerType
, HandlerType
);
1092 InitializeListHead (&SmiEntry
->SmiHandlers
);
1095 // Add it to SMI entry list
1097 InsertTailList (&mHardwareSmiEntryList
, &SmiEntry
->AllEntries
);
1104 Convert EFI_SMM_USB_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT.
1106 @param UsbContext A pointer to EFI_SMM_USB_REGISTER_CONTEXT
1107 @param UsbContextSize The size of EFI_SMM_USB_REGISTER_CONTEXT in bytes
1108 @param SmiHandlerUsbContextSize The size of SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT in bytes
1110 @return SmiHandlerUsbContext A pointer to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
1112 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*
1113 ConvertSmiHandlerUsbContext (
1114 IN EFI_SMM_USB_REGISTER_CONTEXT
*UsbContext
,
1115 IN UINTN UsbContextSize
,
1116 OUT UINTN
*SmiHandlerUsbContextSize
1119 UINTN DevicePathSize
;
1120 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
*SmiHandlerUsbContext
;
1122 ASSERT (UsbContextSize
== sizeof(EFI_SMM_USB_REGISTER_CONTEXT
));
1124 DevicePathSize
= GetDevicePathSize (UsbContext
->Device
);
1125 SmiHandlerUsbContext
= AllocatePool (sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
) + DevicePathSize
);
1126 if (SmiHandlerUsbContext
== NULL
) {
1127 *SmiHandlerUsbContextSize
= 0;
1130 SmiHandlerUsbContext
->Type
= UsbContext
->Type
;
1131 SmiHandlerUsbContext
->DevicePathSize
= (UINT32
)DevicePathSize
;
1132 CopyMem (SmiHandlerUsbContext
+ 1, UsbContext
->Device
, DevicePathSize
);
1133 *SmiHandlerUsbContextSize
= sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT
) + DevicePathSize
;
1134 return SmiHandlerUsbContext
;
1138 Convert EFI_SMM_SW_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT.
1140 @param SwContext A pointer to EFI_SMM_SW_REGISTER_CONTEXT
1141 @param SwContextSize The size of EFI_SMM_SW_REGISTER_CONTEXT in bytes
1142 @param SmiHandlerSwContextSize The size of SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT in bytes
1144 @return SmiHandlerSwContext A pointer to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
1146 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*
1147 ConvertSmiHandlerSwContext (
1148 IN EFI_SMM_SW_REGISTER_CONTEXT
*SwContext
,
1149 IN UINTN SwContextSize
,
1150 OUT UINTN
*SmiHandlerSwContextSize
1153 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
*SmiHandlerSwContext
;
1155 ASSERT (SwContextSize
== sizeof(EFI_SMM_SW_REGISTER_CONTEXT
));
1157 SmiHandlerSwContext
= AllocatePool (sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
));
1158 if (SmiHandlerSwContext
== NULL
) {
1159 *SmiHandlerSwContextSize
= 0;
1162 SmiHandlerSwContext
->SwSmiInputValue
= SwContext
->SwSmiInputValue
;
1163 *SmiHandlerSwContextSize
= sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT
);
1164 return SmiHandlerSwContext
;
1168 This function is called by SmmChildDispatcher module to report
1169 a new SMI handler is registered, to SmmCore.
1171 @param This The protocol instance
1172 @param HandlerGuid The GUID to identify the type of the handler.
1173 For the SmmChildDispatch protocol, the HandlerGuid
1174 must be the GUID of SmmChildDispatch protocol.
1175 @param Handler The SMI handler.
1176 @param CallerAddress The address of the module who registers the SMI handler.
1177 @param Context The context of the SMI handler.
1178 For the SmmChildDispatch protocol, the Context
1179 must match the one defined for SmmChildDispatch protocol.
1180 @param ContextSize The size of the context in bytes.
1181 For the SmmChildDispatch protocol, the Context
1182 must match the one defined for SmmChildDispatch protocol.
1184 @retval EFI_SUCCESS The information is recorded.
1185 @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.
1189 SmiHandlerProfileRegisterHandler (
1190 IN SMI_HANDLER_PROFILE_PROTOCOL
*This
,
1191 IN EFI_GUID
*HandlerGuid
,
1192 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler
,
1193 IN PHYSICAL_ADDRESS CallerAddress
,
1194 IN VOID
*Context
, OPTIONAL
1195 IN UINTN ContextSize OPTIONAL
1198 SMI_HANDLER
*SmiHandler
;
1199 SMI_ENTRY
*SmiEntry
;
1202 if (((ContextSize
== 0) && (Context
!= NULL
)) ||
1203 ((ContextSize
!= 0) && (Context
== NULL
))) {
1204 return EFI_INVALID_PARAMETER
;
1207 SmiHandler
= AllocateZeroPool (sizeof (SMI_HANDLER
));
1208 if (SmiHandler
== NULL
) {
1209 return EFI_OUT_OF_RESOURCES
;
1212 SmiHandler
->Signature
= SMI_HANDLER_SIGNATURE
;
1213 SmiHandler
->Handler
= Handler
;
1214 SmiHandler
->CallerAddr
= (UINTN
)CallerAddress
;
1215 SmiHandler
->Context
= Context
;
1216 SmiHandler
->ContextSize
= ContextSize
;
1218 if (Context
!= NULL
) {
1219 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1220 SmiHandler
->Context
= ConvertSmiHandlerUsbContext (Context
, ContextSize
, &SmiHandler
->ContextSize
);
1221 } else if (CompareGuid (HandlerGuid
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
1222 SmiHandler
->Context
= ConvertSmiHandlerSwContext (Context
, ContextSize
, &SmiHandler
->ContextSize
);
1224 SmiHandler
->Context
= AllocateCopyPool (ContextSize
, Context
);
1227 if (SmiHandler
->Context
== NULL
) {
1228 SmiHandler
->ContextSize
= 0;
1231 SmiEntry
= SmmCoreFindHardwareSmiEntry (HandlerGuid
, TRUE
);
1232 if (SmiEntry
== NULL
) {
1233 if (SmiHandler
->Context
!= NULL
) {
1234 FreePool (SmiHandler
->Context
);
1236 FreePool (SmiHandler
);
1237 return EFI_OUT_OF_RESOURCES
;
1240 List
= &SmiEntry
->SmiHandlers
;
1242 SmiHandler
->SmiEntry
= SmiEntry
;
1243 InsertTailList (List
, &SmiHandler
->Link
);
1249 This function is called by SmmChildDispatcher module to report
1250 an existing SMI handler is unregistered, to SmmCore.
1252 @param This The protocol instance
1253 @param HandlerGuid The GUID to identify the type of the handler.
1254 For the SmmChildDispatch protocol, the HandlerGuid
1255 must be the GUID of SmmChildDispatch protocol.
1256 @param Handler The SMI handler.
1257 @param Context The context of the SMI handler.
1258 If it is NOT NULL, it will be used to check what is registered.
1259 @param ContextSize The size of the context in bytes.
1260 If Context is NOT NULL, it will be used to check what is registered.
1262 @retval EFI_SUCCESS The original record is removed.
1263 @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.
1267 SmiHandlerProfileUnregisterHandler (
1268 IN SMI_HANDLER_PROFILE_PROTOCOL
*This
,
1269 IN EFI_GUID
*HandlerGuid
,
1270 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler
,
1271 IN VOID
*Context
, OPTIONAL
1272 IN UINTN ContextSize OPTIONAL
1277 SMI_HANDLER
*SmiHandler
;
1278 SMI_ENTRY
*SmiEntry
;
1279 SMI_HANDLER
*TargetSmiHandler
;
1280 VOID
*SearchContext
;
1281 UINTN SearchContextSize
;
1283 if (((ContextSize
== 0) && (Context
!= NULL
)) ||
1284 ((ContextSize
!= 0) && (Context
== NULL
))) {
1285 return EFI_INVALID_PARAMETER
;
1288 SmiEntry
= SmmCoreFindHardwareSmiEntry (HandlerGuid
, FALSE
);
1289 if (SmiEntry
== NULL
) {
1290 return EFI_NOT_FOUND
;
1293 SearchContext
= Context
;
1294 SearchContextSize
= ContextSize
;
1295 if (Context
!= NULL
) {
1296 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1297 SearchContext
= ConvertSmiHandlerUsbContext (Context
, ContextSize
, &SearchContextSize
);
1298 } else if (CompareGuid (HandlerGuid
, &gEfiSmmSwDispatch2ProtocolGuid
)) {
1299 SearchContext
= ConvertSmiHandlerSwContext (Context
, ContextSize
, &SearchContextSize
);
1303 TargetSmiHandler
= NULL
;
1304 Head
= &SmiEntry
->SmiHandlers
;
1305 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
1306 SmiHandler
= CR (Link
, SMI_HANDLER
, Link
, SMI_HANDLER_SIGNATURE
);
1307 if (SmiHandler
->Handler
== Handler
) {
1308 if ((SearchContext
== NULL
) ||
1309 ((SearchContextSize
== SmiHandler
->ContextSize
) && (CompareMem (SearchContext
, SmiHandler
->Context
, SearchContextSize
) == 0))) {
1310 TargetSmiHandler
= SmiHandler
;
1316 if (SearchContext
!= NULL
) {
1317 if (CompareGuid (HandlerGuid
, &gEfiSmmUsbDispatch2ProtocolGuid
)) {
1318 FreePool (SearchContext
);
1322 if (TargetSmiHandler
== NULL
) {
1323 return EFI_NOT_FOUND
;
1325 SmiHandler
= TargetSmiHandler
;
1327 RemoveEntryList (&SmiHandler
->Link
);
1328 if (SmiHandler
->Context
!= NULL
) {
1329 FreePool (SmiHandler
->Context
);
1331 FreePool (SmiHandler
);
1333 if (IsListEmpty (&SmiEntry
->SmiHandlers
)) {
1334 RemoveEntryList (&SmiEntry
->AllEntries
);
1335 FreePool (SmiEntry
);
1342 Initialize SmiHandler profile feature.
1345 SmmCoreInitializeSmiHandlerProfile (
1353 if ((PcdGet8 (PcdSmiHandlerProfilePropertyMask
) & 0x1) != 0) {
1354 InsertTailList (&mRootSmiEntryList
, &mRootSmiEntry
.AllEntries
);
1356 Status
= gSmst
->SmmRegisterProtocolNotify (
1357 &gEfiSmmReadyToLockProtocolGuid
,
1358 SmmReadyToLockInSmiHandlerProfile
,
1361 ASSERT_EFI_ERROR (Status
);
1364 Status
= gSmst
->SmmInstallProtocolInterface (
1366 &gSmiHandlerProfileGuid
,
1367 EFI_NATIVE_INTERFACE
,
1370 ASSERT_EFI_ERROR (Status
);