]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
ArmPlatformPkg/EblCmdLib: Fixed 'performance' command
[mirror_edk2.git] / ArmPlatformPkg / Library / EblCmdLib / EblCmdLib.c
CommitLineData
1d5d0ae9 1/** @file\r
2*\r
96a8bc11 3* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
1d5d0ae9 4* \r
5* This program and the accompanying materials \r
6* are licensed and made available under the terms and conditions of the BSD License \r
7* which accompanies this distribution. The full text of the license may be found at \r
8* http://opensource.org/licenses/bsd-license.php \r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12*\r
13**/\r
14\r
15#include <PiDxe.h>\r
16#include <Library/ArmLib.h>\r
17#include <Library/CacheMaintenanceLib.h>\r
18#include <Library/EblCmdLib.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/DxeServicesTableLib.h>\r
21#include <Library/DebugLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/UefiRuntimeServicesTableLib.h>\r
24#include <Library/MemoryAllocationLib.h>\r
25#include <Library/UefiLib.h>\r
26#include <Library/PcdLib.h>\r
27#include <Library/EfiFileLib.h>\r
28#include <Library/ArmDisassemblerLib.h>\r
29#include <Library/PeCoffGetEntryPointLib.h>\r
30#include <Library/PerformanceLib.h>\r
31#include <Library/TimerLib.h>\r
6a15908f 32#include <Library/BdsLib.h>\r
1d5d0ae9 33\r
34#include <Guid/DebugImageInfoTable.h>\r
35\r
36#include <Protocol/DebugSupport.h>\r
37#include <Protocol/LoadedImage.h>\r
6a15908f 38#include <Protocol/DevicePathToText.h>\r
1d5d0ae9 39\r
40EFI_STATUS\r
41EblDumpMmu (\r
42 IN UINTN Argc,\r
43 IN CHAR8 **Argv\r
44 );\r
45\r
46/**\r
47 Simple arm disassembler via a library\r
48\r
49 Argv[0] - symboltable\r
50 Argv[1] - Optional qoted format string \r
51 Argv[2] - Optional flag\r
52\r
53 @param Argc Number of command arguments in Argv\r
54 @param Argv Array of strings that represent the parsed command line. \r
96a8bc11 55 Argv[0] is the command name\r
1d5d0ae9 56\r
57 @return EFI_SUCCESS\r
58\r
59**/\r
60EFI_STATUS\r
61EblSymbolTable (\r
62 IN UINTN Argc,\r
63 IN CHAR8 **Argv\r
64 )\r
65{\r
66 EFI_STATUS Status;\r
67 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *DebugImageTableHeader = NULL;\r
68 EFI_DEBUG_IMAGE_INFO *DebugTable;\r
69 UINTN Entry;\r
70 CHAR8 *Format;\r
71 CHAR8 *Pdb;\r
72 UINT32 PeCoffSizeOfHeaders;\r
73 UINT32 ImageBase;\r
74 BOOLEAN Elf;\r
75 \r
76 // Need to add lots of error checking on the passed in string\r
77 // Default string is for RealView debugger\r
96a8bc11 78#if (__ARMCC_VERSION < 500000)\r
1d5d0ae9 79 Format = (Argc > 1) ? Argv[1] : "load /a /ni /np %a &0x%x";\r
96a8bc11 80#else\r
81 Format = (Argc > 1) ? Argv[1] : "add-symbol-file %a 0x%x";\r
82#endif\r
1d5d0ae9 83 Elf = (Argc > 2) ? FALSE : TRUE;\r
84 \r
85 Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugImageTableHeader);\r
86 if (EFI_ERROR (Status)) {\r
87 return Status;\r
88 }\r
89 \r
90 DebugTable = DebugImageTableHeader->EfiDebugImageInfoTable;\r
91 if (DebugTable == NULL) {\r
92 return EFI_SUCCESS;\r
93 }\r
94\r
95 for (Entry = 0; Entry < DebugImageTableHeader->TableSize; Entry++, DebugTable++) {\r
96 if (DebugTable->NormalImage != NULL) {\r
97 if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {\r
98 ImageBase = (UINT32)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;\r
99 PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageBase);\r
100 Pdb = PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);\r
101 if (Pdb != NULL) {\r
102 if (Elf) {\r
103 // ELF and Mach-O images don't include the header so the linked address does not include header\r
104 ImageBase += PeCoffSizeOfHeaders;\r
105 } \r
106 AsciiPrint (Format, Pdb, ImageBase);\r
107 AsciiPrint ("\n");\r
108 } else {\r
109 }\r
110 }\r
111 } \r
112 }\r
113\r
114 return EFI_SUCCESS;\r
115}\r
116\r
117\r
118/**\r
119 Simple arm disassembler via a library\r
120\r
121 Argv[0] - disasm\r
122 Argv[1] - Address to start disassembling from\r
123 ARgv[2] - Number of instructions to disassembly (optional)\r
124\r
125 @param Argc Number of command arguments in Argv\r
126 @param Argv Array of strings that represent the parsed command line. \r
886f97c8 127 Argv[0] is the command name\r
1d5d0ae9 128\r
129 @return EFI_SUCCESS\r
130\r
131**/\r
132EFI_STATUS\r
133EblDisassembler (\r
134 IN UINTN Argc,\r
135 IN CHAR8 **Argv\r
136 )\r
137{\r
138 UINT8 *Ptr, *CurrentAddress;\r
139 UINT32 Address;\r
140 UINT32 Count;\r
141 CHAR8 Buffer[80];\r
142 UINT32 ItBlock;\r
143 \r
144 if (Argc < 2) {\r
145 return EFI_INVALID_PARAMETER;\r
146 }\r
147 \r
148 Address = AsciiStrHexToUintn (Argv[1]);\r
149 Count = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 20;\r
150\r
151 Ptr = (UINT8 *)(UINTN)Address; \r
152 ItBlock = 0;\r
153 do {\r
154 CurrentAddress = Ptr;\r
155 DisassembleInstruction (&Ptr, TRUE, TRUE, &ItBlock, Buffer, sizeof (Buffer));\r
156 AsciiPrint ("0x%08x: %a\n", CurrentAddress, Buffer);\r
157 } while (Count-- > 0);\r
158 \r
159\r
160 return EFI_SUCCESS;\r
161}\r
162\r
163\r
164CHAR8 *\r
165ImageHandleToPdbFileName (\r
166 IN EFI_HANDLE Handle\r
167 )\r
168{\r
169 EFI_STATUS Status;\r
170 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
171 CHAR8 *Pdb;\r
172 CHAR8 *StripLeading;\r
173\r
174 Status = gBS->HandleProtocol (Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);\r
175 if (EFI_ERROR (Status)) {\r
176 return "";\r
177 }\r
178\r
179 Pdb = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);\r
180 StripLeading = AsciiStrStr (Pdb, "\\ARM\\");\r
181 if (StripLeading == NULL) {\r
182 StripLeading = AsciiStrStr (Pdb, "/ARM/");\r
183 if (StripLeading == NULL) {\r
184 return Pdb;\r
185 }\r
186 }\r
187 // Hopefully we hacked off the unneeded part\r
188 return (StripLeading + 5);\r
189}\r
190\r
191\r
6a15908f 192STATIC CHAR8 *mTokenList[] = {\r
1d5d0ae9 193 /*"SEC",*/\r
194 "PEI",\r
195 "DXE",\r
196 /*"BDS",*/\r
197 NULL\r
198};\r
199\r
200/**\r
201 Simple arm disassembler via a library\r
202\r
203 Argv[0] - disasm\r
204 Argv[1] - Address to start disassembling from\r
205 ARgv[2] - Number of instructions to disassembly (optional)\r
206\r
207 @param Argc Number of command arguments in Argv\r
208 @param Argv Array of strings that represent the parsed command line. \r
886f97c8 209 Argv[0] is the command name\r
1d5d0ae9 210\r
211 @return EFI_SUCCESS\r
212\r
213**/\r
214EFI_STATUS\r
215EblPerformance (\r
216 IN UINTN Argc,\r
217 IN CHAR8 **Argv\r
218 )\r
219{\r
220 UINTN Key;\r
221 CONST VOID *Handle;\r
222 CONST CHAR8 *Token, *Module;\r
223 UINT64 Start, Stop, TimeStamp;\r
224 UINT64 Delta, TicksPerSecond, Milliseconds, Microseconds;\r
225 UINTN Index;\r
68978a52 226 BOOLEAN CountUp;\r
1d5d0ae9 227\r
68978a52 228 TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop);\r
229 if (Start < Stop) {\r
230 CountUp = TRUE;\r
231 } else {\r
232 CountUp = FALSE;\r
233 }\r
1d5d0ae9 234\r
235 Key = 0;\r
236 do {\r
237 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
238 if (Key != 0) {\r
239 if (AsciiStriCmp ("StartImage:", Token) == 0) {\r
240 if (Stop == 0) {\r
241 // The entry for EBL is still running so the stop time will be zero. Skip it\r
242 AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));\r
243 } else {\r
68978a52 244 Delta = CountUp?(Stop - Start):(Start - Stop);\r
1d5d0ae9 245 Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);\r
246 AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));\r
247 }\r
248 }\r
249 }\r
250 } while (Key != 0);\r
251\r
252 AsciiPrint ("\n");\r
253\r
254 TimeStamp = 0;\r
255 Key = 0;\r
256 do {\r
257 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
258 if (Key != 0) {\r
259 for (Index = 0; mTokenList[Index] != NULL; Index++) {\r
260 if (AsciiStriCmp (mTokenList[Index], Token) == 0) {\r
68978a52 261 Delta = CountUp?(Stop - Start):(Start - Stop);\r
1d5d0ae9 262 TimeStamp += Delta;\r
263 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);\r
264 AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);\r
265 break;\r
266 }\r
267 } \r
268 }\r
269 } while (Key != 0);\r
270\r
271 AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));\r
272\r
273 return EFI_SUCCESS;\r
274}\r
275\r
276#define EFI_MEMORY_PORT_IO 0x4000000000000000ULL\r
277\r
278EFI_STATUS\r
279EblDumpGcd (\r
280 IN UINTN Argc,\r
281 IN CHAR8 **Argv\r
282 )\r
283{\r
6a15908f 284 EFI_STATUS Status;\r
285 UINTN NumberOfDescriptors;\r
286 UINTN i;\r
287 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
288 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;\r
1d5d0ae9 289\r
6a15908f 290 Status = gDS->GetMemorySpaceMap(&NumberOfDescriptors,&MemorySpaceMap);\r
291 if (EFI_ERROR (Status)) {\r
292 return Status;\r
293 }\r
294 AsciiPrint (" Address Range Image Device Attributes\n");\r
295 AsciiPrint ("__________________________________________________________\n");\r
296 for (i=0; i < NumberOfDescriptors; i++) {\r
297 AsciiPrint ("MEM %016lx - %016lx",(UINT64)MemorySpaceMap[i].BaseAddress,MemorySpaceMap[i].BaseAddress+MemorySpaceMap[i].Length-1);\r
298 AsciiPrint (" %08x %08x",MemorySpaceMap[i].ImageHandle,MemorySpaceMap[i].DeviceHandle);\r
299\r
300 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RUNTIME)\r
301 AsciiPrint (" RUNTIME");\r
302 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_PORT_IO)\r
303 AsciiPrint (" PORT_IO");\r
304\r
305 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UC)\r
306 AsciiPrint (" MEM_UC");\r
307 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WC)\r
308 AsciiPrint (" MEM_WC");\r
309 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WT)\r
310 AsciiPrint (" MEM_WT");\r
311 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WB)\r
312 AsciiPrint (" MEM_WB");\r
313 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UCE)\r
314 AsciiPrint (" MEM_UCE");\r
315 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WP)\r
316 AsciiPrint (" MEM_WP");\r
317 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RP)\r
318 AsciiPrint (" MEM_RP");\r
319 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_XP)\r
320 AsciiPrint (" MEM_XP");\r
321\r
322 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeNonExistent)\r
323 AsciiPrint (" TYPE_NONEXISTENT");\r
324 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeReserved)\r
325 AsciiPrint (" TYPE_RESERVED");\r
326 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeSystemMemory)\r
327 AsciiPrint (" TYPE_SYSMEM");\r
328 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeMemoryMappedIo)\r
329 AsciiPrint (" TYPE_MEMMAP");\r
330\r
331 AsciiPrint ("\n");\r
332 }\r
333\r
334 Status = gDS->GetIoSpaceMap(&NumberOfDescriptors,&IoSpaceMap);\r
335 if (EFI_ERROR (Status)) {\r
336 return Status;\r
337 }\r
338 for (i=0; i < NumberOfDescriptors; i++) {\r
339 AsciiPrint ("IO %08lx - %08lx",IoSpaceMap[i].BaseAddress,IoSpaceMap[i].BaseAddress+IoSpaceMap[i].Length);\r
340 AsciiPrint ("\t%08x %08x",IoSpaceMap[i].ImageHandle,IoSpaceMap[i].DeviceHandle);\r
341\r
342 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeNonExistent)\r
343 AsciiPrint (" TYPE_NONEXISTENT");\r
344 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeReserved)\r
345 AsciiPrint (" TYPE_RESERVED");\r
346 if (IoSpaceMap[i].GcdIoType & EfiGcdIoTypeIo)\r
347 AsciiPrint (" TYPE_IO");\r
348\r
349 AsciiPrint ("\n");\r
350 }\r
1d5d0ae9 351\r
6a15908f 352 return EFI_SUCCESS;\r
353}\r
354\r
355EFI_STATUS\r
356EblDevicePaths (\r
357 IN UINTN Argc,\r
358 IN CHAR8 **Argv\r
359 )\r
360{\r
361 EFI_STATUS Status;\r
362 UINTN HandleCount;\r
363 EFI_HANDLE *HandleBuffer;\r
364 UINTN Index;\r
365 CHAR16* String;\r
366 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
367 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
368\r
369 BdsConnectAllDrivers();\r
370\r
371 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
372 if (EFI_ERROR (Status)) {\r
373 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");\r
374 return EFI_SUCCESS;\r
375 }\r
376\r
377 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
378 if (EFI_ERROR (Status)) {\r
379 AsciiPrint ("No device path found\n");\r
1d5d0ae9 380 return EFI_SUCCESS;\r
6a15908f 381 }\r
382\r
383 for (Index = 0; Index < HandleCount; Index++) {\r
384 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
385 String = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathProtocol,TRUE,TRUE);\r
386 Print (L"[0x%X] %s\n",(UINT32)HandleBuffer[Index], String);\r
387 }\r
388\r
389 return EFI_SUCCESS;\r
1d5d0ae9 390}\r
391\r
392GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =\r
393{\r
394 {\r
395 "disasm address [count]",\r
396 " disassemble count instructions",\r
397 NULL,\r
398 EblDisassembler\r
399 },\r
400 {\r
401 "performance",\r
402 " Display boot performance info",\r
403 NULL,\r
404 EblPerformance\r
405 },\r
406 {\r
407 "symboltable [\"format string\"] [PECOFF]",\r
408 " show symbol table commands for debugger",\r
409 NULL,\r
410 EblSymbolTable\r
411 },\r
412 {\r
413 "dumpgcd",\r
414 " dump Global Coherency Domain",\r
415 NULL,\r
416 EblDumpGcd\r
417 },\r
418 {\r
419 "dumpmmu",\r
420 " dump MMU Table",\r
421 NULL,\r
422 EblDumpMmu\r
6a15908f 423 },\r
424 {\r
425 "devicepaths",\r
426 " list all the Device Paths",\r
427 NULL,\r
428 EblDevicePaths\r
1d5d0ae9 429 }\r
430};\r
431\r
432\r
433VOID\r
434EblInitializeExternalCmd (\r
435 VOID\r
436 )\r
437{\r
438 EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));\r
439 return;\r
440}\r