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