]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
ArmPkg/PeCoffExtraActionLib: Enabled DS-5 command line when using ARM Toolchain v5
[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
227 TicksPerSecond = GetPerformanceCounterProperties (NULL, NULL);
228
229 Key = 0;
230 do {
231 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
232 if (Key != 0) {
233 if (AsciiStriCmp ("StartImage:", Token) == 0) {
234 if (Stop == 0) {
235 // The entry for EBL is still running so the stop time will be zero. Skip it
236 AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
237 } else {
238 Delta = Start - Stop;
239 Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);
240 AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
241 }
242 }
243 }
244 } while (Key != 0);
245
246 AsciiPrint ("\n");
247
248 TimeStamp = 0;
249 Key = 0;
250 do {
251 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
252 if (Key != 0) {
253 for (Index = 0; mTokenList[Index] != NULL; Index++) {
254 if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
255 Delta = Start - Stop;
256 TimeStamp += Delta;
257 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
258 AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);
259 break;
260 }
261 }
262 }
263 } while (Key != 0);
264
265 AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));
266
267 return EFI_SUCCESS;
268 }
269
270 #define EFI_MEMORY_PORT_IO 0x4000000000000000ULL
271
272 EFI_STATUS
273 EblDumpGcd (
274 IN UINTN Argc,
275 IN CHAR8 **Argv
276 )
277 {
278 EFI_STATUS Status;
279 UINTN NumberOfDescriptors;
280 UINTN i;
281 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
282 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;
283
284 Status = gDS->GetMemorySpaceMap(&NumberOfDescriptors,&MemorySpaceMap);
285 if (EFI_ERROR (Status)) {
286 return Status;
287 }
288 AsciiPrint (" Address Range Image Device Attributes\n");
289 AsciiPrint ("__________________________________________________________\n");
290 for (i=0; i < NumberOfDescriptors; i++) {
291 AsciiPrint ("MEM %016lx - %016lx",(UINT64)MemorySpaceMap[i].BaseAddress,MemorySpaceMap[i].BaseAddress+MemorySpaceMap[i].Length-1);
292 AsciiPrint (" %08x %08x",MemorySpaceMap[i].ImageHandle,MemorySpaceMap[i].DeviceHandle);
293
294 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RUNTIME)
295 AsciiPrint (" RUNTIME");
296 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_PORT_IO)
297 AsciiPrint (" PORT_IO");
298
299 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UC)
300 AsciiPrint (" MEM_UC");
301 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WC)
302 AsciiPrint (" MEM_WC");
303 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WT)
304 AsciiPrint (" MEM_WT");
305 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WB)
306 AsciiPrint (" MEM_WB");
307 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UCE)
308 AsciiPrint (" MEM_UCE");
309 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WP)
310 AsciiPrint (" MEM_WP");
311 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RP)
312 AsciiPrint (" MEM_RP");
313 if (MemorySpaceMap[i].Attributes & EFI_MEMORY_XP)
314 AsciiPrint (" MEM_XP");
315
316 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeNonExistent)
317 AsciiPrint (" TYPE_NONEXISTENT");
318 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeReserved)
319 AsciiPrint (" TYPE_RESERVED");
320 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeSystemMemory)
321 AsciiPrint (" TYPE_SYSMEM");
322 if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeMemoryMappedIo)
323 AsciiPrint (" TYPE_MEMMAP");
324
325 AsciiPrint ("\n");
326 }
327
328 Status = gDS->GetIoSpaceMap(&NumberOfDescriptors,&IoSpaceMap);
329 if (EFI_ERROR (Status)) {
330 return Status;
331 }
332 for (i=0; i < NumberOfDescriptors; i++) {
333 AsciiPrint ("IO %08lx - %08lx",IoSpaceMap[i].BaseAddress,IoSpaceMap[i].BaseAddress+IoSpaceMap[i].Length);
334 AsciiPrint ("\t%08x %08x",IoSpaceMap[i].ImageHandle,IoSpaceMap[i].DeviceHandle);
335
336 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeNonExistent)
337 AsciiPrint (" TYPE_NONEXISTENT");
338 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeReserved)
339 AsciiPrint (" TYPE_RESERVED");
340 if (IoSpaceMap[i].GcdIoType & EfiGcdIoTypeIo)
341 AsciiPrint (" TYPE_IO");
342
343 AsciiPrint ("\n");
344 }
345
346 return EFI_SUCCESS;
347 }
348
349 EFI_STATUS
350 EblDevicePaths (
351 IN UINTN Argc,
352 IN CHAR8 **Argv
353 )
354 {
355 EFI_STATUS Status;
356 UINTN HandleCount;
357 EFI_HANDLE *HandleBuffer;
358 UINTN Index;
359 CHAR16* String;
360 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
361 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
362
363 BdsConnectAllDrivers();
364
365 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
366 if (EFI_ERROR (Status)) {
367 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");
368 return EFI_SUCCESS;
369 }
370
371 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &HandleCount, &HandleBuffer);
372 if (EFI_ERROR (Status)) {
373 AsciiPrint ("No device path found\n");
374 return EFI_SUCCESS;
375 }
376
377 for (Index = 0; Index < HandleCount; Index++) {
378 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
379 String = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathProtocol,TRUE,TRUE);
380 Print (L"[0x%X] %s\n",(UINT32)HandleBuffer[Index], String);
381 }
382
383 return EFI_SUCCESS;
384 }
385
386 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =
387 {
388 {
389 "disasm address [count]",
390 " disassemble count instructions",
391 NULL,
392 EblDisassembler
393 },
394 {
395 "performance",
396 " Display boot performance info",
397 NULL,
398 EblPerformance
399 },
400 {
401 "symboltable [\"format string\"] [PECOFF]",
402 " show symbol table commands for debugger",
403 NULL,
404 EblSymbolTable
405 },
406 {
407 "dumpgcd",
408 " dump Global Coherency Domain",
409 NULL,
410 EblDumpGcd
411 },
412 {
413 "dumpmmu",
414 " dump MMU Table",
415 NULL,
416 EblDumpMmu
417 },
418 {
419 "devicepaths",
420 " list all the Device Paths",
421 NULL,
422 EblDevicePaths
423 }
424 };
425
426
427 VOID
428 EblInitializeExternalCmd (
429 VOID
430 )
431 {
432 EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
433 return;
434 }