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