]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
ArmPlatformPkg/EblCmdLib: Add the 'devicepaths' EBL command
[mirror_edk2.git] / ArmPlatformPkg / Library / EblCmdLib / EblCmdLib.c
CommitLineData
1d5d0ae9 1/** @file\r
2*\r
3* Copyright (c) 2011, ARM Limited. All rights reserved.\r
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
55 Argv[0] is the comamnd name\r
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
78 Format = (Argc > 1) ? Argv[1] : "load /a /ni /np %a &0x%x";\r
79 Elf = (Argc > 2) ? FALSE : TRUE;\r
80 \r
81 Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugImageTableHeader);\r
82 if (EFI_ERROR (Status)) {\r
83 return Status;\r
84 }\r
85 \r
86 DebugTable = DebugImageTableHeader->EfiDebugImageInfoTable;\r
87 if (DebugTable == NULL) {\r
88 return EFI_SUCCESS;\r
89 }\r
90\r
91 for (Entry = 0; Entry < DebugImageTableHeader->TableSize; Entry++, DebugTable++) {\r
92 if (DebugTable->NormalImage != NULL) {\r
93 if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {\r
94 ImageBase = (UINT32)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;\r
95 PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageBase);\r
96 Pdb = PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);\r
97 if (Pdb != NULL) {\r
98 if (Elf) {\r
99 // ELF and Mach-O images don't include the header so the linked address does not include header\r
100 ImageBase += PeCoffSizeOfHeaders;\r
101 } \r
102 AsciiPrint (Format, Pdb, ImageBase);\r
103 AsciiPrint ("\n");\r
104 } else {\r
105 }\r
106 }\r
107 } \r
108 }\r
109\r
110 return EFI_SUCCESS;\r
111}\r
112\r
113\r
114/**\r
115 Simple arm disassembler via a library\r
116\r
117 Argv[0] - disasm\r
118 Argv[1] - Address to start disassembling from\r
119 ARgv[2] - Number of instructions to disassembly (optional)\r
120\r
121 @param Argc Number of command arguments in Argv\r
122 @param Argv Array of strings that represent the parsed command line. \r
123 Argv[0] is the comamnd name\r
124\r
125 @return EFI_SUCCESS\r
126\r
127**/\r
128EFI_STATUS\r
129EblDisassembler (\r
130 IN UINTN Argc,\r
131 IN CHAR8 **Argv\r
132 )\r
133{\r
134 UINT8 *Ptr, *CurrentAddress;\r
135 UINT32 Address;\r
136 UINT32 Count;\r
137 CHAR8 Buffer[80];\r
138 UINT32 ItBlock;\r
139 \r
140 if (Argc < 2) {\r
141 return EFI_INVALID_PARAMETER;\r
142 }\r
143 \r
144 Address = AsciiStrHexToUintn (Argv[1]);\r
145 Count = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 20;\r
146\r
147 Ptr = (UINT8 *)(UINTN)Address; \r
148 ItBlock = 0;\r
149 do {\r
150 CurrentAddress = Ptr;\r
151 DisassembleInstruction (&Ptr, TRUE, TRUE, &ItBlock, Buffer, sizeof (Buffer));\r
152 AsciiPrint ("0x%08x: %a\n", CurrentAddress, Buffer);\r
153 } while (Count-- > 0);\r
154 \r
155\r
156 return EFI_SUCCESS;\r
157}\r
158\r
159\r
160CHAR8 *\r
161ImageHandleToPdbFileName (\r
162 IN EFI_HANDLE Handle\r
163 )\r
164{\r
165 EFI_STATUS Status;\r
166 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
167 CHAR8 *Pdb;\r
168 CHAR8 *StripLeading;\r
169\r
170 Status = gBS->HandleProtocol (Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);\r
171 if (EFI_ERROR (Status)) {\r
172 return "";\r
173 }\r
174\r
175 Pdb = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);\r
176 StripLeading = AsciiStrStr (Pdb, "\\ARM\\");\r
177 if (StripLeading == NULL) {\r
178 StripLeading = AsciiStrStr (Pdb, "/ARM/");\r
179 if (StripLeading == NULL) {\r
180 return Pdb;\r
181 }\r
182 }\r
183 // Hopefully we hacked off the unneeded part\r
184 return (StripLeading + 5);\r
185}\r
186\r
187\r
6a15908f 188STATIC CHAR8 *mTokenList[] = {\r
1d5d0ae9 189 /*"SEC",*/\r
190 "PEI",\r
191 "DXE",\r
192 /*"BDS",*/\r
193 NULL\r
194};\r
195\r
196/**\r
197 Simple arm disassembler via a library\r
198\r
199 Argv[0] - disasm\r
200 Argv[1] - Address to start disassembling from\r
201 ARgv[2] - Number of instructions to disassembly (optional)\r
202\r
203 @param Argc Number of command arguments in Argv\r
204 @param Argv Array of strings that represent the parsed command line. \r
205 Argv[0] is the comamnd name\r
206\r
207 @return EFI_SUCCESS\r
208\r
209**/\r
210EFI_STATUS\r
211EblPerformance (\r
212 IN UINTN Argc,\r
213 IN CHAR8 **Argv\r
214 )\r
215{\r
216 UINTN Key;\r
217 CONST VOID *Handle;\r
218 CONST CHAR8 *Token, *Module;\r
219 UINT64 Start, Stop, TimeStamp;\r
220 UINT64 Delta, TicksPerSecond, Milliseconds, Microseconds;\r
221 UINTN Index;\r
222\r
223 TicksPerSecond = GetPerformanceCounterProperties (NULL, NULL);\r
224\r
225 Key = 0;\r
226 do {\r
227 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
228 if (Key != 0) {\r
229 if (AsciiStriCmp ("StartImage:", Token) == 0) {\r
230 if (Stop == 0) {\r
231 // The entry for EBL is still running so the stop time will be zero. Skip it\r
232 AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));\r
233 } else {\r
234 Delta = Start - Stop;\r
235 Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);\r
236 AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));\r
237 }\r
238 }\r
239 }\r
240 } while (Key != 0);\r
241\r
242 AsciiPrint ("\n");\r
243\r
244 TimeStamp = 0;\r
245 Key = 0;\r
246 do {\r
247 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
248 if (Key != 0) {\r
249 for (Index = 0; mTokenList[Index] != NULL; Index++) {\r
250 if (AsciiStriCmp (mTokenList[Index], Token) == 0) {\r
251 Delta = Start - Stop;\r
252 TimeStamp += Delta;\r
253 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);\r
254 AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);\r
255 break;\r
256 }\r
257 } \r
258 }\r
259 } while (Key != 0);\r
260\r
261 AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));\r
262\r
263 return EFI_SUCCESS;\r
264}\r
265\r
266#define EFI_MEMORY_PORT_IO 0x4000000000000000ULL\r
267\r
268EFI_STATUS\r
269EblDumpGcd (\r
270 IN UINTN Argc,\r
271 IN CHAR8 **Argv\r
272 )\r
273{\r
6a15908f 274 EFI_STATUS Status;\r
275 UINTN NumberOfDescriptors;\r
276 UINTN i;\r
277 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
278 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;\r
1d5d0ae9 279\r
6a15908f 280 Status = gDS->GetMemorySpaceMap(&NumberOfDescriptors,&MemorySpaceMap);\r
281 if (EFI_ERROR (Status)) {\r
282 return Status;\r
283 }\r
284 AsciiPrint (" Address Range Image Device Attributes\n");\r
285 AsciiPrint ("__________________________________________________________\n");\r
286 for (i=0; i < NumberOfDescriptors; i++) {\r
287 AsciiPrint ("MEM %016lx - %016lx",(UINT64)MemorySpaceMap[i].BaseAddress,MemorySpaceMap[i].BaseAddress+MemorySpaceMap[i].Length-1);\r
288 AsciiPrint (" %08x %08x",MemorySpaceMap[i].ImageHandle,MemorySpaceMap[i].DeviceHandle);\r
289\r
290 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RUNTIME)\r
291 AsciiPrint (" RUNTIME");\r
292 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_PORT_IO)\r
293 AsciiPrint (" PORT_IO");\r
294\r
295 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UC)\r
296 AsciiPrint (" MEM_UC");\r
297 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WC)\r
298 AsciiPrint (" MEM_WC");\r
299 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WT)\r
300 AsciiPrint (" MEM_WT");\r
301 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WB)\r
302 AsciiPrint (" MEM_WB");\r
303 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UCE)\r
304 AsciiPrint (" MEM_UCE");\r
305 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WP)\r
306 AsciiPrint (" MEM_WP");\r
307 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RP)\r
308 AsciiPrint (" MEM_RP");\r
309 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_XP)\r
310 AsciiPrint (" MEM_XP");\r
311\r
312 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeNonExistent)\r
313 AsciiPrint (" TYPE_NONEXISTENT");\r
314 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeReserved)\r
315 AsciiPrint (" TYPE_RESERVED");\r
316 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeSystemMemory)\r
317 AsciiPrint (" TYPE_SYSMEM");\r
318 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeMemoryMappedIo)\r
319 AsciiPrint (" TYPE_MEMMAP");\r
320\r
321 AsciiPrint ("\n");\r
322 }\r
323\r
324 Status = gDS->GetIoSpaceMap(&NumberOfDescriptors,&IoSpaceMap);\r
325 if (EFI_ERROR (Status)) {\r
326 return Status;\r
327 }\r
328 for (i=0; i < NumberOfDescriptors; i++) {\r
329 AsciiPrint ("IO %08lx - %08lx",IoSpaceMap[i].BaseAddress,IoSpaceMap[i].BaseAddress+IoSpaceMap[i].Length);\r
330 AsciiPrint ("\t%08x %08x",IoSpaceMap[i].ImageHandle,IoSpaceMap[i].DeviceHandle);\r
331\r
332 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeNonExistent)\r
333 AsciiPrint (" TYPE_NONEXISTENT");\r
334 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeReserved)\r
335 AsciiPrint (" TYPE_RESERVED");\r
336 if (IoSpaceMap[i].GcdIoType & EfiGcdIoTypeIo)\r
337 AsciiPrint (" TYPE_IO");\r
338\r
339 AsciiPrint ("\n");\r
340 }\r
1d5d0ae9 341\r
6a15908f 342 return EFI_SUCCESS;\r
343}\r
344\r
345EFI_STATUS\r
346EblDevicePaths (\r
347 IN UINTN Argc,\r
348 IN CHAR8 **Argv\r
349 )\r
350{\r
351 EFI_STATUS Status;\r
352 UINTN HandleCount;\r
353 EFI_HANDLE *HandleBuffer;\r
354 UINTN Index;\r
355 CHAR16* String;\r
356 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
357 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
358\r
359 BdsConnectAllDrivers();\r
360\r
361 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
362 if (EFI_ERROR (Status)) {\r
363 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");\r
364 return EFI_SUCCESS;\r
365 }\r
366\r
367 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
368 if (EFI_ERROR (Status)) {\r
369 AsciiPrint ("No device path found\n");\r
1d5d0ae9 370 return EFI_SUCCESS;\r
6a15908f 371 }\r
372\r
373 for (Index = 0; Index < HandleCount; Index++) {\r
374 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
375 String = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathProtocol,TRUE,TRUE);\r
376 Print (L"[0x%X] %s\n",(UINT32)HandleBuffer[Index], String);\r
377 }\r
378\r
379 return EFI_SUCCESS;\r
1d5d0ae9 380}\r
381\r
382GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =\r
383{\r
384 {\r
385 "disasm address [count]",\r
386 " disassemble count instructions",\r
387 NULL,\r
388 EblDisassembler\r
389 },\r
390 {\r
391 "performance",\r
392 " Display boot performance info",\r
393 NULL,\r
394 EblPerformance\r
395 },\r
396 {\r
397 "symboltable [\"format string\"] [PECOFF]",\r
398 " show symbol table commands for debugger",\r
399 NULL,\r
400 EblSymbolTable\r
401 },\r
402 {\r
403 "dumpgcd",\r
404 " dump Global Coherency Domain",\r
405 NULL,\r
406 EblDumpGcd\r
407 },\r
408 {\r
409 "dumpmmu",\r
410 " dump MMU Table",\r
411 NULL,\r
412 EblDumpMmu\r
6a15908f 413 },\r
414 {\r
415 "devicepaths",\r
416 " list all the Device Paths",\r
417 NULL,\r
418 EblDevicePaths\r
1d5d0ae9 419 }\r
420};\r
421\r
422\r
423VOID\r
424EblInitializeExternalCmd (\r
425 VOID\r
426 )\r
427{\r
428 EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));\r
429 return;\r
430}\r