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