]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Application / SmiHandlerProfileInfo / SmiHandlerProfileInfo.c
1 /** @file
2 Shell application to dump SMI handler profile information.
3
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiDxe.h>
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/UefiRuntimeServicesTableLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/PrintLib.h>
17 #include <Library/UefiLib.h>
18 #include <Library/DevicePathLib.h>
19 #include <Library/DxeServicesLib.h>
20 #include <Protocol/SmmCommunication.h>
21 #include <Guid/PiSmmCommunicationRegionTable.h>
22
23 #include <Guid/SmiHandlerProfile.h>
24
25 #define PROFILE_NAME_STRING_LENGTH 64
26 CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
27
28 VOID *mSmiHandlerProfileDatabase;
29 UINTN mSmiHandlerProfileDatabaseSize;
30
31 /**
32 This function dump raw data.
33
34 @param Data raw data
35 @param Size raw data size
36 **/
37 VOID
38 InternalDumpData (
39 IN UINT8 *Data,
40 IN UINTN Size
41 )
42 {
43 UINTN Index;
44
45 for (Index = 0; Index < Size; Index++) {
46 Print (L"%02x", (UINTN)Data[Index]);
47 if ((Index + 1) != Size) {
48 Print (L" ");
49 }
50 }
51 }
52
53 /**
54 Get SMI handler profile database.
55 **/
56 VOID
57 GetSmiHandlerProfileDatabase (
58 VOID
59 )
60 {
61 EFI_STATUS Status;
62 UINTN CommSize;
63 UINT8 *CommBuffer;
64 EFI_SMM_COMMUNICATE_HEADER *CommHeader;
65 SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *CommGetInfo;
66 SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *CommGetData;
67 EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
68 UINTN MinimalSizeNeeded;
69 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
70 UINT32 Index;
71 EFI_MEMORY_DESCRIPTOR *Entry;
72 VOID *Buffer;
73 UINTN Size;
74 UINTN Offset;
75
76 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&SmmCommunication);
77 if (EFI_ERROR (Status)) {
78 Print (L"SmiHandlerProfile: Locate SmmCommunication protocol - %r\n", Status);
79 return;
80 }
81
82 MinimalSizeNeeded = EFI_PAGE_SIZE;
83
84 Status = EfiGetSystemConfigurationTable (
85 &gEdkiiPiSmmCommunicationRegionTableGuid,
86 (VOID **)&PiSmmCommunicationRegionTable
87 );
88 if (EFI_ERROR (Status)) {
89 Print (L"SmiHandlerProfile: Get PiSmmCommunicationRegionTable - %r\n", Status);
90 return;
91 }
92
93 ASSERT (PiSmmCommunicationRegionTable != NULL);
94 Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);
95 Size = 0;
96 for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
97 if (Entry->Type == EfiConventionalMemory) {
98 Size = EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages);
99 if (Size >= MinimalSizeNeeded) {
100 break;
101 }
102 }
103
104 Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize);
105 }
106
107 ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);
108 CommBuffer = (UINT8 *)(UINTN)Entry->PhysicalStart;
109
110 //
111 // Get Size
112 //
113 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
114 CopyMem (&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof (gSmiHandlerProfileGuid));
115 CommHeader->MessageLength = sizeof (SMI_HANDLER_PROFILE_PARAMETER_GET_INFO);
116
117 CommGetInfo = (SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
118 CommGetInfo->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_INFO;
119 CommGetInfo->Header.DataLength = sizeof (*CommGetInfo);
120 CommGetInfo->Header.ReturnStatus = (UINT64)-1;
121 CommGetInfo->DataSize = 0;
122
123 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
124 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
125 if (EFI_ERROR (Status)) {
126 Print (L"SmiHandlerProfile: SmmCommunication - %r\n", Status);
127 return;
128 }
129
130 if (CommGetInfo->Header.ReturnStatus != 0) {
131 Print (L"SmiHandlerProfile: GetInfo - 0x%0x\n", CommGetInfo->Header.ReturnStatus);
132 return;
133 }
134
135 mSmiHandlerProfileDatabaseSize = (UINTN)CommGetInfo->DataSize;
136
137 //
138 // Get Data
139 //
140 mSmiHandlerProfileDatabase = AllocateZeroPool (mSmiHandlerProfileDatabaseSize);
141 if (mSmiHandlerProfileDatabase == NULL) {
142 Status = EFI_OUT_OF_RESOURCES;
143 Print (L"SmiHandlerProfile: AllocateZeroPool (0x%x) for dump buffer - %r\n", mSmiHandlerProfileDatabaseSize, Status);
144 return;
145 }
146
147 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
148 CopyMem (&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof (gSmiHandlerProfileGuid));
149 CommHeader->MessageLength = sizeof (SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET);
150
151 CommGetData = (SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
152 CommGetData->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET;
153 CommGetData->Header.DataLength = sizeof (*CommGetData);
154 CommGetData->Header.ReturnStatus = (UINT64)-1;
155
156 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
157 Buffer = (UINT8 *)CommHeader + CommSize;
158 Size -= CommSize;
159
160 CommGetData->DataBuffer = (PHYSICAL_ADDRESS)(UINTN)Buffer;
161 CommGetData->DataOffset = 0;
162 while (CommGetData->DataOffset < mSmiHandlerProfileDatabaseSize) {
163 Offset = (UINTN)CommGetData->DataOffset;
164 if (Size <= (mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset)) {
165 CommGetData->DataSize = (UINT64)Size;
166 } else {
167 CommGetData->DataSize = (UINT64)(mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset);
168 }
169
170 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
171 ASSERT_EFI_ERROR (Status);
172
173 if (CommGetData->Header.ReturnStatus != 0) {
174 FreePool (mSmiHandlerProfileDatabase);
175 mSmiHandlerProfileDatabase = NULL;
176 Print (L"SmiHandlerProfile: GetData - 0x%x\n", CommGetData->Header.ReturnStatus);
177 return;
178 }
179
180 CopyMem ((UINT8 *)mSmiHandlerProfileDatabase + Offset, (VOID *)(UINTN)CommGetData->DataBuffer, (UINTN)CommGetData->DataSize);
181 }
182
183 DEBUG ((DEBUG_INFO, "SmiHandlerProfileSize - 0x%x\n", mSmiHandlerProfileDatabaseSize));
184
185 return;
186 }
187
188 /**
189 Get the file name portion of the Pdb File Name.
190
191 The portion of the Pdb File Name between the last backslash and
192 either a following period or the end of the string is copied into
193 AsciiBuffer. The name is truncated, if necessary, to ensure that
194 AsciiBuffer is not overrun.
195
196 @param[in] PdbFileName Pdb file name.
197 @param[out] AsciiBuffer The resultant Ascii File Name.
198
199 **/
200 VOID
201 GetShortPdbFileName (
202 IN CHAR8 *PdbFileName,
203 OUT CHAR8 *AsciiBuffer
204 )
205 {
206 UINTN IndexPdb; // Current work location within a Pdb string.
207 UINTN IndexBuffer; // Current work location within a Buffer string.
208 UINTN StartIndex;
209 UINTN EndIndex;
210
211 ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1);
212
213 if (PdbFileName == NULL) {
214 AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1);
215 } else {
216 StartIndex = 0;
217 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) {
218 }
219
220 for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) {
221 if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) {
222 StartIndex = IndexPdb + 1;
223 }
224
225 if (PdbFileName[IndexPdb] == '.') {
226 EndIndex = IndexPdb;
227 }
228 }
229
230 IndexBuffer = 0;
231 for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) {
232 AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb];
233 IndexBuffer++;
234 if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) {
235 AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
236 break;
237 }
238 }
239 }
240 }
241
242 /**
243 Get a human readable name for an image.
244 The following methods will be tried orderly:
245 1. Image PDB
246 2. FFS UI section
247 3. Image GUID
248
249 @param[in] ImageStruct Point to the image structure.
250
251 @return The resulting Ascii name string is stored in the mNameString global array.
252
253 **/
254 CHAR8 *
255 GetDriverNameString (
256 IN SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct
257 )
258 {
259 EFI_STATUS Status;
260 CHAR16 *NameString;
261 UINTN StringSize;
262
263 if (ImageStruct == NULL) {
264 return "???";
265 }
266
267 //
268 // Method 1: Get the name string from image PDB
269 //
270 if (ImageStruct->PdbStringOffset != 0) {
271 GetShortPdbFileName ((CHAR8 *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset), mNameString);
272 return mNameString;
273 }
274
275 if (!IsZeroGuid (&ImageStruct->FileGuid)) {
276 //
277 // Try to get the image's FFS UI section by image GUID
278 //
279 NameString = NULL;
280 StringSize = 0;
281 Status = GetSectionFromAnyFv (
282 &ImageStruct->FileGuid,
283 EFI_SECTION_USER_INTERFACE,
284 0,
285 (VOID **)&NameString,
286 &StringSize
287 );
288 if (!EFI_ERROR (Status)) {
289 //
290 // Method 2: Get the name string from FFS UI section
291 //
292 if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) {
293 NameString[PROFILE_NAME_STRING_LENGTH] = 0;
294 }
295
296 UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString));
297 FreePool (NameString);
298 return mNameString;
299 }
300 }
301
302 //
303 // Method 3: Get the name string from image GUID
304 //
305 AsciiSPrint (mNameString, sizeof (mNameString), "%g", &ImageStruct->FileGuid);
306 return mNameString;
307 }
308
309 /**
310 Get image structure from reference index.
311
312 @param ImageRef the image reference index
313
314 @return image structure
315 **/
316 SMM_CORE_IMAGE_DATABASE_STRUCTURE *
317 GetImageFromRef (
318 IN UINTN ImageRef
319 )
320 {
321 SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct;
322
323 ImageStruct = (VOID *)mSmiHandlerProfileDatabase;
324 while ((UINTN)ImageStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {
325 if (ImageStruct->Header.Signature == SMM_CORE_IMAGE_DATABASE_SIGNATURE) {
326 if (ImageStruct->ImageRef == ImageRef) {
327 return ImageStruct;
328 }
329 }
330
331 ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length);
332 }
333
334 return NULL;
335 }
336
337 /**
338 Dump SMM loaded image information.
339 **/
340 VOID
341 DumpSmmLoadedImage (
342 VOID
343 )
344 {
345 SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct;
346 CHAR8 *PdbString;
347 CHAR8 *NameString;
348
349 ImageStruct = (VOID *)mSmiHandlerProfileDatabase;
350 while ((UINTN)ImageStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {
351 if (ImageStruct->Header.Signature == SMM_CORE_IMAGE_DATABASE_SIGNATURE) {
352 NameString = GetDriverNameString (ImageStruct);
353 Print (L" <Image Name=\"%a\"", NameString);
354 Print (L" Base=\"0x%lx\" Size=\"0x%lx\"", ImageStruct->ImageBase, ImageStruct->ImageSize);
355 if (ImageStruct->EntryPoint != 0) {
356 Print (L" EntryPoint=\"0x%lx\"", ImageStruct->EntryPoint);
357 }
358
359 Print (L" FvFile=\"%g\"", &ImageStruct->FileGuid);
360 Print (L" RefId=\"0x%x\"", ImageStruct->ImageRef);
361 Print (L">\n");
362 if (ImageStruct->PdbStringOffset != 0) {
363 PdbString = (CHAR8 *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset);
364 Print (L" <Pdb>%a</Pdb>\n", PdbString);
365 }
366
367 Print (L" </Image>\n");
368 }
369
370 ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length);
371 }
372
373 return;
374 }
375
376 CHAR8 *mSxTypeString[] = {
377 "SxS0",
378 "SxS1",
379 "SxS2",
380 "SxS3",
381 "SxS4",
382 "SxS5",
383 };
384
385 /**
386 Convert SxType to a string.
387
388 @param Type SxType
389
390 @return SxType string
391 **/
392 CHAR8 *
393 SxTypeToString (
394 IN EFI_SLEEP_TYPE Type
395 )
396 {
397 if ((Type >= 0) && (Type < ARRAY_SIZE (mSxTypeString))) {
398 return mSxTypeString[Type];
399 } else {
400 AsciiSPrint (mNameString, sizeof (mNameString), "0x%x", Type);
401 return mNameString;
402 }
403 }
404
405 CHAR8 *mSxPhaseString[] = {
406 "SxEntry",
407 "SxExit",
408 };
409
410 /**
411 Convert SxPhase to a string.
412
413 @param Phase SxPhase
414
415 @return SxPhase string
416 **/
417 CHAR8 *
418 SxPhaseToString (
419 IN EFI_SLEEP_PHASE Phase
420 )
421 {
422 if ((Phase >= 0) && (Phase < ARRAY_SIZE (mSxPhaseString))) {
423 return mSxPhaseString[Phase];
424 } else {
425 AsciiSPrint (mNameString, sizeof (mNameString), "0x%x", Phase);
426 return mNameString;
427 }
428 }
429
430 CHAR8 *mPowerButtonPhaseString[] = {
431 "PowerButtonEntry",
432 "PowerButtonExit",
433 };
434
435 /**
436 Convert PowerButtonPhase to a string.
437
438 @param Phase PowerButtonPhase
439
440 @return PowerButtonPhase string
441 **/
442 CHAR8 *
443 PowerButtonPhaseToString (
444 IN EFI_POWER_BUTTON_PHASE Phase
445 )
446 {
447 if ((Phase >= 0) && (Phase < ARRAY_SIZE (mPowerButtonPhaseString))) {
448 return mPowerButtonPhaseString[Phase];
449 } else {
450 AsciiSPrint (mNameString, sizeof (mNameString), "0x%x", Phase);
451 return mNameString;
452 }
453 }
454
455 CHAR8 *mStandbyButtonPhaseString[] = {
456 "StandbyButtonEntry",
457 "StandbyButtonExit",
458 };
459
460 /**
461 Convert StandbyButtonPhase to a string.
462
463 @param Phase StandbyButtonPhase
464
465 @return StandbyButtonPhase string
466 **/
467 CHAR8 *
468 StandbyButtonPhaseToString (
469 IN EFI_STANDBY_BUTTON_PHASE Phase
470 )
471 {
472 if ((Phase >= 0) && (Phase < ARRAY_SIZE (mStandbyButtonPhaseString))) {
473 return mStandbyButtonPhaseString[Phase];
474 } else {
475 AsciiSPrint (mNameString, sizeof (mNameString), "0x%x", Phase);
476 return mNameString;
477 }
478 }
479
480 CHAR8 *mIoTrapTypeString[] = {
481 "WriteTrap",
482 "ReadTrap",
483 "ReadWriteTrap",
484 };
485
486 /**
487 Convert IoTrapType to a string.
488
489 @param Type IoTrapType
490
491 @return IoTrapType string
492 **/
493 CHAR8 *
494 IoTrapTypeToString (
495 IN EFI_SMM_IO_TRAP_DISPATCH_TYPE Type
496 )
497 {
498 if ((Type >= 0) && (Type < ARRAY_SIZE (mIoTrapTypeString))) {
499 return mIoTrapTypeString[Type];
500 } else {
501 AsciiSPrint (mNameString, sizeof (mNameString), "0x%x", Type);
502 return mNameString;
503 }
504 }
505
506 CHAR8 *mUsbTypeString[] = {
507 "UsbLegacy",
508 "UsbWake",
509 };
510
511 /**
512 Convert UsbType to a string.
513
514 @param Type UsbType
515
516 @return UsbType string
517 **/
518 CHAR8 *
519 UsbTypeToString (
520 IN EFI_USB_SMI_TYPE Type
521 )
522 {
523 if ((Type >= 0) && (Type < ARRAY_SIZE (mUsbTypeString))) {
524 return mUsbTypeString[Type];
525 } else {
526 AsciiSPrint (mNameString, sizeof (mNameString), "0x%x", Type);
527 return mNameString;
528 }
529 }
530
531 /**
532 Dump SMI child context.
533
534 @param HandlerType the handler type
535 @param Context the handler context
536 @param ContextSize the handler context size
537 **/
538 VOID
539 DumpSmiChildContext (
540 IN EFI_GUID *HandlerType,
541 IN VOID *Context,
542 IN UINTN ContextSize
543 )
544 {
545 CHAR16 *Str;
546
547 if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) {
548 Print (L" SwSmi=\"0x%lx\"", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *)Context)->SwSmiInputValue);
549 } else if (CompareGuid (HandlerType, &gEfiSmmSxDispatch2ProtocolGuid)) {
550 Print (L" SxType=\"%a\"", SxTypeToString (((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Type));
551 Print (L" SxPhase=\"%a\"", SxPhaseToString (((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Phase));
552 } else if (CompareGuid (HandlerType, &gEfiSmmPowerButtonDispatch2ProtocolGuid)) {
553 Print (L" PowerButtonPhase=\"%a\"", PowerButtonPhaseToString (((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT *)Context)->Phase));
554 } else if (CompareGuid (HandlerType, &gEfiSmmStandbyButtonDispatch2ProtocolGuid)) {
555 Print (L" StandbyButtonPhase=\"%a\"", StandbyButtonPhaseToString (((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT *)Context)->Phase));
556 } else if (CompareGuid (HandlerType, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid)) {
557 Print (L" PeriodicTimerPeriod=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->Period);
558 Print (L" PeriodicTimerSmiTickInterval=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->SmiTickInterval);
559 } else if (CompareGuid (HandlerType, &gEfiSmmGpiDispatch2ProtocolGuid)) {
560 Print (L" GpiNum=\"0x%lx\"", ((EFI_SMM_GPI_REGISTER_CONTEXT *)Context)->GpiNum);
561 } else if (CompareGuid (HandlerType, &gEfiSmmIoTrapDispatch2ProtocolGuid)) {
562 Print (L" IoTrapAddress=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Address);
563 Print (L" IoTrapLength=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Length);
564 Print (L" IoTrapType=\"%a\"", IoTrapTypeToString (((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Type));
565 } else if (CompareGuid (HandlerType, &gEfiSmmUsbDispatch2ProtocolGuid)) {
566 Print (L" UsbType=\"0x%x\"", UsbTypeToString (((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context)->Type));
567 Str = ConvertDevicePathToText ((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE);
568 Print (L" UsbDevicePath=\"%s\"", Str);
569 if (Str != NULL) {
570 FreePool (Str);
571 }
572 } else {
573 Print (L" Context=\"");
574 InternalDumpData (Context, ContextSize);
575 Print (L"\"");
576 }
577 }
578
579 /**
580 Dump SMI handler in HandlerCategory.
581
582 @param HandlerCategory SMI handler category
583 **/
584 VOID
585 DumpSmiHandler (
586 IN UINT32 HandlerCategory
587 )
588 {
589 SMM_CORE_SMI_DATABASE_STRUCTURE *SmiStruct;
590 SMM_CORE_SMI_HANDLER_STRUCTURE *SmiHandlerStruct;
591 UINTN Index;
592 SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct;
593 CHAR8 *NameString;
594
595 SmiStruct = (VOID *)mSmiHandlerProfileDatabase;
596 while ((UINTN)SmiStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {
597 if ((SmiStruct->Header.Signature == SMM_CORE_SMI_DATABASE_SIGNATURE) && (SmiStruct->HandlerCategory == HandlerCategory)) {
598 SmiHandlerStruct = (VOID *)(SmiStruct + 1);
599 Print (L" <SmiEntry");
600 if (!IsZeroGuid (&SmiStruct->HandlerType)) {
601 Print (L" HandlerType=\"%g\"", &SmiStruct->HandlerType);
602 }
603
604 Print (L">\n");
605 for (Index = 0; Index < SmiStruct->HandlerCount; Index++) {
606 Print (L" <SmiHandler");
607 if (SmiHandlerStruct->ContextBufferSize != 0) {
608 DumpSmiChildContext (&SmiStruct->HandlerType, (UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandlerStruct->ContextBufferSize);
609 }
610
611 Print (L">\n");
612 ImageStruct = GetImageFromRef ((UINTN)SmiHandlerStruct->ImageRef);
613 NameString = GetDriverNameString (ImageStruct);
614 Print (L" <Module RefId=\"0x%x\" Name=\"%a\">\n", SmiHandlerStruct->ImageRef, NameString);
615 if ((ImageStruct != NULL) && (ImageStruct->PdbStringOffset != 0)) {
616 Print (L" <Pdb>%a</Pdb>\n", (UINT8 *)ImageStruct + ImageStruct->PdbStringOffset);
617 }
618
619 Print (L" </Module>\n");
620 Print (L" <Handler Address=\"0x%lx\">\n", SmiHandlerStruct->Handler);
621 if (ImageStruct != NULL) {
622 Print (L" <RVA>0x%x</RVA>\n", (UINTN)(SmiHandlerStruct->Handler - ImageStruct->ImageBase));
623 }
624
625 Print (L" </Handler>\n", SmiHandlerStruct->Handler);
626 Print (L" <Caller Address=\"0x%lx\">\n", SmiHandlerStruct->CallerAddr);
627 if (ImageStruct != NULL) {
628 Print (L" <RVA>0x%x</RVA>\n", (UINTN)(SmiHandlerStruct->CallerAddr - ImageStruct->ImageBase));
629 }
630
631 Print (L" </Caller>\n", SmiHandlerStruct->Handler);
632 SmiHandlerStruct = (VOID *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length);
633 Print (L" </SmiHandler>\n");
634 }
635
636 Print (L" </SmiEntry>\n");
637 }
638
639 SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length);
640 }
641
642 return;
643 }
644
645 /**
646 The Entry Point for SMI handler profile info application.
647
648 @param ImageHandle The firmware allocated handle for the EFI image.
649 @param SystemTable A pointer to the EFI System Table.
650
651 @retval EFI_SUCCESS The entry point is executed successfully.
652 @retval Other Some error occurred when executing this entry point.
653 **/
654 EFI_STATUS
655 EFIAPI
656 SmiHandlerProfileInfoEntrypoint (
657 IN EFI_HANDLE ImageHandle,
658 IN EFI_SYSTEM_TABLE *SystemTable
659 )
660 {
661 GetSmiHandlerProfileDatabase ();
662
663 if (mSmiHandlerProfileDatabase == NULL) {
664 return EFI_SUCCESS;
665 }
666
667 //
668 // Dump all image
669 //
670 Print (L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
671 Print (L"<SmiHandlerProfile>\n");
672 Print (L"<ImageDatabase>\n");
673 Print (L" <!-- SMM image loaded -->\n");
674 DumpSmmLoadedImage ();
675 Print (L"</ImageDatabase>\n\n");
676
677 //
678 // Dump SMI Handler
679 //
680 Print (L"<SmiHandlerDatabase>\n");
681 Print (L" <!-- SMI Handler registered -->\n\n");
682 Print (L" <SmiHandlerCategory Name=\"RootSmi\">\n");
683 Print (L" <!-- The root SMI Handler registered by SmmCore -->\n");
684 DumpSmiHandler (SmmCoreSmiHandlerCategoryRootHandler);
685 Print (L" </SmiHandlerCategory>\n\n");
686
687 Print (L" <SmiHandlerCategory Name=\"GuidSmi\">\n");
688 Print (L" <!-- The GUID SMI Handler registered by SmmCore -->\n");
689 DumpSmiHandler (SmmCoreSmiHandlerCategoryGuidHandler);
690 Print (L" </SmiHandlerCategory>\n\n");
691
692 Print (L" <SmiHandlerCategory Name=\"HardwareSmi\">\n");
693 Print (L" <!-- The hardware SMI Handler registered by SmmChildDispatcher -->\n");
694 DumpSmiHandler (SmmCoreSmiHandlerCategoryHardwareHandler);
695 Print (L" </SmiHandlerCategory>\n\n");
696
697 Print (L"</SmiHandlerDatabase>\n");
698 Print (L"</SmiHandlerProfile>\n");
699
700 if (mSmiHandlerProfileDatabase != NULL) {
701 FreePool (mSmiHandlerProfileDatabase);
702 }
703
704 return EFI_SUCCESS;
705 }