]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
ArmPlatformPkg: Fixed unsigned type to be architecture independent
[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 Status = gDS->GetIoSpaceMap(&NumberOfDescriptors,&IoSpaceMap);
341 if (EFI_ERROR (Status)) {
342 return Status;
343 }
344 for (i=0; i < NumberOfDescriptors; i++) {
345 AsciiPrint ("IO %08lx - %08lx",IoSpaceMap[i].BaseAddress,IoSpaceMap[i].BaseAddress+IoSpaceMap[i].Length);
346 AsciiPrint ("\t%08x %08x",IoSpaceMap[i].ImageHandle,IoSpaceMap[i].DeviceHandle);
347
348 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeNonExistent)
349 AsciiPrint (" TYPE_NONEXISTENT");
350 if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeReserved)
351 AsciiPrint (" TYPE_RESERVED");
352 if (IoSpaceMap[i].GcdIoType & EfiGcdIoTypeIo)
353 AsciiPrint (" TYPE_IO");
354
355 AsciiPrint ("\n");
356 }
357
358 return EFI_SUCCESS;
359 }
360
361 EFI_STATUS
362 EblDevicePaths (
363 IN UINTN Argc,
364 IN CHAR8 **Argv
365 )
366 {
367 EFI_STATUS Status;
368 UINTN HandleCount;
369 EFI_HANDLE *HandleBuffer;
370 UINTN Index;
371 CHAR16* String;
372 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
373 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
374
375 BdsConnectAllDrivers();
376
377 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
378 if (EFI_ERROR (Status)) {
379 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");
380 return EFI_SUCCESS;
381 }
382
383 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &HandleCount, &HandleBuffer);
384 if (EFI_ERROR (Status)) {
385 AsciiPrint ("No device path found\n");
386 return EFI_SUCCESS;
387 }
388
389 for (Index = 0; Index < HandleCount; Index++) {
390 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
391 String = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathProtocol,TRUE,TRUE);
392 Print (L"[0x%X] %s\n",(UINTN)HandleBuffer[Index], String);
393 }
394
395 return EFI_SUCCESS;
396 }
397
398 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =
399 {
400 {
401 "disasm address [count]",
402 " disassemble count instructions",
403 NULL,
404 EblDisassembler
405 },
406 {
407 "performance",
408 " Display boot performance info",
409 NULL,
410 EblPerformance
411 },
412 {
413 "symboltable [\"format string\"] [PECOFF]",
414 " show symbol table commands for debugger",
415 NULL,
416 EblSymbolTable
417 },
418 {
419 "dumpgcd",
420 " dump Global Coherency Domain",
421 NULL,
422 EblDumpGcd
423 },
424 {
425 "dumpmmu",
426 " dump MMU Table",
427 NULL,
428 EblDumpMmu
429 },
430 {
431 "devicepaths",
432 " list all the Device Paths",
433 NULL,
434 EblDevicePaths
435 },
436 {
437 "dumpfdt",
438 " dump the current fdt or the one defined in the arguments",
439 NULL,
440 EblDumpFdt
441 }
442 };
443
444
445 VOID
446 EblInitializeExternalCmd (
447 VOID
448 )
449 {
450 EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
451 return;
452 }