#include <Library/EfiFileLib.h>\r
#include <Library/ArmDisassemblerLib.h>\r
#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/TimerLib.h>\r
\r
#include <Guid/DebugImageInfoTable.h>\r
+\r
#include <Protocol/DebugSupport.h>\r
#include <Protocol/LoadedImage.h>\r
\r
}\r
\r
\r
+CHAR8 *\r
+ImageHandleToPdbFileName (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+\r
+ Status = gBS->HandleProtocol (Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);\r
+ if (EFI_ERROR (Status)) {\r
+ return "";\r
+ }\r
+\r
+ return PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);\r
+}\r
+\r
+CHAR8 *mTokenList[] = {\r
+ "SEC",\r
+ "PEI",\r
+ "DXE",\r
+ "BDS",\r
+ NULL\r
+};\r
+\r
+/**\r
+ Simple arm disassembler via a library\r
+\r
+ Argv[0] - disasm\r
+ Argv[1] - Address to start disassembling from\r
+ ARgv[2] - Number of instructions to disassembly (optional)\r
+\r
+ @param Argc Number of command arguments in Argv\r
+ @param Argv Array of strings that represent the parsed command line. \r
+ Argv[0] is the comamnd name\r
+\r
+ @return EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+EblPerformance (\r
+ IN UINTN Argc,\r
+ IN CHAR8 **Argv\r
+ )\r
+{\r
+ UINTN Key;\r
+ CONST VOID *Handle;\r
+ CONST CHAR8 *Token, *Module;\r
+ UINT64 Start, Stop, TimeStamp;\r
+ UINT64 Delta, TicksPerSecond, Milliseconds, Microseconds;\r
+ UINTN Index;\r
+\r
+ TicksPerSecond = GetPerformanceCounterProperties (NULL, NULL);\r
+\r
+ Key = 0;\r
+ do {\r
+ Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
+ if (Key != 0) {\r
+ if (AsciiStriCmp ("StartImage:", Token) == 0) {\r
+ if (Stop == 0) {\r
+ // The entry for EBL is still running so the stop time will be zero. Skip it\r
+ AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));\r
+ } else {\r
+ Delta = Stop - Start;\r
+ Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);\r
+ AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));\r
+ }\r
+ }\r
+ }\r
+ } while (Key != 0);\r
+\r
+ AsciiPrint ("\n");\r
+\r
+ TimeStamp = 0;\r
+ Key = 0;\r
+ do {\r
+ Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
+ if (Key != 0) {\r
+ for (Index = 0; mTokenList[Index] != NULL; Index++) {\r
+ if (AsciiStriCmp (mTokenList[Index], Token) == 0) {\r
+ Delta = Stop - Start;\r
+ TimeStamp += Delta;\r
+ Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);\r
+ AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);\r
+ break;\r
+ }\r
+ } \r
+ }\r
+ } while (Key != 0);\r
+\r
+ AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =\r
{\r
{\r
NULL,\r
EblDisassembler\r
},\r
+ {\r
+ "performance",\r
+ " Display boot performance info",\r
+ NULL,\r
+ EblPerformance\r
+ },\r
{\r
"symboltable [\"format string\"] [PECOFF]",\r
" show symbol table commands for debugger",\r