3 * Copyright (c) 2011-2013, ARM Limited. All rights reserved.
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
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.
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>
34 #include <Guid/DebugImageInfoTable.h>
36 #include <Protocol/DebugSupport.h>
37 #include <Protocol/LoadedImage.h>
38 #include <Protocol/DevicePathToText.h>
53 Simple arm disassembler via a library
56 Argv[1] - Optional qoted format string
57 Argv[2] - Optional flag
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
73 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
*DebugImageTableHeader
= NULL
;
74 EFI_DEBUG_IMAGE_INFO
*DebugTable
;
78 UINT32 PeCoffSizeOfHeaders
;
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";
87 Format
= (Argc
> 1) ? Argv
[1] : "add-symbol-file %a 0x%x";
89 Elf
= (Argc
> 2) ? FALSE
: TRUE
;
91 Status
= EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid
, (VOID
**)&DebugImageTableHeader
);
92 if (EFI_ERROR (Status
)) {
96 DebugTable
= DebugImageTableHeader
->EfiDebugImageInfoTable
;
97 if (DebugTable
== NULL
) {
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
);
109 // ELF and Mach-O images don't include the header so the linked address does not include header
110 ImageBase
+= PeCoffSizeOfHeaders
;
112 AsciiPrint (Format
, Pdb
, ImageBase
);
125 Simple arm disassembler via a library
128 Argv[1] - Address to start disassembling from
129 ARgv[2] - Number of instructions to disassembly (optional)
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
144 UINT8
*Ptr
, *CurrentAddress
;
151 return EFI_INVALID_PARAMETER
;
154 Address
= AsciiStrHexToUintn (Argv
[1]);
155 Count
= (Argc
> 2) ? (UINT32
)AsciiStrHexToUintn (Argv
[2]) : 20;
157 Ptr
= (UINT8
*)(UINTN
)Address
;
160 CurrentAddress
= Ptr
;
161 DisassembleInstruction (&Ptr
, TRUE
, TRUE
, &ItBlock
, Buffer
, sizeof (Buffer
));
162 AsciiPrint ("0x%08x: %a\n", CurrentAddress
, Buffer
);
163 } while (Count
-- > 0);
171 ImageHandleToPdbFileName (
176 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
180 Status
= gBS
->HandleProtocol (Handle
, &gEfiLoadedImageProtocolGuid
, (VOID
**)&LoadedImage
);
181 if (EFI_ERROR (Status
)) {
185 Pdb
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
186 StripLeading
= AsciiStrStr (Pdb
, "\\ARM\\");
187 if (StripLeading
== NULL
) {
188 StripLeading
= AsciiStrStr (Pdb
, "/ARM/");
189 if (StripLeading
== NULL
) {
193 // Hopefully we hacked off the unneeded part
194 return (StripLeading
+ 5);
198 STATIC CHAR8
*mTokenList
[] = {
207 Simple arm disassembler via a library
210 Argv[1] - Address to start disassembling from
211 ARgv[2] - Number of instructions to disassembly (optional)
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
228 CONST CHAR8
*Token
, *Module
;
229 UINT64 Start
, Stop
, TimeStamp
;
230 UINT64 Delta
, TicksPerSecond
, Milliseconds
, Microseconds
;
234 TicksPerSecond
= GetPerformanceCounterProperties (&Start
, &Stop
);
243 Key
= GetPerformanceMeasurement (Key
, (CONST VOID
**)&Handle
, &Token
, &Module
, &Start
, &Stop
);
245 if (AsciiStriCmp ("StartImage:", Token
) == 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
));
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
));
263 Key
= GetPerformanceMeasurement (Key
, (CONST VOID
**)&Handle
, &Token
, &Module
, &Start
, &Stop
);
265 for (Index
= 0; mTokenList
[Index
] != NULL
; Index
++) {
266 if (AsciiStriCmp (mTokenList
[Index
], Token
) == 0) {
267 Delta
= CountUp
?(Stop
- Start
):(Start
- Stop
);
269 Milliseconds
= DivU64x64Remainder (MultU64x32 (Delta
, 1000), TicksPerSecond
, NULL
);
270 AsciiPrint ("%6a %6ld ms\n", Token
, Milliseconds
);
277 AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp
, 1000), TicksPerSecond
, NULL
));
282 #define EFI_MEMORY_PORT_IO 0x4000000000000000ULL
291 UINTN NumberOfDescriptors
;
293 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
294 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
296 Status
= gDS
->GetMemorySpaceMap(&NumberOfDescriptors
,&MemorySpaceMap
);
297 if (EFI_ERROR (Status
)) {
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
);
306 if (MemorySpaceMap
[i
].Attributes
& EFI_MEMORY_RUNTIME
)
307 AsciiPrint (" RUNTIME");
308 if (MemorySpaceMap
[i
].Attributes
& EFI_MEMORY_PORT_IO
)
309 AsciiPrint (" PORT_IO");
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");
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");
340 FreePool (MemorySpaceMap
);
342 Status
= gDS
->GetIoSpaceMap(&NumberOfDescriptors
,&IoSpaceMap
);
343 if (EFI_ERROR (Status
)) {
346 for (i
=0; i
< NumberOfDescriptors
; i
++) {
347 AsciiPrint ("IO %08lx - %08lx",IoSpaceMap
[i
].BaseAddress
,IoSpaceMap
[i
].BaseAddress
+IoSpaceMap
[i
].Length
);
348 AsciiPrint ("\t%08x %08x",IoSpaceMap
[i
].ImageHandle
,IoSpaceMap
[i
].DeviceHandle
);
350 if (IoSpaceMap
[i
].GcdIoType
& EfiGcdMemoryTypeNonExistent
)
351 AsciiPrint (" TYPE_NONEXISTENT");
352 if (IoSpaceMap
[i
].GcdIoType
& EfiGcdMemoryTypeReserved
)
353 AsciiPrint (" TYPE_RESERVED");
354 if (IoSpaceMap
[i
].GcdIoType
& EfiGcdIoTypeIo
)
355 AsciiPrint (" TYPE_IO");
360 FreePool (IoSpaceMap
);
373 EFI_HANDLE
*HandleBuffer
;
376 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
377 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
379 BdsConnectAllDrivers();
381 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
382 if (EFI_ERROR (Status
)) {
383 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");
387 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
388 if (EFI_ERROR (Status
)) {
389 AsciiPrint ("No device path found\n");
393 for (Index
= 0; Index
< HandleCount
; Index
++) {
394 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
395 String
= DevicePathToTextProtocol
->ConvertDevicePathToText(DevicePathProtocol
,TRUE
,TRUE
);
396 Print (L
"[0x%X] %s\n",(UINTN
)HandleBuffer
[Index
], String
);
402 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mLibCmdTemplate
[] =
405 "disasm address [count]",
406 " disassemble count instructions",
412 " Display boot performance info",
417 "symboltable [\"format string\"] [PECOFF]",
418 " show symbol table commands for debugger",
424 " dump Global Coherency Domain",
436 " list all the Device Paths",
442 " dump the current fdt or the one defined in the arguments",
450 EblInitializeExternalCmd (
454 EblAddCommands (mLibCmdTemplate
, sizeof (mLibCmdTemplate
)/sizeof (EBL_COMMAND_TABLE
));