Add ArmPlatformPkg from ARM Ltd. patch.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11291 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
andrewfish
2011-02-01 05:41:42 +00:00
parent fb334ef6c5
commit 1d5d0ae92d
103 changed files with 14402 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -0,0 +1,53 @@
#/** @file
#
# Copyright (c) 2010, ARM Ltd. All rights reserved.<BR>
# 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = ArmVeEblCmdLib
FILE_GUID = 6085e1ca-0d2d-4ba4-9872-c59b36ffd6ad
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = EblCmdLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
EblCmdLib.c
EblCmdMmu.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
BaseLib
ArmLib
DebugLib
ArmDisassemblerLib
PerformanceLib
TimerLib
[Protocols]
gEfiDebugSupportProtocolGuid
gEfiLoadedImageProtocolGuid
[Guids]
gEfiDebugImageInfoTableGuid

View File

@@ -0,0 +1,354 @@
/** @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/UefiLib.h>
#include <Library/ArmLib.h>
#include <Chipset/ArmV7.h>
#include <Library/CacheMaintenanceLib.h>
#include <Library/EblCmdLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#define GET_TT_ATTRIBUTES(TTEntry) ((TTEntry) & ~(TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK))
#define GET_TT_PAGE_ATTRIBUTES(TTEntry) ((TTEntry) & 0xFFF)
#define GET_TT_LARGEPAGE_ATTRIBUTES(TTEntry) ((TTEntry) & 0xFFFF)
// Section
#define TT_DESCRIPTOR_SECTION_STRONGLY_ORDER (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
TT_DESCRIPTOR_SECTION_AP_RW_RW | \
TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED)
// Small Page
#define TT_DESCRIPTOR_PAGE_WRITE_BACK (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC)
#define TT_DESCRIPTOR_PAGE_WRITE_THROUGH (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)
#define TT_DESCRIPTOR_PAGE_DEVICE (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE)
#define TT_DESCRIPTOR_PAGE_UNCACHED (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE)
#define TT_DESCRIPTOR_PAGE_STRONGLY_ORDER (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED)
// Large Page
#define TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC)
#define TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)
#define TT_DESCRIPTOR_LARGEPAGE_DEVICE (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE)
#define TT_DESCRIPTOR_LARGEPAGE_UNCACHED (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE)
typedef enum { Level0, Level1,Level2 } MMU_LEVEL;
typedef struct {
MMU_LEVEL Level;
UINT32 Value;
UINT32 Index;
UINT32* Table;
} MMU_ENTRY;
MMU_ENTRY MmuEntryCreate(MMU_LEVEL Level,UINT32* Table,UINT32 Index) {
MMU_ENTRY Entry;
Entry.Level = Level;
Entry.Value = Table[Index];
Entry.Table = Table;
Entry.Index = Index;
return Entry;
}
UINT32 MmuEntryIsValidAddress(MMU_LEVEL Level, UINT32 Entry) {
if (Level == Level0) {
return 0;
} else if (Level == Level1) {
if ((Entry & 0x3) == 0) { // Ignored
return 0;
} else if ((Entry & 0x3) == 2) { // Section Type
return 1;
} else { // Page Type
return 0;
}
} else if (Level == Level2){
if ((Entry & 0x3) == 0) { // Ignored
return 0;
} else { // Page Type
return 1;
}
} else {
DEBUG((EFI_D_ERROR,"MmuEntryIsValidAddress: Level:%d Entry:0x%X\n",(UINT32)Level,(UINT32)Entry));
ASSERT(0);
return 0;
}
}
UINT32 MmuEntryGetAddress(MMU_ENTRY Entry) {
if (Entry.Level == Level1) {
if ((Entry.Value & 0x3) == 0) {
return 0;
} else if ((Entry.Value & 0x3) == 2) { // Section Type
return Entry.Value & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;
} else if ((Entry.Value & 0x3) == 1) { // Level2 Table
MMU_ENTRY Entry = MmuEntryCreate(Level2,(UINT32*)(Entry.Value & 0xFFFFC000),0);
return MmuEntryGetAddress(Entry);
} else { // Page Type
return 0;
}
} else if (Entry.Level == Level2) {
if ((Entry.Value & 0x3) == 0) { // Ignored
return 0;
} else if ((Entry.Value & 0x3) == 1) { // Large Page
return Entry.Value & 0xFFFF0000;
} else if ((Entry.Value & 0x2) == 2) { // Small Page
return Entry.Value & 0xFFFFF000;
} else {
return 0;
}
} else {
ASSERT(0);
return 0;
}
}
UINT32 MmuEntryGetSize(MMU_ENTRY Entry) {
if (Entry.Level == Level1) {
if ((Entry.Value & 0x3) == 0) {
return 0;
} else if ((Entry.Value & 0x3) == 2) {
if (Entry.Value & (1 << 18))
return 16*SIZE_1MB;
else
return SIZE_1MB;
} else if ((Entry.Value & 0x3) == 1) { // Level2 Table split 1MB section
return SIZE_1MB;
} else {
DEBUG((EFI_D_ERROR, "MmuEntryGetSize: Value:0x%X",Entry.Value));
ASSERT(0);
return 0;
}
} else if (Entry.Level == Level2) {
if ((Entry.Value & 0x3) == 0) { // Ignored
return 0;
} else if ((Entry.Value & 0x3) == 1) { // Large Page
return SIZE_64KB;
} else if ((Entry.Value & 0x2) == 2) { // Small Page
return SIZE_4KB;
} else {
ASSERT(0);
return 0;
}
} else {
ASSERT(0);
return 0;
}
}
CONST CHAR8* MmuEntryGetAttributesName(MMU_ENTRY Entry) {
if (Entry.Level == Level1) {
if (GET_TT_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_SECTION_WRITE_BACK(0))
return "TT_DESCRIPTOR_SECTION_WRITE_BACK";
else if (GET_TT_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0))
return "TT_DESCRIPTOR_SECTION_WRITE_THROUGH";
else if (GET_TT_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_SECTION_DEVICE(0))
return "TT_DESCRIPTOR_SECTION_DEVICE";
else if (GET_TT_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_SECTION_UNCACHED(0))
return "TT_DESCRIPTOR_SECTION_UNCACHED";
else if (GET_TT_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_SECTION_STRONGLY_ORDER)
return "TT_DESCRIPTOR_SECTION_STRONGLY_ORDERED";
else {
return "SectionUnknown";
}
} else if ((Entry.Level == Level2) && ((Entry.Value & 0x2) == 2)) { //Small Page
if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_WRITE_BACK)
return "TT_DESCRIPTOR_PAGE_WRITE_BACK";
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_WRITE_THROUGH)
return "TT_DESCRIPTOR_PAGE_WRITE_THROUGH";
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_DEVICE)
return "TT_DESCRIPTOR_PAGE_DEVICE";
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_UNCACHED)
return "TT_DESCRIPTOR_PAGE_UNCACHED";
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_STRONGLY_ORDER)
return "TT_DESCRIPTOR_PAGE_STRONGLY_ORDERED";
else {
return "PageUnknown";
}
} else if ((Entry.Level == Level2) && ((Entry.Value & 0x3) == 1)) { //Large Page
if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK)
return "TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK";
else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH)
return "TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH";
else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_DEVICE)
return "TT_DESCRIPTOR_LARGEPAGE_DEVICE";
else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_UNCACHED)
return "TT_DESCRIPTOR_LARGEPAGE_UNCACHED";
else {
return "LargePageUnknown";
}
} else {
ASSERT(0);
return "";
}
}
UINT32 MmuEntryGetAttributes(MMU_ENTRY Entry) {
if (Entry.Level == Level1) {
if ((Entry.Value & 0x3) == 0) {
return 0;
} else if ((Entry.Value & 0x3) == 2) {
return GET_TT_ATTRIBUTES(Entry.Value);
} else {
return 0;
}
} else if ((Entry.Level == Level2) && ((Entry.Value & 0x2) == 2)) { //Small Page
if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_WRITE_BACK)
return TT_DESCRIPTOR_SECTION_WRITE_BACK(0);
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_WRITE_THROUGH)
return TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_DEVICE)
return TT_DESCRIPTOR_SECTION_DEVICE(0);
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_UNCACHED)
return TT_DESCRIPTOR_SECTION_UNCACHED(0);
else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_STRONGLY_ORDER)
return TT_DESCRIPTOR_SECTION_STRONGLY_ORDER;
else {
return 0;
}
} else if ((Entry.Level == Level2) && ((Entry.Value & 0x3) == 1)) { //Large Page
if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK)
return TT_DESCRIPTOR_SECTION_WRITE_BACK(0);
else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH)
return TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);
else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_DEVICE)
return TT_DESCRIPTOR_SECTION_DEVICE(0);
else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_UNCACHED)
return TT_DESCRIPTOR_SECTION_UNCACHED(0);
else {
return 0;
}
} else {
return 0;
}
}
MMU_ENTRY DumpMmuLevel(MMU_LEVEL Level, UINT32* Table, MMU_ENTRY PreviousEntry) {
UINT32 Index = 0, Count;
MMU_ENTRY LastEntry, Entry;
ASSERT((Level == Level1) || (Level == Level2));
if (Level == Level1) Count = 4096;
else Count = 256;
// At Level1, we will get into this function because PreviousEntry is not valid
if (!MmuEntryIsValidAddress((MMU_LEVEL)(Level-1),PreviousEntry.Value)) {
// Find the first valid address
for (; (Index < Count) && (!MmuEntryIsValidAddress(Level,Table[Index])); Index++);
LastEntry = MmuEntryCreate(Level,Table,Index);
Index++;
} else {
LastEntry = PreviousEntry;
}
for (; Index < Count; Index++) {
Entry = MmuEntryCreate(Level,Table,Index);
if ((Level == Level1) && ((Entry.Value & 0x3) == 1)) { // We have got a Level2 table redirection
LastEntry = DumpMmuLevel(Level2,(UINT32*)(Entry.Value & 0xFFFFFC00),LastEntry);
} else if (!MmuEntryIsValidAddress(Level,Table[Index])) {
if (MmuEntryIsValidAddress(LastEntry.Level,LastEntry.Value)) {
AsciiPrint("0x%08X-0x%08X\t%a\n",
MmuEntryGetAddress(LastEntry),MmuEntryGetAddress(PreviousEntry)+MmuEntryGetSize(PreviousEntry)-1,
MmuEntryGetAttributesName(LastEntry));
}
LastEntry = Entry;
} else {
if (MmuEntryGetAttributes(LastEntry) != MmuEntryGetAttributes(Entry)) {
if (MmuEntryIsValidAddress(Level,LastEntry.Value)) {
AsciiPrint("0x%08X-0x%08X\t%a\n",
MmuEntryGetAddress(LastEntry),MmuEntryGetAddress(PreviousEntry)+MmuEntryGetSize(PreviousEntry)-1,
MmuEntryGetAttributesName(LastEntry));
}
LastEntry = Entry;
} else {
ASSERT(LastEntry.Value != 0);
}
}
PreviousEntry = Entry;
}
if ((Level == Level1) && (LastEntry.Index != Index) && MmuEntryIsValidAddress(Level,LastEntry.Value)) {
AsciiPrint("0x%08X-0x%08X\t%a\n",
MmuEntryGetAddress(LastEntry),MmuEntryGetAddress(PreviousEntry)+MmuEntryGetSize(PreviousEntry)-1,
MmuEntryGetAttributesName(LastEntry));
}
return LastEntry;
}
EFI_STATUS
EblDumpMmu (
IN UINTN Argc,
IN CHAR8 **Argv
)
{
UINT32 *TTEntry;
MMU_ENTRY NoEntry;
TTEntry = ArmGetTTBR0BaseAddress();
AsciiPrint ("\nTranslation Table:0x%X\n",TTEntry);
AsciiPrint ("Address Range\t\tAttributes\n");
AsciiPrint ("____________________________________________________\n");
NoEntry.Level = (MMU_LEVEL)200;
DumpMmuLevel(Level1,TTEntry,NoEntry);
return EFI_SUCCESS;
}