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