summaryrefslogtreecommitdiff
path: root/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c')
-rw-r--r--ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c386
1 files changed, 386 insertions, 0 deletions
diff --git a/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c b/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
new file mode 100644
index 0000000000..9289444756
--- /dev/null
+++ b/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
@@ -0,0 +1,386 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiDxe.h>
+#include <Library/ArmLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/EblCmdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/EfiFileLib.h>
+#include <Library/ArmDisassemblerLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/TimerLib.h>
+
+#include <Guid/DebugImageInfoTable.h>
+
+#include <Protocol/DebugSupport.h>
+#include <Protocol/LoadedImage.h>
+
+EFI_STATUS
+EblDumpMmu (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ );
+
+/**
+ Simple arm disassembler via a library
+
+ Argv[0] - symboltable
+ Argv[1] - Optional qoted format string
+ Argv[2] - Optional flag
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblSymbolTable (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *DebugImageTableHeader = NULL;
+ EFI_DEBUG_IMAGE_INFO *DebugTable;
+ UINTN Entry;
+ CHAR8 *Format;
+ CHAR8 *Pdb;
+ UINT32 PeCoffSizeOfHeaders;
+ UINT32 ImageBase;
+ BOOLEAN Elf;
+
+ // Need to add lots of error checking on the passed in string
+ // Default string is for RealView debugger
+ Format = (Argc > 1) ? Argv[1] : "load /a /ni /np %a &0x%x";
+ Elf = (Argc > 2) ? FALSE : TRUE;
+
+ Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugImageTableHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DebugTable = DebugImageTableHeader->EfiDebugImageInfoTable;
+ if (DebugTable == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ for (Entry = 0; Entry < DebugImageTableHeader->TableSize; Entry++, DebugTable++) {
+ if (DebugTable->NormalImage != NULL) {
+ if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
+ ImageBase = (UINT32)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;
+ PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageBase);
+ Pdb = PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);
+ if (Pdb != NULL) {
+ if (Elf) {
+ // ELF and Mach-O images don't include the header so the linked address does not include header
+ ImageBase += PeCoffSizeOfHeaders;
+ }
+ AsciiPrint (Format, Pdb, ImageBase);
+ AsciiPrint ("\n");
+ } else {
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Simple arm disassembler via a library
+
+ Argv[0] - disasm
+ Argv[1] - Address to start disassembling from
+ ARgv[2] - Number of instructions to disassembly (optional)
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblDisassembler (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINT8 *Ptr, *CurrentAddress;
+ UINT32 Address;
+ UINT32 Count;
+ CHAR8 Buffer[80];
+ UINT32 ItBlock;
+
+ if (Argc < 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = AsciiStrHexToUintn (Argv[1]);
+ Count = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 20;
+
+ Ptr = (UINT8 *)(UINTN)Address;
+ ItBlock = 0;
+ do {
+ CurrentAddress = Ptr;
+ DisassembleInstruction (&Ptr, TRUE, TRUE, &ItBlock, Buffer, sizeof (Buffer));
+ AsciiPrint ("0x%08x: %a\n", CurrentAddress, Buffer);
+ } while (Count-- > 0);
+
+
+ return EFI_SUCCESS;
+}
+
+
+CHAR8 *
+ImageHandleToPdbFileName (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ CHAR8 *Pdb;
+ CHAR8 *StripLeading;
+
+ Status = gBS->HandleProtocol (Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
+ if (EFI_ERROR (Status)) {
+ return "";
+ }
+
+ Pdb = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
+ StripLeading = AsciiStrStr (Pdb, "\\ARM\\");
+ if (StripLeading == NULL) {
+ StripLeading = AsciiStrStr (Pdb, "/ARM/");
+ if (StripLeading == NULL) {
+ return Pdb;
+ }
+ }
+ // Hopefully we hacked off the unneeded part
+ return (StripLeading + 5);
+}
+
+
+CHAR8 *mTokenList[] = {
+ /*"SEC",*/
+ "PEI",
+ "DXE",
+ /*"BDS",*/
+ NULL
+};
+
+/**
+ Simple arm disassembler via a library
+
+ Argv[0] - disasm
+ Argv[1] - Address to start disassembling from
+ ARgv[2] - Number of instructions to disassembly (optional)
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblPerformance (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Key;
+ CONST VOID *Handle;
+ CONST CHAR8 *Token, *Module;
+ UINT64 Start, Stop, TimeStamp;
+ UINT64 Delta, TicksPerSecond, Milliseconds, Microseconds;
+ UINTN Index;
+
+ TicksPerSecond = GetPerformanceCounterProperties (NULL, NULL);
+
+ Key = 0;
+ do {
+ Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
+ if (Key != 0) {
+ if (AsciiStriCmp ("StartImage:", Token) == 0) {
+ if (Stop == 0) {
+ // The entry for EBL is still running so the stop time will be zero. Skip it
+ AsciiPrint (" running %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
+ } else {
+ Delta = Start - Stop;
+ Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);
+ AsciiPrint ("%10ld us %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
+ }
+ }
+ }
+ } while (Key != 0);
+
+ AsciiPrint ("\n");
+
+ TimeStamp = 0;
+ Key = 0;
+ do {
+ Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
+ if (Key != 0) {
+ for (Index = 0; mTokenList[Index] != NULL; Index++) {
+ if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
+ Delta = Start - Stop;
+ TimeStamp += Delta;
+ Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
+ AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);
+ break;
+ }
+ }
+ }
+ } while (Key != 0);
+
+ AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));
+
+ return EFI_SUCCESS;
+}
+
+#define EFI_MEMORY_PORT_IO 0x4000000000000000ULL
+
+EFI_STATUS
+EblDumpGcd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfDescriptors;
+ UINTN i;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;
+
+ Status = gDS->GetMemorySpaceMap(&NumberOfDescriptors,&MemorySpaceMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ AsciiPrint (" Address Range Image Device Attributes\n");
+ AsciiPrint ("__________________________________________________________\n");
+ for (i=0; i < NumberOfDescriptors; i++) {
+ //AsciiPrint ("%016lx - %016lx",MemorySpaceMap[i].BaseAddress,MemorySpaceMap[i].BaseAddress+MemorySpaceMap[i].Length);
+ AsciiPrint ("MEM %08lx - %08lx",(UINT64)MemorySpaceMap[i].BaseAddress,MemorySpaceMap[i].BaseAddress+MemorySpaceMap[i].Length-1);
+ AsciiPrint (" %08x %08x",MemorySpaceMap[i].ImageHandle,MemorySpaceMap[i].DeviceHandle);
+
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RUNTIME)
+ AsciiPrint (" RUNTIME");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_PORT_IO)
+ AsciiPrint (" PORT_IO");
+
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UC)
+ AsciiPrint (" MEM_UC");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WC)
+ AsciiPrint (" MEM_WC");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WT)
+ AsciiPrint (" MEM_WT");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WB)
+ AsciiPrint (" MEM_WB");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_UCE)
+ AsciiPrint (" MEM_UCE");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_WP)
+ AsciiPrint (" MEM_WP");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_RP)
+ AsciiPrint (" MEM_RP");
+ if (MemorySpaceMap[i].Attributes & EFI_MEMORY_XP)
+ AsciiPrint (" MEM_XP");
+
+ if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeNonExistent)
+ AsciiPrint (" TYPE_NONEXISTENT");
+ if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeReserved)
+ AsciiPrint (" TYPE_RESERVED");
+ if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeSystemMemory)
+ AsciiPrint (" TYPE_SYSMEM");
+ if (MemorySpaceMap[i].GcdMemoryType & EfiGcdMemoryTypeMemoryMappedIo)
+ AsciiPrint (" TYPE_MEMMAP");
+
+ AsciiPrint ("\n");
+ }
+
+ Status = gDS->GetIoSpaceMap(&NumberOfDescriptors,&IoSpaceMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ for (i=0; i < NumberOfDescriptors; i++) {
+ AsciiPrint ("IO %08lx - %08lx",IoSpaceMap[i].BaseAddress,IoSpaceMap[i].BaseAddress+IoSpaceMap[i].Length);
+ AsciiPrint ("\t%08x %08x",IoSpaceMap[i].ImageHandle,IoSpaceMap[i].DeviceHandle);
+
+ if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeNonExistent)
+ AsciiPrint (" TYPE_NONEXISTENT");
+ if (IoSpaceMap[i].GcdIoType & EfiGcdMemoryTypeReserved)
+ AsciiPrint (" TYPE_RESERVED");
+ if (IoSpaceMap[i].GcdIoType & EfiGcdIoTypeIo)
+ AsciiPrint (" TYPE_IO");
+
+ AsciiPrint ("\n");
+ }
+
+ return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =
+{
+ {
+ "disasm address [count]",
+ " disassemble count instructions",
+ NULL,
+ EblDisassembler
+ },
+ {
+ "performance",
+ " Display boot performance info",
+ NULL,
+ EblPerformance
+ },
+ {
+ "symboltable [\"format string\"] [PECOFF]",
+ " show symbol table commands for debugger",
+ NULL,
+ EblSymbolTable
+ },
+ {
+ "dumpgcd",
+ " dump Global Coherency Domain",
+ NULL,
+ EblDumpGcd
+ },
+ {
+ "dumpmmu",
+ " dump MMU Table",
+ NULL,
+ EblDumpMmu
+ }
+};
+
+
+VOID
+EblInitializeExternalCmd (
+ VOID
+ )
+{
+ EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
+ return;
+}