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