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