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