MdeModulePkg SmiHandlerProfile: Use fixed data type in data structure
[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->PdbStringOffset != 0) {
270 GetShortPdbFileName ((CHAR8 *) ((UINTN) ImageStruct + ImageStruct->PdbStringOffset), 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%lx\" Size=\"0x%lx\"", ImageStruct->ImageBase, ImageStruct->ImageSize);
352 if (ImageStruct->EntryPoint != 0) {
353 Print(L" EntryPoint=\"0x%lx\"", ImageStruct->EntryPoint);
354 }
355 Print(L" FvFile=\"%g\"", &ImageStruct->FileGuid);
356 Print(L" RefId=\"0x%x\"", ImageStruct->ImageRef);
357 Print(L">\n");
358 if (ImageStruct->PdbStringOffset != 0) {
359 PdbString = (CHAR8 *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset);
360 Print(L" <Pdb>%a</Pdb>\n", PdbString);
361 }
362 Print(L" </Image>\n");
363 }
364
365 ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length);
366 }
367
368 return;
369 }
370
371 CHAR8 *mSxTypeString[] = {
372 "SxS0",
373 "SxS1",
374 "SxS2",
375 "SxS3",
376 "SxS4",
377 "SxS5",
378 };
379
380 /**
381 Convert SxType to a string.
382
383 @param Type SxType
384
385 @return SxType string
386 **/
387 CHAR8 *
388 SxTypeToString (
389 IN EFI_SLEEP_TYPE Type
390 )
391 {
392 if (Type >= 0 && Type <= ARRAY_SIZE(mSxTypeString)) {
393 return mSxTypeString[Type];
394 } else {
395 AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type);
396 return mNameString;
397 }
398 }
399
400 CHAR8 *mSxPhaseString[] = {
401 "SxEntry",
402 "SxExit",
403 };
404
405 /**
406 Convert SxPhase to a string.
407
408 @param Phase SxPhase
409
410 @return SxPhase string
411 **/
412 CHAR8 *
413 SxPhaseToString (
414 IN EFI_SLEEP_PHASE Phase
415 )
416 {
417 if (Phase >= 0 && Phase <= ARRAY_SIZE(mSxPhaseString)) {
418 return mSxPhaseString[Phase];
419 } else {
420 AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase);
421 return mNameString;
422 }
423 }
424
425 CHAR8 *mPowerButtonPhaseString[] = {
426 "PowerButtonEntry",
427 "PowerButtonExit",
428 };
429
430 /**
431 Convert PowerButtonPhase to a string.
432
433 @param Phase PowerButtonPhase
434
435 @return PowerButtonPhase string
436 **/
437 CHAR8 *
438 PowerButtonPhaseToString (
439 IN EFI_POWER_BUTTON_PHASE Phase
440 )
441 {
442 if (Phase >= 0 && Phase <= ARRAY_SIZE(mPowerButtonPhaseString)) {
443 return mPowerButtonPhaseString[Phase];
444 } else {
445 AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase);
446 return mNameString;
447 }
448 }
449
450 CHAR8 *mStandbyButtonPhaseString[] = {
451 "StandbyButtonEntry",
452 "StandbyButtonExit",
453 };
454
455 /**
456 Convert StandbyButtonPhase to a string.
457
458 @param Phase StandbyButtonPhase
459
460 @return StandbyButtonPhase string
461 **/
462 CHAR8 *
463 StandbyButtonPhaseToString (
464 IN EFI_STANDBY_BUTTON_PHASE Phase
465 )
466 {
467 if (Phase >= 0 && Phase <= ARRAY_SIZE(mStandbyButtonPhaseString)) {
468 return mStandbyButtonPhaseString[Phase];
469 } else {
470 AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase);
471 return mNameString;
472 }
473 }
474
475 CHAR8 *mIoTrapTypeString[] = {
476 "WriteTrap",
477 "ReadTrap",
478 "ReadWriteTrap",
479 };
480
481 /**
482 Convert IoTrapType to a string.
483
484 @param Type IoTrapType
485
486 @return IoTrapType string
487 **/
488 CHAR8 *
489 IoTrapTypeToString (
490 IN EFI_SMM_IO_TRAP_DISPATCH_TYPE Type
491 )
492 {
493 if (Type >= 0 && Type <= ARRAY_SIZE(mIoTrapTypeString)) {
494 return mIoTrapTypeString[Type];
495 } else {
496 AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type);
497 return mNameString;
498 }
499 }
500
501 CHAR8 *mUsbTypeString[] = {
502 "UsbLegacy",
503 "UsbWake",
504 };
505
506 /**
507 Convert UsbType to a string.
508
509 @param Type UsbType
510
511 @return UsbType string
512 **/
513 CHAR8 *
514 UsbTypeToString (
515 IN EFI_USB_SMI_TYPE Type
516 )
517 {
518 if (Type >= 0 && Type <= ARRAY_SIZE(mUsbTypeString)) {
519 return mUsbTypeString[Type];
520 } else {
521 AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type);
522 return mNameString;
523 }
524 }
525
526 /**
527 Dump SMI child context.
528
529 @param HandlerType the handler type
530 @param Context the handler context
531 @param ContextSize the handler context size
532 **/
533 VOID
534 DumpSmiChildContext (
535 IN EFI_GUID *HandlerType,
536 IN VOID *Context,
537 IN UINTN ContextSize
538 )
539 {
540 CHAR16 *Str;
541
542 if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) {
543 Print(L" SwSmi=\"0x%lx\"", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *)Context)->SwSmiInputValue);
544 } else if (CompareGuid (HandlerType, &gEfiSmmSxDispatch2ProtocolGuid)) {
545 Print(L" SxType=\"%a\"", SxTypeToString(((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Type));
546 Print(L" SxPhase=\"%a\"", SxPhaseToString(((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Phase));
547 } else if (CompareGuid (HandlerType, &gEfiSmmPowerButtonDispatch2ProtocolGuid)) {
548 Print(L" PowerButtonPhase=\"%a\"", PowerButtonPhaseToString(((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT *)Context)->Phase));
549 } else if (CompareGuid (HandlerType, &gEfiSmmStandbyButtonDispatch2ProtocolGuid)) {
550 Print(L" StandbyButtonPhase=\"%a\"", StandbyButtonPhaseToString(((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT *)Context)->Phase));
551 } else if (CompareGuid (HandlerType, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid)) {
552 Print(L" PeriodicTimerPeriod=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->Period);
553 Print(L" PeriodicTimerSmiTickInterval=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->SmiTickInterval);
554 } else if (CompareGuid (HandlerType, &gEfiSmmGpiDispatch2ProtocolGuid)) {
555 Print(L" GpiNum=\"0x%lx\"", ((EFI_SMM_GPI_REGISTER_CONTEXT *)Context)->GpiNum);
556 } else if (CompareGuid (HandlerType, &gEfiSmmIoTrapDispatch2ProtocolGuid)) {
557 Print(L" IoTrapAddress=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Address);
558 Print(L" IoTrapLength=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Length);
559 Print(L" IoTrapType=\"%a\"", IoTrapTypeToString(((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Type));
560 } else if (CompareGuid (HandlerType, &gEfiSmmUsbDispatch2ProtocolGuid)) {
561 Print(L" UsbType=\"0x%x\"", UsbTypeToString(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context)->Type));
562 Str = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE);
563 Print(L" UsbDevicePath=\"%s\"", Str);
564 if (Str != NULL) {
565 FreePool (Str);
566 }
567 } else {
568 Print(L" Context=\"");
569 InternalDumpData (Context, ContextSize);
570 Print(L"\"");
571 }
572 }
573
574 /**
575 Dump SMI handler in HandlerCategory.
576
577 @param HandlerCategory SMI handler category
578 **/
579 VOID
580 DumpSmiHandler(
581 IN UINT32 HandlerCategory
582 )
583 {
584 SMM_CORE_SMI_DATABASE_STRUCTURE *SmiStruct;
585 SMM_CORE_SMI_HANDLER_STRUCTURE *SmiHandlerStruct;
586 UINTN Index;
587 SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct;
588 CHAR8 *NameString;
589
590 SmiStruct = (VOID *)mSmiHandlerProfileDatabase;
591 while ((UINTN)SmiStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {
592 if ((SmiStruct->Header.Signature == SMM_CORE_SMI_DATABASE_SIGNATURE) && (SmiStruct->HandlerCategory == HandlerCategory)) {
593 SmiHandlerStruct = (VOID *)(SmiStruct + 1);
594 Print(L" <SmiEntry");
595 if (!IsZeroGuid (&SmiStruct->HandlerType)) {
596 Print(L" HandlerType=\"%g\"", &SmiStruct->HandlerType);
597 }
598 Print(L">\n");
599 for (Index = 0; Index < SmiStruct->HandlerCount; Index++) {
600 Print(L" <SmiHandler");
601 if (SmiHandlerStruct->ContextBufferSize != 0) {
602 DumpSmiChildContext (&SmiStruct->HandlerType, (UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandlerStruct->ContextBufferSize);
603 }
604 Print(L">\n");
605 ImageStruct = GetImageFromRef((UINTN)SmiHandlerStruct->ImageRef);
606 NameString = GetDriverNameString (ImageStruct);
607 Print(L" <Module RefId=\"0x%x\" Name=\"%a\">\n", SmiHandlerStruct->ImageRef, NameString);
608 if ((ImageStruct != NULL) && (ImageStruct->PdbStringOffset != 0)) {
609 Print(L" <Pdb>%a</Pdb>\n", (UINT8 *)ImageStruct + ImageStruct->PdbStringOffset);
610 }
611 Print(L" </Module>\n");
612 Print(L" <Handler Address=\"0x%lx\">\n", SmiHandlerStruct->Handler);
613 if (ImageStruct != NULL) {
614 Print(L" <RVA>0x%x</RVA>\n", (UINTN) (SmiHandlerStruct->Handler - ImageStruct->ImageBase));
615 }
616 Print(L" </Handler>\n", SmiHandlerStruct->Handler);
617 Print(L" <Caller Address=\"0x%lx\">\n", SmiHandlerStruct->CallerAddr);
618 if (ImageStruct != NULL) {
619 Print(L" <RVA>0x%x</RVA>\n", (UINTN) (SmiHandlerStruct->CallerAddr - ImageStruct->ImageBase));
620 }
621 Print(L" </Caller>\n", SmiHandlerStruct->Handler);
622 SmiHandlerStruct = (VOID *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length);
623 Print(L" </SmiHandler>\n");
624 }
625 Print(L" </SmiEntry>\n");
626 }
627 SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length);
628 }
629
630 return;
631 }
632
633 /**
634 The Entry Point for SMI handler profile info application.
635
636 @param ImageHandle The firmware allocated handle for the EFI image.
637 @param SystemTable A pointer to the EFI System Table.
638
639 @retval EFI_SUCCESS The entry point is executed successfully.
640 @retval Other Some error occurred when executing this entry point.
641 **/
642 EFI_STATUS
643 EFIAPI
644 SmiHandlerProfileInfoEntrypoint (
645 IN EFI_HANDLE ImageHandle,
646 IN EFI_SYSTEM_TABLE *SystemTable
647 )
648 {
649 GetSmiHandlerProfileDatabase();
650
651 if (mSmiHandlerProfileDatabase == NULL) {
652 return EFI_SUCCESS;
653 }
654
655 //
656 // Dump all image
657 //
658 Print(L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
659 Print(L"<SmiHandlerProfile>\n");
660 Print(L"<ImageDatabase>\n");
661 Print(L" <!-- SMM image loaded -->\n");
662 DumpSmmLoadedImage();
663 Print(L"</ImageDatabase>\n\n");
664
665 //
666 // Dump SMI Handler
667 //
668 Print(L"<SmiHandlerDatabase>\n");
669 Print(L" <!-- SMI Handler registered -->\n\n");
670 Print(L" <SmiHandlerCategory Name=\"RootSmi\">\n");
671 Print(L" <!-- The root SMI Handler registered by SmmCore -->\n");
672 DumpSmiHandler(SmmCoreSmiHandlerCategoryRootHandler);
673 Print(L" </SmiHandlerCategory>\n\n");
674
675 Print(L" <SmiHandlerCategory Name=\"GuidSmi\">\n");
676 Print(L" <!-- The GUID SMI Handler registered by SmmCore -->\n");
677 DumpSmiHandler(SmmCoreSmiHandlerCategoryGuidHandler);
678 Print(L" </SmiHandlerCategory>\n\n");
679
680 Print(L" <SmiHandlerCategory Name=\"HardwareSmi\">\n");
681 Print(L" <!-- The hardware SMI Handler registered by SmmChildDispatcher -->\n");
682 DumpSmiHandler(SmmCoreSmiHandlerCategoryHardwareHandler);
683 Print(L" </SmiHandlerCategory>\n\n");
684
685 Print(L"</SmiHandlerDatabase>\n");
686 Print(L"</SmiHandlerProfile>\n");
687
688 if (mSmiHandlerProfileDatabase != NULL) {
689 FreePool(mSmiHandlerProfileDatabase);
690 }
691
692 return EFI_SUCCESS;
693 }