blob: 46204a4386b6bccb9e62d16b65309e11ab529f2e [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/** @file
2 Add custom commands for BeagleBoard development.
3
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include <PiDxe.h>
17#include <Library/ArmLib.h>
18#include <Library/CacheMaintenanceLib.h>
19#include <Library/EblCmdLib.h>
20#include <Library/BaseLib.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/**
39 Simple arm disassembler via a library
40
41 Argv[0] - symboltable
42 Argv[1] - Optional quoted format string
43 Argv[2] - Optional flag
44
45 @param Argc Number of command arguments in Argv
46 @param Argv Array of strings that represent the parsed command line.
47 Argv[0] is the command name
48
49 @return EFI_SUCCESS
50
51**/
52EFI_STATUS
53EblSymbolTable (
54 IN UINTN Argc,
55 IN CHAR8 **Argv
56 )
57{
58 EFI_STATUS Status;
59 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *DebugImageTableHeader = NULL;
60 EFI_DEBUG_IMAGE_INFO *DebugTable;
61 UINTN Entry;
62 CHAR8 *Format;
63 CHAR8 *Pdb;
64 UINT32 PeCoffSizeOfHeaders;
65 UINT32 ImageBase;
66 BOOLEAN Elf;
67
68 // Need to add lots of error checking on the passed in string
69 // Default string is for RealView debugger or gdb depending on toolchain used.
70 if (Argc > 1) {
71 Format = Argv[1];
72 } else {
73#if __GNUC__
74 // Assume gdb
75 Format = "add-symbol-file %a 0x%x";
76#else
77 // Default to RVCT
78 Format = "load /a /ni /np %a &0x%x";
79#endif
80 }
81 Elf = (Argc > 2) ? FALSE : TRUE;
82
83 Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugImageTableHeader);
84 if (EFI_ERROR (Status)) {
85 return Status;
86 }
87
88 DebugTable = DebugImageTableHeader->EfiDebugImageInfoTable;
89 if (DebugTable == NULL) {
90 return EFI_SUCCESS;
91 }
92
93 for (Entry = 0; Entry < DebugImageTableHeader->TableSize; Entry++, DebugTable++) {
94 if (DebugTable->NormalImage != NULL) {
95 if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
96 ImageBase = (UINT32)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;
97 PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageBase);
98 Pdb = PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);
99 if (Pdb != NULL) {
100 if (Elf) {
101 // ELF and Mach-O images don't include the header so the linked address does not include header
102 ImageBase += PeCoffSizeOfHeaders;
103 }
104 AsciiPrint (Format, Pdb, ImageBase);
105 AsciiPrint ("\n");
106 } else {
107 }
108 }
109 }
110 }
111
112 return EFI_SUCCESS;
113}
114
115
116/**
117 Simple arm disassembler via a library
118
119 Argv[0] - disasm
120 Argv[1] - Address to start disassembling from
121 ARgv[2] - Number of instructions to disassembly (optional)
122
123 @param Argc Number of command arguments in Argv
124 @param Argv Array of strings that represent the parsed command line.
125 Argv[0] is the command name
126
127 @return EFI_SUCCESS
128
129**/
130EFI_STATUS
131EblDisassembler (
132 IN UINTN Argc,
133 IN CHAR8 **Argv
134 )
135{
136 UINT8 *Ptr, *CurrentAddress;
137 UINT32 Address;
138 UINT32 Count;
139 CHAR8 Buffer[80];
140 UINT32 ItBlock;
141
142 if (Argc < 2) {
143 return EFI_INVALID_PARAMETER;
144 }
145
146 Address = AsciiStrHexToUintn (Argv[1]);
147 Count = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 20;
148
149 Ptr = (UINT8 *)(UINTN)Address;
150 ItBlock = 0;
151 do {
152 CurrentAddress = Ptr;
153 DisassembleInstruction (&Ptr, TRUE, TRUE, &ItBlock, Buffer, sizeof (Buffer));
154 AsciiPrint ("0x%08x: %a\n", CurrentAddress, Buffer);
155 } while (Count-- > 0);
156
157
158 return EFI_SUCCESS;
159}
160
161
162CHAR8 *
163ImageHandleToPdbFileName (
164 IN EFI_HANDLE Handle
165 )
166{
167 EFI_STATUS Status;
168 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
169 CHAR8 *Pdb;
170 CHAR8 *StripLeading;
171
172 Status = gBS->HandleProtocol (Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
173 if (EFI_ERROR (Status)) {
174 return "";
175 }
176
177 Pdb = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
178 StripLeading = AsciiStrStr (Pdb, "\\ARM\\");
179 if (StripLeading == NULL) {
180 StripLeading = AsciiStrStr (Pdb, "/ARM/");
181 if (StripLeading == NULL) {
182 return Pdb;
183 }
184 }
185 // Hopefully we hacked off the unneeded part
186 return (StripLeading + 5);
187}
188
189
190CHAR8 *mTokenList[] = {
191 "SEC",
192 "PEI",
193 "DXE",
194 "BDS",
195 NULL
196};
197
198/**
199 Simple arm disassembler via a library
200
201 Argv[0] - disasm
202 Argv[1] - Address to start disassembling from
203 ARgv[2] - Number of instructions to disassembly (optional)
204
205 @param Argc Number of command arguments in Argv
206 @param Argv Array of strings that represent the parsed command line.
207 Argv[0] is the command name
208
209 @return EFI_SUCCESS
210
211**/
212EFI_STATUS
213EblPerformance (
214 IN UINTN Argc,
215 IN CHAR8 **Argv
216 )
217{
218 UINTN Key;
219 CONST VOID *Handle;
220 CONST CHAR8 *Token, *Module;
221 UINT64 Start, Stop, TimeStamp;
222 UINT64 Delta, TicksPerSecond, Milliseconds, Microseconds;
223 UINTN Index;
224
225 TicksPerSecond = GetPerformanceCounterProperties (NULL, NULL);
226
227 Key = 0;
228 do {
229 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
230 if (Key != 0) {
231 if (AsciiStriCmp ("StartImage:", Token) == 0) {
232 if (Stop == 0) {
233 // The entry for EBL is still running so the stop time will be zero. Skip it
234 AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
235 } else {
236 Delta = Stop - Start;
237 Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);
238 AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
239 }
240 }
241 }
242 } while (Key != 0);
243
244 AsciiPrint ("\n");
245
246 TimeStamp = 0;
247 Key = 0;
248 do {
249 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
250 if (Key != 0) {
251 for (Index = 0; mTokenList[Index] != NULL; Index++) {
252 if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
253 Delta = Stop - Start;
254 TimeStamp += Delta;
255 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
256 AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);
257 break;
258 }
259 }
260 }
261 } while (Key != 0);
262
263 AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));
264
265 return EFI_SUCCESS;
266}
267
268
269GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =
270{
271 {
272 "disasm address [count]",
273 " disassemble count instructions",
274 NULL,
275 EblDisassembler
276 },
277 {
278 "performance",
279 " Display boot performance info",
280 NULL,
281 EblPerformance
282 },
283 {
284 "symboltable [\"format string\"] [PECOFF]",
285 " show symbol table commands for debugger",
286 NULL,
287 EblSymbolTable
288 }
289};
290
291
292VOID
293EblInitializeExternalCmd (
294 VOID
295 )
296{
297 EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
298 return;
299}