Home | History | Annotate | Download | only in EblCmdLib
      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
     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
    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 *
    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
    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
    293 EblInitializeExternalCmd (
    294   VOID
    295   )
    296 {
    297   EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
    298   return;
    299 }
    300