• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @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 **/
52 EFI_STATUS
EblSymbolTable(IN UINTN Argc,IN CHAR8 ** Argv)53 EblSymbolTable (
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 **/
130 EFI_STATUS
EblDisassembler(IN UINTN Argc,IN CHAR8 ** Argv)131 EblDisassembler (
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 
162 CHAR8 *
ImageHandleToPdbFileName(IN EFI_HANDLE Handle)163 ImageHandleToPdbFileName (
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 
190 CHAR8 *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 **/
212 EFI_STATUS
EblPerformance(IN UINTN Argc,IN CHAR8 ** Argv)213 EblPerformance (
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 
269 GLOBAL_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 
292 VOID
EblInitializeExternalCmd(VOID)293 EblInitializeExternalCmd (
294   VOID
295   )
296 {
297   EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
298   return;
299 }
300