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