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