summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ArmPkg/ArmPkg.dec65
-rw-r--r--ArmPkg/ArmPkg.dsc59
-rw-r--r--ArmPkg/Drivers/CpuDxe/CpuDxe.inf3
-rw-r--r--ArmPkg/Drivers/CpuDxe/Exception.c104
-rw-r--r--ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S29
-rw-r--r--ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm10
-rw-r--r--ArmPkg/Drivers/CpuDxe/ExceptionSupport.S10
-rw-r--r--ArmPkg/Drivers/CpuDxe/Mmu.c302
-rw-r--r--ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c119
-rw-r--r--ArmPkg/Drivers/PL180MciDxe/PL180Mci.c387
-rw-r--r--ArmPkg/Drivers/PL180MciDxe/PL180Mci.h117
-rw-r--r--ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf51
-rw-r--r--ArmPkg/Drivers/PL301Axi/PL301Axi.c108
-rw-r--r--ArmPkg/Drivers/PL301Axi/PL301Axi.inf29
-rw-r--r--ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c130
-rw-r--r--ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf30
-rw-r--r--ArmPkg/Drivers/PL34xDmc/PL341Dmc.c373
-rw-r--r--ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf29
-rw-r--r--ArmPkg/Drivers/PL35xSmc/InitializeSMC.S189
-rw-r--r--ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm183
-rw-r--r--ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf30
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicDxe.c435
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf (renamed from ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf)99
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c97
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf29
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicSec.c135
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicSec.inf29
-rw-r--r--ArmPkg/Include/Chipset/ARM1176JZ-S.h12
-rw-r--r--ArmPkg/Include/Chipset/ArmV7.h333
-rw-r--r--ArmPkg/Include/Drivers/PL341Dmc.h84
-rw-r--r--ArmPkg/Include/Drivers/PL390Gic.h120
-rw-r--r--ArmPkg/Include/Library/ArmLib.h23
-rw-r--r--ArmPkg/Include/Library/ArmMPCoreMailBoxLib.h22
-rw-r--r--ArmPkg/Include/Library/ArmTrustZoneLib.h69
-rw-r--r--ArmPkg/Include/Library/BdsUnixLib.h38
-rw-r--r--ArmPkg/Include/Library/L2X0CacheLib.h62
-rw-r--r--ArmPkg/Include/Protocol/MmcHost.h112
-rwxr-xr-xArmPkg/Library/ArmDmaLib/ArmDmaLib.c2
-rw-r--r--ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c19
-rw-r--r--ArmPkg/Library/ArmLib/Arm11/Arm11Support.S63
-rw-r--r--ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c9
-rw-r--r--ArmPkg/Library/ArmLib/Arm9/Arm9Support.S57
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S130
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm72
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c124
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h36
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf1
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf1
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf40
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCore.c57
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.S48
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.asm48
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf51
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf49
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibSec.inf43
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c162
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S166
-rw-r--r--ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm167
-rw-r--r--ArmPkg/Library/ArmLib/Common/ArmLibSupport.S51
-rw-r--r--ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm18
-rw-r--r--ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBox.c25
-rw-r--r--ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf37
-rw-r--r--ArmPkg/Library/ArmTrustZoneLib/ArmTrustZone.c79
-rw-r--r--ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf32
-rwxr-xr-xArmPkg/Library/BaseMemoryLibStm/Arm/CopyMem.S3
-rwxr-xr-xArmPkg/Library/BaseMemoryLibStm/Arm/SetMem.S3
-rwxr-xr-xArmPkg/Library/BaseMemoryLibVstm/Arm/CopyMem.S3
-rwxr-xr-xArmPkg/Library/BaseMemoryLibVstm/Arm/SetMem.S3
-rwxr-xr-xArmPkg/Library/BasePeCoffLib/BasePeCoff.c2
-rw-r--r--ArmPkg/Library/BdsLib/BdsAppLoader.c102
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePath.c182
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePathFs.c86
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePathFv.c136
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePathMem.c73
-rw-r--r--ArmPkg/Library/BdsLib/BdsHelper.c183
-rw-r--r--ArmPkg/Library/BdsLib/BdsInternal.h136
-rw-r--r--ArmPkg/Library/BdsLib/BdsLib.inf63
-rw-r--r--ArmPkg/Library/BdsLib/BdsLinuxLoader.c337
-rw-r--r--ArmPkg/Library/BdsLib/BdsLinuxLoader.h165
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S3
-rwxr-xr-xArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S3
-rwxr-xr-xArmPkg/Library/CompilerIntrinsicsLib/Arm/sourcery.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S4
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S5
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S3
-rwxr-xr-xArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S3
-rw-r--r--ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S3
-rwxr-xr-xArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.c42
-rw-r--r--ArmPkg/Library/L2X0CacheLibNull/L2X0Cache.c20
-rw-r--r--ArmPkg/Library/L2X0CacheLibNull/L2X0CacheLibNull.inf27
-rw-r--r--ArmPkg/Universal/MmcDxe/ComponentName.c162
-rw-r--r--ArmPkg/Universal/MmcDxe/Diagnostics.c215
-rw-r--r--ArmPkg/Universal/MmcDxe/Mmc.c387
-rw-r--r--ArmPkg/Universal/MmcDxe/Mmc.h284
-rw-r--r--ArmPkg/Universal/MmcDxe/MmcBlockIo.c558
-rw-r--r--ArmPkg/Universal/MmcDxe/MmcDxe.inf50
113 files changed, 7979 insertions, 964 deletions
diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index 0b8c101c82..63445756d9 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -44,11 +44,76 @@
[Protocols.common]
gVirtualUncachedPagesProtocolGuid = { 0xAD651C7D, 0x3C22, 0x4DBF, { 0x92, 0xe8, 0x38, 0xa7, 0xcd, 0xae, 0x87, 0xb2 } }
+ ## Include/Protocol/MmcHost.h
+ gEfiMmcHostProtocolGuid = { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B }}
+
[PcdsFeatureFlag.common]
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE|BOOLEAN|0x00000001
+ # On ARM Architecture with the Security Extension, the address for the
+ # Vector Table can be mapped anywhere in the memory map. It means we can
+ # point the Exception Vector Table to its location in CpuDxe.
+ # By default we copy the Vector Table at PcdGet32(PcdCpuVectorBaseAddress)
+ gArmTokenSpaceGuid.PcdRelocateVectorTable|TRUE|BOOLEAN|0x00000022
+
+ gArmTokenSpaceGuid.PcdEfiUncachedMemoryToStronglyOrdered|FALSE|BOOLEAN|0x00000025
+ gArmTokenSpaceGuid.PcdSkipPeiCore|FALSE|BOOLEAN|0x00000026
+
[PcdsFixedAtBuild.common]
+ # This PCD should be a FeaturePcd. But we used this PCD as an '#if' in an ASM file.
+ # Using a FeaturePcd make a '(BOOLEAN) casting for its value which is not understood by the preprocessor.
+ gArmTokenSpaceGuid.PcdVFPEnabled|0|UINT32|0x00000024
+
gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000080000000|UINT64|0x00000002
gArmTokenSpaceGuid.PcdArmCacheOperationThreshold|1024|UINT32|0x00000003
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0xfff00000|UINT32|0x00000004
gArmTokenSpaceGuid.PcdCpuResetAddress|0x00000000|UINT32|0x00000005
+
+ #
+ # ARM PL180 MCI
+ #
+ gArmTokenSpaceGuid.PcdPL180SysMciRegAddress|0x00000000|UINT32|0x00000006
+ gArmTokenSpaceGuid.PcdPL180MciBaseAddress|0x00000000|UINT32|0x00000007
+
+ #
+ # ARM PL390 General Interrupt Controller
+ #
+ gArmTokenSpaceGuid.PcdGicDistributorBase|0|UINT32|0x0000000C
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0|UINT32|0x0000000D
+ gArmTokenSpaceGuid.PcdGicNumInterrupts|96|UINT32|0x00000023
+
+ #
+ # ARM Secure SEC PCDs
+ #
+ gArmTokenSpaceGuid.PcdSecureFdBaseAddress|0|UINT32|0x00000015
+ gArmTokenSpaceGuid.PcdSecureFdSize|0|UINT32|0x00000016
+
+ #
+ # ARM MPCore MailBox PCDs
+ #
+ # Address to Set/Get to Mailbox in Multicore system
+ gArmTokenSpaceGuid.PcdMPCoreMailboxSetAddress|0|UINT32|0x00000017
+ gArmTokenSpaceGuid.PcdMPCoreMailboxGetAddress|0|UINT32|0x00000018
+ # Address/Value to clear Mailbox in Multicore system
+ gArmTokenSpaceGuid.PcdMPCoreMailboxClearAddress|0|UINT32|0x00000019
+ gArmTokenSpaceGuid.PcdMPCoreMailboxClearValue|0|UINT32|0x0000001A
+
+ #
+ # ARM L2x0 PCDs
+ #
+ gArmTokenSpaceGuid.PcdL2x0ControllerBase|0|UINT32|0x0000001B
+
+ #
+ # ARM PL390 General Interrupt Controller
+ #
+ gArmTokenSpaceGuid.PcdGicDistributorBase|0|UINT32|0x0000001C
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0|UINT32|0x0000001D
+
+ #
+ # BdsLib
+ #
+ gArmTokenSpaceGuid.PcdArmMachineType|0|UINT32|0x0000001E
+ gArmTokenSpaceGuid.PcdLinuxKernelDP|L""|VOID*|0x0000001F
+ gArmTokenSpaceGuid.PcdLinuxAtag|""|VOID*|0x00000020
+ gArmTokenSpaceGuid.PcdFdtDP|L""|VOID*|0x00000021
+
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 4185a11259..8cc748c849 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -67,6 +67,24 @@
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
DmaLib|ArmPkg/Library/ArmDmaLib/ArmDmaLib.inf
+ ArmTrustZoneLib|ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf
+ ArmMPCoreMailBoxLib|ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf
+
+ PL354SmcSecLib|ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf
+ PL341DmcLib|ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf
+ PL301AxiLib|ArmPkg/Drivers/PL301Axi/PL301Axi.inf
+ PL310L2CacheSecLib|ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
+
+ BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf
+
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
[LibraryClasses.ARM]
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
@@ -74,22 +92,47 @@
[Components.common]
ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
-## ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf
-## ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf
-## ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf
-## ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf
+ ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
+ ArmPkg/Library/ArmDmaLib/ArmDmaLib.inf
+ ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf
+ ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf
+ ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf
+ ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf
ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf
ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf
+ ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf
+ ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf
+ ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf
+ ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibSec.inf
ArmPkg/Library/ArmLib/Null/NullArmLib.inf
+ ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf
+ ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf
+ ArmPkg/Library/BaseMemoryLibStm/BaseMemoryLibStm.inf
+ ArmPkg/Library/BaseMemoryLibVstm/BaseMemoryLibVstm.inf
+ ArmPkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ ArmPkg/Library/BdsLib/BdsLib.inf
ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+ ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf
+ ArmPkg/Library/DebugUncachedMemoryAllocationLib/DebugUncachedMemoryAllocationLib.inf
+ ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
+ ArmPkg/Library/L2X0CacheLibNull/L2X0CacheLibNull.inf
+ ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf
ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf
ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf
ArmPkg/Library/SemihostLib/SemihostLib.inf
ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
- ArmPkg/Library/DebugUncachedMemoryAllocationLib/DebugUncachedMemoryAllocationLib.inf
- ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf
- ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
- ArmPkg/Library/ArmDmaLib/ArmDmaLib.inf
ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+ ArmPkg/Drivers/CpuPei/CpuPei.inf
+ ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
+ ArmPkg/Drivers/PL301Axi/PL301Axi.inf
+ ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
+ ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf
+ ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf
+ ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
+ ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf
+ ArmPkg/Drivers/PL390Gic/PL390GicSec.inf
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
+ ArmPkg/Universal/MmcDxe/MmcDxe.inf
+
+
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
index 2fc5fda691..25c0b880b2 100644
--- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
@@ -67,10 +67,13 @@
gEfiDebugImageInfoTableGuid
[Pcd.common]
+ gArmTokenSpaceGuid.PcdVFPEnabled
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
[FeaturePcd.common]
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport
+ gArmTokenSpaceGuid.PcdRelocateVectorTable
+ gArmTokenSpaceGuid.PcdEfiUncachedMemoryToStronglyOrdered
[depex]
gHardwareInterruptProtocolGuid
diff --git a/ArmPkg/Drivers/CpuDxe/Exception.c b/ArmPkg/Drivers/CpuDxe/Exception.c
index e0aca46cd7..21a4c035a9 100644
--- a/ArmPkg/Drivers/CpuDxe/Exception.c
+++ b/ArmPkg/Drivers/CpuDxe/Exception.c
@@ -14,6 +14,8 @@
#include "CpuDxe.h"
+//FIXME: Will not compile on non-ARMv7 builds
+#include <Chipset/ArmV7.h>
VOID
ExceptionHandlersStart (
@@ -127,6 +129,7 @@ InitializeExceptions (
EFI_PHYSICAL_ADDRESS Base;
UINT32 *VectorBase;
+ Status = EFI_SUCCESS;
//
// Disable interrupts
//
@@ -140,54 +143,63 @@ InitializeExceptions (
FiqEnabled = ArmGetFiqState ();
ArmDisableFiq ();
- //
- // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
- //
- Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
-
- //
- // Reserve space for the exception handlers
- //
- Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);
- VectorBase = (UINT32 *)(UINTN)Base;
- Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);
- // If the request was for memory that's not in the memory map (which is often the case for 0x00000000
- // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of
- // EFI_NOT_FOUND, and continue in that case.
- if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {
- ASSERT_EFI_ERROR (Status);
- }
-
- // Save existing vector table, in case debugger is already hooked in
- CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));
-
- // Copy our assembly code into the page that contains the exception vectors.
- CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
-
- //
- // Patch in the common Assembly exception handler
- //
- Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
- *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
-
- //
- // Initialize the C entry points for interrupts
- //
- for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
- if ((gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {
- // Exception handler contains branch to vector location (jmp $) so no handler
- // NOTE: This code assumes vectors are ARM and not Thumb code
- Status = RegisterInterruptHandler (Index, NULL);
- ASSERT_EFI_ERROR (Status);
- } else {
- // If the debugger has alread hooked put its vector back
- VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];
- }
+ if (FeaturePcdGet(PcdRelocateVectorTable) == TRUE) {
+ //
+ // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
+ //
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
+
+ //
+ // Reserve space for the exception handlers
+ //
+ Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);
+ VectorBase = (UINT32 *)(UINTN)Base;
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);
+ // If the request was for memory that's not in the memory map (which is often the case for 0x00000000
+ // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of
+ // EFI_NOT_FOUND, and continue in that case.
+ if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ // Save existing vector table, in case debugger is already hooked in
+ CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));
+
+ // Copy our assembly code into the page that contains the exception vectors.
+ CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
+
+ //
+ // Patch in the common Assembly exception handler
+ //
+ Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
+ *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
+
+ //
+ // Initialize the C entry points for interrupts
+ //
+ for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
+ if ((gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {
+ // Exception handler contains branch to vector location (jmp $) so no handler
+ // NOTE: This code assumes vectors are ARM and not Thumb code
+ Status = RegisterInterruptHandler (Index, NULL);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ // If the debugger has alread hooked put its vector back
+ VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];
+ }
+ }
+
+ // Flush Caches since we updated executable stuff
+ InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
+
+ //Note: On ARM processor with the Security Extension, the Vector Table can be located anywhere in the memory.
+ // The Vector Base Address Register defines the location
+ ArmWriteVBar(PcdGet32(PcdCpuVectorBaseAddress));
+ } else {
+ // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector Base Address to point into CpuDxe code.
+ ArmWriteVBar((UINT32)ExceptionHandlersStart);
}
- // Flush Caches since we updated executable stuff
- InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
-
if (FiqEnabled) {
ArmEnableFiq ();
}
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
index 1c2bb62605..86d2a7135f 100644
--- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
+++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
@@ -14,6 +14,8 @@
#
#------------------------------------------------------------------------------
+#include <Library/PcdLib.h>
+
/*
This is the stack constructed by the exception handler (low address to high address)
@@ -50,22 +52,17 @@ This is the stack constructed by the exception handler (low address to high addr
*/
-.globl ASM_PFX(ExceptionHandlersStart)
-INTERWORK_FUNC(ExceptionHandlersStart)
-.globl ASM_PFX(ExceptionHandlersEnd)
-INTERWORK_FUNC(ExceptionHandlersEnd)
-.globl ASM_PFX(CommonExceptionEntry)
-INTERWORK_FUNC(CommonExceptionEntry)
-.globl ASM_PFX(AsmCommonExceptionEntry)
-INTERWORK_FUNC(AsmCommonExceptionEntry)
-.globl ASM_PFX(CommonCExceptionHandler)
-INTERWORK_FUNC(CommonCExceptionHandler)
+GCC_ASM_EXPORT(ExceptionHandlersStart)
+GCC_ASM_EXPORT(ExceptionHandlersEnd)
+GCC_ASM_EXPORT(CommonExceptionEntry)
+GCC_ASM_EXPORT(AsmCommonExceptionEntry)
+GCC_ASM_EXPORT(CommonCExceptionHandler)
.text
#if !defined(__APPLE__)
.fpu neon @ makes vpush/vpop assemble
#endif
-.align 3
+.align 5
//
@@ -198,10 +195,7 @@ ASM_PFX(FiqEntry):
// This gets patched by the C code that patches in the vector table
//
ASM_PFX(CommonExceptionEntry):
- .byte 0x12
- .byte 0x34
- .byte 0x56
- .byte 0x78
+ .word ASM_PFX(AsmCommonExceptionEntry)
ASM_PFX(ExceptionHandlersEnd):
@@ -254,8 +248,9 @@ NoAdjustNeeded:
@ R0 is ExceptionType
mov R1,SP @ R1 is SystemContext
+#if (FixedPcdGet32(PcdVFPEnabled))
vpush {d0-d15} @ save vstm registers in case they are used in optimizations
-
+#endif
/*
VOID
@@ -268,7 +263,9 @@ CommonCExceptionHandler (
*/
blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
+#if (FixedPcdGet32(PcdVFPEnabled))
vpop {d0-d15}
+#endif
ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
index a8a477026e..240e1e38ae 100644
--- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
+++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
@@ -14,7 +14,7 @@
//
//------------------------------------------------------------------------------
-
+#include <Library/PcdLib.h>
/*
@@ -61,6 +61,8 @@ This is the stack constructed by the exception handler (low address to high addr
PRESERVE8
AREA DxeExceptionHandlers, CODE, READONLY
+ ALIGN 32
+
//
// This code gets copied to the ARM vector table
// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
@@ -190,7 +192,7 @@ FiqEntry
// This gets patched by the C code that patches in the vector table
//
CommonExceptionEntry
- dcd 0x12345678
+ dcd AsmCommonExceptionEntry
ExceptionHandlersEnd
@@ -243,7 +245,9 @@ NoAdjustNeeded
; R0 is ExceptionType
mov R1,SP ; R1 is SystemContext
+#if (FixedPcdGet32(PcdVFPEnabled))
vpush {d0-d15} ; save vstm registers in case they are used in optimizations
+#endif
/*
VOID
@@ -256,7 +260,9 @@ CommonCExceptionHandler (
*/
blx CommonCExceptionHandler ; Call exception handler
+#if (FixedPcdGet32(PcdVFPEnabled))
vpop {d0-d15}
+#endif
ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
mcr p15, 0, R1, c5, c0, 1 ; Write IFSR
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S
index 223a383d36..96bd68246f 100644
--- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S
+++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S
@@ -15,11 +15,11 @@
.text
.align 3
-.globl ASM_PFX(ExceptionHandlersStart)
-.globl ASM_PFX(ExceptionHandlersEnd)
-.globl ASM_PFX(CommonExceptionEntry)
-.globl ASM_PFX(AsmCommonExceptionEntry)
-.globl ASM_PFX(CommonCExceptionHandler)
+GCC_ASM_EXPORT(ExceptionHandlersStart)
+GCC_ASM_EXPORT(ExceptionHandlersEnd)
+GCC_ASM_EXPORT(CommonExceptionEntry)
+GCC_ASM_EXPORT(AsmCommonExceptionEntry)
+GCC_ASM_EXPORT(CommonCExceptionHandler)
ASM_PFX(ExceptionHandlersStart):
diff --git a/ArmPkg/Drivers/CpuDxe/Mmu.c b/ArmPkg/Drivers/CpuDxe/Mmu.c
index 3662e739e3..d7ea0eb551 100644
--- a/ArmPkg/Drivers/CpuDxe/Mmu.c
+++ b/ArmPkg/Drivers/CpuDxe/Mmu.c
@@ -15,129 +15,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
--*/
#include "CpuDxe.h"
-
-
-//
-// Translation/page table definitions
-//
+//FIXME: Remove this ARMv7 specific header
+#include <Chipset/ArmV7.h>
// First Level Descriptors
typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR;
-// memory space covered by a first level descriptor
-#define ARM_PAGE_DESC_ENTRY_MVA_SIZE 0x00100000 // 1MB
-
-// number of first level descriptors to cover entire 32-bit memory space
-#define FIRST_LEVEL_ENTRY_COUNT (0xFFFFFFFF / ARM_PAGE_DESC_ENTRY_MVA_SIZE + 1)
-
-
-// page table 1st level descriptor entries
-#define ARM_PAGE_DESC_BASE_MASK 0xFFFFFC00
-#define ARM_PAGE_DESC_BASE_SHFIT 10
-#define ARM_PAGE_DESC_DOMAIN_MASK 0x000001E0
-#define ARM_PAGE_DESC_DOMAIN_SHIFT 5
-#define ARM_PAGE_DESC_NS 0x00000008
-
-#define ARM_FIRST_LEVEL_DESC_ALIGN 0x00004000 // 16KB
-
-// section 1st level desriptor entries
-#define ARM_SECTION_BASE_MASK 0xFFF00000
-#define ARM_SECTION_BASE_SHIFT 20
-#define ARM_SECTION_NS 0x00080000
-#define ARM_SECTION_nG 0x00020000
-#define ARM_SECTION_S 0x00010000
-#define ARM_SECTION_AP2 0x00008000
-#define ARM_SECTION_TEX_MASK 0x00007000
-#define ARM_SECTION_TEX_SHIFT 12
-#define ARM_SECTION_AP10_MASK 0x00000C00
-#define ARM_SECTION_AP10_SHIFT 10
-#define ARM_SECTION_DOMAIN_MASK 0x000001E0
-#define ARM_SECTION_DOMAIN_SHIFT 5
-#define ARM_SECTION_XN 0x00000010
-#define ARM_SECTION_C 0x00000008
-#define ARM_SECTION_B 0x00000004
-
-// section level AP[2:0] definitions
-#define ARM_SECTION_AP_NO_ACCESS 0 // AP[2:0] = 0
-#define ARM_SECTION_AP_READ_WRITE ARM_SECTION_AP10_MASK // AP[2:0] = 011
-#define ARM_SECTION_AP_READ_ONLY (ARM_SECTION_AP2 | ARM_SECTION_AP10_MASK) // AP[2:0] = 111
-
-// common 1st level descriptor fields
-#define ARM_DESC_TYPE_MASK 0x00000003
-
-// descriptor type values
-#define ARM_DESC_TYPE_FAULT 0x0
-#define ARM_DESC_TYPE_PAGE_TABLE 0x1
-#define ARM_DESC_TYPE_SECTION 0x2
-
-
// Second Level Descriptors
typedef UINT32 ARM_PAGE_TABLE_ENTRY;
-// small page 2nd level descriptor entries
-#define ARM_SMALL_PAGE_BASE_MASK 0xFFFFF000
-#define ARM_SMALL_PAGE_INDEX_MASK 0x000FF000
-#define ARM_SMALL_PAGE_BASE_SHIFT 12
-#define ARM_SMALL_PAGE_TEX_MASK 0x000001C0
-#define ARM_SMALL_PAGE_TEX_SHIFT 6
-#define ARM_SMALL_PAGE_XN 0x00000001
-
-// large page 2nd level descriptor entries
-#define ARM_LARGE_PAGE_BASE_MASK 0xFFFF0000
-#define ARM_LARGE_PAGE_BASE_SHIFT 16
-#define ARM_LARGE_PAGE_TEX_MASK 0x00007000
-#define ARM_LARGE_PAGE_TEX_SHIFT 12
-#define ARM_LARGE_PAGE_XN 0x00008000
-
-// common 2nd level desriptor fields
-#define ARM_PAGE_nG 0x00000800
-#define ARM_PAGE_S 0x00000400
-#define ARM_PAGE_AP2 0x00000200
-#define ARM_PAGE_AP10_MASK 0x00000030
-#define ARM_PAGE_AP10_SHIFT 4
-#define ARM_PAGE_C 0x00000008
-#define ARM_PAGE_B 0x00000004
-#define ARM_PAGE_DESC_TYPE_MASK 0x00000003
-
-// descriptor type values
-#define ARM_PAGE_TYPE_FAULT 0x0
-#define ARM_PAGE_TYPE_LARGE 0x1
-#define ARM_PAGE_TYPE_SMALL 0x2
-#define ARM_PAGE_TYPE_SMALL_XN 0x3
-
-#define SMALL_PAGE_TABLE_ENTRY_COUNT (ARM_PAGE_DESC_ENTRY_MVA_SIZE / SIZE_4KB)
-
-
-// Translation Table Base 0 fields
-#define ARM_TTBR0_BASE_MASK 0xFFFFC000
-#define ARM_TTBR0_BASE_SHIFT 14
-#define ARM_TTRB0_NOS 0x00000020
-
-// define the combination of interesting attributes: cacheability and access permissions
-#define ARM_SECTION_CACHEABILITY_MASK ( ARM_SECTION_TEX_MASK | ARM_SECTION_C | ARM_SECTION_B )
-#define ARM_SECTION_RW_PERMISSIONS_MASK ( ARM_SECTION_AP2 | ARM_SECTION_AP10_MASK )
-#define ARM_DESCRIPTOR_ATTRIBUTES ( ARM_SECTION_CACHEABILITY_MASK | ARM_SECTION_RW_PERMISSIONS_MASK | ARM_SECTION_XN )
-
-// cacheability values for section entries
-#define ARM_SECTION_STRONGLY_ORDERED 0
-#define ARM_SECTION_SHAREABLE_DEVICE ARM_SECTION_B
-#define ARM_SECTION_WRITE_THROUGH ARM_SECTION_C
-#define ARM_SECTION_WRITE_BACK_NWA ( ARM_SECTION_C| ARM_SECTION_B )
-#define ARM_SECTION_NORMAL_UNCACHEABLE ( 0x1 << ARM_SECTION_TEX_SHIFT )
-#define ARM_SECTION_WRITE_BACK ( ( 0x1 << ARM_SECTION_TEX_SHIFT ) | ARM_SECTION_C | ARM_SECTION_B )
-#define ARM_SECTION_NONSHAREABLE_DEVICE ( 0x2 << ARM_SECTION_TEX_SHIFT )
-
-// permissions values for section entries
-#define ARM_SECTION_NO_ACCESS 0
-#define ARM_SECTION_PRIV_ACCESS_ONLY ( 0x1 << ARM_SECTION_AP10_SHIFT)
-#define ARM_SECTION_USER_READ_ONLY ( 0x2 << ARM_SECTION_AP10_SHIFT)
-#define ARM_SECTION_FULL_ACCESS ( 0x3 << ARM_SECTION_AP10_SHIFT)
-#define ARM_SECTION_PRIV_READ_ONLY ( ARM_SECTION_AP2 | (0x1 << ARM_SECTION_AP10_SHIFT) )
-#define ARM_SECTION_READ_ONLY_DEP ( ARM_SECTION_AP2 | (0x2 << ARM_SECTION_AP10_SHIFT) )
-#define ARM_SECTION_READ_ONLY ( ARM_SECTION_AP2 | (0x3 << ARM_SECTION_AP10_SHIFT) )
-
-
-
EFI_STATUS
SectionToGcdAttributes (
IN UINT32 SectionAttributes,
@@ -147,47 +33,46 @@ SectionToGcdAttributes (
*GcdAttributes = 0;
// determine cacheability attributes
- switch(SectionAttributes & ARM_SECTION_CACHEABILITY_MASK) {
- case ARM_SECTION_STRONGLY_ORDERED:
+ switch(SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:
*GcdAttributes |= EFI_MEMORY_UC;
break;
- case ARM_SECTION_SHAREABLE_DEVICE:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:
*GcdAttributes |= EFI_MEMORY_UC;
break;
- case ARM_SECTION_WRITE_THROUGH:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
*GcdAttributes |= EFI_MEMORY_WT;
break;
- case ARM_SECTION_WRITE_BACK_NWA:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
*GcdAttributes |= EFI_MEMORY_WB;
break;
- case ARM_SECTION_NORMAL_UNCACHEABLE:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:
*GcdAttributes |= EFI_MEMORY_WC;
break;
- case ARM_SECTION_WRITE_BACK:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:
*GcdAttributes |= EFI_MEMORY_WB;
break;
- case ARM_SECTION_NONSHAREABLE_DEVICE:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:
*GcdAttributes |= EFI_MEMORY_UC;
break;
default:
return EFI_UNSUPPORTED;
}
-
+
// determine protection attributes
- switch(SectionAttributes & ARM_SECTION_RW_PERMISSIONS_MASK) {
- case ARM_SECTION_NO_ACCESS: // no read, no write
+ switch(SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {
+ case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write
//*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP;
break;
- case ARM_SECTION_PRIV_ACCESS_ONLY:
- case ARM_SECTION_FULL_ACCESS:
+ case TT_DESCRIPTOR_SECTION_AP_RW_NO:
+ case TT_DESCRIPTOR_SECTION_AP_RW_RW:
// normal read/write access, do not add additional attributes
break;
// read only cases map to write-protect
- case ARM_SECTION_PRIV_READ_ONLY:
- case ARM_SECTION_READ_ONLY_DEP:
- case ARM_SECTION_READ_ONLY:
+ case TT_DESCRIPTOR_SECTION_AP_RO_NO:
+ case TT_DESCRIPTOR_SECTION_AP_RO_RO:
*GcdAttributes |= EFI_MEMORY_WP;
break;
@@ -196,7 +81,7 @@ SectionToGcdAttributes (
}
// now process eXectue Never attribute
- if ((SectionAttributes & ARM_SECTION_XN) != 0 ) {
+ if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {
*GcdAttributes |= EFI_MEMORY_XP;
}
@@ -369,22 +254,22 @@ SyncCacheConfig (
// with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTranslationTableBaseAddress ());
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());
// iterate through each 1MB descriptor
NextRegionBase = NextRegionLength = 0;
- for (i=0; i< FIRST_LEVEL_ENTRY_COUNT; i++) {
+ for (i=0; i< TRANSLATION_TABLE_SECTION_COUNT; i++) {
// obtain existing descriptor and make sure it contains a valid Base Address even if it is a fault section
- Descriptor = FirstLevelTable[i] | (ARM_SECTION_BASE_MASK & (i << ARM_SECTION_BASE_SHIFT));
+ Descriptor = FirstLevelTable[i] | TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
// extract attributes (cacheability and permissions)
- SectionAttributes = Descriptor & 0xDEC;
+ SectionAttributes = Descriptor & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);
// do we already have an existing region (or are we about to finish)?
// Skip the first entry, and make sure we close on the last entry
- if ( (NextRegionLength > 0) || (i == (FIRST_LEVEL_ENTRY_COUNT-1)) ) {
+ if ( (NextRegionLength > 0) || (i == (TRANSLATION_TABLE_SECTION_COUNT-1)) ) {
// attributes are changing, update attributes in GCD
if (SectionAttributes != NextRegionAttributes) {
@@ -398,7 +283,7 @@ SyncCacheConfig (
// start on a new region
NextRegionLength = 0;
- NextRegionBase = Descriptor & ARM_SECTION_BASE_MASK;
+ NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(Descriptor);
}
}
@@ -407,7 +292,7 @@ SyncCacheConfig (
NextRegionAttributes = SectionAttributes;
}
- NextRegionLength += ARM_PAGE_DESC_ENTRY_MVA_SIZE;
+ NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
} // section entry loop
@@ -444,37 +329,42 @@ UpdatePageEntries (
// EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)
// EntryValue: values at bit positions specified by EntryMask
- EntryMask = ARM_PAGE_DESC_TYPE_MASK;
- EntryValue = ARM_PAGE_TYPE_SMALL;
+ EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK;
+ EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
// Although the PI spec is unclear on this the GCD guarantees that only
// one Attribute bit is set at a time, so we can safely use a switch statement
switch (Attributes) {
case EFI_MEMORY_UC:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
- // map to strongly ordered
- EntryValue |= 0; // TEX[2:0] = 0, C=0, B=0
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
+ if (FeaturePcdGet(PcdEfiUncachedMemoryToStronglyOrdered)) {
+ // map to strongly ordered
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
+ } else {
+ // map to normal non-cachable
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
+ }
break;
case EFI_MEMORY_WC:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
// map to normal non-cachable
- EntryValue |= (0x1 << ARM_SMALL_PAGE_TEX_SHIFT); // TEX [2:0]= 001 = 0x2, B=0, C=0
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
break;
case EFI_MEMORY_WT:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
// write through with no-allocate
- EntryValue |= ARM_PAGE_C; // TEX [2:0] = 0, C=1, B=0
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
break;
case EFI_MEMORY_WB:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
// write back (with allocate)
- EntryValue |= (0x1 << ARM_SMALL_PAGE_TEX_SHIFT) | ARM_PAGE_C | ARM_PAGE_B; // TEX [2:0] = 001, C=1, B=1
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
break;
case EFI_MEMORY_WP:
@@ -482,7 +372,7 @@ UpdatePageEntries (
case EFI_MEMORY_UCE:
// cannot be implemented UEFI definition unclear for ARM
// Cause a page fault if these ranges are accessed.
- EntryValue = ARM_PAGE_TYPE_FAULT;
+ EntryValue = TT_DESCRIPTOR_PAGE_TYPE_FAULT;
DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting page %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));
break;
@@ -491,7 +381,7 @@ UpdatePageEntries (
}
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress ();
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
// calculate number of 4KB page table entries to change
NumPageEntries = Length/SIZE_4KB;
@@ -501,15 +391,15 @@ UpdatePageEntries (
for(p=0; p<NumPageEntries; p++) {
// calculate index into first level translation table for page table value
- FirstLevelIdx = ((BaseAddress + Offset) & ARM_SECTION_BASE_MASK) >> ARM_SECTION_BASE_SHIFT;
- ASSERT (FirstLevelIdx < FIRST_LEVEL_ENTRY_COUNT);
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
// read the descriptor from the first level page table
Descriptor = FirstLevelTable[FirstLevelIdx];
// does this descriptor need to be converted from section entry to 4K pages?
- if ((Descriptor & ARM_DESC_TYPE_MASK) != ARM_DESC_TYPE_PAGE_TABLE ) {
- Status = ConvertSectionToPages (FirstLevelIdx << ARM_SECTION_BASE_SHIFT);
+ if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {
+ Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
if (EFI_ERROR(Status)) {
// exit for loop
break;
@@ -520,11 +410,11 @@ UpdatePageEntries (
}
// obtain page table base address
- PageTable = (ARM_PAGE_TABLE_ENTRY *)(Descriptor & ARM_SMALL_PAGE_BASE_MASK);
+ PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);
// calculate index into the page table
- PageTableIndex = ((BaseAddress + Offset) & ARM_SMALL_PAGE_INDEX_MASK) >> ARM_SMALL_PAGE_BASE_SHIFT;
- ASSERT (PageTableIndex < SMALL_PAGE_TABLE_ENTRY_COUNT);
+ PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
+ ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
// get the entry
CurrentPageTableEntry = PageTable[PageTableIndex];
@@ -541,8 +431,8 @@ UpdatePageEntries (
}
if (CurrentPageTableEntry != PageTableEntry) {
- Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << ARM_SECTION_BASE_SHIFT) + (PageTableIndex << ARM_SMALL_PAGE_BASE_SHIFT));
- if ((CurrentPageTableEntry & ARM_PAGE_C) == ARM_PAGE_C) {
+ Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));
+ if ((CurrentPageTableEntry & TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) == TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) {
// The current section mapping is cacheable so Clean/Invalidate the MVA of the page
// Note assumes switch(Attributes), not ARMv7 possibilities
WriteBackInvalidateDataCacheRange (Mva, SIZE_4KB);
@@ -586,38 +476,43 @@ UpdateSectionEntries (
// EntryValue: values at bit positions specified by EntryMask
// Make sure we handle a section range that is unmapped
- EntryMask = ARM_DESC_TYPE_MASK;
- EntryValue = ARM_DESC_TYPE_SECTION;
+ EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK;
+ EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;
// Although the PI spec is unclear on this the GCD guarantees that only
// one Attribute bit is set at a time, so we can safely use a switch statement
switch(Attributes) {
case EFI_MEMORY_UC:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
- // map to strongly ordered
- EntryValue |= 0; // TEX[2:0] = 0, C=0, B=0
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
+ if (FeaturePcdGet(PcdEfiUncachedMemoryToStronglyOrdered)) {
+ // map to strongly ordered
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
+ } else {
+ // map to normal non-cachable
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
+ }
break;
case EFI_MEMORY_WC:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
// map to normal non-cachable
- EntryValue |= (0x1 << ARM_SECTION_TEX_SHIFT); // TEX [2:0]= 001 = 0x2, B=0, C=0
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
break;
case EFI_MEMORY_WT:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
// write through with no-allocate
- EntryValue |= ARM_SECTION_C; // TEX [2:0] = 0, C=1, B=0
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
break;
case EFI_MEMORY_WB:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
// write back (with allocate)
- EntryValue |= (0x1 << ARM_SECTION_TEX_SHIFT) | ARM_SECTION_C | ARM_SECTION_B; // TEX [2:0] = 001, C=1, B=1
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
break;
case EFI_MEMORY_WP:
@@ -626,7 +521,7 @@ UpdateSectionEntries (
case EFI_MEMORY_UCE:
// cannot be implemented UEFI definition unclear for ARM
// Cause a page fault if these ranges are accessed.
- EntryValue = ARM_DESC_TYPE_FAULT;
+ EntryValue = TT_DESCRIPTOR_SECTION_TYPE_FAULT;
DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting section %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));
break;
@@ -636,23 +531,23 @@ UpdateSectionEntries (
}
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress ();
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
// calculate index into first level translation table for start of modification
- FirstLevelIdx = (BaseAddress & ARM_SECTION_BASE_MASK) >> ARM_SECTION_BASE_SHIFT;
- ASSERT (FirstLevelIdx < FIRST_LEVEL_ENTRY_COUNT);
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
// calculate number of 1MB first level entries this applies to
- NumSections = Length / ARM_PAGE_DESC_ENTRY_MVA_SIZE;
+ NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;
// iterate through each descriptor
for(i=0; i<NumSections; i++) {
CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];
// has this descriptor already been coverted to pages?
- if ((CurrentDescriptor & ARM_DESC_TYPE_MASK) != ARM_DESC_TYPE_PAGE_TABLE ) {
+ if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {
// forward this 1MB range to page table function instead
- Status = UpdatePageEntries ((FirstLevelIdx + i) << ARM_SECTION_BASE_SHIFT, ARM_PAGE_DESC_ENTRY_MVA_SIZE, Attributes, VirtualMask);
+ Status = UpdatePageEntries ((FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT, TT_DESCRIPTOR_SECTION_SIZE, Attributes, VirtualMask);
} else {
// still a section entry
@@ -666,8 +561,8 @@ UpdateSectionEntries (
}
if (CurrentDescriptor != Descriptor) {
- Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << ARM_SECTION_BASE_SHIFT);
- if ((CurrentDescriptor & ARM_SECTION_C) == ARM_SECTION_C) {
+ Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
+ if ((CurrentDescriptor & TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) == TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) {
// The current section mapping is cacheable so Clean/Invalidate the MVA of the section
// Note assumes switch(Attributes), not ARMv7 possabilities
WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);
@@ -704,35 +599,20 @@ ConvertSectionToPages (
DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress ();
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
// calculate index into first level translation table for start of modification
- FirstLevelIdx = (BaseAddress & ARM_SECTION_BASE_MASK) >> ARM_SECTION_BASE_SHIFT;
- ASSERT (FirstLevelIdx < FIRST_LEVEL_ENTRY_COUNT);
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
// get section attributes and convert to page attributes
SectionDescriptor = FirstLevelTable[FirstLevelIdx];
- PageDescriptor = ARM_PAGE_TYPE_SMALL;
- PageDescriptor |= ((SectionDescriptor & ARM_SECTION_TEX_MASK) >> ARM_SECTION_TEX_SHIFT) << ARM_SMALL_PAGE_TEX_SHIFT;
- if ((SectionDescriptor & ARM_SECTION_B) != 0) {
- PageDescriptor |= ARM_PAGE_B;
- }
- if ((SectionDescriptor & ARM_SECTION_C) != 0) {
- PageDescriptor |= ARM_PAGE_C;
- }
- PageDescriptor |= ((SectionDescriptor & ARM_SECTION_AP10_MASK) >> ARM_SECTION_AP10_SHIFT) << ARM_PAGE_AP10_SHIFT;
- if ((SectionDescriptor & ARM_SECTION_AP2) != 0) {
- PageDescriptor |= ARM_PAGE_AP2;
- }
- if ((SectionDescriptor & ARM_SECTION_XN) != 0) {
- PageDescriptor |= ARM_PAGE_TYPE_SMALL_XN;
- }
- if ((SectionDescriptor & ARM_SECTION_nG) != 0) {
- PageDescriptor |= ARM_PAGE_nG;
- }
- if ((SectionDescriptor & ARM_SECTION_S) != 0) {
- PageDescriptor |= ARM_PAGE_S;
- }
+ PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(SectionDescriptor,0);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(SectionDescriptor);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(SectionDescriptor,0);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(SectionDescriptor);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S(SectionDescriptor);
// allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)
Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, 1, &PageTableAddr);
@@ -743,15 +623,15 @@ ConvertSectionToPages (
PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)(UINTN)PageTableAddr;
// write the page table entries out
- for (i=0; i<(ARM_PAGE_DESC_ENTRY_MVA_SIZE/SIZE_4KB); i++) {
- PageTable[i] = ((BaseAddress + (i << 12)) & ARM_SMALL_PAGE_BASE_MASK) | PageDescriptor;
+ for (i=0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {
+ PageTable[i] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (i << 12)) | PageDescriptor;
}
// flush d-cache so descriptors make it back to uncached memory for subsequent table walks
WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)PageTableAddr, SIZE_4KB);
// formulate page table entry, Domain=0, NS=0
- PageTableDescriptor = (((UINTN)PageTableAddr) & ARM_PAGE_DESC_BASE_MASK) | ARM_DESC_TYPE_PAGE_TABLE;
+ PageTableDescriptor = (((UINTN)PageTableAddr) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
// write the page table entry out, repalcing section entry
FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;
@@ -910,7 +790,3 @@ VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = {
CpuConvertPagesToUncachedVirtualAddress,
CpuReconvertPages
};
-
-
-
-
diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c b/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c
deleted file mode 100644
index 5498aabc75..0000000000
--- a/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. 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.
-
-**/
-
-#include <Uefi.h>
-
-#include <Library/CacheMaintenanceLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-
-#include <Protocol/Cpu.h>
-#include <Protocol/DebugSupport.h>
-#include <Protocol/TimerDebugSupport.h>
-
-EFI_STATUS
-EFIAPI
-DebugSupportGetMaximumProcessorIndex (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- OUT UINTN *MaxProcessorIndex
- )
-{
- if (MaxProcessorIndex == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- *MaxProcessorIndex = 0;
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-EFIAPI
-DebugSupportRegisterPeriodicCallback (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- IN UINTN ProcessorIndex,
- IN EFI_PERIODIC_CALLBACK PeriodicCallback
- )
-{
- TIMER_DEBUG_SUPPORT_PROTOCOL *Timer;
- EFI_STATUS Status;
-
- Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback);
-
- return Status;
-}
-
-EFI_STATUS
-EFIAPI
-DebugSupportRegisterExceptionCallback (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- IN UINTN ProcessorIndex,
- IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
- IN EFI_EXCEPTION_TYPE ExceptionType
- )
-{
- EFI_CPU_ARCH_PROTOCOL *Cpu;
- EFI_STATUS Status;
-
- Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback);
-
- return Status;
-}
-
-EFI_STATUS
-EFIAPI
-DebugSupportInvalidateInstructionCache (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- IN UINTN ProcessorIndex,
- IN VOID *Start,
- IN UINT64 Length
- )
-{
- InvalidateInstructionCacheRange(Start, Length);
- return EFI_SUCCESS;
-}
-
-EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = {
- IsaArm,
- DebugSupportGetMaximumProcessorIndex,
- DebugSupportRegisterPeriodicCallback,
- DebugSupportRegisterExceptionCallback,
- DebugSupportInvalidateInstructionCache
-};
-
-EFI_STATUS
-DebugSupportDxeInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle = NULL;
-
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid);
- Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL);
-
- return Status;
-}
-
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c
new file mode 100644
index 0000000000..fe6c904ff3
--- /dev/null
+++ b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c
@@ -0,0 +1,387 @@
+/** @file
+ This file implement the MMC Host Protocol for the ARM PrimeCell PL180.
+
+ 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 "PL180Mci.h"
+
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+
+EFI_MMC_HOST_PROTOCOL *gpMmcHost;
+
+// Untested ...
+//#define USE_STREAM
+
+#define MMCI0_BLOCKLEN 512
+#define MMCI0_POW2_BLOCKLEN 9
+#define MMCI0_TIMEOUT 1000
+
+BOOLEAN MciIsPowerOn() {
+ return ((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+}
+
+EFI_STATUS MciInitialize() {
+ MCI_TRACE("MciInitialize()");
+ return EFI_SUCCESS;
+}
+
+BOOLEAN MciIsCardPresent() {
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 1);
+}
+
+BOOLEAN MciIsReadOnly() {
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 2);
+}
+
+// Convert block size to 2^n
+UINT32 GetPow2BlockLen(UINT32 BlockLen) {
+ UINTN Loop;
+ UINTN Pow2BlockLen;
+
+ Loop = 0x8000;
+ Pow2BlockLen = 15;
+ do {
+ Loop = (Loop >> 1) & 0xFFFF;
+ Pow2BlockLen--;
+ } while (Pow2BlockLen && (!(Loop & BlockLen)));
+
+ return Pow2BlockLen;
+}
+
+VOID MciPrepareDataPath(UINTN TransferDirection) {
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,MMCI0_BLOCKLEN);
+
+#ifndef USE_STREAM
+ //Note: we are using a hardcoded BlockLen (=512). If we decide to use a variable size, we could
+ // compute the pow2 of BlockLen with the above function GetPow2BlockLen()
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
+#else
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
+#endif
+}
+
+EFI_STATUS MciSendCommand(MMC_CMD MmcCmd, UINT32 Argument) {
+ UINT32 Status;
+ UINT32 Timer;
+ UINT32 Cmd;
+
+ if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {
+ MciPrepareDataPath(MCI_DATACTL_CARD_TO_CONT);
+ } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
+ MciPrepareDataPath(MCI_DATACTL_CONT_TO_CARD);
+ }
+
+ // Create Command for PL180
+ Cmd = INDX(MmcCmd);
+ if (MmcCmd & MMC_CMD_WAIT_RESPONSE)
+ Cmd |= MCI_CPSM_WAIT_RESPONSE;
+ if (MmcCmd & MMC_CMD_LONG_RESPONSE)
+ Cmd |= MCI_CPSM_LONG_RESPONSE;
+
+ MmioWrite32(MCI_CLEAR_STATUS_REG,0x5FFF);
+ MmioWrite32(MCI_ARGUMENT_REG,Argument);
+ MmioWrite32(MCI_COMMAND_REG,Cmd);
+
+ Timer = 1000;
+ if (Cmd & MCI_CPSM_WAIT_RESPONSE) {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT)) && Timer) {
+ //NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ if ((Timer == 0) || (Status == MCI_STATUS_CMD_CMDTIMEOUT)) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%X\n",Cmd & 0x3F,MmioRead32(MCI_RESPONSE0_REG),Status));
+ return EFI_TIMEOUT;
+ } else if (!((Cmd & 0x3F) == INDX(1)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
+ // The CMD1 does not contain CRC. We should ignore the CRC failed Status.
+ return EFI_CRC_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & MCI_STATUS_CMD_SENT) && Timer) {
+ //NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ if (Timer == 0) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT2! 0x%X\n",Cmd & 0x3F,MmioRead32(MCI_RESPONSE0_REG)));
+ return EFI_TIMEOUT;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+EFI_STATUS MciReceiveResponse(MMC_RESPONSE_TYPE Type, UINT32* Buffer) {
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == MMC_RESPONSE_TYPE_R1) || (Type == MMC_RESPONSE_TYPE_R1b) ||
+ (Type == MMC_RESPONSE_TYPE_R3) || (Type == MMC_RESPONSE_TYPE_R6) ||
+ (Type == MMC_RESPONSE_TYPE_R7)) {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ } else if (Type == MMC_RESPONSE_TYPE_R2) {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ Buffer[2] = MmioRead32(MCI_RESPONSE2_REG);
+ Buffer[3] = MmioRead32(MCI_RESPONSE3_REG);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS MciReadBlockData(EFI_LBA Lba, UINTN Length, UINT32* Buffer) {
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Timer;
+ UINTN Status;
+
+ // Read data from the RX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ Timer = MMCI0_TIMEOUT * 10;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
+ // Do eight reads if possible else a single read
+ if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ }
+ else if (!(Status & MCI_STATUS_CMD_RXFIFOEMPTY)) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ } else
+ Timer--;
+ } while ((Loop < Finish) && Timer);
+
+ if (Timer == 0) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData: Timeout Status:0x%X Loop:%d // Finish:%d\n",MmioRead32(MCI_STATUS_REG),Loop,Finish));
+ return EFI_TIMEOUT;
+ } else
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS MciWriteBlockData(EFI_LBA Lba, UINTN Length, UINT32* Buffer) {
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Timer;
+ UINTN Status;
+
+ // Write the data to the TX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ Timer = MMCI0_TIMEOUT * 100;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
+
+ // Do eight writes if possible else a single write
+ if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ }
+ else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ }
+ else
+ Timer--;
+ } while ((Loop < Finish) && Timer);
+
+ ASSERT(Timer > 0);
+
+ // Wait for FIFO to drain
+ Timer = MMCI0_TIMEOUT;
+ Status = MmioRead32(MCI_STATUS_REG);
+/*#ifndef USE_STREAM
+ // Single block
+ while (((Status & MCI_STATUS_CMD_TXDONE) != MCI_STATUS_CMD_TXDONE) && Timer) {
+#else*/
+ // Stream
+ while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
+//#endif
+ NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ ASSERT(Timer > 0);
+
+ if (Timer == 0)
+ return EFI_TIMEOUT;
+ else
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS MciNotifyState(MMC_STATE State) {
+ UINT32 Data32;
+
+ switch(State) {
+ case MmcInvalidState:
+ ASSERT(0);
+ break;
+ case MmcHwInitializationState:
+ // If device already turn on then restart it
+ Data32 = MmioRead32(MCI_POWER_CONTROL_REG);
+ if ((Data32 & 0x2) == MCI_POWER_UP) {
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOff MCI");
+
+ // Turn off
+ MmioWrite32(MCI_CLOCK_CONTROL_REG, 0);
+ MmioWrite32(MCI_POWER_CONTROL_REG, 0);
+ MicroSecondDelay(100);
+ }
+
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOn MCI");
+ // Setup clock
+ // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
+ //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);
+
+ // Set the voltage
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_OPENDRAIN | (15<<2));
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);
+ MicroSecondDelay(10);
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);
+ MicroSecondDelay(100);
+
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,8);
+
+ ASSERT((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+ break;
+ case MmcIdleState:
+ MCI_TRACE("MciNotifyState(MmcIdleState)");
+ break;
+ case MmcReadyState:
+ MCI_TRACE("MciNotifyState(MmcReadyState)");
+ break;
+ case MmcIdentificationState:
+ MCI_TRACE("MciNotifyState(MmcIdentificationState)");
+ break;
+ case MmcStandByState:
+ MCI_TRACE("MciNotifyState(MmcStandByState)");
+
+ // Enable MCICMD push-pull drive
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | (15<<2) | MCI_POWER_ON);
+
+ /*// Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);*/
+ // Set MMCI0 clock to 24MHz (by bypassing the divider)
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);
+ break;
+ case MmcTransferState:
+ //MCI_TRACE("MciNotifyState(MmcTransferState)");
+ break;
+ case MmcSendingDataState:
+ MCI_TRACE("MciNotifyState(MmcSendingDataState)");
+ break;
+ case MmcReceiveDataState:
+ MCI_TRACE("MciNotifyState(MmcReceiveDataState)");
+ break;
+ case MmcProgrammingState:
+ MCI_TRACE("MciNotifyState(MmcProgrammingState)");
+ break;
+ case MmcDisconnectState:
+ MCI_TRACE("MciNotifyState(MmcDisconnectState)");
+ break;
+ default:
+ ASSERT(0);
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_GUID mPL180MciDevicePathGuid = { 0x621b6fa5, 0x4dc1, 0x476f, 0xb9, 0xd8, 0x52, 0xc5, 0x57, 0xd8, 0x10, 0x70 };
+
+EFI_STATUS MciBuildDevicePath(EFI_DEVICE_PATH_PROTOCOL **DevicePath) {
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+
+ NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
+ CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
+
+ *DevicePath = NewDevicePathNode;
+ return EFI_SUCCESS;
+}
+
+EFI_MMC_HOST_PROTOCOL gMciHost = {
+ MciIsCardPresent,
+ MciIsReadOnly,
+ MciBuildDevicePath,
+ MciNotifyState,
+ MciSendCommand,
+ MciReceiveResponse,
+ MciReadBlockData,
+ MciWriteBlockData
+};
+
+EFI_STATUS
+PL180MciDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ MCI_TRACE("PL180MciDxeInitialize()");
+
+ //Publish Component Name, BlockIO protocol interfaces
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiMmcHostProtocolGuid, &gMciHost,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h
new file mode 100644
index 0000000000..2120716554
--- /dev/null
+++ b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h
@@ -0,0 +1,117 @@
+/** @file
+ Header for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
+
+ 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.
+
+**/
+
+#ifndef __PL180_MCI_H
+#define __PL180_MCI_H
+
+#include <Uefi.h>
+
+#include <Protocol/MmcHost.h>
+
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+
+#define PL180_MCI_DXE_VERSION 0x10
+
+#define MCI_SYSCTL FixedPcdGet32(PcdPL180MciBaseAddress)
+
+#define MCI_POWER_CONTROL_REG (MCI_SYSCTL+0x000)
+#define MCI_CLOCK_CONTROL_REG (MCI_SYSCTL+0x004)
+#define MCI_ARGUMENT_REG (MCI_SYSCTL+0x008)
+#define MCI_COMMAND_REG (MCI_SYSCTL+0x00C)
+#define MCI_RESPCMD_REG (MCI_SYSCTL+0x010)
+#define MCI_RESPONSE0_REG (MCI_SYSCTL+0x014)
+#define MCI_RESPONSE1_REG (MCI_SYSCTL+0x018)
+#define MCI_RESPONSE2_REG (MCI_SYSCTL+0x01C)
+#define MCI_RESPONSE3_REG (MCI_SYSCTL+0x020)
+#define MCI_DATA_TIMER_REG (MCI_SYSCTL+0x024)
+#define MCI_DATA_LENGTH_REG (MCI_SYSCTL+0x028)
+#define MCI_DATA_CTL_REG (MCI_SYSCTL+0x02C)
+#define MCI_DATA_COUNTER (MCI_SYSCTL+0x030)
+#define MCI_STATUS_REG (MCI_SYSCTL+0x034)
+#define MCI_CLEAR_STATUS_REG (MCI_SYSCTL+0x038)
+#define MCI_INT0_MASK_REG (MCI_SYSCTL+0x03C)
+#define MCI_INT1_MASK_REG (MCI_SYSCTL+0x040)
+#define MCI_FIFOCOUNT_REG (MCI_SYSCTL+0x048)
+#define MCI_FIFO_REG (MCI_SYSCTL+0x080)
+
+#define MCI_POWER_UP 0x2
+#define MCI_POWER_ON 0x3
+#define MCI_POWER_OPENDRAIN (1 << 6)
+#define MCI_POWER_ROD (1 << 7)
+
+#define MCI_CLOCK_ENABLE 0x100
+#define MCI_CLOCK_POWERSAVE 0x200
+#define MCI_CLOCK_BYPASS 0x400
+
+#define MCI_STATUS_CMD_CMDCRCFAIL 0x1
+#define MCI_STATUS_CMD_DATACRCFAIL 0x2
+#define MCI_STATUS_CMD_CMDTIMEOUT 0x4
+#define MCI_STATUS_CMD_DATATIMEOUT 0x8
+#define MCI_STATUS_CMD_RXOVERRUN 0x20
+#define MCI_STATUS_CMD_RESPEND 0x40
+#define MCI_STATUS_CMD_SENT 0x80
+#define MCI_STATUS_CMD_TXDONE (MCI_STATUS_CMD_DATAEND | MCI_STATUS_CMD_DATABLOCKEND)
+#define MCI_STATUS_CMD_DATAEND 0x000100 // Command Status - Data end
+#define MCI_STATUS_CMD_DATABLOCKEND 0x000400 // Command Status - Data end
+#define MCI_STATUS_CMD_ACTIVE 0x800
+#define MCI_STATUS_CMD_RXACTIVE (1 << 13)
+#define MCI_STATUS_CMD_RXFIFOHALFFULL 0x008000
+#define MCI_STATUS_CMD_RXFIFOEMPTY 0x080000
+#define MCI_STATUS_CMD_RXDATAAVAILBL (1 << 21)
+#define MCI_STATUS_CMD_TXACTIVE (1 << 12)
+#define MCI_STATUS_CMD_TXFIFOFULL (1 << 16)
+#define MCI_STATUS_CMD_TXFIFOHALFEMPTY (1 << 14)
+#define MCI_STATUS_CMD_TXFIFOEMPTY (1 << 18)
+#define MCI_STATUS_CMD_TXDATAAVAILBL (1 << 20)
+
+#define MCI_DATACTL_ENABLE 1
+#define MCI_DATACTL_CONT_TO_CARD 0
+#define MCI_DATACTL_CARD_TO_CONT 2
+#define MCI_DATACTL_BLOCK_TRANS 0
+#define MCI_DATACTL_STREAM_TRANS 4
+#define MCI_DATACTL_DMA_ENABLE 8
+
+#define INDX(CMD_INDX) ((CMD_INDX & 0x3F) | MCI_CPSM_ENABLED)
+
+#define MCI_CPSM_ENABLED (1 << 10)
+#define MCI_CPSM_WAIT_RESPONSE (1 << 6)
+#define MCI_CPSM_LONG_RESPONSE (1 << 7)
+
+#define MCI_TRACE(txt) DEBUG((EFI_D_BLKIO, "ARM_MCI: " txt "\n"))
+
+EFI_STATUS
+EFIAPI
+MciGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+MciGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf b/ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
new file mode 100644
index 0000000000..7ce555bd1d
--- /dev/null
+++ b/ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
@@ -0,0 +1,51 @@
+#/** @file
+# INF file for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
+#
+# 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL180MciDxe
+ FILE_GUID = 09831032-6fa3-4484-af4f-0a000a8d3a82
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PL180MciDxeInitialize
+
+[Sources.common]
+ PL180Mci.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ ArmLib
+ IoLib
+ TimerLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiMmcHostProtocolGuid
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdPL180SysMciRegAddress
+ gArmTokenSpaceGuid.PcdPL180MciBaseAddress
+
+[Depex]
+ TRUE
diff --git a/ArmPkg/Drivers/PL301Axi/PL301Axi.c b/ArmPkg/Drivers/PL301Axi/PL301Axi.c
new file mode 100644
index 0000000000..7241f5cef2
--- /dev/null
+++ b/ArmPkg/Drivers/PL301Axi/PL301Axi.c
@@ -0,0 +1,108 @@
+/** @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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+
+#define PL301_QOS_TIDEMARK_MI_0 0x400
+#define PL301_QOS_ACCESSCONTROL_MI_0 0x404
+
+#define PL301_QOS_TIDEMARK_MI_1 0x420
+#define PL301_QOS_ACCESSCONTROL_MI_1 0x424
+
+#define PL301_QOS_TIDEMARK_MI_2 0x440
+#define PL301_QOS_ACCESSCONTROL_MI_2 0x444
+
+#define PL301_AR_ARB_MI_0 0x408
+#define PL301_AW_ARB_MI_0 0x40C
+
+#define PL301_AR_ARB_MI_1 0x428
+#define PL301_AW_ARB_MI_1 0x42C
+
+#define PL301_AR_ARB_MI_2 0x448
+#define PL301_AW_ARB_MI_2 0x44C
+
+#define PL301_MI_1_OFFSET 0x20
+#define PL301_MI_2_OFFSET 0x40
+#define PL301_MI_3_OFFSET 0x60
+#define PL301_MI_4_OFFSET 0x80
+#define PL301_MI_5_OFFSET 0xa0
+
+#define V2P_CA9_FAXI_MI0_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI0_ACCESSCNTRL_VAL 0x1
+
+#define V2P_CA9_FAXI_MI1_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI1_ACCESSCNTRL_VAL 0x1
+
+#define V2P_CA9_FAXI_MI2_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI2_ACCESSCNTRL_VAL 0x1
+
+
+#define FAxiWriteReg(reg,val) MmioWrite32(FAxiBase + reg, val)
+#define FAxiReadReg(reg) MmioRead32(FAxiBase + reg)
+
+// IN FAxiBase
+// Initialize PL301 Dynamic Memory Controller
+VOID PL301AxiInit(UINTN FAxiBase) {
+ // Configure Tidemark Register for Master Port 0 (MI 0)
+ FAxiWriteReg(PL301_QOS_TIDEMARK_MI_0, V2P_CA9_FAXI_MI0_TIDEMARK_VAL);
+
+ // Configure the Access Control Register (MI 0)
+ FAxiWriteReg(PL301_QOS_ACCESSCONTROL_MI_0, V2P_CA9_FAXI_MI0_ACCESSCNTRL_VAL);
+
+ // MP0
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x01000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x02000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x03000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x04000200);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x04000200);
+
+ // MP1
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x01000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x02000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x03000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x04000200);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x04000200);
+
+ // MP2
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x01000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x02000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x03000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x04000100);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x04000200);
+}
diff --git a/ArmPkg/Drivers/PL301Axi/PL301Axi.inf b/ArmPkg/Drivers/PL301Axi/PL301Axi.inf
new file mode 100644
index 0000000000..2358124887
--- /dev/null
+++ b/ArmPkg/Drivers/PL301Axi/PL301Axi.inf
@@ -0,0 +1,29 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL301AxiSec
+ FILE_GUID = 2ea84160-aba0-11df-9896-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL301AxiLib
+
+[Sources]
+ PL301Axi.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c b/ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c
new file mode 100644
index 0000000000..6cc6cc6193
--- /dev/null
+++ b/ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c
@@ -0,0 +1,130 @@
+/** @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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmLib.h>
+#include <Library/L2X0CacheLib.h>
+#include <Library/PcdLib.h>
+
+#define L2x0WriteReg(reg,val) MmioWrite32(PcdGet32(PcdL2x0ControllerBase) + reg, val)
+#define L2x0ReadReg(reg) MmioRead32(PcdGet32(PcdL2x0ControllerBase) + reg)
+
+// Initialize PL320 L2 Cache Controller
+VOID L2x0CacheInit(UINTN L2x0Base, BOOLEAN CacheEnabled) {
+ UINT32 Data;
+ UINT32 Revision;
+ UINT32 Aux;
+ UINT32 PfCtl;
+ UINT32 PwrCtl;
+
+ // Check if L2x0 is present and is an ARM implementation
+ Data = L2x0ReadReg(L2X0_CACHEID);
+ if ((Data >> 24) != L2X0_CACHEID_IMPLEMENTER_ARM) {
+ ASSERT(0);
+ return;
+ }
+
+ // Check if L2x0 is PL310
+ if (((Data >> 6) & 0xF) != L2X0_CACHEID_PARTNUM_PL310) {
+ ASSERT(0);
+ return;
+ }
+
+ // RTL release
+ Revision = Data & 0x3F;
+
+ // Check if L2x0 is already enabled then we disable it
+ Data = L2x0ReadReg(L2X0_CTRL);
+ if (Data & L2X0_CTRL_ENABLED) {
+ L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_DISABLED);
+ }
+
+ //
+ // Set up global configurations
+ //
+
+ // Auxiliary register: Non-secure interrupt access Control + Event monitor bus enable + SBO
+ Aux = L2X0_AUXCTRL_NSAC | L2X0_AUXCTRL_EM | L2X0_AUXCTRL_SBO;
+ // Use AWCACHE attributes for WA
+ Aux |= L2x0_AUXCTRL_AW_AWCACHE;
+ // Use default Size
+ Data = L2x0ReadReg(L2X0_AUXCTRL);
+ Aux |= Data & (0x7 << 17);
+ // Use default associativity
+ Aux |= Data & (0x1 << 16);
+ // Enabled I & D Prefetch
+ Aux |= L2x0_AUXCTRL_IPREFETCH | L2x0_AUXCTRL_DPREFETCH;
+
+ if (Revision >= 5) {
+ // Prefetch Offset Register
+ PfCtl = L2x0ReadReg(L2X0_PFCTRL);
+ // - Prefetch increment set to 0
+ // - Prefetch dropping off
+ // - Double linefills off
+ L2x0WriteReg(L2X0_PFCTRL, PfCtl);
+
+ // Power Control Register - L2X0_PWRCTRL
+ PwrCtl = L2x0ReadReg(L2X0_PWRCTRL);
+ // - Standby when idle off
+ // - Dynamic clock gating off
+ // - Nc,NC-shared dropping off
+ L2x0WriteReg(L2X0_PWRCTRL, PwrCtl);
+ }
+
+ if (Revision >= 4) {
+ // Tag RAM Latency register
+ // - Use default latency
+
+ // Data RAM Latency Control register
+ // - Use default latency
+ } else if (Revision >= 2) {
+ L2x0WriteReg(L230_TAG_LATENCY,
+ (L2_TAG_ACCESS_LATENCY << 8)
+ | (L2_TAG_ACCESS_LATENCY << 4)
+ | L2_TAG_SETUP_LATENCY
+ );
+
+ L2x0WriteReg(L230_DATA_LATENCY,
+ (L2_DATA_ACCESS_LATENCY << 8)
+ | (L2_DATA_ACCESS_LATENCY << 4)
+ | L2_DATA_SETUP_LATENCY
+ );
+ } else {
+ Aux |= (L2_TAG_ACCESS_LATENCY << 6)
+ | (L2_DATA_ACCESS_LATENCY << 3)
+ | L2_DATA_ACCESS_LATENCY;
+ }
+
+ // Write Auxiliary value
+ L2x0WriteReg(L2X0_AUXCTRL, Aux);
+
+ //
+ // Invalidate all entries in cache
+ //
+ L2x0WriteReg(L2X0_INVWAY, 0xffff);
+ // Poll cache maintenance register until invalidate operation is complete
+ while(L2x0ReadReg(L2X0_INVWAY) & 0xffff);
+
+ // Write to the Lockdown D and Lockdown I Register 9 if required
+ // - Not required
+
+ // Clear any residual raw interrupts
+ L2x0WriteReg(L2X0_INTCLEAR, 0x1FF);
+
+ // Enable the cache
+ if (CacheEnabled) {
+ L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_ENABLED);
+ }
+}
diff --git a/ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf b/ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
new file mode 100644
index 0000000000..73c9689ee5
--- /dev/null
+++ b/ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
@@ -0,0 +1,30 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL310L2Cache
+ FILE_GUID = 16ad4fe0-b5b1-11df-8cbf-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = L2X0CacheLib
+
+[Sources]
+ PL310L2Cache.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdL2x0ControllerBase
diff --git a/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c
new file mode 100644
index 0000000000..9c62a1a92b
--- /dev/null
+++ b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c
@@ -0,0 +1,373 @@
+/** @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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Drivers/PL341Dmc.h>
+
+//
+// DMC Configuration Register Map
+//
+#define DMC_STATUS_REG 0x00
+#define DMC_COMMAND_REG 0x04
+#define DMC_DIRECT_CMD_REG 0x08
+#define DMC_MEMORY_CONFIG_REG 0x0C
+#define DMC_REFRESH_PRD_REG 0x10
+#define DMC_CAS_LATENCY_REG 0x14
+#define DMC_WRITE_LATENCY_REG 0x18
+#define DMC_T_MRD_REG 0x1C
+#define DMC_T_RAS_REG 0x20
+#define DMC_T_RC_REG 0x24
+#define DMC_T_RCD_REG 0x28
+#define DMC_T_RFC_REG 0x2C
+#define DMC_T_RP_REG 0x30
+#define DMC_T_RRD_REG 0x34
+#define DMC_T_WR_REG 0x38
+#define DMC_T_WTR_REG 0x3C
+#define DMC_T_XP_REG 0x40
+#define DMC_T_XSR_REG 0x44
+#define DMC_T_ESR_REG 0x48
+#define DMC_MEMORY_CFG2_REG 0x4C
+#define DMC_MEMORY_CFG3_REG 0x50
+#define DMC_T_FAW_REG 0x54
+
+// Returns the state of the memory controller:
+#define DMC_STATUS_CONFIG 0x0
+#define DMC_STATUS_READY 0x1
+#define DMC_STATUS_PAUSED 0x2
+#define DMC_STATUS_LOWPOWER 0x3
+
+// Changes the state of the memory controller:
+#define DMC_COMMAND_GO 0x0
+#define DMC_COMMAND_SLEEP 0x1
+#define DMC_COMMAND_WAKEUP 0x2
+#define DMC_COMMAND_PAUSE 0x3
+#define DMC_COMMAND_CONFIGURE 0x4
+#define DMC_COMMAND_ACTIVEPAUSE 0x7
+
+// Determines the command required
+#define DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL 0x0
+#define DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH (0x1 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_MODEREG (0x2 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_EXTMODEREG (0x2 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_NOP (0x3 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_DPD (0x1 << 22)
+#define DMC_DIRECT_CMD_BANKADDR(n) ((n & 0x3) << 16)
+#define DMC_DIRECT_CMD_CHIP_ADDR(n) ((n & 0x3) << 20)
+
+
+//
+// AXI ID configuration register map
+//
+#define DMC_ID_0_CFG_REG 0x100
+#define DMC_ID_1_CFG_REG 0x104
+#define DMC_ID_2_CFG_REG 0x108
+#define DMC_ID_3_CFG_REG 0x10C
+#define DMC_ID_4_CFG_REG 0x110
+#define DMC_ID_5_CFG_REG 0x114
+#define DMC_ID_6_CFG_REG 0x118
+#define DMC_ID_7_CFG_REG 0x11C
+#define DMC_ID_8_CFG_REG 0x120
+#define DMC_ID_9_CFG_REG 0x124
+#define DMC_ID_10_CFG_REG 0x128
+#define DMC_ID_11_CFG_REG 0x12C
+#define DMC_ID_12_CFG_REG 0x130
+#define DMC_ID_13_CFG_REG 0x134
+#define DMC_ID_14_CFG_REG 0x138
+#define DMC_ID_15_CFG_REG 0x13C
+
+// Set the QoS
+#define DMC_ID_CFG_QOS_DISABLE 0
+#define DMC_ID_CFG_QOS_ENABLE 1
+#define DMC_ID_CFG_QOS_MIN 2
+
+
+//
+// Chip configuration register map
+//
+#define DMC_CHIP_0_CFG_REG 0x200
+#define DMC_CHIP_1_CFG_REG 0x204
+#define DMC_CHIP_2_CFG_REG 0x208
+#define DMC_CHIP_3_CFG_REG 0x20C
+
+//
+// User Defined Pins
+//
+#define DMC_USER_STATUS_REG 0x300
+#define DMC_USER_0_CFG_REG 0x304
+#define DMC_USER_1_CFG_REG 0x308
+#define DMC_FEATURE_CRTL_REG 0x30C
+#define DMC_USER_2_CFG_REG 0x310
+
+
+//
+// PHY Register Settings
+//
+#define TC_UIOLHNC_MASK 0x000003C0
+#define TC_UIOLHNC_SHIFT 0x6
+#define TC_UIOLHPC_MASK 0x0000003F
+#define TC_UIOLHPC_SHIFT 0x2
+#define TC_UIOHOCT_MASK 0x2
+#define TC_UIOHOCT_SHIFT 0x1
+#define TC_UIOHSTOP_SHIFT 0x0
+#define TC_UIOLHXC_VALUE 0x4
+
+//
+// Extended Mode Register settings
+//
+#define DDR_EMR_OCD_MASK 0x0000380
+#define DDR_EMR_OCD_SHIFT 0x7
+#define DDR_EMR_RTT_MASK 0x00000044 // DDR2 Device RTT (ODT) settings
+#define DDR_EMR_RTT_SHIFT 0x2
+#define DDR_EMR_ODS_MASK 0x00000002 // DDR2 Output Drive Strength
+#define DDR_EMR_ODS_SHIFT 0x0001
+// Termination Values:
+#define DDR_EMR_RTT_50 0x00000044 // DDR2 50 Ohm termination
+#define DDR_EMR_RTT_75R 0x00000004 // DDR2 75 Ohm termination
+#define DDR_EMR_RTT_150 0x00000040 // DDR2 150 Ohm termination
+// Output Drive Strength Values:
+#define DDR_EMR_ODS_FULL 0x0 // DDR2 Full Drive Strength
+#define DDR_EMR_ODS_HALF 0x1 // DDR2 Half Drive Strength
+// OCD values
+#define DDR_EMR_OCD_DEFAULT 0x7
+#define DDR_EMR_OCD_NS 0x0
+
+#define DDR_EMR_ODS_VAL DDR_EMR_ODS_FULL
+
+
+
+#define DmcWriteReg(reg,val) MmioWrite32(DmcBase + reg, val)
+#define DmcReadReg(reg) MmioRead32(DmcBase + reg)
+
+// Initialize PL341 Dynamic Memory Controller
+VOID PL341DmcInit(struct pl341_dmc_config *config) {
+ UINTN DmcBase = config->base;
+ UINT32 i, chip, val32;
+
+ // Set config mode
+ DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_CONFIGURE);
+
+ //
+ // Setup the QoS AXI ID bits
+ //
+
+ if (config->has_qos) {
+ // CLCD AXIID = 000
+ DmcWriteReg(DMC_ID_0_CFG_REG, DMC_ID_CFG_QOS_ENABLE | DMC_ID_CFG_QOS_MIN);
+
+ // Default disable QoS
+ DmcWriteReg(DMC_ID_1_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_2_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_3_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_4_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_5_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_6_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_7_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_8_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_9_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_10_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_11_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_12_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_13_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_14_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_15_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ }
+
+ //
+ // Initialise memory controlller
+ //
+ DmcWriteReg(DMC_REFRESH_PRD_REG, config->refresh_prd);
+ DmcWriteReg(DMC_CAS_LATENCY_REG, config->cas_latency);
+ DmcWriteReg(DMC_WRITE_LATENCY_REG, config->write_latency);
+ DmcWriteReg(DMC_T_MRD_REG, config->t_mrd);
+ DmcWriteReg(DMC_T_RAS_REG, config->t_ras);
+ DmcWriteReg(DMC_T_RC_REG, config->t_rc);
+ DmcWriteReg(DMC_T_RCD_REG, config->t_rcd);
+ DmcWriteReg(DMC_T_RFC_REG, config->t_rfc);
+ DmcWriteReg(DMC_T_RP_REG, config->t_rp);
+ DmcWriteReg(DMC_T_RRD_REG, config->t_rrd);
+ DmcWriteReg(DMC_T_WR_REG, config->t_wr);
+ DmcWriteReg(DMC_T_WTR_REG, config->t_wtr);
+ DmcWriteReg(DMC_T_XP_REG, config->t_xp);
+ DmcWriteReg(DMC_T_XSR_REG, config->t_xsr);
+ DmcWriteReg(DMC_T_ESR_REG, config->t_esr);
+ DmcWriteReg(DMC_T_FAW_REG, config->t_faw);
+
+ // =======================================================================
+ // Initialise PL341 Mem Config Registers
+ // =======================================================================
+
+ // |======================================
+ // | Set PL341 Memory Config
+ // |======================================
+ DmcWriteReg(DMC_MEMORY_CONFIG_REG, config->memory_cfg);
+
+ // |======================================
+ // | Set PL341 Memory Config 2
+ // |======================================
+ DmcWriteReg(DMC_MEMORY_CFG2_REG, config->memory_cfg2);
+
+ // |======================================
+ // | Set PL341 Chip Select <n>
+ // |======================================
+ DmcWriteReg(DMC_CHIP_0_CFG_REG, config->chip_cfg0);
+ DmcWriteReg(DMC_CHIP_1_CFG_REG, config->chip_cfg1);
+ DmcWriteReg(DMC_CHIP_2_CFG_REG, config->chip_cfg2);
+ DmcWriteReg(DMC_CHIP_3_CFG_REG, config->chip_cfg3);
+
+ // |======================================
+ // | Set PL341 Memory Config 3
+ // |======================================
+ DmcWriteReg(DMC_MEMORY_CFG3_REG, config->memory_cfg3);
+
+ // |========================================================
+ // |Set Test Chip PHY Registers via PL341 User Config Reg
+ // |Note that user_cfgX registers are Write Only
+ // |
+ // |DLL Freq set = 250MHz - 266MHz
+ // |========================================================
+ DmcWriteReg(DMC_USER_0_CFG_REG, 0x7C924924);
+
+ // user_config2
+ // ------------
+ // Set defaults before calibrating the DDR2 buffer impendence
+ // -Disable ODT
+ // -Default drive strengths
+ DmcWriteReg(DMC_USER_2_CFG_REG, 0x40000198);
+
+ // |=======================================================
+ // |Auto calibrate the DDR2 buffers impendence
+ // |=======================================================
+ val32 = DmcReadReg(DMC_USER_STATUS_REG);
+ while (!(val32 & 0x100)) {
+ val32 = DmcReadReg(DMC_USER_STATUS_REG);
+ }
+
+ // Set the output driven strength
+ DmcWriteReg(DMC_USER_2_CFG_REG, 0x40800000 |
+ (TC_UIOLHXC_VALUE << TC_UIOLHNC_SHIFT) |
+ (TC_UIOLHXC_VALUE << TC_UIOLHPC_SHIFT) |
+ (0x1 << TC_UIOHOCT_SHIFT) |
+ (0x1 << TC_UIOHSTOP_SHIFT));
+
+ // |======================================
+ // | Set PL341 Feature Control Register
+ // |======================================
+ // | Disable early BRESP - use to optimise CLCD performance
+ DmcWriteReg(DMC_FEATURE_CRTL_REG, 0x00000001);
+
+ //=================
+ // Config memories
+ //=================
+
+ for (chip = 0; chip <= config-> max_chip; chip++) {
+ // send nop
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_NOP);
+ // pre-charge all
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // set (EMR2) extended mode register 2
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(chip) |
+ DMC_DIRECT_CMD_BANKADDR(2) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+ // set (EMR3) extended mode register 3
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(chip) |
+ DMC_DIRECT_CMD_BANKADDR(3) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ // =================================
+ // set (EMR) Extended Mode Register
+ // ==================================
+ // Put into OCD default state
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(chip) |
+ DMC_DIRECT_CMD_BANKADDR(1) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ // ===========================================================
+ // set (MR) mode register - With DLL reset
+ // ===========================================================
+ // Burst Length = 4 (010)
+ // Burst Type = Seq (0)
+ // Latency = 4 (100)
+ // Test mode = Off (0)
+ // DLL reset = Yes (1)
+ // Wr Recovery = 4 (011)
+ // PD = Normal (0)
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080742);
+
+ // pre-charge all
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);
+ // auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+ // auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // ===========================================================
+ // set (MR) mode register - Without DLL reset
+ // ===========================================================
+ // auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080642);
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // ======================================================
+ // set (EMR) extended mode register - Enable OCD defaults
+ // ======================================================
+ val32 = 0; //NOP
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 |
+ (DDR_EMR_OCD_DEFAULT << DDR_EMR_OCD_SHIFT) |
+ DDR_EMR_RTT_75R |
+ (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK));
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // Set (EMR) extended mode register - OCD Exit
+ val32 = 0; //NOP
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 |
+ (DDR_EMR_OCD_NS << DDR_EMR_OCD_SHIFT) |
+ DDR_EMR_RTT_75R |
+ (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK));
+
+ }
+
+ //----------------------------------------
+ // go command
+ DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_GO);
+
+ // wait for ready
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ while (!(val32 & DMC_STATUS_READY)) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+}
diff --git a/ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf
new file mode 100644
index 0000000000..1000058713
--- /dev/null
+++ b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf
@@ -0,0 +1,29 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL341Dmc
+ FILE_GUID = edf8da40-aad1-11df-a1f4-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL341DmcLib
+
+[Sources]
+ PL341Dmc.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL35xSmc/InitializeSMC.S b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.S
new file mode 100644
index 0000000000..b3b597a50c
--- /dev/null
+++ b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.S
@@ -0,0 +1,189 @@
+#
+# 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 <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+#include <AsmMacroIoLib.h>
+
+#Start of the code section
+.text
+
+#Maintain 8 byte alignment
+.align 3
+
+#Export Initialize SMC symbol
+GCC_ASM_EXPORT(InitializeSMC)
+
+# Static memory configuation definitions for SMC
+.set SmcDirectCmd, 0x10
+.set SmcSetCycles, 0x14
+.set SmcSetOpMode, 0x18
+
+# CS0 CS0-Interf0 NOR1 flash on the motherboard
+# CS1 CS1-Interf0 Reserved for the motherboard
+# CS2 CS2-Interf0 SRAM on the motherboard
+# CS3 CS3-Interf0 memory-mapped Ethernet and USB controllers on the motherboard
+# CS4 CS0-Interf1 NOR2 flash on the motherboard
+# CS5 CS1-Interf1 memory-mapped peripherals
+# CS6 CS2-Interf1 memory-mapped peripherals
+# CS7 CS3-Interf1 system memory-mapped peripherals on the motherboard.
+
+# IN r1 SmcBase
+# IN r2 VideoSRamBase
+# NOTE: This code is been called before any stack has been setup. It means some registers
+# could be overwritten (case of 'r0')
+
+
+ASM_PFX(InitializeSMC):
+#
+# Setup NOR1 (CS0-Interface0)
+#
+
+ #Write to set_cycle register(holding register for NOR 1 cycle register or NAND cycle register)
+ #Read cycle timeout = 0xA (0:3)
+ #Write cycle timeout = 0x3(7:4)
+ #OE Assertion Delay = 0x9(11:8)
+ #WE Assertion delay = 0x3(15:12)
+ #Page cycle timeout = 0x2(19:16)
+ LoadConstantToReg (0x0002393A,r0) @ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ #Write to set_opmode register(holding register for NOR 1 opomode register or NAND opmode register)
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000028 = ReadMemoryBurstLength:continuous
+ # 0x00000280 = WriteMemoryBurstLength:continuous
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000AAA,r0) @ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ #Write to direct_cmd register so that the NOR 1 registers(set-cycles and opmode) are updated with holding registers
+ # 0x00000000 = ChipSelect0-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x00400000,r0) @ldr r0, = 0x00400000
+ str r0, [r1, #SmcDirectCmd]
+
+
+#
+# Setup SRAM (CS2-Interface0)
+#
+ LoadConstantToReg (0x00027158,r0) @ldr r0, = 0x00027158
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000802,r0) @ldr r0, = 0x00000802
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x01000000 = ChipSelect2-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x01400000,r0) @ldr r0, = 0x01400000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# USB/Eth/VRAM (CS3-Interface0)
+#
+ LoadConstantToReg (0x000CD2AA,r0) @ldr r0, = 0x000CD2AA
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x01800000 = ChipSelect3-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x01C00000,r0) @ldr r0, = 0x01C00000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Setup NOR3 (CS0-Interface1)
+#
+ LoadConstantToReg (0x0002393A,r0) @ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000028 = ReadMemoryBurstLength:continuous
+ # 0x00000280 = WriteMemoryBurstLength:continuous
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000AAA,r0) @ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x02000000 = ChipSelect0-Interface 1
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x02400000,r0) @ldr r0, = 0x02400000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Setup Peripherals (CS3-Interface1)
+#
+ LoadConstantToReg (0x00025156,r0) @ldr r0, = 0x00025156
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x03800000 = ChipSelect3-Interface 1
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x03C00000,r0) @ldr r0, = 0x03C00000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Setup VRAM (CS1-Interface0)
+#
+ LoadConstantToReg (0x00049249,r0) @ldr r0, = 0x00049249
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x00800000 = ChipSelect1-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x00C00000,r0) @ldr r0, = 0x00C00000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Page mode setup for VRAM
+#
+ #read current state
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ #enable page mode
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ LoadConstantToReg (0x00900090,r0) @ldr r0, = 0x00900090
+ str r0, [r2, #0]
+
+ #confirm page mode enabled
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ bx lr
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED \ No newline at end of file
diff --git a/ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm
new file mode 100644
index 0000000000..ebf6a7980e
--- /dev/null
+++ b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm
@@ -0,0 +1,183 @@
+//
+// 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 <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT InitializeSMC
+
+ PRESERVE8
+ AREA ModuleInitializeSMC, CODE, READONLY
+
+// Static memory configuation definitions for SMC
+SmcDirectCmd EQU 0x10
+SmcSetCycles EQU 0x14
+SmcSetOpMode EQU 0x18
+
+// CS0 CS0-Interf0 NOR1 flash on the motherboard
+// CS1 CS1-Interf0 Reserved for the motherboard
+// CS2 CS2-Interf0 SRAM on the motherboard
+// CS3 CS3-Interf0 memory-mapped Ethernet and USB controllers on the motherboard
+// CS4 CS0-Interf1 NOR2 flash on the motherboard
+// CS5 CS1-Interf1 memory-mapped peripherals
+// CS6 CS2-Interf1 memory-mapped peripherals
+// CS7 CS3-Interf1 system memory-mapped peripherals on the motherboard.
+
+// IN r1 SmcBase
+// IN r2 VideoSRamBase
+// NOTE: This code is been called before any stack has been setup. It means some registers
+// could be overwritten (case of 'r0')
+InitializeSMC
+//
+// Setup NOR1 (CS0-Interface0)
+//
+
+ //Write to set_cycle register(holding register for NOR 1 cycle register or NAND cycle register)
+ //Read cycle timeout = 0xA (0:3)
+ //Write cycle timeout = 0x3(7:4)
+ //OE Assertion Delay = 0x9(11:8)
+ //WE Assertion delay = 0x3(15:12)
+ //Page cycle timeout = 0x2(19:16)
+ ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ //Write to set_opmode register(holding register for NOR 1 opomode register or NAND opmode register)
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000028 = ReadMemoryBurstLength:continuous
+ // 0x00000280 = WriteMemoryBurstLength:continuous
+ // 0x00000800 = Set Address Valid
+ ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ //Write to direct_cmd register so that the NOR 1 registers(set-cycles and opmode) are updated with holding registers
+ // 0x00000000 = ChipSelect0-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x00400000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup SRAM (CS2-Interface0)
+//
+ ldr r0, = 0x00027158
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000800 = Set Address Valid
+ ldr r0, = 0x00000802
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x01000000 = ChipSelect2-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x01400000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// USB/Eth/VRAM (CS3-Interface0)
+//
+ ldr r0, = 0x000CD2AA
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000004 = Memory reads are synchronous
+ // 0x00000040 = Memory writes are synchronous
+ ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x01800000 = ChipSelect3-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x01C00000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup NOR3 (CS0-Interface1)
+//
+ ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000028 = ReadMemoryBurstLength:continuous
+ // 0x00000280 = WriteMemoryBurstLength:continuous
+ // 0x00000800 = Set Address Valid
+ ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x02000000 = ChipSelect0-Interface 1
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x02400000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup Peripherals (CS3-Interface1)
+//
+ ldr r0, = 0x00025156
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000004 = Memory reads are synchronous
+ // 0x00000040 = Memory writes are synchronous
+ ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x03800000 = ChipSelect3-Interface 1
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x03C00000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup VRAM (CS1-Interface0)
+//
+ ldr r0, = 0x00049249
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000004 = Memory reads are synchronous
+ // 0x00000040 = Memory writes are synchronous
+ ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x00800000 = ChipSelect1-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x00C00000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Page mode setup for VRAM
+//
+ //read current state
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ //enable page mode
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, = 0x00900090
+ str r0, [r2, #0]
+
+ //confirm page mode enabled
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ bx lr
+
+ END
diff --git a/ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf b/ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf
new file mode 100644
index 0000000000..188f080ffc
--- /dev/null
+++ b/ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf
@@ -0,0 +1,30 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL354SmcSec
+ FILE_GUID = 10952220-aa32-11df-a438-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL354SmcSecLib
+
+[Sources.common]
+ InitializeSMC.asm | RVCT
+ InitializeSMC.S | GCC
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicDxe.c b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.c
new file mode 100644
index 0000000000..da86bbcd84
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.c
@@ -0,0 +1,435 @@
+/*++
+
+Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
+Portions copyright (c) 2010, Apple Inc. 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.
+
+Module Name:
+
+ Gic.c
+
+Abstract:
+
+ Driver implementing the GIC interrupt controller protocol
+
+--*/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/HardwareInterrupt.h>
+
+#include <Drivers/PL390Gic.h>
+
+// number of 32-bit registers needed to represent those interrupts as a bit
+// (used for enable set, enable clear, pending set, pending clear, and active regs)
+#define GIC_NUM_REG_PER_INT_BITS (PcdGet32(PcdGicNumInterrupts) / 32)
+
+// number of 32-bit registers needed to represent those interrupts as two bits
+// (used for configuration reg)
+#define GIC_NUM_REG_PER_INT_CFG (PcdGet32(PcdGicNumInterrupts) / 16)
+
+// number of 32-bit registers needed to represent interrupts as 8-bit priority field
+// (used for priority regs)
+#define GIC_NUM_REG_PER_INT_BYTES (PcdGet32(PcdGicNumInterrupts) / 4)
+
+#define GIC_DEFAULT_PRIORITY 0x80
+
+extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
+
+//
+// Notifications
+//
+VOID *CpuProtocolNotificationToken = NULL;
+EFI_EVENT CpuProtocolNotificationEvent = (EFI_EVENT)NULL;
+EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
+
+HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[FixedPcdGet32(PcdGicNumInterrupts)];
+
+/**
+ Register Handler for the specified interrupt source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param Handler Callback for interrupt. NULL to unregister
+
+ @retval EFI_SUCCESS Source was updated to support Handler.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN HARDWARE_INTERRUPT_HANDLER Handler
+ )
+{
+ if (Source > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gRegisteredInterruptHandlers[Source] = Handler;
+ return This->EnableInterruptSource(This, Source);
+}
+
+/**
+ Enable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt enabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ if (Source > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ // write set-enable register
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDISER+(4*RegOffset), 1 << RegShift);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt disabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ if (Source > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ // write set-enable register
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDICER+(4*RegOffset), 1 << RegShift);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return current state of interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param InterruptState TRUE: source enabled, FALSE: source disabled.
+
+ @retval EFI_SUCCESS InterruptState is valid
+ @retval EFI_DEVICE_ERROR InterruptState is not valid
+
+**/
+EFI_STATUS
+EFIAPI
+GetInterruptSourceState (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN BOOLEAN *InterruptState
+ )
+{
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ if (Source > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDISER+(4*RegOffset)) & (1<<RegShift)) == 0) {
+ *InterruptState = FALSE;
+ } else {
+ *InterruptState = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Signal to the hardware that the End Of Intrrupt state
+ has been reached.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt EOI'ed.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+EndOfInterrupt (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ if (Source > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCEIOR, Source);
+ return EFI_SUCCESS;
+}
+
+/**
+ EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+
+ @return None
+
+**/
+VOID
+EFIAPI
+IrqInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 GicInterrupt;
+ HARDWARE_INTERRUPT_HANDLER InterruptHandler;
+
+ GicInterrupt = MmioRead32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCIAR);
+ if (GicInterrupt >= PcdGet32(PcdGicNumInterrupts)) {
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCEIOR, GicInterrupt);
+ }
+
+ InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
+ if (InterruptHandler != NULL) {
+ // Call the registered interrupt handler.
+ InterruptHandler (GicInterrupt, SystemContext);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
+ }
+
+ EndOfInterrupt (&gHardwareInterruptProtocol, GicInterrupt);
+}
+
+//
+// Making this global saves a few bytes in image size
+//
+EFI_HANDLE gHardwareInterruptHandle = NULL;
+
+//
+// The protocol instance produced by this driver
+//
+EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
+ RegisterInterruptSource,
+ EnableInterruptSource,
+ DisableInterruptSource,
+ GetInterruptSourceState,
+ EndOfInterrupt
+};
+
+/**
+ Shutdown our hardware
+
+ DXE Core will disable interrupts and turn off the timer and disable interrupts
+ after all the event handlers have run.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+ExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN i;
+
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, i);
+ }
+
+ // Acknowledge all pending interrupts
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, i);
+ }
+
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ EndOfInterrupt (&gHardwareInterruptProtocol, i);
+ }
+
+ // Disable Gic Interface
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCICR, 0x0);
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCPMR, 0x0);
+
+ // Disable Gic Distributor
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDDCR, 0x0);
+}
+
+//
+// Notification routines
+//
+VOID
+CpuProtocolInstalledNotification (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+
+ //
+ // Get the cpu protocol that this driver requires.
+ //
+ Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Unregister the default exception handler.
+ //
+ Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register to receive interrupts
+ //
+ Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
+ ASSERT_EFI_ERROR(Status);
+}
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+InterruptDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN i;
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ // Make sure the Interrupt Controller Protocol is not already installed in the system.
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
+
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, i);
+
+ // Set Priority
+ RegOffset = i / 4;
+ RegShift = (i % 4) * 8;
+ MmioAndThenOr32 (
+ PcdGet32(PcdGicDistributorBase) + GIC_ICDIPR+(4*RegOffset),
+ ~(0xff << RegShift),
+ GIC_DEFAULT_PRIORITY << RegShift
+ );
+ }
+
+ // configure interrupts for cpu 0
+ for (i = 0; i < GIC_NUM_REG_PER_INT_BYTES; i++) {
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDIPTR + (i*4), 0x01010101);
+ }
+
+ // set binary point reg to 0x7 (no preemption)
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCBPR, 0x7);
+
+ // set priority mask reg to 0xff to allow all priorities through
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCPMR, 0xff);
+
+ // enable gic cpu interface
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCICR, 0x1);
+
+ // enable gic distributor
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDDCR, 0x1);
+
+ ZeroMem (&gRegisteredInterruptHandlers, sizeof (gRegisteredInterruptHandlers));
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gHardwareInterruptHandle,
+ &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Set up to be notified when the Cpu protocol is installed.
+ Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->RegisterProtocolNotify (&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);
+ ASSERT_EFI_ERROR (Status);
+
+ // Register for an ExitBootServicesEvent
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
index 31310fc6e8..907756542a 100644
--- a/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
@@ -1,44 +1,55 @@
-#/** @file
-#
-# DXE CPU driver
-#
-# Copyright (c) 2009 - 2010, Apple Inc. 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 = ArmDebugSupportDxe
- FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
-
- ENTRY_POINT = DebugSupportDxeInitialize
-
-[Sources.common]
- DebugSupport.c
-
-[Packages]
- ArmPkg/ArmPkg.dec
- MdePkg/MdePkg.dec
-
-[LibraryClasses]
- BaseMemoryLib
- CacheMaintenanceLib
- UefiDriverEntryPoint
- ArmLib
-
-[Protocols]
- gEfiCpuArchProtocolGuid
- gEfiDebugSupportProtocolGuid
- gTimerDebugSupportProtocolGuid
-
-[Depex]
- TRUE \ No newline at end of file
+#/** @file
+#
+# Copyright (c) 2008 - 2010, Apple Inc. 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 = PL390GicDxe
+ FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InterruptDxeInitialize
+
+
+[Sources.common]
+ PL390GicDxe.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ DebugLib
+ PrintLib
+ UefiDriverEntryPoint
+ IoLib
+
+[Guids]
+
+
+[Protocols]
+ gHardwareInterruptProtocolGuid
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd.common]
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gArmTokenSpaceGuid.PcdGicNumInterrupts
+
+[depex]
+ TRUE
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c
new file mode 100644
index 0000000000..e5faa40a33
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c
@@ -0,0 +1,97 @@
+/** @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 <Library/IoLib.h>
+#include <Drivers/PL390Gic.h>
+
+
+VOID
+EFIAPI
+PL390GicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ /*
+ * Enable the CPU interface in Non-Secure world
+ * Note: The ICCICR register is banked when Security extensions are implemented
+ */
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCICR,0x00000001);
+}
+
+VOID
+EFIAPI
+PL390GicEnableDistributor (
+ IN INTN GicDistributorBase
+ )
+{
+ /*
+ * Enable GIC distributor in Non-Secure world.
+ * Note: The ICDDCR register is banked when Security extensions are implemented
+ */
+ MmioWrite32(GicDistributorBase + GIC_ICDDCR, 0x00000001);
+}
+
+VOID
+EFIAPI
+PL390GicSendSgiTo (
+ IN INTN GicDistributorBase,
+ IN INTN TargetListFilter,
+ IN INTN CPUTargetList
+ )
+{
+ MmioWrite32(GicDistributorBase + GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16));
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgiFrom (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if (((CoreId & 0x7) << 10) == (InterruptId & 0x1C00)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgi2From (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId,
+ IN INTN SgiId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if((((CoreId & 0x7) << 10) | (SgiId & 0x3FF)) == (InterruptId & 0x1FFF)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf
new file mode 100644
index 0000000000..f5ffd7febb
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf
@@ -0,0 +1,29 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL390GicNonSec
+ FILE_GUID = 03d05ee4-cdeb-458c-9dfc-993f09bdf405
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL390GicNonSecLib
+
+[Sources]
+ PL390GicNonSec.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicSec.c b/ArmPkg/Drivers/PL390Gic/PL390GicSec.c
new file mode 100644
index 0000000000..46b14e0746
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicSec.c
@@ -0,0 +1,135 @@
+/** @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 <Library/IoLib.h>
+#include <Drivers/PL390Gic.h>
+
+/*
+ * This function configures the all interrupts to be Non-secure.
+ *
+ */
+VOID
+EFIAPI
+PL390GicSetupNonSecure (
+ IN INTN GicDistributorBase,
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ UINTN CachedPriorityMask = MmioRead32(GicInterruptInterfaceBase + GIC_ICCPMR);
+
+ //Set priority Mask so that no interrupts get through to CPU
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCPMR, 0);
+
+ //Check if there are any pending interrupts
+ while(0 != (MmioRead32(GicDistributorBase + GIC_ICDICPR) & 0xF))
+ {
+ //Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal
+ UINTN InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Write to End of interrupt signal
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ }
+
+ // Ensure all GIC interrupts are Non-Secure
+ MmioWrite32(GicDistributorBase + GIC_ICDISR, 0xffffffff); // IRQs 0-31 are Non-Secure : Private Peripheral Interrupt[31:16] & Software Generated Interrupt[15:0]
+ MmioWrite32(GicDistributorBase + GIC_ICDISR + 4, 0xffffffff); // IRQs 32-63 are Non-Secure : Shared Peripheral Interrupt
+ MmioWrite32(GicDistributorBase + GIC_ICDISR + 8, 0xffffffff); // And another 32 in case we're on the testchip : Shared Peripheral Interrupt (2)
+
+ // Ensure all interrupts can get through the priority mask
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCPMR, CachedPriorityMask);
+}
+
+VOID
+EFIAPI
+PL390GicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCPMR, 0x000000FF); /* Set Priority Mask to allow interrupts */
+
+ /*
+ * Enable CPU interface in Secure world
+ * Enable CPU inteface in Non-secure World
+ * Signal Secure Interrupts to CPU using FIQ line *
+ */
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCICR,
+ GIC_ICCICR_ENABLE_SECURE(1) |
+ GIC_ICCICR_ENABLE_NS(1) |
+ GIC_ICCICR_ACK_CTL(0) |
+ GIC_ICCICR_SIGNAL_SECURE_TO_FIQ(1) |
+ GIC_ICCICR_USE_SBPR(0));
+}
+
+VOID
+EFIAPI
+PL390GicEnableDistributor (
+ IN INTN GicDistributorBase
+ )
+{
+ MmioWrite32(GicDistributorBase + GIC_ICDDCR, 1); // turn on the GIC distributor
+}
+
+VOID
+EFIAPI
+PL390GicSendSgiTo (
+ IN INTN GicDistributorBase,
+ IN INTN TargetListFilter,
+ IN INTN CPUTargetList
+ )
+{
+ MmioWrite32(GicDistributorBase + GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16));
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgiFrom (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if (((CoreId & 0x7) << 10) == (InterruptId & 0x1C00)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgi2From (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId,
+ IN INTN SgiId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if((((CoreId & 0x7) << 10) | (SgiId & 0x3FF)) == (InterruptId & 0x1FFF)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicSec.inf b/ArmPkg/Drivers/PL390Gic/PL390GicSec.inf
new file mode 100644
index 0000000000..9cbdb6e8b3
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicSec.inf
@@ -0,0 +1,29 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL390GicSec
+ FILE_GUID = 85f3cf80-b5f4-11df-9855-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL390GicSecLib
+
+[Sources]
+ PL390GicSec.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Include/Chipset/ARM1176JZ-S.h b/ArmPkg/Include/Chipset/ARM1176JZ-S.h
index 5bf679458d..68e120abcd 100644
--- a/ArmPkg/Include/Chipset/ARM1176JZ-S.h
+++ b/ArmPkg/Include/Chipset/ARM1176JZ-S.h
@@ -86,22 +86,22 @@
#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000)
#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
-#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_TYPE_SECTION | \
- TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+#define TT_DESCRIPTOR_SECTION_WRITE_BACK(Secure) (TT_DESCRIPTOR_TYPE_SECTION | \
+ (Secure ? TT_DESCRIPTOR_SECTION_NS_SECURE : 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_WRITE_BACK_ALLOC)
-#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_TYPE_SECTION | \
- TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH(Secure) (TT_DESCRIPTOR_TYPE_SECTION | \
+ (Secure ? TT_DESCRIPTOR_SECTION_NS_SECURE : 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_WRITE_THROUGH_NO_ALLOC)
-#define TT_DESCRIPTOR_SECTION_UNCACHED (TT_DESCRIPTOR_TYPE_SECTION | \
- TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+#define TT_DESCRIPTOR_SECTION_UNCACHED(Secure) (TT_DESCRIPTOR_TYPE_SECTION | \
+ (Secure ? TT_DESCRIPTOR_SECTION_NS_SECURE : TT_DESCRIPTOR_SECTION_NS_NON_SECURE ) | \
TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
diff --git a/ArmPkg/Include/Chipset/ArmV7.h b/ArmPkg/Include/Chipset/ArmV7.h
index 1f7aa46f70..b9d7430580 100644
--- a/ArmPkg/Include/Chipset/ArmV7.h
+++ b/ArmPkg/Include/Chipset/ArmV7.h
@@ -22,17 +22,52 @@
#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a)))
#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a)))
-#define TRANSLATION_TABLE_SIZE (16 * 1024)
-#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024)
-#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1)
+#define TTBR_NOT_OUTER_SHAREABLE BIT5
+#define TTBR_RGN_OUTER_NON_CACHEABLE 0
+#define TTBR_RGN_OUTER_WRITE_BACK_ALLOC BIT3
+#define TTBR_RGN_OUTER_WRITE_THROUGH BIT4
+#define TTBR_RGN_OUTER_WRITE_BACK_NO_ALLOC (BIT3|BIT4)
+#define TTBR_SHAREABLE BIT1
+#define TTBR_NON_SHAREABLE 0
+#define TTBR_INNER_CACHEABLE BIT0
+#define TTBR_NON_INNER_CACHEABLE BIT0
+#define TTBR_RGN_INNER_NON_CACHEABLE 0
+#define TTBR_RGN_INNER_WRITE_BACK_ALLOC BIT6
+#define TTBR_RGN_INNER_WRITE_THROUGH BIT0
+#define TTBR_RGN_INNER_WRITE_BACK_NO_ALLOC (BIT0|BIT6)
+
+#define TTBR_WRITE_THROUGH_NO_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_ALLOC | TTBR_RGN_INNER_WRITE_BACK_ALLOC )
+#define TTBR_WRITE_BACK_NO_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_NO_ALLOC | TTBR_RGN_INNER_WRITE_BACK_NO_ALLOC )
+#define TTBR_NON_CACHEABLE ( TTBR_RGN_OUTER_NON_CACHEABLE | TTBR_RGN_INNER_NON_CACHEABLE )
+#define TTBR_WRITE_BACK_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_ALLOC | TTBR_RGN_INNER_WRITE_BACK_ALLOC )
+
+
+#define TRANSLATION_TABLE_SECTION_COUNT 4096
+#define TRANSLATION_TABLE_SECTION_SIZE (sizeof(UINT32) * TRANSLATION_TABLE_SECTION_COUNT)
+#define TRANSLATION_TABLE_SECTION_ALIGNMENT (sizeof(UINT32) * TRANSLATION_TABLE_SECTION_COUNT)
+#define TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK (TRANSLATION_TABLE_SECTION_ALIGNMENT - 1)
+
+#define TRANSLATION_TABLE_PAGE_COUNT 256
+#define TRANSLATION_TABLE_PAGE_SIZE (sizeof(UINT32) * TRANSLATION_TABLE_PAGE_COUNT)
+#define TRANSLATION_TABLE_PAGE_ALIGNMENT (sizeof(UINT32) * TRANSLATION_TABLE_PAGE_COUNT)
+#define TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK (TRANSLATION_TABLE_PAGE_ALIGNMENT - 1)
#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20))
// Translation table descriptor types
-#define TT_DESCRIPTOR_TYPE_MASK ((1UL << 18) | (3UL << 0))
-#define TT_DESCRIPTOR_TYPE_PAGE_TABLE ((0UL << 18) | (1UL << 0))
-#define TT_DESCRIPTOR_TYPE_SECTION ((0UL << 18) | (2UL << 0))
-#define TT_DESCRIPTOR_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0))
+#define TT_DESCRIPTOR_SECTION_TYPE_MASK ((1UL << 18) | (3UL << 0))
+#define TT_DESCRIPTOR_SECTION_TYPE_FAULT (0UL << 0)
+#define TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE (1UL << 0)
+#define TT_DESCRIPTOR_SECTION_TYPE_SECTION ((0UL << 18) | (2UL << 0))
+#define TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0))
+#define TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Desc) (((Desc) & 3UL) == TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE)
+
+// Translation table descriptor types
+#define TT_DESCRIPTOR_PAGE_TYPE_MASK (3UL << 0)
+#define TT_DESCRIPTOR_PAGE_TYPE_FAULT (0UL << 0)
+#define TT_DESCRIPTOR_PAGE_TYPE_PAGE (2UL << 0)
+#define TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN (3UL << 0)
+#define TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE (1UL << 0)
// Section descriptor definitions
#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000)
@@ -45,10 +80,18 @@
#define TT_DESCRIPTOR_SECTION_NG_GLOBAL (0UL << 17)
#define TT_DESCRIPTOR_SECTION_NG_LOCAL (1UL << 17)
+#define TT_DESCRIPTOR_PAGE_NG_MASK (1UL << 11)
+#define TT_DESCRIPTOR_PAGE_NG_GLOBAL (0UL << 11)
+#define TT_DESCRIPTOR_PAGE_NG_LOCAL (1UL << 11)
+
#define TT_DESCRIPTOR_SECTION_S_MASK (1UL << 16)
#define TT_DESCRIPTOR_SECTION_S_NOT_SHARED (0UL << 16)
#define TT_DESCRIPTOR_SECTION_S_SHARED (1UL << 16)
+#define TT_DESCRIPTOR_PAGE_S_MASK (1UL << 10)
+#define TT_DESCRIPTOR_PAGE_S_NOT_SHARED (0UL << 10)
+#define TT_DESCRIPTOR_PAGE_S_SHARED (1UL << 10)
+
#define TT_DESCRIPTOR_SECTION_AP_MASK ((1UL << 15) | (3UL << 10))
#define TT_DESCRIPTOR_SECTION_AP_NO_NO ((0UL << 15) | (0UL << 10))
#define TT_DESCRIPTOR_SECTION_AP_RW_NO ((0UL << 15) | (1UL << 10))
@@ -57,7 +100,20 @@
#define TT_DESCRIPTOR_SECTION_AP_RO_NO ((1UL << 15) | (1UL << 10))
#define TT_DESCRIPTOR_SECTION_AP_RO_RO ((1UL << 15) | (3UL << 10))
-#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK ((3UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_PAGE_AP_MASK ((1UL << 9) | (3UL << 4))
+#define TT_DESCRIPTOR_PAGE_AP_NO_NO ((0UL << 9) | (0UL << 4))
+#define TT_DESCRIPTOR_PAGE_AP_RW_NO ((0UL << 9) | (1UL << 4))
+#define TT_DESCRIPTOR_PAGE_AP_RW_RO ((0UL << 9) | (2UL << 4))
+#define TT_DESCRIPTOR_PAGE_AP_RW_RW ((0UL << 9) | (3UL << 4))
+#define TT_DESCRIPTOR_PAGE_AP_RO_NO ((1UL << 9) | (1UL << 4))
+#define TT_DESCRIPTOR_PAGE_AP_RO_RO ((1UL << 9) | (3UL << 4))
+
+#define TT_DESCRIPTOR_SECTION_XN_MASK (0x1UL << 4)
+#define TT_DESCRIPTOR_PAGE_XN_MASK (0x1UL << 0)
+#define TT_DESCRIPTOR_LARGEPAGE_XN_MASK (0x1UL << 15)
+
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK ((3UL << 12) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHEABLE_MASK (1UL << 3)
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 12) | (0UL << 3) | (0UL << 2))
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 12) | (0UL << 3) | (1UL << 2))
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 12) | (1UL << 3) | (0UL << 2))
@@ -66,39 +122,240 @@
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2))
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK ((3UL << 6) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHEABLE_MASK (1UL << 3)
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 6) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 6) | (0UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 6) | (1UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 6) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE ((1UL << 6) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 6) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 6) | (0UL << 3) | (0UL << 2))
+
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK ((3UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 12) | (0UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 12) | (1UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 12) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_NON_CACHEABLE ((1UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2))
+
+#define TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(Desc) ((((Desc) & TT_DESCRIPTOR_SECTION_AP_MASK) >> 6) & TT_DESCRIPTOR_PAGE_AP_MASK)
+#define TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(Desc) ((((Desc) & TT_DESCRIPTOR_SECTION_NG_MASK) >> 6) & TT_DESCRIPTOR_PAGE_NG_MASK)
+#define TT_DESCRIPTOR_CONVERT_TO_PAGE_S(Desc) ((((Desc) & TT_DESCRIPTOR_SECTION_S_MASK) >> 6) & TT_DESCRIPTOR_PAGE_S_MASK)
+#define TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(Desc,IsLargePage) ((IsLargePage)? \
+ ((((Desc) & TT_DESCRIPTOR_SECTION_XN_MASK) >> 4) & TT_DESCRIPTOR_LARGEPAGE_XN_MASK): \
+ ((((Desc) & TT_DESCRIPTOR_SECTION_XN_MASK) << 11) & TT_DESCRIPTOR_PAGE_XN_MASK))
+#define TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(Desc,IsLargePage) (IsLargePage? \
+ (((Desc) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) & TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK): \
+ (((((Desc) & (0x3 << 12)) >> 6) | (Desc & (0x3 << 2)))))
+
#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5)
#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5)
#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000)
-#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
-
-#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_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_WRITE_BACK_ALLOC)
-#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_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_WRITE_THROUGH_NO_ALLOC)
-#define TT_DESCRIPTOR_SECTION_DEVICE (TT_DESCRIPTOR_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_SHAREABLE_DEVICE)
-#define TT_DESCRIPTOR_SECTION_UNCACHED (TT_DESCRIPTOR_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_NON_CACHEABLE)
+#define TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK (0xFFFFFC00)
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) ((a) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
+#define TT_DESCRIPTOR_SECTION_BASE_SHIFT 20
+
+#define TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK (0xFFFFF000)
+#define TT_DESCRIPTOR_PAGE_INDEX_MASK (0x000FF000)
+#define TT_DESCRIPTOR_PAGE_BASE_ADDRESS(a) ((a) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK)
+#define TT_DESCRIPTOR_PAGE_BASE_SHIFT 12
+
+#define TT_DESCRIPTOR_SECTION_WRITE_BACK(Secure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
+ ((Secure) ? TT_DESCRIPTOR_SECTION_NS_SECURE : 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_WRITE_BACK_ALLOC)
+#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH(Secure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
+ ((Secure) ? TT_DESCRIPTOR_SECTION_NS_SECURE : 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_WRITE_THROUGH_NO_ALLOC)
+#define TT_DESCRIPTOR_SECTION_DEVICE(Secure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
+ ((Secure) ? TT_DESCRIPTOR_SECTION_NS_SECURE : 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_SHAREABLE_DEVICE)
+#define TT_DESCRIPTOR_SECTION_UNCACHED(Secure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
+ ((Secure) ? TT_DESCRIPTOR_SECTION_NS_SECURE : 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_NON_CACHEABLE)
+
+// Cortex A9 feature bit definitions
+#define A9_FEATURE_PARITY (1<<9)
+#define A9_FEATURE_AOW (1<<8)
+#define A9_FEATURE_EXCL (1<<7)
+#define A9_FEATURE_SMP (1<<6)
+#define A9_FEATURE_FOZ (1<<3)
+#define A9_FEATURE_DPREF (1<<2)
+#define A9_FEATURE_HINT (1<<1)
+#define A9_FEATURE_FWD (1<<0)
+
+// SCU register offsets & masks
+#define SCU_CONTROL_OFFSET 0x0
+#define SCU_CONFIG_OFFSET 0x4
+#define SCU_INVALL_OFFSET 0xC
+#define SCU_FILT_START_OFFSET 0x40
+#define SCU_FILT_END_OFFSET 0x44
+#define SCU_SACR_OFFSET 0x50
+#define SCU_SSACR_OFFSET 0x54
+
+#define SMP_GIC_CPUIF_BASE 0x100
+#define SMP_GIC_DIST_BASE 0x1000
+
+// CPACR - Coprocessor Access Control Register defintions
+#define CPACR_CP_DENIED(cp) 0x00
+#define CPACR_CP_PRIV(cp) ((0x1 << ((cp) << 1)) & 0x0FFFFFFF)
+#define CPACR_CP_FULL(cp) ((0x3 << ((cp) << 1)) & 0x0FFFFFFF)
+#define CPACR_ASEDIS (1 << 31)
+#define CPACR_D32DIS (1 << 30)
+#define CPACR_CP_FULL_ACCESS 0x0FFFFFFF
+
+// NSACR - Non-Secure Access Control Register defintions
+#define NSACR_CP(cp) ((1 << (cp)) & 0x3FFF)
+#define NSACR_NSD32DIS (1 << 14)
+#define NSACR_NSASEDIS (1 << 15)
+#define NSACR_PLE (1 << 16)
+#define NSACR_TL (1 << 17)
+#define NSACR_NS_SMP (1 << 18)
+#define NSACR_RFR (1 << 19)
+
+// SCR - Secure Configuration Register defintions
+#define SCR_NS (1 << 0)
+#define SCR_IRQ (1 << 1)
+#define SCR_FIQ (1 << 2)
+#define SCR_EA (1 << 3)
+#define SCR_FW (1 << 4)
+#define SCR_AW (1 << 5)
+
+VOID
+EFIAPI
+ArmEnableSWPInstruction (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmWriteNsacr (
+ IN UINT32 SetWayFormat
+ );
+
+VOID
+EFIAPI
+ArmWriteScr (
+ IN UINT32 SetWayFormat
+ );
+
+VOID
+EFIAPI
+ArmWriteVMBar (
+ IN UINT32 SetWayFormat
+ );
+
+VOID
+EFIAPI
+ArmWriteVBar (
+ IN UINT32 SetWayFormat
+ );
+
+UINT32
+EFIAPI
+ArmReadVBar (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmWriteCPACR (
+ IN UINT32 SetWayFormat
+ );
+
+VOID
+EFIAPI
+ArmEnableVFP (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmCallWFI (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmInvalidScu (
+ VOID
+ );
+
+
+UINTN
+EFIAPI
+ArmGetScuBaseAddress (
+ VOID
+ );
+
+UINT32
+EFIAPI
+ArmIsScuEnable(
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmWriteAuxCr (
+ IN UINT32 Bit
+ );
+
+UINT32
+EFIAPI
+ArmReadAuxCr (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmSetAuxCrBit (
+ IN UINT32 Bits
+ );
+
+VOID
+EFIAPI
+ArmSetupSmpNonSecure (
+ IN UINTN CoreId
+ );
+
+
+UINTN
+EFIAPI
+ArmReadCbar(
+VOID
+);
+
+VOID
+EFIAPI
+ArmInvalidateInstructionAndDataTlb(
+VOID
+);
+
+
+UINTN
+EFIAPI
+ArmReadMpidr(
+VOID
+);
+
#endif // __ARM_V7_H__
diff --git a/ArmPkg/Include/Drivers/PL341Dmc.h b/ArmPkg/Include/Drivers/PL341Dmc.h
new file mode 100644
index 0000000000..68b8be444a
--- /dev/null
+++ b/ArmPkg/Include/Drivers/PL341Dmc.h
@@ -0,0 +1,84 @@
+/** @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.
+*
+**/
+
+#ifndef PL341DMC_H_
+#define PL341DMC_H_
+
+
+struct pl341_dmc_config {
+ UINTN base; // base address for the controller
+ UINTN has_qos; // has QoS registers
+ UINTN max_chip; // number of memory chips accessible
+ UINT32 refresh_prd;
+ UINT32 cas_latency;
+ UINT32 write_latency;
+ UINT32 t_mrd;
+ UINT32 t_ras;
+ UINT32 t_rc;
+ UINT32 t_rcd;
+ UINT32 t_rfc;
+ UINT32 t_rp;
+ UINT32 t_rrd;
+ UINT32 t_wr;
+ UINT32 t_wtr;
+ UINT32 t_xp;
+ UINT32 t_xsr;
+ UINT32 t_esr;
+ UINT32 memory_cfg;
+ UINT32 memory_cfg2;
+ UINT32 memory_cfg3;
+ UINT32 chip_cfg0;
+ UINT32 chip_cfg1;
+ UINT32 chip_cfg2;
+ UINT32 chip_cfg3;
+ UINT32 t_faw;
+};
+
+/* Memory config bit fields */
+#define DMC_MEMORY_CONFIG_COLUMN_ADDRESS_9 0x1
+#define DMC_MEMORY_CONFIG_COLUMN_ADDRESS_10 0x2
+#define DMC_MEMORY_CONFIG_COLUMN_ADDRESS_11 0x3
+#define DMC_MEMORY_CONFIG_COLUMN_ADDRESS_12 0x4
+#define DMC_MEMORY_CONFIG_ROW_ADDRESS_11 (0x0 << 3)
+#define DMC_MEMORY_CONFIG_ROW_ADDRESS_12 (0x1 << 3)
+#define DMC_MEMORY_CONFIG_ROW_ADDRESS_13 (0x2 << 3)
+#define DMC_MEMORY_CONFIG_ROW_ADDRESS_14 (0x3 << 3)
+#define DMC_MEMORY_CONFIG_ROW_ADDRESS_15 (0x4 << 3)
+#define DMC_MEMORY_CONFIG_ROW_ADDRESS_16 (0x5 << 3)
+#define DMC_MEMORY_CONFIG_BURST_2 (0x1 << 15)
+#define DMC_MEMORY_CONFIG_BURST_4 (0x2 << 15)
+#define DMC_MEMORY_CONFIG_BURST_8 (0x3 << 15)
+#define DMC_MEMORY_CONFIG_BURST_16 (0x4 << 15)
+#define DMC_MEMORY_CONFIG_ACTIVE_CHIP_1 (0x0 << 21)
+#define DMC_MEMORY_CONFIG_ACTIVE_CHIP_2 (0x1 << 21)
+#define DMC_MEMORY_CONFIG_ACTIVE_CHIP_3 (0x2 << 21)
+#define DMC_MEMORY_CONFIG_ACTIVE_CHIP_4 (0x3 << 21)
+
+#define DMC_MEMORY_CFG2_CLK_ASYNC (0x0 << 0)
+#define DMC_MEMORY_CFG2_CLK_SYNC (0x1 << 0)
+#define DMC_MEMORY_CFG2_DQM_INIT (0x1 << 2)
+#define DMC_MEMORY_CFG2_CKE_INIT (0x1 << 3)
+#define DMC_MEMORY_CFG2_BANK_BITS_2 (0x0 << 4)
+#define DMC_MEMORY_CFG2_BANK_BITS_3 (0x3 << 4)
+#define DMC_MEMORY_CFG2_MEM_WIDTH_16 (0x0 << 6)
+#define DMC_MEMORY_CFG2_MEM_WIDTH_32 (0x1 << 6)
+#define DMC_MEMORY_CFG2_MEM_WIDTH_64 (0x2 << 6)
+#define DMC_MEMORY_CFG2_MEM_WIDTH_RESERVED (0x3 << 6)
+
+
+
+VOID PL341DmcInit(struct pl341_dmc_config *config);
+
+
+#endif /* PL341DMC_H_ */
diff --git a/ArmPkg/Include/Drivers/PL390Gic.h b/ArmPkg/Include/Drivers/PL390Gic.h
new file mode 100644
index 0000000000..823e6c0200
--- /dev/null
+++ b/ArmPkg/Include/Drivers/PL390Gic.h
@@ -0,0 +1,120 @@
+/** @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.
+*
+**/
+
+#ifndef __PL390GIC_H
+#define __PL390GIC_H
+
+//
+// GIC definitions
+//
+
+// Distributor
+#define GIC_ICDDCR 0x000 // Distributor Control Register
+#define GIC_ICDICTR 0x004 // Interrupt Controller Type Register
+#define GIC_ICDIIDR 0x008 // Implementer Identification Register
+
+// each reg base below repeats for VE_NUM_GIC_REG_PER_INT_BITS (see GIC spec)
+#define GIC_ICDISR 0x080 // Interrupt Security Registers
+#define GIC_ICDISER 0x100 // Interrupt Set-Enable Registers
+#define GIC_ICDICER 0x180 // Interrupt Clear-Enable Registers
+#define GIC_ICDSPR 0x200 // Interrupt Set-Pending Registers
+#define GIC_ICDICPR 0x280 // Interrupt Clear-Pending Registers
+#define GIC_ICDABR 0x300 // Active Bit Registers
+
+// each reg base below repeats for VE_NUM_GIC_REG_PER_INT_BYTES
+#define GIC_ICDIPR 0x400 // Interrupt Priority Registers
+
+// each reg base below repeats for VE_NUM_GIC_INTERRUPTS
+#define GIC_ICDIPTR 0x800 // Interrupt Processor Target Registers
+#define GIC_ICDICFR 0xC00 // Interrupt Configuration Registers
+
+// just one of these
+#define GIC_ICDSGIR 0xF00 // Software Generated Interrupt Register
+
+// Cpu interface
+#define GIC_ICCICR 0x00 // CPU Interface Control Register
+#define GIC_ICCPMR 0x04 // Interrupt Priority Mask Register
+#define GIC_ICCBPR 0x08 // Binary Point Register
+#define GIC_ICCIAR 0x0C // Interrupt Acknowledge Register
+#define GIC_ICCEIOR 0x10 // End Of Interrupt Register
+#define GIC_ICCRPR 0x14 // Running Priority Register
+#define GIC_ICCPIR 0x18 // Highest Pending Interrupt Register
+#define GIC_ICCABPR 0x1C // Aliased Binary Point Register
+#define GIC_ICCIDR 0xFC // Identification Register
+
+#define GIC_ICDSGIR_FILTER_TARGETLIST 0x0
+#define GIC_ICDSGIR_FILTER_EVERYONEELSE 0x1
+#define GIC_ICDSGIR_FILTER_ITSELF 0x2
+
+//Bit-masks to configure the CPU Interface Control register
+#define GIC_ICCICR_ENABLE_SECURE(a) ((a << 0) & 0x01)
+#define GIC_ICCICR_ENABLE_NS(a) ((a << 1) & 0x02)
+#define GIC_ICCICR_ACK_CTL(a) ((a << 2) & 0x04)
+#define GIC_ICCICR_SIGNAL_SECURE_TO_FIQ(a)((a << 3) & 0x08)
+#define GIC_ICCICR_USE_SBPR(a) ((a << 4) & 0x10)
+
+
+//
+// GIC SEC interfaces
+//
+VOID
+EFIAPI
+PL390GicSetupNonSecure (
+ IN INTN GicDistributorBase,
+ IN INTN GicInterruptInterfaceBase
+ );
+
+VOID
+EFIAPI
+PL390GicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ );
+
+VOID
+EFIAPI
+PL390GicEnableDistributor (
+ IN INTN GicDistributorBase
+ );
+
+VOID
+EFIAPI
+PL390GicSendSgiTo (
+ IN INTN GicDistributorBase,
+ IN INTN TargetListFilter,
+ IN INTN CPUTargetList
+ );
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgiFrom (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId
+ );
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgi2From (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId,
+ IN INTN SgiId
+ );
+
+UINTN
+EFIAPI
+PL390GicSetPriorityMask (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN PriorityMask
+ );
+
+#endif
diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index a7920a0204..de3cddf66c 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -43,7 +43,11 @@ typedef enum {
ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED,
ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK,
ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH,
- ARM_MEMORY_REGION_ATTRIBUTE_DEVICE
+ ARM_MEMORY_REGION_ATTRIBUTE_DEVICE,
+ ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED,
+ ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK,
+ ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH,
+ ARM_MEMORY_REGION_ATTRIBUTE_SECURE_DEVICE
} ARM_MEMORY_REGION_ATTRIBUTES;
typedef struct {
@@ -145,6 +149,12 @@ Cp15CacheInfo (
VOID
);
+BOOLEAN
+EFIAPI
+ArmIsMPCore (
+ VOID
+ );
+
VOID
EFIAPI
ArmInvalidateDataCache (
@@ -226,6 +236,12 @@ ArmDisableMmu (
VOID
EFIAPI
+ArmDisableCachesAndMmu (
+ VOID
+ );
+
+VOID
+EFIAPI
ArmEnableInterrupts (
VOID
);
@@ -241,6 +257,7 @@ EFIAPI
ArmGetInterruptState (
VOID
);
+
VOID
EFIAPI
ArmEnableFiq (
@@ -280,13 +297,13 @@ ArmSetDomainAccessControl (
VOID
EFIAPI
-ArmSetTranslationTableBaseAddress (
+ArmSetTTBR0 (
IN VOID *TranslationTableBase
);
VOID *
EFIAPI
-ArmGetTranslationTableBaseAddress (
+ArmGetTTBR0BaseAddress (
VOID
);
diff --git a/ArmPkg/Include/Library/ArmMPCoreMailBoxLib.h b/ArmPkg/Include/Library/ArmMPCoreMailBoxLib.h
new file mode 100644
index 0000000000..1588c31782
--- /dev/null
+++ b/ArmPkg/Include/Library/ArmMPCoreMailBoxLib.h
@@ -0,0 +1,22 @@
+/** @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.
+*
+**/
+
+#ifndef _ARM_MPCORE_MAILBOX_LIB_H_
+#define _ARM_MPCORE_MAILBOX_LIB_H_
+
+VOID ArmClearMPCoreMailbox(VOID);
+
+UINTN ArmGetMPCoreMailbox(VOID);
+
+#endif
diff --git a/ArmPkg/Include/Library/ArmTrustZoneLib.h b/ArmPkg/Include/Library/ArmTrustZoneLib.h
new file mode 100644
index 0000000000..8eeb6a2fee
--- /dev/null
+++ b/ArmPkg/Include/Library/ArmTrustZoneLib.h
@@ -0,0 +1,69 @@
+/** @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.
+*
+**/
+
+#ifndef __ARM_TRUSTZONE_LIB_H__
+#define __ARM_TRUSTZONE_LIB_H__
+
+#include <Uefi.h>
+
+// Setup TZ Protection Controller
+#define TZPC_DECPROT_0 0
+#define TZPC_DECPROT_1 1
+#define TZPC_DECPROT_2 2
+#define TZPC_DECPROT_MAX 2
+
+/**
+ FIXME: Need documentation
+**/
+EFI_STATUS TZPCSetDecProtBits(UINTN tzpc_base, UINTN tzpc_id, UINTN bits);
+
+/**
+ FIXME: Need documentation
+**/
+EFI_STATUS TZPCClearDecProtBits(UINTN tzpc_base, UINTN tzpc_id, UINTN bits);
+
+// Setup TZ Address Space Controller
+#define TZASC_REGION_ENABLED 1
+#define TZASC_REGION_DISABLED 0
+#define TZASC_REGION_SIZE_32KB 0xE
+#define TZASC_REGION_SIZE_64KB 0xF
+#define TZASC_REGION_SIZE_128KB 0x10
+#define TZASC_REGION_SIZE_256KB 0x11
+#define TZASC_REGION_SIZE_512KB 0x12
+#define TZASC_REGION_SIZE_1MB 0x13
+#define TZASC_REGION_SIZE_2MB 0x14
+#define TZASC_REGION_SIZE_4MB 0x15
+#define TZASC_REGION_SIZE_8MB 0x16
+#define TZASC_REGION_SIZE_16MB 0x17
+#define TZASC_REGION_SIZE_32MB 0x18
+#define TZASC_REGION_SIZE_64MB 0x19
+#define TZASC_REGION_SIZE_128MB 0x1A
+#define TZASC_REGION_SIZE_256MB 0x1B
+#define TZASC_REGION_SIZE_512MB 0x1C
+#define TZASC_REGION_SIZE_1GB 0x1D
+#define TZASC_REGION_SIZE_2GB 0x1E
+#define TZASC_REGION_SIZE_4GB 0x1F
+#define TZASC_REGION_SECURITY_SR (1 << 3)
+#define TZASC_REGION_SECURITY_SW (1 << 2)
+#define TZASC_REGION_SECURITY_SRW (TZASC_REGION_SECURITY_SR|TZASC_REGION_SECURITY_SW)
+#define TZASC_REGION_SECURITY_NSR (1 << 1)
+#define TZASC_REGION_SECURITY_NSW 1
+#define TZASC_REGION_SECURITY_NSRW (TZASC_REGION_SECURITY_NSR|TZASC_REGION_SECURITY_NSW)
+
+/**
+ FIXME: Need documentation
+**/
+EFI_STATUS TZASCSetRegion(UINTN tzasc_base, UINTN region_id, UINTN enabled, UINTN low_address, UINTN high_address, UINTN size, UINTN security);
+
+#endif
diff --git a/ArmPkg/Include/Library/BdsUnixLib.h b/ArmPkg/Include/Library/BdsUnixLib.h
new file mode 100644
index 0000000000..969f951124
--- /dev/null
+++ b/ArmPkg/Include/Library/BdsUnixLib.h
@@ -0,0 +1,38 @@
+/** @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.
+*
+**/
+
+#ifndef __BDS_ENTRY_H__
+#define __BDS_ENTRY_H__
+
+EFI_STATUS
+BdsConnectAllDrivers ( VOID );
+
+EFI_STATUS
+BdsBootLinux (
+ IN CONST CHAR16* LinuxKernel,
+ IN CONST CHAR8* ATag,
+ IN CONST CHAR16* Fdt
+);
+
+EFI_STATUS
+BdsLoadApplication (
+ IN CHAR16* EfiApp
+);
+
+EFI_STATUS
+BdsLoadApplicationFromPath (
+ IN CHAR16* EfiAppPath
+);
+
+#endif
diff --git a/ArmPkg/Include/Library/L2X0CacheLib.h b/ArmPkg/Include/Library/L2X0CacheLib.h
new file mode 100644
index 0000000000..4f95b993d0
--- /dev/null
+++ b/ArmPkg/Include/Library/L2X0CacheLib.h
@@ -0,0 +1,62 @@
+/** @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.
+*
+**/
+
+#ifndef L2CACHELIB_H_
+#define L2CACHELIB_H_
+
+#define L2_LATENCY 7
+
+#define L2_TAG_ACCESS_LATENCY L2_LATENCY
+#define L2_TAG_SETUP_LATENCY L2_LATENCY
+#define L2_DATA_ACCESS_LATENCY L2_LATENCY
+#define L2_DATA_SETUP_LATENCY L2_LATENCY
+
+
+#define L2X0_CACHEID 0x000
+#define L2X0_CTRL 0x100
+#define L2X0_AUXCTRL 0x104
+#define L230_TAG_LATENCY 0x108
+#define L230_DATA_LATENCY 0x10C
+#define L2X0_INTCLEAR 0x220
+#define L2X0_CACHE_SYNC 0x730
+#define L2X0_INVWAY 0x77C
+#define L2X0_CLEAN_WAY 0x7BC
+#define L2X0_PFCTRL 0xF60
+#define L2X0_PWRCTRL 0xF80
+
+#define L2X0_CACHEID_IMPLEMENTER_ARM 0x41
+#define L2X0_CACHEID_PARTNUM_PL310 0x03
+
+#define L2X0_CTRL_ENABLED 0x1
+#define L2X0_CTRL_DISABLED 0x0
+
+#define L2X0_AUXCTRL_EXCLUSIVE (1<<12)
+#define L2X0_AUXCTRL_WAYSIZE_16KB (0x001 << 17)
+#define L2X0_AUXCTRL_WAYSIZE_32KB (0x010 << 17)
+#define L2X0_AUXCTRL_WAYSIZE_64KB (0x011 << 17)
+#define L2X0_AUXCTRL_WAYSIZE_128KB (0x100 << 17)
+#define L2X0_AUXCTRL_WAYSIZE_256KB (0x101 << 17)
+#define L2X0_AUXCTRL_WAYSIZE_512KB (0x110 << 17)
+#define L2X0_AUXCTRL_EM (1 << 20)
+#define L2x0_AUXCTRL_AW_AWCACHE (0x00 << 23)
+#define L2x0_AUXCTRL_AW_NOALLOC (0x01 << 23)
+#define L2x0_AUXCTRL_AW_OVERRIDE (0x10 << 23)
+#define L2X0_AUXCTRL_SBO (1 << 25)
+#define L2X0_AUXCTRL_NSAC (1 << 27)
+#define L2x0_AUXCTRL_DPREFETCH (1 << 28)
+#define L2x0_AUXCTRL_IPREFETCH (1 << 29)
+
+VOID L2x0CacheInit(UINTN L2x0Base, BOOLEAN CacheEnabled);
+
+#endif /* L2CACHELIB_H_ */
diff --git a/ArmPkg/Include/Protocol/MmcHost.h b/ArmPkg/Include/Protocol/MmcHost.h
new file mode 100644
index 0000000000..096b479aa0
--- /dev/null
+++ b/ArmPkg/Include/Protocol/MmcHost.h
@@ -0,0 +1,112 @@
+/** @file
+ Definition of the MMC Host Protocol
+
+ 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.
+
+**/
+
+#ifndef __MMC_HOST_H__
+#define __MMC_HOST_H__
+
+///
+/// Global ID for the MMC Host Protocol
+///
+#define EFI_MMC_HOST_PROTOCOL_GUID \
+ { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B } }
+
+#define MMC_RESPONSE_TYPE_R1 0
+#define MMC_RESPONSE_TYPE_R1b 0
+#define MMC_RESPONSE_TYPE_R2 1
+#define MMC_RESPONSE_TYPE_R3 0
+#define MMC_RESPONSE_TYPE_R6 0
+#define MMC_RESPONSE_TYPE_R7 0
+#define MMC_RESPONSE_TYPE_OCR 0
+#define MMC_RESPONSE_TYPE_CID 1
+#define MMC_RESPONSE_TYPE_CSD 1
+#define MMC_RESPONSE_TYPE_RCA 0
+
+typedef UINT32 MMC_RESPONSE_TYPE;
+
+typedef UINT32 MMC_CMD;
+
+#define MMC_CMD_WAIT_RESPONSE (1 << 16)
+#define MMC_CMD_LONG_RESPONSE (1 << 17)
+
+#define MMC_INDX(CMD_INDX) (CMD_INDX & 0xFFFF)
+
+#define MMC_CMD0 MMC_INDX(0)
+#define MMC_CMD1 (MMC_INDX(1) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
+#define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
+#define MMC_CMD11 (MMC_INDX(11) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD12 (MMC_INDX(12) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD13 (MMC_INDX(13) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD16 (MMC_INDX(16) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD17 (MMC_INDX(17) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD18 (MMC_INDX(18) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE)
+
+typedef enum _MMC_STATE {
+ MmcInvalidState = 0,
+ MmcHwInitializationState,
+ MmcIdleState,
+ MmcReadyState,
+ MmcIdentificationState,
+ MmcStandByState,
+ MmcTransferState,
+ MmcSendingDataState,
+ MmcReceiveDataState,
+ MmcProgrammingState,
+ MmcDisconnectState,
+} MMC_STATE;
+
+typedef BOOLEAN (*MMC_ISCARDPRESENT)();
+
+typedef BOOLEAN (*MMC_ISREADONLY)();
+
+typedef EFI_STATUS (*MMC_BUILDDEVICEPATH)(EFI_DEVICE_PATH_PROTOCOL **DevicePath);
+
+typedef EFI_STATUS (*MMC_NOTIFYSTATE)(MMC_STATE State);
+
+typedef EFI_STATUS (*MMC_SENDCOMMAND)(MMC_CMD Cmd, UINT32 Argument);
+
+typedef EFI_STATUS (*MMC_RECEIVERESPONSE)(MMC_RESPONSE_TYPE Type, UINT32* Buffer);
+
+typedef EFI_STATUS (*MMC_READBLOCKDATA)(EFI_LBA Lba, UINTN Length, UINT32* Buffer);
+
+typedef EFI_STATUS (*MMC_WRITEBLOCKDATA)(EFI_LBA Lba, UINTN Length, UINT32* Buffer);
+
+typedef struct _EFI_MMC_HOST_PROTOCOL {
+ MMC_ISCARDPRESENT IsCardPresent;
+ MMC_ISREADONLY IsReadOnly;
+ MMC_BUILDDEVICEPATH BuildDevicePath;
+
+ MMC_NOTIFYSTATE NotifyState;
+
+ MMC_SENDCOMMAND SendCommand;
+ MMC_RECEIVERESPONSE ReceiveResponse;
+
+ MMC_READBLOCKDATA ReadBlockData;
+ MMC_WRITEBLOCKDATA WriteBlockData;
+} EFI_MMC_HOST_PROTOCOL;
+
+extern EFI_GUID gEfiMmcHostProtocolGuid;
+
+#endif
+
diff --git a/ArmPkg/Library/ArmDmaLib/ArmDmaLib.c b/ArmPkg/Library/ArmDmaLib/ArmDmaLib.c
index 7fef208c78..adea97ff29 100755
--- a/ArmPkg/Library/ArmDmaLib/ArmDmaLib.c
+++ b/ArmPkg/Library/ArmDmaLib/ArmDmaLib.c
@@ -215,7 +215,7 @@ DmaAllocateBuffer (
//
if (MemoryType == EfiBootServicesData) {
*HostAddress = UncachedAllocatePages (Pages);
- } else if (MemoryType != EfiRuntimeServicesData) {
+ } else if (MemoryType == EfiRuntimeServicesData) {
*HostAddress = UncachedAllocateRuntimePages (Pages);
} else {
return EFI_INVALID_PARAMETER;
diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c b/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c
index 710b838073..1257be8cf6 100644
--- a/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c
+++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c
@@ -31,14 +31,25 @@ FillTranslationTable (
switch (MemoryRegion->Attributes) {
case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:
- Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK;
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(0);
break;
case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:
- Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH;
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);
break;
case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK:
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(1);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH:
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(1);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED:
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(1);
+ break;
default:
- Attributes = TT_DESCRIPTOR_SECTION_UNCACHED;
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);
break;
}
@@ -93,7 +104,7 @@ ArmConfigureMmu (
MemoryTable++;
}
- ArmSetTranslationTableBaseAddress(TranslationTable);
+ ArmSetTTBR0(TranslationTable);
ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) |
DOMAIN_ACCESS_CONTROL_NONE(14) |
diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S
index 8c2ce60f5a..35774a8e62 100644
--- a/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S
+++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S
@@ -12,46 +12,29 @@
#
#------------------------------------------------------------------------------
+#include <AsmMacroIoLib.h>
+
.text
.align 2
-.globl ASM_PFX(ArmCleanInvalidateDataCache)
-INTERWORK_FUNC(ArmCleanInvalidateDataCache)
-.globl ASM_PFX(ArmCleanDataCache)
-INTERWORK_FUNC(ArmCleanDataCache)
-.globl ASM_PFX(ArmInvalidateDataCache)
-INTERWORK_FUNC(ArmInvalidateDataCache)
-.globl ASM_PFX(ArmInvalidateInstructionCache)
-INTERWORK_FUNC(ArmInvalidateInstructionCache)
-.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmInvalidateDataCacheEntryByMVA)
-.globl ASM_PFX(ArmCleanDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmCleanDataCacheEntryByMVA)
-.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmCleanInvalidateDataCacheEntryByMVA)
-.globl ASM_PFX(ArmEnableMmu)
-INTERWORK_FUNC(ArmEnableMmu)
-.globl ASM_PFX(ArmDisableMmu)
-INTERWORK_FUNC(ArmDisableMmu)
-.globl ASM_PFX(ArmMmuEnabled)
-INTERWORK_FUNC(ArmMmuEnabled)
-.globl ASM_PFX(ArmEnableDataCache)
-INTERWORK_FUNC(ArmEnableDataCache)
-.globl ASM_PFX(ArmDisableDataCache)
-INTERWORK_FUNC(ArmDisableDataCache)
-.globl ASM_PFX(ArmEnableInstructionCache)
-INTERWORK_FUNC(ArmEnableInstructionCache)
-.globl ASM_PFX(ArmDisableInstructionCache)
-INTERWORK_FUNC(ArmDisableInstructionCache)
-.globl ASM_PFX(ArmEnableBranchPrediction)
-INTERWORK_FUNC(ArmEnableBranchPrediction)
-.globl ASM_PFX(ArmDisableBranchPrediction)
-INTERWORK_FUNC(ArmDisableBranchPrediction)
-.globl ASM_PFX(ArmDataMemoryBarrier)
-INTERWORK_FUNC(ArmDataMemoryBarrier)
-.globl ASM_PFX(ArmDataSyncronizationBarrier)
-INTERWORK_FUNC(ArmDataSyncronizationBarrier)
-.globl ASM_PFX(ArmInstructionSynchronizationBarrier)
-INTERWORK_FUNC(ArmInstructionSynchronizationBarrier)
+GCC_ASM_EXPORT(ArmCleanInvalidateDataCache)
+GCC_ASM_EXPORT(ArmCleanDataCache)
+GCC_ASM_EXPORT(ArmInvalidateDataCache)
+GCC_ASM_EXPORT(ArmInvalidateInstructionCache)
+GCC_ASM_EXPORT(ArmInvalidateDataCacheEntryByMVA)
+GCC_ASM_EXPORT(ArmCleanDataCacheEntryByMVA)
+GCC_ASM_EXPORT(ArmCleanInvalidateDataCacheEntryByMVA)
+GCC_ASM_EXPORT(ArmEnableMmu)
+GCC_ASM_EXPORT(ArmDisableMmu)
+GCC_ASM_EXPORT(ArmMmuEnabled)
+GCC_ASM_EXPORT(ArmEnableDataCache)
+GCC_ASM_EXPORT(ArmDisableDataCache)
+GCC_ASM_EXPORT(ArmEnableInstructionCache)
+GCC_ASM_EXPORT(ArmDisableInstructionCache)
+GCC_ASM_EXPORT(ArmEnableBranchPrediction)
+GCC_ASM_EXPORT(ArmDisableBranchPrediction)
+GCC_ASM_EXPORT(ArmDataMemoryBarrier)
+GCC_ASM_EXPORT(ArmDataSyncronizationBarrier)
+GCC_ASM_EXPORT(ArmInstructionSynchronizationBarrier)
.set DC_ON, (0x1<<2)
@@ -116,14 +99,14 @@ ASM_PFX(ArmDisableMmu):
bx LR
ASM_PFX(ArmEnableDataCache):
- ldr R1,=DC_ON
+ LoadConstantToReg(DC_ON, R1) @ldr R1,=DC_ON
mrc p15,0,R0,c1,c0,0 @Read control register configuration data
orr R0,R0,R1 @Set C bit
mcr p15,0,r0,c1,c0,0 @Write control register configuration data
bx LR
ASM_PFX(ArmDisableDataCache):
- ldr R1,=DC_ON
+ LoadConstantToReg(DC_ON, R1) @ldr R1,=DC_ON
mrc p15,0,R0,c1,c0,0 @Read control register configuration data
bic R0,R0,R1 @Clear C bit
mcr p15,0,r0,c1,c0,0 @Write control register configuration data
diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c b/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c
index e8834ef47d..1bdc439258 100644
--- a/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c
+++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c
@@ -16,6 +16,7 @@
#include <Library/ArmLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
VOID
FillTranslationTable (
@@ -37,6 +38,12 @@ FillTranslationTable (
Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH;
break;
case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED_UNBUFFERED;
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK:
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH:
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED:
+ ASSERT(0); // Trustzone is not supported on ARMv5
default:
Attributes = TT_DESCRIPTOR_SECTION_UNCACHED_UNBUFFERED;
break;
@@ -93,7 +100,7 @@ ArmConfigureMmu (
MemoryTable++;
}
- ArmSetTranslationTableBaseAddress(TranslationTable);
+ ArmSetTTBR0(TranslationTable);
ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) |
DOMAIN_ACCESS_CONTROL_NONE(14) |
diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S
index f570f75059..8e75a3d79e 100644
--- a/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S
+++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S
@@ -14,44 +14,25 @@
.text
.align 2
-.globl ASM_PFX(ArmCleanInvalidateDataCache)
-INTERWORK_FUNC(ArmCleanInvalidateDataCache)
-.globl ASM_PFX(ArmCleanDataCache)
-INTERWORK_FUNC(ArmCleanDataCache)
-.globl ASM_PFX(ArmInvalidateDataCache)
-INTERWORK_FUNC(ArmInvalidateDataCache)
-.globl ASM_PFX(ArmInvalidateInstructionCache)
-INTERWORK_FUNC(ArmInvalidateInstructionCache)
-.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmInvalidateDataCacheEntryByMVA)
-.globl ASM_PFX(ArmCleanDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmCleanDataCacheEntryByMVA)
-.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmCleanInvalidateDataCacheEntryByMVA)
-.globl ASM_PFX(ArmEnableMmu)
-INTERWORK_FUNC(ArmEnableMmu)
-.globl ASM_PFX(ArmDisableMmu)
-INTERWORK_FUNC(ArmDisableMmu)
-.globl ASM_PFX(ArmMmuEnabled)
-INTERWORK_FUNC(ArmMmuEnabled)
-.globl ASM_PFX(ArmEnableDataCache)
-INTERWORK_FUNC(ArmEnableDataCache)
-.globl ASM_PFX(ArmDisableDataCache)
-INTERWORK_FUNC(ArmDisableDataCache)
-.globl ASM_PFX(ArmEnableInstructionCache)
-INTERWORK_FUNC(ArmEnableInstructionCache)
-.globl ASM_PFX(ArmDisableInstructionCache)
-INTERWORK_FUNC(ArmDisableInstructionCache)
-.globl ASM_PFX(ArmEnableBranchPrediction)
-INTERWORK_FUNC(ArmEnableBranchPrediction)
-.globl ASM_PFX(ArmDisableBranchPrediction)
-INTERWORK_FUNC(ArmDisableBranchPrediction)
-.globl ASM_PFX(ArmDataMemoryBarrier)
-INTERWORK_FUNC(ArmDataMemoryBarrier)
-.globl ASM_PFX(ArmDataSyncronizationBarrier)
-INTERWORK_FUNC(ArmDataSyncronizationBarrier)
-.globl ASM_PFX(ArmInstructionSynchronizationBarrier)
-INTERWORK_FUNC(ArmInstructionSynchronizationBarrier)
+GCC_ASM_EXPORT(ArmCleanInvalidateDataCache)
+GCC_ASM_EXPORT(ArmCleanDataCache)
+GCC_ASM_EXPORT(ArmInvalidateDataCache)
+GCC_ASM_EXPORT(ArmInvalidateInstructionCache)
+GCC_ASM_EXPORT(ArmInvalidateDataCacheEntryByMVA)
+GCC_ASM_EXPORT(ArmCleanDataCacheEntryByMVA)
+GCC_ASM_EXPORT(ArmCleanInvalidateDataCacheEntryByMVA)
+GCC_ASM_EXPORT(ArmEnableMmu)
+GCC_ASM_EXPORT(ArmDisableMmu)
+GCC_ASM_EXPORT(ArmMmuEnabled)
+GCC_ASM_EXPORT(ArmEnableDataCache)
+GCC_ASM_EXPORT(ArmDisableDataCache)
+GCC_ASM_EXPORT(ArmEnableInstructionCache)
+GCC_ASM_EXPORT(ArmDisableInstructionCache)
+GCC_ASM_EXPORT(ArmEnableBranchPrediction)
+GCC_ASM_EXPORT(ArmDisableBranchPrediction)
+GCC_ASM_EXPORT(ArmDataMemoryBarrier)
+GCC_ASM_EXPORT(ArmDataSyncronizationBarrier)
+GCC_ASM_EXPORT(ArmInstructionSynchronizationBarrier)
.set DC_ON, (1<<2)
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S b/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S
index 8ca37f0be0..54f36174bb 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S
@@ -12,44 +12,36 @@
#
#------------------------------------------------------------------------------
-.globl ASM_PFX(Cp15IdCode)
-INTERWORK_FUNC(Cp15IdCode)
-.globl ASM_PFX(Cp15CacheInfo)
-INTERWORK_FUNC(Cp15CacheInfo)
-.globl ASM_PFX(ArmEnableInterrupts)
-INTERWORK_FUNC(ArmEnableInterrupts)
-.globl ASM_PFX(ArmDisableInterrupts)
-INTERWORK_FUNC(ArmDisableInterrupts)
-.globl ASM_PFX(ArmGetInterruptState)
-INTERWORK_FUNC(ArmGetInterruptState)
-.globl ASM_PFX(ArmEnableFiq)
-INTERWORK_FUNC(ArmEnableFiq)
-.globl ASM_PFX(ArmDisableFiq)
-INTERWORK_FUNC(ArmDisableFiq)
-.globl ASM_PFX(ArmGetFiqState)
-INTERWORK_FUNC(ArmGetFiqState)
-.globl ASM_PFX(ArmInvalidateTlb)
-INTERWORK_FUNC(ArmInvalidateTlb)
-.globl ASM_PFX(ArmSetTranslationTableBaseAddress)
-INTERWORK_FUNC(ArmSetTranslationTableBaseAddress)
-.globl ASM_PFX(ArmGetTranslationTableBaseAddress)
-INTERWORK_FUNC(ArmGetTranslationTableBaseAddress)
-.globl ASM_PFX(ArmSetDomainAccessControl)
-INTERWORK_FUNC(ArmSetDomainAccessControl)
-.globl ASM_PFX(ArmUpdateTranslationTableEntry)
-INTERWORK_FUNC(ArmUpdateTranslationTableEntry)
-.globl ASM_PFX(CPSRMaskInsert)
-INTERWORK_FUNC(CPSRMaskInsert)
-.globl ASM_PFX(CPSRRead)
-INTERWORK_FUNC(CPSRRead)
-.globl ASM_PFX(ReadCCSIDR)
-INTERWORK_FUNC(ReadCCSIDR)
-.globl ASM_PFX(ReadCLIDR)
-INTERWORK_FUNC(ReadCLIDR)
+#include <AsmMacroIoLib.h>
.text
.align 2
+GCC_ASM_EXPORT(Cp15IdCode)
+GCC_ASM_EXPORT(Cp15CacheInfo)
+GCC_ASM_EXPORT(ArmIsMPCore)
+GCC_ASM_EXPORT(ArmEnableAsynchronousAbort)
+GCC_ASM_EXPORT(ArmDisableAsynchronousAbort)
+GCC_ASM_EXPORT(ArmEnableIrq)
+GCC_ASM_EXPORT(ArmDisableIrq)
+GCC_ASM_EXPORT(ArmGetInterruptState)
+GCC_ASM_EXPORT(ArmEnableFiq)
+GCC_ASM_EXPORT(ArmDisableFiq)
+GCC_ASM_EXPORT(ArmEnableInterrupts)
+GCC_ASM_EXPORT(ArmDisableInterrupts)
+GCC_ASM_EXPORT(ArmGetFiqState)
+GCC_ASM_EXPORT(ArmInvalidateTlb)
+GCC_ASM_EXPORT(ArmSetTTBR0)
+GCC_ASM_EXPORT(ArmGetTTBR0BaseAddress)
+GCC_ASM_EXPORT(ArmSetDomainAccessControl)
+GCC_ASM_EXPORT(ArmUpdateTranslationTableEntry)
+GCC_ASM_EXPORT(CPSRMaskInsert)
+GCC_ASM_EXPORT(CPSRRead)
+GCC_ASM_EXPORT(ReadCCSIDR)
+GCC_ASM_EXPORT(ReadCLIDR)
+
+
+
#------------------------------------------------------------------------------
ASM_PFX(Cp15IdCode):
@@ -60,35 +52,67 @@ ASM_PFX(Cp15CacheInfo):
mrc p15,0,R0,c0,c0,1
bx LR
-ASM_PFX(ArmEnableInterrupts):
+ASM_PFX(ArmIsMPCore):
+ mrc p15,0,R0,c0,c0,5
+ // Get Multiprocessing extension (bit31) & U bit (bit30)
+ and R0, R0, #0xC0000000
+ // if bit30 == 0 then the processor is part of a multiprocessor system)
+ and R0, R0, #0x80000000
+ bx LR
+
+ASM_PFX(ArmEnableAsynchronousAbort):
+ cpsie a
+ isb
+ bx LR
+
+ASM_PFX(ArmDisableAsynchronousAbort):
+ cpsid a
+ isb
+ bx LR
+
+ASM_PFX(ArmEnableIrq):
cpsie i
- bx LR
+ isb
+ bx LR
-ASM_PFX(ArmDisableInterrupts):
+ASM_PFX(ArmDisableIrq):
cpsid i
- bx LR
+ isb
+ bx LR
ASM_PFX(ArmGetInterruptState):
- mrs R0,CPSR
- tst R0,#0x80 @Check if IRQ is enabled.
- moveq R0,#1
- movne R0,#0
- bx LR
+ mrs R0,CPSR
+ tst R0,#0x80 @Check if IRQ is enabled.
+ moveq R0,#1
+ movne R0,#0
+ bx LR
ASM_PFX(ArmEnableFiq):
cpsie f
- bx LR
+ isb
+ bx LR
ASM_PFX(ArmDisableFiq):
cpsid f
- bx LR
+ isb
+ bx LR
+
+ASM_PFX(ArmEnableInterrupts):
+ cpsie if
+ isb
+ bx LR
+
+ASM_PFX(ArmDisableInterrupts):
+ cpsid if
+ isb
+ bx LR
ASM_PFX(ArmGetFiqState):
- mrs R0,CPSR
- tst R0,#0x40 @Check if FIQ is enabled.
- moveq R0,#1
- movne R0,#0
- bx LR
+ mrs R0,CPSR
+ tst R0,#0x40 @Check if FIQ is enabled.
+ moveq R0,#1
+ movne R0,#0
+ bx LR
ASM_PFX(ArmInvalidateTlb):
mov r0,#0
@@ -98,13 +122,15 @@ ASM_PFX(ArmInvalidateTlb):
isb
bx lr
-ASM_PFX(ArmSetTranslationTableBaseAddress):
+ASM_PFX(ArmSetTTBR0):
mcr p15,0,r0,c2,c0,0
isb
bx lr
-ASM_PFX(ArmGetTranslationTableBaseAddress):
+ASM_PFX(ArmGetTTBR0BaseAddress):
mrc p15,0,r0,c2,c0,0
+ LoadConstantToReg(0xFFFFC000, r1)
+ and r0, r0, r1
isb
bx lr
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm b/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm
index 08a2d900fd..7099ced8f4 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm
@@ -15,15 +15,20 @@
EXPORT Cp15IdCode
EXPORT Cp15CacheInfo
- EXPORT ArmEnableInterrupts
- EXPORT ArmDisableInterrupts
+ EXPORT ArmIsMPCore
+ EXPORT ArmEnableAsynchronousAbort
+ EXPORT ArmDisableAsynchronousAbort
+ EXPORT ArmEnableIrq
+ EXPORT ArmDisableIrq
EXPORT ArmGetInterruptState
EXPORT ArmEnableFiq
EXPORT ArmDisableFiq
+ EXPORT ArmEnableInterrupts
+ EXPORT ArmDisableInterrupts
EXPORT ArmGetFiqState
EXPORT ArmInvalidateTlb
- EXPORT ArmSetTranslationTableBaseAddress
- EXPORT ArmGetTranslationTableBaseAddress
+ EXPORT ArmSetTTBR0
+ EXPORT ArmGetTTBR0BaseAddress
EXPORT ArmSetDomainAccessControl
EXPORT ArmUpdateTranslationTableEntry
EXPORT CPSRMaskInsert
@@ -44,27 +49,59 @@ Cp15CacheInfo
mrc p15,0,R0,c0,c0,1
bx LR
-ArmEnableInterrupts
+ArmIsMPCore
+ mrc p15,0,R0,c0,c0,5
+ // Get Multiprocessing extension (bit31) & U bit (bit30)
+ and R0, R0, #0xC0000000
+ // if bit30 == 0 then the processor is part of a multiprocessor system)
+ and R0, R0, #0x80000000
+ bx LR
+
+ArmEnableAsynchronousAbort
+ cpsie a
+ isb
+ bx LR
+
+ArmDisableAsynchronousAbort
+ cpsid a
+ isb
+ bx LR
+
+ArmEnableIrq
cpsie i
+ isb
bx LR
-ArmDisableInterrupts
+ArmDisableIrq
cpsid i
- bx LR
-
-ArmGetInterruptState
- mrs R0,CPSR
- tst R0,#0x80 ;Check if IRQ is enabled.
- moveq R0,#1
- movne R0,#0
+ isb
bx LR
ArmEnableFiq
cpsie f
+ isb
bx LR
ArmDisableFiq
cpsid f
+ isb
+ bx LR
+
+ArmEnableInterrupts
+ cpsie if
+ isb
+ bx LR
+
+ArmDisableInterrupts
+ cpsid if
+ isb
+ bx LR
+
+ArmGetInterruptState
+ mrs R0,CPSR
+ tst R0,#0x80 ;Check if IRQ is enabled.
+ moveq R0,#1
+ movne R0,#0
bx LR
ArmGetFiqState
@@ -82,13 +119,15 @@ ArmInvalidateTlb
isb
bx lr
-ArmSetTranslationTableBaseAddress
+ArmSetTTBR0
mcr p15,0,r0,c2,c0,0
isb
bx lr
-ArmGetTranslationTableBaseAddress
+ArmGetTTBR0BaseAddress
mrc p15,0,r0,c2,c0,0
+ ldr r1, = 0xFFFFC000
+ and r0, r0, r1
isb
bx lr
@@ -150,7 +189,4 @@ ReadCLIDR
mrc p15,1,r0,c0,c0,1 ; Read CP15 Cache Level ID Register
bx lr
-
END
-
-
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c
index cad3c13ba4..4329bd7239 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c
@@ -15,113 +15,10 @@
#include <Chipset/ArmV7.h>
#include <Library/ArmLib.h>
#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
#include "ArmV7Lib.h"
#include "ArmLibPrivate.h"
-VOID
-FillTranslationTable (
- IN UINT32 *TranslationTable,
- IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion
- )
-{
- UINT32 *Entry;
- UINTN Sections;
- UINTN Index;
- UINT32 Attributes;
- UINT32 PhysicalBase = MemoryRegion->PhysicalBase;
-
- switch (MemoryRegion->Attributes) {
- case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:
- Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK;
- break;
- case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:
- Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH;
- break;
- case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:
- Attributes = TT_DESCRIPTOR_SECTION_DEVICE;
- break;
- case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:
- default:
- Attributes = TT_DESCRIPTOR_SECTION_UNCACHED;
- break;
- }
-
- Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase);
- Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE;
-
- for (Index = 0; Index < Sections; Index++) {
- *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;
- PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;
- }
-}
-
-VOID
-EFIAPI
-ArmConfigureMmu (
- IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable,
- OUT VOID **TranslationTableBase OPTIONAL,
- OUT UINTN *TranslationTableSize OPTIONAL
- )
-{
- VOID *TranslationTable;
-
- // Allocate pages for translation table.
- TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT));
- TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK);
-
- if (TranslationTableBase != NULL) {
- *TranslationTableBase = TranslationTable;
- }
-
- if (TranslationTableBase != NULL) {
- *TranslationTableSize = TRANSLATION_TABLE_SIZE;
- }
-
- ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE);
-
- ArmCleanInvalidateDataCache();
- ArmInvalidateInstructionCache();
- ArmInvalidateTlb();
-
- ArmDisableDataCache();
- ArmDisableInstructionCache();
- ArmDisableMmu();
-
- // Make sure nothing sneaked into the cache
- ArmCleanInvalidateDataCache();
- ArmInvalidateInstructionCache();
-
- while (MemoryTable->Length != 0) {
- FillTranslationTable(TranslationTable, MemoryTable);
- MemoryTable++;
- }
-
- ArmSetTranslationTableBaseAddress(TranslationTable);
-
- ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) |
- DOMAIN_ACCESS_CONTROL_NONE(14) |
- DOMAIN_ACCESS_CONTROL_NONE(13) |
- DOMAIN_ACCESS_CONTROL_NONE(12) |
- DOMAIN_ACCESS_CONTROL_NONE(11) |
- DOMAIN_ACCESS_CONTROL_NONE(10) |
- DOMAIN_ACCESS_CONTROL_NONE( 9) |
- DOMAIN_ACCESS_CONTROL_NONE( 8) |
- DOMAIN_ACCESS_CONTROL_NONE( 7) |
- DOMAIN_ACCESS_CONTROL_NONE( 6) |
- DOMAIN_ACCESS_CONTROL_NONE( 5) |
- DOMAIN_ACCESS_CONTROL_NONE( 4) |
- DOMAIN_ACCESS_CONTROL_NONE( 3) |
- DOMAIN_ACCESS_CONTROL_NONE( 2) |
- DOMAIN_ACCESS_CONTROL_NONE( 1) |
- DOMAIN_ACCESS_CONTROL_MANAGER(0));
-
- ArmEnableInstructionCache();
- ArmEnableDataCache();
- ArmEnableMmu();
-}
-
ARM_CACHE_TYPE
EFIAPI
ArmCacheType (
@@ -139,7 +36,7 @@ ArmCacheArchitecture (
{
UINT32 CLIDR = ReadCLIDR ();
- return CLIDR; // BugBug Fix Me
+ return (ARM_CACHE_ARCHITECTURE)CLIDR; // BugBug Fix Me
}
BOOLEAN
@@ -173,7 +70,7 @@ ArmDataCacheSize (
UINT32 LineSize;
UINT32 CCSIDR = ReadCCSIDR (0);
- LineSize = (1 << (CCSIDR + 2));
+ LineSize = (1 << ((CCSIDR & 0x7) + 2));
Associativity = ((CCSIDR >> 3) & 0x3ff) + 1;
NumSets = ((CCSIDR >> 13) & 0x7fff) + 1;
@@ -245,7 +142,7 @@ ArmInstructionCacheSize (
UINT32 LineSize;
UINT32 CCSIDR = ReadCCSIDR (1);
- LineSize = (1 << (CCSIDR + 2));
+ LineSize = (1 << ((CCSIDR & 0x7) + 2));
Associativity = ((CCSIDR >> 3) & 0x3ff) + 1;
NumSets = ((CCSIDR >> 13) & 0x7fff) + 1;
@@ -299,6 +196,8 @@ ArmV7DataCacheOperation (
UINTN SavedInterruptState;
SavedInterruptState = ArmGetInterruptState ();
+ ArmDisableInterrupts();
+
ArmV7AllDataCachesOperation (DataCacheOperation);
@@ -335,3 +234,14 @@ ArmCleanDataCache (
{
ArmV7DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
}
+
+VOID
+EFIAPI
+ArmSetAuxCrBit (
+ IN UINT32 Bits
+ )
+{
+ UINT32 val = ArmReadAuxCr();
+ val |= Bits;
+ ArmWriteAuxCr(val);
+}
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h
index 2e8c39b3b3..7eaeb15661 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h
@@ -40,5 +40,41 @@ ArmCleanInvalidateDataCacheEntryBySetWay (
IN UINT32 SetWayFormat
);
+VOID
+EFIAPI
+ArmEnableAsynchronousAbort (
+ VOID
+ );
+
+UINTN
+EFIAPI
+ArmDisableAsynchronousAbort (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmEnableIrq (
+ VOID
+ );
+
+UINTN
+EFIAPI
+ArmDisableIrq (
+ VOID
+ );
+
+VOID
+EFIAPI
+ArmEnableFiq (
+ VOID
+ );
+
+UINTN
+EFIAPI
+ArmDisableFiq (
+ VOID
+ );
+
#endif // __ARM_V7_LIB_H__
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf
index bbd2576460..2452c28734 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf
@@ -30,6 +30,7 @@
ArmV7Support.asm | RVCT
ArmV7Lib.c
+ ArmV7Mmu.c
[Packages]
ArmPkg/ArmPkg.dec
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf
index cbdef6cfb9..f97b5a4cee 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf
@@ -30,6 +30,7 @@
ArmV7Support.asm | RVCT
ArmV7Lib.c
+ ArmV7Mmu.c
[Packages]
ArmPkg/ArmPkg.dec
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf
new file mode 100644
index 0000000000..73bf09a5a3
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf
@@ -0,0 +1,40 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmV7Lib
+ FILE_GUID = 411cdfd8-f964-4b9d-a3e3-1719a9c15559
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ArmLibSupport.S | GCC
+ ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ ArmV7Support.S | GCC
+ ArmV7Support.asm | RVCT
+
+ ArmV7Lib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCore.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCore.c
new file mode 100644
index 0000000000..65c09a1a35
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCore.c
@@ -0,0 +1,57 @@
+/** @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 <Uefi.h>
+#include <Chipset/ArmV7.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include "ArmV7Lib.h"
+#include "ArmLibPrivate.h"
+
+VOID
+EFIAPI
+ArmSetupSmpNonSecure (
+ IN UINTN CoreId
+ )
+{
+ INTN scu_base;
+
+ ArmSetAuxCrBit (A9_FEATURE_SMP);
+
+ if (CoreId == 0) {
+ scu_base = ArmGetScuBaseAddress();
+
+ // Allow NS access to SCU register
+ MmioOr32(scu_base + SCU_SACR_OFFSET, 0xf);
+ // Allow NS access to Private Peripherals
+ MmioOr32(scu_base + SCU_SSACR_OFFSET, 0xfff);
+ }
+}
+
+VOID
+EFIAPI
+ArmInvalidScu (
+ VOID
+ )
+{
+ INTN scu_base;
+
+ scu_base = ArmGetScuBaseAddress();
+
+ /* Invalidate all: write -1 to SCU Invalidate All register */
+ MmioWrite32(scu_base + SCU_INVALL_OFFSET, 0xffffffff);
+ /* Enable SCU */
+ MmioWrite32(scu_base + SCU_CONTROL_OFFSET, 0x1);
+}
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.S b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.S
new file mode 100644
index 0000000000..0636897b87
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.S
@@ -0,0 +1,48 @@
+#
+# 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 <AsmMacroIoLib.h>
+#include <Base.h>
+#include <Library/PcdLib.h>
+#include <Chipset/ArmV7.h>
+#include <AutoGen.h>
+#.include AsmMacroIoLib.inc
+
+.text
+.align 2
+
+GCC_ASM_EXPORT(ArmIsScuEnable)
+GCC_ASM_EXPORT(ArmGetScuBaseAddress)
+
+# IN None
+# OUT r0 = SCU Base Address
+ASM_PFX(ArmGetScuBaseAddress):
+ # Read Configuration Base Address Register. ArmCBar cannot be called to get
+ # the Configuration BAR as a stack is not necessary setup. The SCU is at the
+ # offset 0x0000 from the Private Memory Region.
+ mrc p15, 4, r0, c15, c0, 0
+ bx lr
+
+# IN None
+# OUT r1 = SCU enabled (boolean)
+ASM_PFX(ArmIsScuEnable):
+ # Read Configuration Base Address Register. ArmCBar cannot be called to get
+ # the Configuration BAR as a stack is not necessary setup. The SCU is at the
+ # offset 0x0000 from the Private Memory Region.
+ mrc p15, 4, r0, c15, c0, 0
+ add r1, r0, #SCU_CONTROL_OFFSET
+ ldr r1, [r1]
+ and r1, r1, #1
+ bx lr
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.asm b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.asm
new file mode 100644
index 0000000000..08528fc4ec
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.asm
@@ -0,0 +1,48 @@
+//
+// 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 <AsmMacroIoLib.h>
+#include <Base.h>
+#include <Library/PcdLib.h>
+#include <Chipset/ArmV7.h>
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT ArmIsScuEnable
+ EXPORT ArmGetScuBaseAddress
+
+ AREA ArmV7MPCore, CODE, READONLY
+
+// IN None
+// OUT r0 = SCU Base Address
+ArmGetScuBaseAddress
+ // Read Configuration Base Address Register. ArmCBar cannot be called to get
+ // the Configuration BAR as a stack is not necessary setup. The SCU is at the
+ // offset 0x0000 from the Private Memory Region.
+ mrc p15, 4, r0, c15, c0, 0
+ bx lr
+
+// IN None
+// OUT r1 = SCU enabled (boolean)
+ArmIsScuEnable
+ // Read Configuration Base Address Register. ArmCBar cannot be called to get
+ // the Configuration BAR as a stack is not necessary setup. The SCU is at the
+ // offset 0x0000 from the Private Memory Region.
+ mrc p15, 4, r0, c15, c0, 0
+ add r1, r0, #SCU_CONTROL_OFFSET
+ ldr r1, [r1]
+ and r1, r1, #1
+ bx lr
+
+ END
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf
new file mode 100644
index 0000000000..c847d89eca
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf
@@ -0,0 +1,51 @@
+#/** @file
+# Helper Library for ARMv7 MPCore architecture
+
+# 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmV7Lib
+ FILE_GUID = 411cdfd8-f964-4b9d-a3e3-1719a9c15559
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ArmLibSupport.S | GCC
+ ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ ArmV7Support.S | GCC
+ ArmV7Support.asm | RVCT
+
+ ArmV7Lib.c
+ ArmV7Mmu.c
+
+ ArmV7MPCore.c
+ ArmV7MPCoreHelper.S | GCC
+ ArmV7MPCoreHelper.asm | RVCT
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf
new file mode 100644
index 0000000000..e1de26f426
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf
@@ -0,0 +1,49 @@
+#/** @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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmV7LibPrePi
+ FILE_GUID = A150FA0C-F4E8-4207-9BEB-CD6DFB430D73
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ArmLibSupport.S | GCC
+ ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ ArmV7Support.S | GCC
+ ArmV7Support.asm | RVCT
+
+ ArmV7Lib.c
+ ArmV7Mmu.c
+
+ ArmV7MPCore.c
+ ArmV7MPCoreHelper.S | GCC
+ ArmV7MPCoreHelper.asm | RVCT
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PrePiLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibSec.inf b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibSec.inf
new file mode 100644
index 0000000000..05c8d362f1
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibSec.inf
@@ -0,0 +1,43 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmV7Lib
+ FILE_GUID = 411cdfd8-f964-4b9d-a3e3-1719a9c15559
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ArmLibSupport.S | GCC
+ ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ ArmV7Support.S | GCC
+ ArmV7Support.asm | RVCT
+
+ ArmV7Lib.c
+ ArmV7MPCore.c
+ ArmV7MPCoreHelper.S | GCC
+ ArmV7MPCoreHelper.asm | RVCT
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c
new file mode 100644
index 0000000000..9bb3c2690f
--- /dev/null
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c
@@ -0,0 +1,162 @@
+/** @file
+* File managing the MMU for ARMv7 architecture
+*
+* 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 <Uefi.h>
+#include <Chipset/ArmV7.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include "ArmV7Lib.h"
+#include "ArmLibPrivate.h"
+
+VOID
+FillTranslationTable (
+ IN UINT32 *TranslationTable,
+ IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion
+ )
+{
+ UINT32 *Entry;
+ UINTN Sections;
+ UINTN Index;
+ UINT32 Attributes;
+ UINT32 PhysicalBase = MemoryRegion->PhysicalBase;
+
+ switch (MemoryRegion->Attributes) {
+ case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(0);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:
+ Attributes = TT_DESCRIPTOR_SECTION_DEVICE(0);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK:
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK(1);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH:
+ Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH(1);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_DEVICE:
+ Attributes = TT_DESCRIPTOR_SECTION_DEVICE(1);
+ break;
+ case ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED:
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(1);
+ break;
+ default:
+ Attributes = TT_DESCRIPTOR_SECTION_UNCACHED(0);
+ break;
+ }
+
+ Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase);
+ Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE;
+
+ for (Index = 0; Index < Sections; Index++) {
+ *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;
+ PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;
+ }
+}
+
+VOID
+EFIAPI
+ArmConfigureMmu (
+ IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable,
+ OUT VOID **TranslationTableBase OPTIONAL,
+ OUT UINTN *TranslationTableSize OPTIONAL
+ )
+{
+ UINTN TranslationTable;
+ ARM_MEMORY_REGION_ATTRIBUTES TranslationTableAttribute;
+ UINT32 TTBRAttributes;
+
+ // Allocate pages for translation table.
+ TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SECTION_SIZE + TRANSLATION_TABLE_SECTION_ALIGNMENT));
+ TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK;
+
+ if (TranslationTableBase != NULL) {
+ *TranslationTableBase = (VOID *)TranslationTable;
+ }
+
+ if (TranslationTableBase != NULL) {
+ *TranslationTableSize = TRANSLATION_TABLE_SECTION_SIZE;
+ }
+
+ ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);
+
+ ArmCleanInvalidateDataCache();
+ ArmInvalidateInstructionCache();
+ ArmInvalidateTlb();
+
+ ArmDisableDataCache();
+ ArmDisableInstructionCache();
+ ArmDisableMmu();
+
+ // Make sure nothing sneaked into the cache
+ ArmCleanInvalidateDataCache();
+ ArmInvalidateInstructionCache();
+
+ TranslationTableAttribute = 0;
+ while (MemoryTable->Length != 0) {
+ // Find the memory attribute for the Translation Table
+ if ((TranslationTable >= MemoryTable->PhysicalBase) && (TranslationTable < MemoryTable->PhysicalBase + MemoryTable->Length)) {
+ TranslationTableAttribute = MemoryTable->Attributes;
+ }
+
+ FillTranslationTable ((VOID *)TranslationTable, MemoryTable);
+ MemoryTable++;
+ }
+
+ // Translate the Memory Attributes into Translation Table Register Attributes
+ if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED) ||
+ (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_SECURE_UNCACHED_UNBUFFERED)) {
+ TTBRAttributes = TTBR_NON_CACHEABLE;
+ } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) ||
+ (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_BACK)) {
+ TTBRAttributes = TTBR_WRITE_BACK_ALLOC;
+ } else if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH) ||
+ (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_SECURE_WRITE_THROUGH)) {
+ TTBRAttributes = TTBR_WRITE_THROUGH_NO_ALLOC;
+ } else {
+ //TODO: We should raise an error here
+ TTBRAttributes = TTBR_NON_CACHEABLE;
+ }
+
+ ArmSetTTBR0 ((VOID *)(UINTN)((TranslationTable & 0xFFFFC000) | (TTBRAttributes & 0x7F)));
+
+ ArmSetDomainAccessControl (DOMAIN_ACCESS_CONTROL_NONE(15) |
+ DOMAIN_ACCESS_CONTROL_NONE(14) |
+ DOMAIN_ACCESS_CONTROL_NONE(13) |
+ DOMAIN_ACCESS_CONTROL_NONE(12) |
+ DOMAIN_ACCESS_CONTROL_NONE(11) |
+ DOMAIN_ACCESS_CONTROL_NONE(10) |
+ DOMAIN_ACCESS_CONTROL_NONE( 9) |
+ DOMAIN_ACCESS_CONTROL_NONE( 8) |
+ DOMAIN_ACCESS_CONTROL_NONE( 7) |
+ DOMAIN_ACCESS_CONTROL_NONE( 6) |
+ DOMAIN_ACCESS_CONTROL_NONE( 5) |
+ DOMAIN_ACCESS_CONTROL_NONE( 4) |
+ DOMAIN_ACCESS_CONTROL_NONE( 3) |
+ DOMAIN_ACCESS_CONTROL_NONE( 2) |
+ DOMAIN_ACCESS_CONTROL_NONE( 1) |
+ DOMAIN_ACCESS_CONTROL_MANAGER(0));
+
+ ArmEnableInstructionCache();
+ ArmEnableDataCache();
+ ArmEnableMmu();
+}
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S
index 991de89a96..cfbb8f545c 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S
@@ -12,55 +12,51 @@
#
#------------------------------------------------------------------------------
-.globl ASM_PFX(ArmInvalidateInstructionCache)
-INTERWORK_FUNC(ArmInvalidateInstructionCache)
-.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmInvalidateDataCacheEntryByMVA)
-.globl ASM_PFX(ArmCleanDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmCleanDataCacheEntryByMVA)
-.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA)
-INTERWORK_FUNC(ArmCleanInvalidateDataCacheEntryByMVA)
-.globl ASM_PFX(ArmInvalidateDataCacheEntryBySetWay)
-INTERWORK_FUNC(ArmInvalidateDataCacheEntryBySetWay)
-.globl ASM_PFX(ArmCleanDataCacheEntryBySetWay)
-INTERWORK_FUNC(ArmCleanDataCacheEntryBySetWay)
-.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryBySetWay)
-INTERWORK_FUNC(ArmCleanInvalidateDataCacheEntryBySetWay)
-.globl ASM_PFX(ArmDrainWriteBuffer)
-INTERWORK_FUNC(ArmDrainWriteBuffer)
-.globl ASM_PFX(ArmEnableMmu)
-INTERWORK_FUNC(ArmEnableMmu)
-.globl ASM_PFX(ArmDisableMmu)
-INTERWORK_FUNC(ArmDisableMmu)
-.globl ASM_PFX(ArmMmuEnabled)
-INTERWORK_FUNC(ArmMmuEnabled)
-.globl ASM_PFX(ArmEnableDataCache)
-INTERWORK_FUNC(ArmEnableDataCache)
-.globl ASM_PFX(ArmDisableDataCache)
-INTERWORK_FUNC(ArmDisableDataCache)
-.globl ASM_PFX(ArmEnableInstructionCache)
-INTERWORK_FUNC(ArmEnableInstructionCache)
-.globl ASM_PFX(ArmDisableInstructionCache)
-INTERWORK_FUNC(ArmDisableInstructionCache)
-.globl ASM_PFX(ArmEnableBranchPrediction)
-INTERWORK_FUNC(ArmEnableBranchPrediction)
-.globl ASM_PFX(ArmDisableBranchPrediction)
-INTERWORK_FUNC(ArmDisableBranchPrediction)
-.globl ASM_PFX(ArmV7AllDataCachesOperation)
-INTERWORK_FUNC(ArmV7AllDataCachesOperation)
-.globl ASM_PFX(ArmDataMemoryBarrier)
-INTERWORK_FUNC(ArmDataMemoryBarrier)
-.globl ASM_PFX(ArmDataSyncronizationBarrier)
-INTERWORK_FUNC(ArmDataSyncronizationBarrier)
-.globl ASM_PFX(ArmInstructionSynchronizationBarrier)
-INTERWORK_FUNC(ArmInstructionSynchronizationBarrier)
-
.text
.align 2
+GCC_ASM_EXPORT (ArmInvalidateInstructionCache)
+GCC_ASM_EXPORT (ArmInvalidateDataCacheEntryByMVA)
+GCC_ASM_EXPORT (ArmCleanDataCacheEntryByMVA)
+GCC_ASM_EXPORT (ArmCleanInvalidateDataCacheEntryByMVA)
+GCC_ASM_EXPORT (ArmInvalidateDataCacheEntryBySetWay)
+GCC_ASM_EXPORT (ArmCleanDataCacheEntryBySetWay)
+GCC_ASM_EXPORT (ArmCleanInvalidateDataCacheEntryBySetWay)
+GCC_ASM_EXPORT (ArmDrainWriteBuffer)
+GCC_ASM_EXPORT (ArmEnableMmu)
+GCC_ASM_EXPORT (ArmDisableMmu)
+GCC_ASM_EXPORT (ArmDisableCachesAndMmu)
+GCC_ASM_EXPORT (ArmMmuEnabled)
+GCC_ASM_EXPORT (ArmEnableDataCache)
+GCC_ASM_EXPORT (ArmDisableDataCache)
+GCC_ASM_EXPORT (ArmEnableInstructionCache)
+GCC_ASM_EXPORT (ArmDisableInstructionCache)
+GCC_ASM_EXPORT (ArmEnableSWPInstruction)
+GCC_ASM_EXPORT (ArmEnableBranchPrediction)
+GCC_ASM_EXPORT (ArmDisableBranchPrediction)
+GCC_ASM_EXPORT (ArmV7AllDataCachesOperation)
+GCC_ASM_EXPORT (ArmDataMemoryBarrier)
+GCC_ASM_EXPORT (ArmDataSyncronizationBarrier)
+GCC_ASM_EXPORT (ArmInstructionSynchronizationBarrier)
+GCC_ASM_EXPORT (ArmWriteNsacr)
+GCC_ASM_EXPORT (ArmWriteScr)
+GCC_ASM_EXPORT (ArmWriteVMBar)
+GCC_ASM_EXPORT (ArmWriteVBar)
+GCC_ASM_EXPORT (ArmWriteCPACR)
+GCC_ASM_EXPORT (ArmEnableVFP)
+GCC_ASM_EXPORT (ArmCallWFI)
+GCC_ASM_EXPORT (ArmWriteAuxCr)
+GCC_ASM_EXPORT (ArmReadAuxCr)
+GCC_ASM_EXPORT (ArmReadCbar)
+GCC_ASM_EXPORT (ArmInvalidateInstructionAndDataTlb)
+GCC_ASM_EXPORT (ArmReadMpidr)
+
.set DC_ON, (0x1<<2)
.set IC_ON, (0x1<<12)
-
+.set CTRL_M_BIT, (1 << 0)
+.set CTRL_C_BIT, (1 << 2)
+.set CTRL_B_BIT, (1 << 7)
+.set CTRL_I_BIT, (1 << 12)
ASM_PFX(ArmInvalidateDataCacheEntryByMVA):
@@ -69,7 +65,6 @@ ASM_PFX(ArmInvalidateDataCacheEntryByMVA):
isb
bx lr
-
ASM_PFX(ArmCleanDataCacheEntryByMVA):
mcr p15, 0, r0, c7, c10, 1 @clean single data cache line
dsb
@@ -104,7 +99,6 @@ ASM_PFX(ArmCleanDataCacheEntryBySetWay):
isb
bx lr
-
ASM_PFX(ArmInvalidateInstructionCache):
mcr p15,0,R0,c7,c5,0 @Invalidate entire instruction cache
dsb
@@ -119,10 +113,6 @@ ASM_PFX(ArmEnableMmu):
isb
bx LR
-ASM_PFX(ArmMmuEnabled):
- mrc p15,0,R0,c1,c0,0
- and R0,R0,#1
- bx LR
ASM_PFX(ArmDisableMmu):
mrc p15,0,R0,c1,c0,0
@@ -135,6 +125,21 @@ ASM_PFX(ArmDisableMmu):
isb
bx LR
+ASM_PFX(ArmDisableCachesAndMmu):
+ mrc p15, 0, r0, c1, c0, 0 @ Get control register
+ bic r0, r0, #CTRL_M_BIT @ Disable MMU
+ bic r0, r0, #CTRL_C_BIT @ Disable D Cache
+ bic r0, r0, #CTRL_I_BIT @ Disable I Cache
+ mcr p15, 0, r0, c1, c0, 0 @ Write control register
+ dsb
+ isb
+ bx LR
+
+ASM_PFX(ArmMmuEnabled):
+ mrc p15,0,R0,c1,c0,0
+ and R0,R0,#1
+ bx LR
+
ASM_PFX(ArmEnableDataCache):
ldr R1,=DC_ON
mrc p15,0,R0,c1,c0,0 @Read control register configuration data
@@ -171,6 +176,13 @@ ASM_PFX(ArmDisableInstructionCache):
isb
bx LR
+ASM_PFX(ArmEnableSWPInstruction):
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #0x00000400
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+ bx LR
+
ASM_PFX(ArmEnableBranchPrediction):
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0x00000800
@@ -254,5 +266,59 @@ ASM_PFX(ArmInstructionSynchronizationBarrier):
isb
bx LR
+ASM_PFX(ArmWriteNsacr):
+ mcr p15, 0, r0, c1, c1, 2
+ bx lr
+
+ASM_PFX(ArmWriteScr):
+ mcr p15, 0, r0, c1, c1, 0
+ bx lr
+
+ASM_PFX(ArmWriteAuxCr):
+ mcr p15, 0, r0, c1, c0, 1
+ bx lr
+
+ASM_PFX(ArmReadAuxCr):
+ mrc p15, 0, r0, c1, c0, 1
+ bx lr
+
+ASM_PFX(ArmWriteVMBar):
+ mcr p15, 0, r0, c12, c0, 1
+ bx lr
+
+ASM_PFX(ArmWriteVBar):
+ mcr p15, 0, r0, c12, c0, 0
+ bx lr
+
+ASM_PFX(ArmWriteCPACR):
+ mcr p15, 0, r0, c1, c0, 2
+ bx lr
+
+ASM_PFX(ArmEnableVFP):
+ // Enable VFP registers
+ mrc p15, 0, r0, c1, c0, 2
+ orr r0, r0, #0x00f00000 // Enable VPF access (V* instructions)
+ mcr p15, 0, r0, c1, c0, 2
+ mov r0, #0x40000000 // Set EN bit in FPEXC
+ mcr p10,#0x7,r0,c8,c0,#0 // msr FPEXC,r0 in ARM assembly
+ bx lr
+
+ASM_PFX(ArmCallWFI):
+ wfi
+ bx lr
+
+//Note: Return 0 in Uniprocessor implementation
+ASM_PFX(ArmReadCbar):
+ mrc p15, 4, r0, c15, c0, 0 //Read Configuration Base Address Register
+ bx lr
+
+ASM_PFX(ArmInvalidateInstructionAndDataTlb):
+ mcr p15, 0, r0, c8, c7, 0 @ Invalidate Inst TLB and Data TLB
+ dsb
+ bx lr
+
+ASM_PFX(ArmReadMpidr):
+ mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
+ bx lr
ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm
index 8758b80ba5..7b4ca425bd 100644
--- a/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm
+++ b/ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm
@@ -22,24 +22,42 @@
EXPORT ArmDrainWriteBuffer
EXPORT ArmEnableMmu
EXPORT ArmDisableMmu
+ EXPORT ArmDisableCachesAndMmu
EXPORT ArmMmuEnabled
EXPORT ArmEnableDataCache
EXPORT ArmDisableDataCache
EXPORT ArmEnableInstructionCache
EXPORT ArmDisableInstructionCache
+ EXPORT ArmEnableSWPInstruction
EXPORT ArmEnableBranchPrediction
EXPORT ArmDisableBranchPrediction
EXPORT ArmV7AllDataCachesOperation
EXPORT ArmDataMemoryBarrier
EXPORT ArmDataSyncronizationBarrier
EXPORT ArmInstructionSynchronizationBarrier
+ EXPORT ArmWriteNsacr
+ EXPORT ArmWriteScr
+ EXPORT ArmWriteVMBar
+ EXPORT ArmWriteVBar
+ EXPORT ArmReadVBar
+ EXPORT ArmWriteCPACR
+ EXPORT ArmEnableVFP
+ EXPORT ArmCallWFI
+ EXPORT ArmWriteAuxCr
+ EXPORT ArmReadAuxCr
+ EXPORT ArmReadCbar
+ EXPORT ArmInvalidateInstructionAndDataTlb
+ EXPORT ArmReadMpidr
AREA ArmCacheLib, CODE, READONLY
PRESERVE8
-DC_ON EQU ( 0x1:SHL:2 )
-IC_ON EQU ( 0x1:SHL:12 )
-
+DC_ON EQU ( 0x1:SHL:2 )
+IC_ON EQU ( 0x1:SHL:12 )
+CTRL_M_BIT EQU (1 << 0)
+CTRL_C_BIT EQU (1 << 2)
+CTRL_B_BIT EQU (1 << 7)
+CTRL_I_BIT EQU (1 << 12)
ArmInvalidateDataCacheEntryByMVA
@@ -90,75 +108,91 @@ ArmInvalidateInstructionCache
bx LR
ArmEnableMmu
- mrc p15,0,R0,c1,c0,0
- orr R0,R0,#1
- mcr p15,0,R0,c1,c0,0
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
+ orr R0,R0,#1 ; Set SCTLR.M bit : Enable MMU
+ mcr p15,0,R0,c1,c0,0 ; Write R0 into SCTLR (Write control register configuration data)
dsb
isb
bx LR
ArmMmuEnabled
- mrc p15,0,R0,c1,c0,0
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
and R0,R0,#1
bx LR
ArmDisableMmu
- mrc p15,0,R0,c1,c0,0
- bic R0,R0,#1
- mcr p15,0,R0,c1,c0,0 ;Disable MMU
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
+ bic R0,R0,#1 ; Clear SCTLR.M bit : Disable MMU
+ mcr p15,0,R0,c1,c0,0 ; Write R0 into SCTLR (Write control register configuration data)
- mcr p15,0,R0,c8,c7,0 ;Invalidate TLB
- mcr p15,0,R0,c7,c5,6 ;Invalidate Branch predictor array
+ mcr p15,0,R0,c8,c7,0 ; TLBIALL : Invalidate unified TLB
+ mcr p15,0,R0,c7,c5,6 ; BPIALL : Invalidate entire branch predictor array
dsb
isb
bx LR
+ArmDisableCachesAndMmu
+ mrc p15, 0, r0, c1, c0, 0 ; Get control register
+ bic r0, r0, #CTRL_M_BIT ; Disable MMU
+ bic r0, r0, #CTRL_C_BIT ; Disable D Cache
+ bic r0, r0, #CTRL_I_BIT ; Disable I Cache
+ mcr p15, 0, r0, c1, c0, 0 ; Write control register
+ dsb
+ isb
+ bx LR
ArmEnableDataCache
- ldr R1,=DC_ON
- mrc p15,0,R0,c1,c0,0 ;Read control register configuration data
- orr R0,R0,R1 ;Set C bit
- mcr p15,0,R0,c1,c0,0 ;Write control register configuration data
+ ldr R1,=DC_ON ; Specify SCTLR.C bit : (Data) Cache enable bit
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
+ orr R0,R0,R1 ; Set SCTLR.C bit : Data and unified caches enabled
+ mcr p15,0,R0,c1,c0,0 ; Write R0 into SCTLR (Write control register configuration data)
dsb
isb
bx LR
ArmDisableDataCache
- ldr R1,=DC_ON
- mrc p15,0,R0,c1,c0,0 ;Read control register configuration data
- bic R0,R0,R1 ;Clear C bit
- mcr p15,0,R0,c1,c0,0 ;Write control register configuration data
+ ldr R1,=DC_ON ; Specify SCTLR.C bit : (Data) Cache enable bit
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
+ bic R0,R0,R1 ; Clear SCTLR.C bit : Data and unified caches disabled
+ mcr p15,0,R0,c1,c0,0 ; Write R0 into SCTLR (Write control register configuration data)
isb
bx LR
ArmEnableInstructionCache
- ldr R1,=IC_ON
- mrc p15,0,R0,c1,c0,0 ;Read control register configuration data
- orr R0,R0,R1 ;Set I bit
- mcr p15,0,R0,c1,c0,0 ;Write control register configuration data
+ ldr R1,=IC_ON ; Specify SCTLR.I bit : Instruction cache enable bit
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
+ orr R0,R0,R1 ; Set SCTLR.I bit : Instruction caches enabled
+ mcr p15,0,R0,c1,c0,0 ; Write R0 into SCTLR (Write control register configuration data)
dsb
isb
bx LR
ArmDisableInstructionCache
- ldr R1,=IC_ON
- mrc p15,0,R0,c1,c0,0 ;Read control register configuration data
- BIC R0,R0,R1 ;Clear I bit.
- mcr p15,0,R0,c1,c0,0 ;Write control register configuration data
+ ldr R1,=IC_ON ; Specify SCTLR.I bit : Instruction cache enable bit
+ mrc p15,0,R0,c1,c0,0 ; Read SCTLR into R0 (Read control register configuration data)
+ BIC R0,R0,R1 ; Clear SCTLR.I bit : Instruction caches disabled
+ mcr p15,0,R0,c1,c0,0 ; Write R0 into SCTLR (Write control register configuration data)
isb
bx LR
-ArmEnableBranchPrediction
+ArmEnableSWPInstruction
mrc p15, 0, r0, c1, c0, 0
- orr r0, r0, #0x00000800
+ orr r0, r0, #0x00000400
mcr p15, 0, r0, c1, c0, 0
isb
bx LR
+ArmEnableBranchPrediction
+ mrc p15, 0, r0, c1, c0, 0 ; Read SCTLR into R0 (Read control register configuration data)
+ orr r0, r0, #0x00000800 ;
+ mcr p15, 0, r0, c1, c0, 0 ; Write R0 into SCTLR (Write control register configuration data)
+ isb
+ bx LR
+
ArmDisableBranchPrediction
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00000800
- mcr p15, 0, r0, c1, c0, 0
+ mrc p15, 0, r0, c1, c0, 0 ; Read SCTLR into R0 (Read control register configuration data)
+ bic r0, r0, #0x00000800 ;
+ mcr p15, 0, r0, c1, c0, 0 ; Write R0 into SCTLR (Write control register configuration data)
isb
bx LR
@@ -173,9 +207,9 @@ ArmV7AllDataCachesOperation
mov R10, #0
Loop1
- add R2, R10, R10, LSR #1 ; Work out 3xcachelevel
- mov R12, R6, LSR R2 ; bottom 3 bits are the Cache type for this level
- and R12, R12, #7 ; get those 3 bits alone
+ add R2, R10, R10, LSR #1 ; Work out 3xcachelevel
+ mov R12, R6, LSR R2 ; bottom 3 bits are the Cache type for this level
+ and R12, R12, #7 ; get those 3 bits alone
cmp R12, #2
blt Skip ; no cache or only instruction cache at this level
mcr p15, 2, R10, c0, c0, 0 ; write the Cache Size selection register (CSSELR) // OR in 1 for Instruction
@@ -226,5 +260,64 @@ ArmInstructionSynchronizationBarrier
isb
bx LR
- END
+ArmWriteNsacr
+ mcr p15, 0, r0, c1, c1, 2
+ bx lr
+
+ArmWriteScr
+ mcr p15, 0, r0, c1, c1, 0
+ bx lr
+
+ArmWriteAuxCr
+ mcr p15, 0, r0, c1, c0, 1
+ bx lr
+
+ArmReadAuxCr
+ mrc p15, 0, r0, c1, c0, 1
+ bx lr
+
+ArmWriteVMBar
+ mcr p15, 0, r0, c12, c0, 1
+ bx lr
+
+ArmWriteVBar
+ mcr p15, 0, r0, c12, c0, 0
+ bx lr
+
+ArmReadVBar
+ mrc p15, 0, r0, c12, c0, 0
+ bx lr
+
+ArmWriteCPACR
+ mcr p15, 0, r0, c1, c0, 2
+ bx lr
+
+ArmEnableVFP
+ // Enable VFP registers
+ mrc p15, 0, r0, c1, c0, 2
+ orr r0, r0, #0x00f00000 // Enable VPF access (V* instructions)
+ mcr p15, 0, r0, c1, c0, 2
+ mov r0, #0x40000000 // Set EN bit in FPEXC
+ mcr p10,#0x7,r0,c8,c0,#0 // msr FPEXC,r0 in ARM assembly
+ bx lr
+
+ArmCallWFI
+ wfi
+ bx lr
+
+//Note: Return 0 in Uniprocessor implementation
+ArmReadCbar
+ mrc p15, 4, r0, c15, c0, 0 //Read Configuration Base Address Register
+ bx lr
+
+ArmInvalidateInstructionAndDataTlb
+ mcr p15, 0, r0, c8, c7, 0 ; Invalidate Inst TLB and Data TLB
+ dsb
+ bx lr
+
+ArmReadMpidr
+ mrc p15, 0, r0, c0, c0, 5 ; read MPIDR
+ bx lr
+
+ END
diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S
index a432acbb80..9b144c82c5 100644
--- a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S
+++ b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S
@@ -12,37 +12,24 @@
#
#------------------------------------------------------------------------------
+#include <AsmMacroIoLib.h>
+
.text
.align 2
-.globl ASM_PFX(Cp15IdCode)
-INTERWORK_FUNC(Cp15IdCode)
-.globl ASM_PFX(Cp15CacheInfo)
-INTERWORK_FUNC(Cp15CacheInfo)
-.globl ASM_PFX(ArmEnableInterrupts)
-INTERWORK_FUNC(ArmEnableInterrupts)
-.globl ASM_PFX(ArmDisableInterrupts)
-INTERWORK_FUNC(ArmDisableInterrupts)
-.globl ASM_PFX(ArmGetInterruptState)
-INTERWORK_FUNC(ArmGetInterruptState)
-.globl ASM_PFX(ArmEnableFiq)
-INTERWORK_FUNC(ArmEnableFiq)
-.globl ASM_PFX(ArmDisableFiq)
-INTERWORK_FUNC(ArmDisableFiq)
-.globl ASM_PFX(ArmGetFiqState)
-INTERWORK_FUNC(ArmGetFiqState)
-.globl ASM_PFX(ArmInvalidateTlb)
-INTERWORK_FUNC(ArmInvalidateTlb)
-.globl ASM_PFX(ArmSetTranslationTableBaseAddress)
-INTERWORK_FUNC(ArmSetTranslationTableBaseAddress)
-.globl ASM_PFX(ArmGetTranslationTableBaseAddress)
-INTERWORK_FUNC(ArmGetTranslationTableBaseAddress)
-.globl ASM_PFX(ArmSetDomainAccessControl)
-INTERWORK_FUNC(ArmSetDomainAccessControl)
-.globl ASM_PFX(CPSRMaskInsert)
-INTERWORK_FUNC(CPSRMaskInsert)
-.globl ASM_PFX(CPSRRead)
-INTERWORK_FUNC(CPSRRead)
-
+GCC_ASM_EXPORT(Cp15IdCode)
+GCC_ASM_EXPORT(Cp15CacheInfo)
+GCC_ASM_EXPORT(ArmEnableInterrupts)
+GCC_ASM_EXPORT(ArmDisableInterrupts)
+GCC_ASM_EXPORT(ArmGetInterruptState)
+GCC_ASM_EXPORT(ArmEnableFiq)
+GCC_ASM_EXPORT(ArmDisableFiq)
+GCC_ASM_EXPORT(ArmGetFiqState)
+GCC_ASM_EXPORT(ArmInvalidateTlb)
+GCC_ASM_EXPORT(ArmSetTTBR0)
+GCC_ASM_EXPORT(ArmGetTTBR0BaseAddress)
+GCC_ASM_EXPORT(ArmSetDomainAccessControl)
+GCC_ASM_EXPORT(CPSRMaskInsert)
+GCC_ASM_EXPORT(CPSRRead)
#------------------------------------------------------------------------------
@@ -103,12 +90,14 @@ ASM_PFX(ArmInvalidateTlb):
mcr p15,0,r0,c8,c7,0
bx lr
-ASM_PFX(ArmSetTranslationTableBaseAddress):
+ASM_PFX(ArmSetTTBR0):
mcr p15,0,r0,c2,c0,0
bx lr
-ASM_PFX(ArmGetTranslationTableBaseAddress):
+ASM_PFX(ArmGetTTBR0BaseAddress):
mrc p15,0,r0,c2,c0,0
+ LoadConstantToReg(0xFFFFC000, r1) @ and r0, r0, #0xFFFFC000
+ and r0, r0, r1
bx lr
diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm
index 459ebd44c8..cf7605f45a 100644
--- a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm
+++ b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm
@@ -15,6 +15,7 @@
EXPORT Cp15IdCode
EXPORT Cp15CacheInfo
+ EXPORT ArmIsMPCore
EXPORT ArmEnableInterrupts
EXPORT ArmDisableInterrupts
EXPORT ArmGetInterruptState
@@ -22,8 +23,8 @@
EXPORT ArmDisableFiq
EXPORT ArmGetFiqState
EXPORT ArmInvalidateTlb
- EXPORT ArmSetTranslationTableBaseAddress
- EXPORT ArmGetTranslationTableBaseAddress
+ EXPORT ArmSetTTBR0
+ EXPORT ArmGetTTBR0BaseAddress
EXPORT ArmSetDomainAccessControl
EXPORT CPSRMaskInsert
EXPORT CPSRRead
@@ -38,6 +39,14 @@ Cp15CacheInfo
mrc p15,0,R0,c0,c0,1
bx LR
+ArmIsMPCore
+ mrc p15,0,R0,c0,c0,5
+ # Get Multiprocessing extension (bit31) & U bit (bit30)
+ and R0, R0, #0xC0000000
+ # if bit30 == 0 then the processor is part of a multiprocessor system)
+ and R0, R0, #0x80000000
+ bx LR
+
ArmEnableInterrupts
mrs R0,CPSR
bic R0,R0,#0x80 ;Enable IRQ interrupts
@@ -87,12 +96,13 @@ ArmInvalidateTlb
mcr p15,0,r0,c8,c7,0
bx lr
-ArmSetTranslationTableBaseAddress
+ArmSetTTBR0
mcr p15,0,r0,c2,c0,0
bx lr
-ArmGetTranslationTableBaseAddress
+ArmGetTTBR0BaseAddress
mrc p15,0,r0,c2,c0,0
+ and r0, r0, #0xFFFFC000
bx lr
ArmSetDomainAccessControl
diff --git a/ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBox.c b/ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBox.c
new file mode 100644
index 0000000000..7648780e52
--- /dev/null
+++ b/ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBox.c
@@ -0,0 +1,25 @@
+/** @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 <Library/ArmMPCoreMailBoxLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+
+VOID ArmClearMPCoreMailbox() {
+ MmioWrite32(PcdGet32(PcdMPCoreMailboxClearAddress),PcdGet32(PcdMPCoreMailboxClearValue));
+}
+
+UINTN ArmGetMPCoreMailbox() {
+ return MmioRead32(PcdGet32(PcdMPCoreMailboxGetAddress));
+}
diff --git a/ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf b/ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf
new file mode 100644
index 0000000000..9003f1db2f
--- /dev/null
+++ b/ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf
@@ -0,0 +1,37 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmMPCoreMailBoxLib
+ FILE_GUID = de76d780-f422-11df-967a-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmMPCoreMailBoxLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ IoLib
+
+[Sources.common]
+ ArmMPCoreMailBox.c
+
+[Protocols]
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdMPCoreMailboxGetAddress
+ gArmTokenSpaceGuid.PcdMPCoreMailboxClearAddress
+ gArmTokenSpaceGuid.PcdMPCoreMailboxClearValue
diff --git a/ArmPkg/Library/ArmTrustZoneLib/ArmTrustZone.c b/ArmPkg/Library/ArmTrustZoneLib/ArmTrustZone.c
new file mode 100644
index 0000000000..ed9abe37f7
--- /dev/null
+++ b/ArmPkg/Library/ArmTrustZoneLib/ArmTrustZone.c
@@ -0,0 +1,79 @@
+/** @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 <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/ArmTrustZoneLib.h>
+
+#define TZPC_DECPROT0_STATUS_REG 0x800
+#define TZPC_DECPROT0_SET_REG 0x804
+#define TZPC_DECPROT0_CLEAR_REG 0x808
+
+#define TZASC_CONFIGURATION_REG 0x000
+#define TZASC_REGIONS_REG 0x100
+#define TZASC_REGION0_LOW_ADDRESS_REG 0x100
+#define TZASC_REGION0_HIGH_ADDRESS_REG 0x104
+#define TZASC_REGION0_ATTRIBUTES 0x108
+
+/**
+ FIXME: Need documentation
+**/
+EFI_STATUS TZPCSetDecProtBits(UINTN TzpcBase, UINTN TzpcId, UINTN Bits) {
+ if (TzpcId > TZPC_DECPROT_MAX) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32((UINTN)TzpcBase + TZPC_DECPROT0_SET_REG + (TzpcId * 0x0C), Bits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ FIXME: Need documentation
+**/
+EFI_STATUS TZPCClearDecProtBits(UINTN TzpcBase, UINTN TzpcId, UINTN Bits) {
+ if (TzpcId> TZPC_DECPROT_MAX) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32((UINTN)TzpcBase + TZPC_DECPROT0_CLEAR_REG + (TzpcId * 0x0C), Bits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ FIXME: Need documentation
+**/
+UINT32 TZASCGetNumRegions(UINTN TzascBase) {
+ return (MmioRead32((UINTN)TzascBase + TZASC_CONFIGURATION_REG) & 0xF);
+}
+
+/**
+ FIXME: Need documentation
+**/
+EFI_STATUS TZASCSetRegion(UINTN TzascBase, UINTN RegionId, UINTN Enabled, UINTN LowAddress, UINTN HighAddress, UINTN Size, UINTN Security) {
+ UINT32* Region;
+
+ if (RegionId > TZASCGetNumRegions(TzascBase)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Region = (UINT32*)((UINTN)TzascBase + TZASC_REGIONS_REG + (RegionId * 0x10));
+
+ MmioWrite32((UINTN)(Region), LowAddress&0xFFFF8000);
+ MmioWrite32((UINTN)(Region+1), HighAddress);
+ MmioWrite32((UINTN)(Region+2), ((Security & 0xF) <<28) | ((Size & 0x3F) << 1) | (Enabled & 0x1));
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf b/ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf
new file mode 100644
index 0000000000..fae82068e6
--- /dev/null
+++ b/ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf
@@ -0,0 +1,32 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmTrustZoneLib
+ FILE_GUID = 5962d040-8b8a-11df-9a71-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmTrustZoneLib
+
+
+[Sources.common]
+ ArmTrustZone.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
diff --git a/ArmPkg/Library/BaseMemoryLibStm/Arm/CopyMem.S b/ArmPkg/Library/BaseMemoryLibStm/Arm/CopyMem.S
index 1cd1dae54f..8339a10195 100755
--- a/ArmPkg/Library/BaseMemoryLibStm/Arm/CopyMem.S
+++ b/ArmPkg/Library/BaseMemoryLibStm/Arm/CopyMem.S
@@ -39,8 +39,7 @@ InternalMemCopyMem (
**/
.text
.align 2
-.globl ASM_PFX(InternalMemCopyMem)
-INTERWORK_FUNC(InternalMemCopyMem)
+GCC_ASM_EXPORT(InternalMemCopyMem)
ASM_PFX(InternalMemCopyMem):
stmfd sp!, {r4-r11, lr}
diff --git a/ArmPkg/Library/BaseMemoryLibStm/Arm/SetMem.S b/ArmPkg/Library/BaseMemoryLibStm/Arm/SetMem.S
index 29a50f5a49..c6dbc7f2c7 100755
--- a/ArmPkg/Library/BaseMemoryLibStm/Arm/SetMem.S
+++ b/ArmPkg/Library/BaseMemoryLibStm/Arm/SetMem.S
@@ -37,8 +37,7 @@ InternalMemSetMem (
.text
.align 2
-.globl ASM_PFX(InternalMemSetMem)
-INTERWORK_FUNC(InternalMemSetMem)
+GCC_ASM_EXPORT(InternalMemSetMem)
ASM_PFX(InternalMemSetMem):
stmfd sp!, {r4-r11, lr}
diff --git a/ArmPkg/Library/BaseMemoryLibVstm/Arm/CopyMem.S b/ArmPkg/Library/BaseMemoryLibVstm/Arm/CopyMem.S
index 69db936555..239807c732 100755
--- a/ArmPkg/Library/BaseMemoryLibVstm/Arm/CopyMem.S
+++ b/ArmPkg/Library/BaseMemoryLibVstm/Arm/CopyMem.S
@@ -39,8 +39,7 @@ InternalMemCopyMem (
**/
.text
.align 2
-.globl ASM_PFX(InternalMemCopyMem)
-INTERWORK_FUNC(InternalMemCopyMem)
+GCC_ASM_EXPORT(InternalMemCopyMem)
ASM_PFX(InternalMemCopyMem):
stmfd sp!, {r4, r9, lr}
diff --git a/ArmPkg/Library/BaseMemoryLibVstm/Arm/SetMem.S b/ArmPkg/Library/BaseMemoryLibVstm/Arm/SetMem.S
index 3eb901b58f..8120cfc1c3 100755
--- a/ArmPkg/Library/BaseMemoryLibVstm/Arm/SetMem.S
+++ b/ArmPkg/Library/BaseMemoryLibVstm/Arm/SetMem.S
@@ -37,8 +37,7 @@ InternalMemSetMem (
.text
.align 2
-.globl ASM_PFX(InternalMemSetMem)
-INTERWORK_FUNC(InternalMemSetMem)
+GCC_ASM_EXPORT(InternalMemSetMem)
ASM_PFX(InternalMemSetMem):
stmfd sp!, {r4-r7, lr}
diff --git a/ArmPkg/Library/BasePeCoffLib/BasePeCoff.c b/ArmPkg/Library/BasePeCoffLib/BasePeCoff.c
index a4c80eaa8b..8e0ceb8810 100755
--- a/ArmPkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/ArmPkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -913,7 +913,7 @@ PeCoffLoaderLoadImage (
ImageContext->Handle,
0,
&ImageContext->SizeOfHeaders,
- (void *)(UINTN)ImageContext->ImageAddress
+ (VOID*)(UINTN)ImageContext->ImageAddress
);
Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);
diff --git a/ArmPkg/Library/BdsLib/BdsAppLoader.c b/ArmPkg/Library/BdsLib/BdsAppLoader.c
new file mode 100644
index 0000000000..1cc4fddbea
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsAppLoader.c
@@ -0,0 +1,102 @@
+/** @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 "BdsInternal.h"
+
+EFI_STATUS
+BdsLoadPeCoff (
+ IN BDS_FILE *EfiAppFile
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE ImageHandle;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ // Only support loading from FV right now
+ ASSERT(EfiAppFile->Type == BDS_FILETYPE_FV);
+
+ // Generate the Device Path for the file
+ DevicePath = DuplicateDevicePath(EfiAppFile->DevicePath);
+ EfiInitializeFwVolDevicepathNode (&NewNode, &(EfiAppFile->File.Fv.Guid));
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);
+
+ Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ }
+
+ return Status;
+}
+
+EFI_STATUS BdsLoadApplicationFromPath(
+ IN CHAR16* EfiAppPath
+) {
+ EFI_STATUS Status;
+ BDS_FILE EfiAppFile;
+
+ // Need to connect every drivers to ensure no dependencies are missing for the application
+ Status = BdsConnectAllDrivers();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));
+ return Status;
+ }
+
+ // Locate the application from a device path
+ Status = BdsLoadFilePath(EfiAppPath, &EfiAppFile);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "ERROR: Do not find EFI application %s\n",EfiAppPath));
+ return Status;
+ }
+
+ // Start the application
+ Status = BdsLoadPeCoff(&EfiAppFile);
+
+ return Status;
+}
+
+EFI_STATUS BdsLoadApplication(
+ IN CHAR16* EfiApp
+) {
+ EFI_STATUS Status;
+ UINTN NoHandles, HandleIndex;
+ EFI_HANDLE *Handles;
+ BDS_FILE EfiAppFile;
+
+ // Need to connect every drivers to ensure no dependencies are missing for the application
+ Status = BdsConnectAllDrivers();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));
+ return Status;
+ }
+
+ // Search the application in any Firmware Volume
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles);
+ if (EFI_ERROR (Status) || (NoHandles == 0)) {
+ DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n"));
+ return Status;
+ }
+
+ // Search in all Firmware Volume for the EFI Application
+ for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {
+ Status = BdsLoadFileFromFirmwareVolume(Handles[HandleIndex],EfiApp,EFI_FV_FILETYPE_APPLICATION,&EfiAppFile);
+ if (!EFI_ERROR (Status)) {
+ // Start the application
+ Status = BdsLoadPeCoff(&EfiAppFile);
+ return Status;
+ }
+ }
+
+ return Status;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePath.c b/ArmPkg/Library/BdsLib/BdsFilePath.c
new file mode 100644
index 0000000000..b1460b9c9d
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsFilePath.c
@@ -0,0 +1,182 @@
+/** @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 "BdsInternal.h"
+
+// Count the number of DevicePath Node
+static UINTN NumberNodeFromDevicePath(
+ IN EFI_DEVICE_PATH_PROTOCOL* DevicePath
+) {
+ UINTN NumberDevicePathNode = 0;
+
+ while (!IsDevicePathEnd (DevicePath)) {
+ NumberDevicePathNode++;
+ DevicePath = NextDevicePathNode(DevicePath);
+ }
+ return NumberDevicePathNode;
+}
+
+// Extract the FilePath from the Device Path
+CHAR16* BdsExtractFilePathFromDevicePath(
+ IN CONST CHAR16 *StrDevicePath,
+ IN UINTN NumberDevicePathNode
+) {
+ UINTN Node;
+ CHAR16 *Str;
+
+ Str = (CHAR16*)StrDevicePath;
+ Node = 0;
+ while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) {
+ if ((*Str == L'/') || (*Str == L'\\')) {
+ Node++;
+ }
+ Str++;
+ }
+
+ if (*Str == L'\0') {
+ return NULL;
+ } else {
+ return Str;
+ }
+}
+
+EFI_STATUS
+BdsLoadDevicePath(
+ IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
+ OUT EFI_HANDLE *Handle
+) {
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_STATUS Status;
+
+ if ((DevicePath == NULL) || (Handle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ do {
+ RemainingDevicePath = DevicePath;
+ // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns
+ // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified
+ // to point to the remaining part of the device path
+ Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle);
+ if (!EFI_ERROR (Status)) {
+ // Recursive = FALSE: We do not want to start all the device tree
+ Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE);
+ }
+
+ // We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling
+ // NextDevicePathNode() will return an undetermined Device Path Node
+ if (!IsDevicePathEnd (RemainingDevicePath)) {
+ RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
+ }
+ } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
+
+ if (!EFI_ERROR (Status)) {
+ // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
+ // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
+ RemainingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle);
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE);
+ if (EFI_ERROR (Status)) {
+ // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
+ if ((RemainingDevicePath->Type == HARDWARE_DEVICE_PATH) && (RemainingDevicePath->SubType == HW_MEMMAP_DP)) {
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+ } else if (IsDevicePathEnd (RemainingDevicePath)) {
+ // Case when the DevicePath contains a MemoryMap Device Path Node and all drivers are connected.
+ // Ensure the Device Path exists
+ RemainingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+BdsLoadFilePath (
+ IN CONST CHAR16 *DeviceFilePath,
+ OUT BDS_FILE *File
+) {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ UINTN NumberDevicePathNode;
+ CHAR16 *FilePath;
+
+ //Do a sanity check on the Device file path
+ if (DeviceFilePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Convert the Device Path String into Device Path Protocol
+ Status = gBS->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
+ ASSERT_EFI_ERROR(Status);
+ DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath(DeviceFilePath);
+
+ //Do a sanity check on the Device Path
+ if (DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Count the number of DevicePath Node
+ NumberDevicePathNode = NumberNodeFromDevicePath(DevicePath);
+ // Extract the FilePath from the Device Path
+ FilePath = BdsExtractFilePathFromDevicePath(DeviceFilePath,NumberDevicePathNode);
+
+ Status = BdsLoadDevicePath(DevicePath,&Handle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //If FilePath == NULL then let consider if a MemoryMap Device Path
+ if (FilePath == NULL) {
+ // Check if the Node is a MemoryMap Device Path
+ Status = BdsLoadFileFromMemMap(Handle,DevicePath,File);
+ } else {
+ Status = BdsLoadFileFromSimpleFileSystem(Handle,FilePath,File);
+ if (EFI_ERROR (Status)) {
+ Status = BdsLoadFileFromFirmwareVolume(Handle,FilePath,EFI_FV_FILETYPE_ALL,File);
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ File->DevicePath = DevicePath;
+ }
+
+ return Status;
+}
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemory(
+ IN BDS_FILE *File,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+) {
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (File->Type == BDS_FILETYPE_FS) {
+ return BdsCopyRawFileToRuntimeMemoryFS(File->File.Fs.Handle,FileImage,FileSize);
+ } else if (File->Type == BDS_FILETYPE_FV) {
+ return BdsCopyRawFileToRuntimeMemoryFV(&(File->File.Fv),FileImage,FileSize);
+ } else if (File->Type == BDS_FILETYPE_MEM) {
+ return BdsCopyRawFileToRuntimeMemoryMemMap(&(File->File.Mem),FileImage,FileSize);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePathFs.c b/ArmPkg/Library/BdsLib/BdsFilePathFs.c
new file mode 100644
index 0000000000..c92824742e
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsFilePathFs.c
@@ -0,0 +1,86 @@
+/** @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 "BdsInternal.h"
+
+EFI_STATUS BdsLoadFileFromSimpleFileSystem(
+ IN EFI_HANDLE Handle,
+ IN CHAR16 *FilePath,
+ OUT BDS_FILE *File
+) {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol;
+ EFI_FILE_PROTOCOL *Fs;
+ EFI_STATUS Status;
+ EFI_FILE_PROTOCOL *FileHandle = NULL;
+
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->HandleProtocol(Handle,&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //Try to Open the volume and get root directory
+ Status = FsProtocol->OpenVolume(FsProtocol, &Fs);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = Fs->Open(Fs, &FileHandle, FilePath, EFI_FILE_MODE_READ, 0);
+
+ File->Type = BDS_FILETYPE_FS;
+ File->FilePath = FilePath;
+ File->File.Fs.Handle = FileHandle;
+
+ return Status;
+}
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemoryFS(
+ IN EFI_FILE_PROTOCOL *File,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+) {
+ EFI_FILE_INFO *FileInfo;
+ UINTN Size;
+ VOID* Image;
+ EFI_STATUS Status;
+
+ Size = 0;
+ File->GetInfo(File, &gEfiFileInfoGuid, &Size, NULL);
+ FileInfo = AllocatePool (Size);
+ Status = File->GetInfo(File, &gEfiFileInfoGuid, &Size, FileInfo);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // Get the file size
+ Size = FileInfo->FileSize;
+ if (FileSize) {
+ *FileSize = Size;
+ }
+ FreePool(FileInfo);
+
+ Image = AllocateRuntimePool(Size);
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = File->Read(File, &Size, Image);
+ if (!EFI_ERROR(Status)) {
+ *FileImage = Image;
+ }
+ return Status;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePathFv.c b/ArmPkg/Library/BdsLib/BdsFilePathFv.c
new file mode 100644
index 0000000000..f5b4e57cbf
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsFilePathFv.c
@@ -0,0 +1,136 @@
+/** @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 "BdsInternal.h"
+
+EFI_STATUS BdsLoadFileFromFirmwareVolume(
+ IN EFI_HANDLE FvHandle,
+ IN CHAR16 *FilePath,
+ IN EFI_FV_FILETYPE FileTypeFilter,
+ OUT BDS_FILE *File
+) {
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ VOID *Key;
+ EFI_STATUS Status, FileStatus;
+ EFI_GUID NameGuid;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN UiStringLen;
+ CHAR16 *UiSection;
+ UINT32 Authentication;
+
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->HandleProtocol(FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // Length of FilePath
+ UiStringLen = StrLen (FilePath);
+
+ // Allocate Key
+ Key = AllocatePool (FvProtocol->KeySize);
+ ASSERT (Key != NULL);
+ ZeroMem (Key, FvProtocol->KeySize);
+
+ do {
+ // Search in all files
+ FileType = FileTypeFilter;
+
+ Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
+ if (!EFI_ERROR (Status)) {
+ UiSection = NULL;
+ FileStatus = FvProtocol->ReadSection (
+ FvProtocol,
+ &NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **)&UiSection,
+ &Size,
+ &Authentication
+ );
+ if (!EFI_ERROR (FileStatus)) {
+ if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) {
+
+ //
+ // We found a UiString match.
+ //
+ //*FileGuid = NameGuid;
+ File->Type = BDS_FILETYPE_FV;
+ File->FilePath = FilePath;
+ CopyGuid (&(File->File.Fv.Guid),&NameGuid);
+ File->File.Fv.FvProtocol = FvProtocol;
+ File->File.Fv.FileType = FileType;
+
+ Status = gBS->HandleProtocol(FvHandle,&gEfiDevicePathProtocolGuid, (VOID **)&(File->DevicePath));
+
+ FreePool (Key);
+ FreePool (UiSection);
+ return FileStatus;
+ }
+ FreePool (UiSection);
+ }
+ }
+ } while (!EFI_ERROR (Status));
+
+ FreePool(Key);
+ return Status;
+}
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemoryFV(
+ IN BDS_FV_FILE *FvFile,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+) {
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ EFI_FV_FILETYPE FileType;
+ EFI_GUID* NameGuid;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINT32 Authentication;
+
+ FvProtocol = FvFile->FvProtocol;
+ FileType = FvFile->FileType;
+ NameGuid = &(FvFile->Guid);
+
+ if (FileType == EFI_FV_FILETYPE_RAW) {
+ *FileImage = NULL;
+ *FileSize = 0;
+ Status = FvProtocol->ReadFile(
+ FvProtocol,NameGuid, // IN
+ FileImage,FileSize, // IN OUT
+ &FileType,&Attributes,&Authentication // OUT
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ // This raw file also contains a header
+ *FileSize = *FileSize - 4;
+ *FileImage = (UINT8*)FileImage + 4;
+ } else if (FileType == EFI_FV_FILETYPE_FREEFORM) {
+ Status = FvProtocol->ReadSection (
+ FvProtocol,NameGuid,EFI_SECTION_RAW,0, // IN
+ FileImage,FileSize, // IN OUT
+ &Authentication // OUT
+ );
+ ASSERT_EFI_ERROR(Status);
+ } else {
+ ASSERT(0); //Maybe support application as well ???
+ }
+
+ return Status;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePathMem.c b/ArmPkg/Library/BdsLib/BdsFilePathMem.c
new file mode 100644
index 0000000000..dddaa3d670
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsFilePathMem.c
@@ -0,0 +1,73 @@
+/** @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 "BdsInternal.h"
+
+
+EFI_STATUS BdsLoadFileFromMemMap (
+ IN EFI_HANDLE Handle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT BDS_FILE *File
+) {
+ EFI_DEVICE_PATH_PROTOCOL *LastDevicePath;
+
+ if ((File == NULL) || (DevicePath == NULL) || (IsDevicePathEnd (DevicePath))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the last node of the device Path is a Memory Map Device Node
+ LastDevicePath = DevicePath;
+ DevicePath = NextDevicePathNode(DevicePath);
+ while (!IsDevicePathEnd (DevicePath)) {
+ LastDevicePath = DevicePath;
+ DevicePath = NextDevicePathNode(DevicePath);
+ }
+ if ((LastDevicePath->Type != HARDWARE_DEVICE_PATH) || (LastDevicePath->SubType != HW_MEMMAP_DP)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ File->Type = BDS_FILETYPE_MEM;
+ File->File.Mem.MemoryType = ((MEMMAP_DEVICE_PATH*)LastDevicePath)->MemoryType;
+ File->File.Mem.StartingAddress = ((MEMMAP_DEVICE_PATH*)LastDevicePath)->StartingAddress;
+ File->File.Mem.EndingAddress = ((MEMMAP_DEVICE_PATH*)LastDevicePath)->EndingAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemoryMemMap(
+ IN BDS_MEM_FILE *MemFile,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+) {
+ UINTN Size;
+ VOID* Image;
+
+ Size = MemFile->EndingAddress - MemFile->StartingAddress;
+
+ if ((Size == 0) || (FileImage == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (FileSize != NULL) {
+ *FileSize = Size;
+ }
+
+ Image = AllocateRuntimePool(Size);
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *FileImage = CopyMem(Image,(CONST VOID*)(UINTN)MemFile->StartingAddress,Size);
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsHelper.c b/ArmPkg/Library/BdsLib/BdsHelper.c
new file mode 100644
index 0000000000..896ae73820
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsHelper.c
@@ -0,0 +1,183 @@
+/** @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 "BdsInternal.h"
+
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+
+EFI_STATUS
+ShutdownUefiBootServices( VOID )
+{
+ EFI_STATUS Status;
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ UINTN Pages;
+
+ MemoryMap = NULL;
+ MemoryMapSize = 0;
+ do {
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+ Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
+ MemoryMap = AllocatePages (Pages);
+
+ //
+ // Get System MemoryMap
+ //
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ // Don't do anything between the GetMemoryMap() and ExitBootServices()
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->ExitBootServices (gImageHandle, MapKey);
+ if (EFI_ERROR (Status)) {
+ FreePages (MemoryMap, Pages);
+ MemoryMap = NULL;
+ MemoryMapSize = 0;
+ }
+ }
+ }
+ } while (EFI_ERROR (Status));
+
+ return Status;
+}
+
+EFI_STATUS
+BdsConnectAllDrivers( VOID ) {
+ UINTN HandleCount, Index;
+ EFI_HANDLE *HandleBuffer;
+ EFI_STATUS Status;
+
+ do {
+ // Locate all the driver handles
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ // Connect every handles
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->ConnectController(HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ // Check if new handles have been created after the start of the previous handles
+ Status = gDS->Dispatch ();
+ } while (!EFI_ERROR(Status));
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS InsertSystemMemoryResources(LIST_ENTRY *ResourceList, EFI_HOB_RESOURCE_DESCRIPTOR *ResHob) {
+ BDS_SYSTEM_MEMORY_RESOURCE NewResource;
+ LIST_ENTRY *Link;
+ BDS_SYSTEM_MEMORY_RESOURCE *Resource;
+
+ //DEBUG ((EFI_D_ERROR, "** InsertSystemMemoryResources(0x%X,0x%X)\n",(UINT32)ResHob->PhysicalStart,(UINT32)ResHob->ResourceLength));
+
+ if (IsListEmpty (ResourceList)) {
+ ZeroMem(&NewResource,sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
+ NewResource.PhysicalStart = ResHob->PhysicalStart;
+ NewResource.ResourceLength = ResHob->ResourceLength;
+ InsertTailList (ResourceList, &NewResource.Link);
+ return EFI_SUCCESS;
+ }
+
+ //for (Link = GetFirstNode (ResourceList); !IsNull (ResourceList,Link); Link = GetNextNode (ResourceList,Link)) {
+ Link = ResourceList->ForwardLink;
+ while (Link != NULL && Link != ResourceList) {
+ Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
+ //DEBUG ((EFI_D_ERROR, " - (0x%X,0x%X)\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->ResourceLength));
+
+ // Sanity Check. The resources should not overlapped.
+ ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));
+ ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength >= Resource->PhysicalStart) &&
+ ((ResHob->PhysicalStart + ResHob->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength))));
+
+ // The new resource is attached after this resource descriptor
+ if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {
+ Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;
+ //DEBUG ((EFI_D_ERROR, "** Attached new Length:0x%X\n",(UINT32)Resource->ResourceLength));
+ return EFI_SUCCESS;
+ }
+ // The new resource is attached before this resource descriptor
+ else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {
+ Resource->PhysicalStart = ResHob->PhysicalStart;
+ Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;
+ //DEBUG ((EFI_D_ERROR, "** Attached2 new Length:0x%X\n",(UINT32)Resource->ResourceLength));
+ return EFI_SUCCESS;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ // None of the Resource of the list is attached to this ResHob. Create a new entry for it
+ ZeroMem(&NewResource,sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
+ NewResource.PhysicalStart = ResHob->PhysicalStart;
+ NewResource.ResourceLength = ResHob->ResourceLength;
+ InsertTailList (ResourceList, &NewResource.Link);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS GetSystemMemoryResources(LIST_ENTRY *ResourceList) {
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
+
+ InitializeListHead (ResourceList);
+
+ // Find the first System Memory Resource Descriptor
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+ }
+
+ // Did not find any
+ if (ResHob == NULL) {
+ return EFI_NOT_FOUND;
+ } else {
+ InsertSystemMemoryResources(ResourceList, ResHob);
+ }
+
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+ while (ResHob != NULL) {
+ if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ InsertSystemMemoryResources(ResourceList, ResHob);
+ }
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsInternal.h b/ArmPkg/Library/BdsLib/BdsInternal.h
new file mode 100644
index 0000000000..07f722e03f
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsInternal.h
@@ -0,0 +1,136 @@
+/** @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.
+*
+**/
+
+#ifndef __BDS_INTERNAL_H__
+#define __BDS_INTERNAL_H__
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BdsUnixLib.h>
+
+#include <Guid/FileInfo.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/FirmwareVolume2.h>
+
+
+typedef enum { BDS_FILETYPE_MEM, BDS_FILETYPE_FS, BDS_FILETYPE_FV } BDS_FILE_TYPE;
+
+typedef struct {
+ UINT32 MemoryType;
+ EFI_PHYSICAL_ADDRESS StartingAddress;
+ EFI_PHYSICAL_ADDRESS EndingAddress;
+} BDS_MEM_FILE;
+
+typedef struct {
+ EFI_FILE_PROTOCOL *Handle;
+} BDS_FS_FILE;
+
+typedef struct {
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ EFI_FV_FILETYPE FileType;
+ EFI_GUID Guid;
+} BDS_FV_FILE;
+
+typedef struct _BDS_FILE {
+ CHAR16* FilePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BDS_FILE_TYPE Type;
+ union {
+ BDS_MEM_FILE Mem;
+ BDS_FS_FILE Fs;
+ BDS_FV_FILE Fv;
+ } File;
+} BDS_FILE;
+
+typedef struct _BDS_SYSTEM_MEMORY_RESOURCE {
+ LIST_ENTRY Link; // This attribute must be the first entry of this structure (to avoid pointer computation)
+ EFI_PHYSICAL_ADDRESS PhysicalStart;
+ UINT64 ResourceLength;
+} BDS_SYSTEM_MEMORY_RESOURCE;
+
+
+// BdsHelper.c
+EFI_STATUS
+ShutdownUefiBootServices( VOID );
+
+EFI_STATUS
+GetSystemMemoryResources (LIST_ENTRY *ResourceList);
+
+// BdsFilePath.c
+EFI_STATUS BdsLoadDevicePath(
+ IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
+ OUT EFI_HANDLE *Handle
+);
+
+EFI_STATUS BdsLoadFilePath(
+ IN CONST CHAR16 *DeviceFilePath,
+ OUT BDS_FILE *File
+);
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemory(
+ IN BDS_FILE *File,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+);
+
+// BdsFilePathFs.c
+EFI_STATUS BdsLoadFileFromSimpleFileSystem(
+ IN EFI_HANDLE Handle,
+ IN CHAR16 *FilePath,
+ OUT BDS_FILE *File
+);
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemoryFS(
+ IN EFI_FILE_PROTOCOL *File,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+);
+
+// BdsFilePathFv.c
+EFI_STATUS BdsLoadFileFromFirmwareVolume(
+ IN EFI_HANDLE FvHandle,
+ IN CHAR16 *FilePath,
+ IN EFI_FV_FILETYPE FileTypeFilter,
+ OUT BDS_FILE *File
+);
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemoryFV(
+ IN BDS_FV_FILE *FvFile,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+);
+
+// BdsFilePathMem.c
+EFI_STATUS BdsLoadFileFromMemMap (
+ IN EFI_HANDLE Handle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT BDS_FILE *File
+);
+
+EFI_STATUS BdsCopyRawFileToRuntimeMemoryMemMap(
+ IN BDS_MEM_FILE *MemFile,
+ OUT VOID **FileImage,
+ OUT UINTN *FileSize
+);
+
+#endif
diff --git a/ArmPkg/Library/BdsLib/BdsLib.inf b/ArmPkg/Library/BdsLib/BdsLib.inf
new file mode 100644
index 0000000000..223f47b3db
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsLib.inf
@@ -0,0 +1,63 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BdsLib
+ FILE_GUID = ddbf73a0-bb25-11df-8e4e-0002a5d5c51b
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BdsLib
+
+[Sources.common]
+ BdsFilePath.c
+ BdsFilePathFs.c
+ BdsFilePathFv.c
+ BdsFilePathMem.c
+ BdsLinuxLoader.c
+ BdsAppLoader.c
+ BdsHelper.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ HobLib
+ DebugLib
+ UefiDriverEntryPoint
+ DxeServicesTableLib
+ ArmLib
+
+[Guids]
+ gEfiFileInfoGuid
+
+[Protocols]
+ gEfiBdsArchProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiDevicePathFromTextProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
+
+[FeaturePcd]
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmMachineType
+
+[Pcd]
+
+[Depex]
+ TRUE
diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
new file mode 100644
index 0000000000..69435936b7
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
@@ -0,0 +1,337 @@
+/** @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 "BdsInternal.h"
+#include "BdsLinuxLoader.h"
+
+#include <Library/PcdLib.h>
+#include <Library/ArmLib.h>
+#include <Library/HobLib.h>
+
+STATIC
+EFI_STATUS
+GetARMLinuxMachineType (
+ IN BOOLEAN FdtSupported,
+ OUT UINT32 *MachineType
+) {
+ if (FdtSupported)
+ {
+ // FDT requires that the machine type is set to the maximum 32-bit number.
+ *MachineType = 0xFFFFFFFF;
+ }
+ else
+ {
+ // Non-FDT requires a specific machine type.
+ // This OS Boot loader supports just one machine type,
+ // but that could change in the future.
+ *MachineType = PcdGet32(PcdArmMachineType);
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+SetupCoreTag( IN UINT32 PageSize )
+{
+ Params->header.size = tag_size(atag_core);
+ Params->header.type = ATAG_CORE;
+
+ Params->body.core_tag.flags = 1; /* ensure read-only */
+ Params->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */
+ Params->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/
+
+ Params = next_tag_address(Params); /* move pointer to next tag */
+}
+
+STATIC
+VOID
+SetupMemTag( IN UINTN StartAddress, IN UINT32 Size )
+{
+ Params->header.size = tag_size(atag_mem);
+ Params->header.type = ATAG_MEM;
+
+ Params->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */
+ Params->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */
+
+ Params = next_tag_address(Params); /* move pointer to next tag */
+}
+
+STATIC
+VOID
+SetupCmdlineTag( IN CONST CHAR8 *CmdLine )
+{
+ UINT32 LineLength;
+
+ // Increment the line length by 1 to account for the null string terminator character
+ LineLength = AsciiStrLen(CmdLine) + 1;
+
+ /* Check for NULL strings.
+ * Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.
+ * Remember, you have at least one null string terminator character.
+ */
+ if( LineLength > 1 )
+ {
+ Params->header.size = ((UINT32)sizeof(struct atag_header) + LineLength + (UINT32)3) >> 2;
+ Params->header.type = ATAG_CMDLINE;
+
+ /* place CommandLine into tag */
+ AsciiStrCpy(Params->body.cmdline_tag.cmdline, CmdLine);
+
+ Params = next_tag_address(Params); /* move pointer to next tag */
+ }
+}
+
+STATIC
+VOID
+SetupEndTag( VOID )
+{
+ // Empty tag ends list; this has zero length and no body
+ Params->header.type = ATAG_NONE;
+ Params->header.size = 0;
+
+ /* We can not calculate the next address by using the standard macro:
+ * Params = next_tag_address(Params);
+ * because it relies on the header.size, which here it is 0 (zero).
+ * The easiest way is to add the sizeof(Params->header).
+ */
+ Params = (struct atag *)((UINT32)Params + sizeof(Params->header));
+}
+
+STATIC
+EFI_STATUS
+PrepareAtagList(
+ IN OUT struct atag **AtagStartAddress,
+ IN CONST CHAR8* CommandLineString,
+ OUT UINT32 *AtagSize
+) {
+ LIST_ENTRY *ResourceLink;
+ LIST_ENTRY ResourceList;
+ BDS_SYSTEM_MEMORY_RESOURCE *Resource;
+
+ // If no address supplied then this function will decide where to put it
+ if( *AtagStartAddress == 0 )
+ {
+ /* WARNING: At the time of writing (2010-July-30) the linux kernel expects
+ * the atag list it in the first 1MB of memory and preferably at address 0x100.
+ * This has a very high risk of overwriting UEFI code, but as
+ * the linux kernel does not expect any runtime services from uefi
+ * and there is no afterlife section following the linux kernel termination,
+ * it does not matter if we stamp over that memory area.
+ *
+ * The proposed workaround is to create the atag list somewhere in boot services memory
+ * and then transfer it to address 0x100 (or to runtime services memory) immediately
+ * before starting the kernel.
+ * An additional benefit of this is that when we copy the ATAG list to it's final place,
+ * we can trim down the memory allocation size. Before we create the list we don't know
+ * how much space it is going to take, so we are over-allocating space.
+ */
+ *AtagStartAddress = (struct atag *) AllocatePool(ATAG_MAX_SIZE);
+ }
+
+ // Ensure the pointer is not NULL.
+ ASSERT( *AtagStartAddress != (struct atag *)NULL );
+
+ // Ready to setup the atag list
+ Params = *AtagStartAddress;
+
+ // Standard core tag 4k PageSize
+ SetupCoreTag( (UINT32)SIZE_4KB );
+
+ // Physical memory setup
+ GetSystemMemoryResources(&ResourceList);
+ ResourceLink = ResourceList.ForwardLink;
+ while (ResourceLink != NULL && ResourceLink != &ResourceList) {
+ Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceList.ForwardLink;
+ SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );
+ ResourceLink = ResourceLink->ForwardLink;
+ }
+
+ // CommandLine setting root device
+ SetupCmdlineTag( CommandLineString );
+
+ // end of tags
+ SetupEndTag();
+
+ // Calculate atag list size
+ *AtagSize = (UINT32)Params - (UINT32)*AtagStartAddress + 1;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+PreparePlatformHardware( VOID )
+{
+ //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.
+
+ // clean, invalidate, disable data cache
+ ArmCleanInvalidateDataCache();
+ ArmDisableDataCache();
+
+ // Invalidate and disable the Instruction cache
+ ArmInvalidateInstructionCache ();
+ ArmDisableInstructionCache ();
+
+ // turn off MMU
+ ArmInvalidateTlb();
+ ArmDisableMmu();
+
+ return EFI_SUCCESS;
+}
+
+/*************************************************
+ * R0, R1, R2 correspond to registers R0, R1, R2
+ *************************************************/
+//STATIC
+EFI_STATUS
+StartLinuxKernel( IN VOID* KernelAddress, IN UINTN R0, IN UINTN R1, IN UINTN R2 )
+{
+ VOID (*Kernel)(UINT32 Zero, UINT32 Arch, UINTN AtagListParams);
+
+ // set the kernel address
+ Kernel = (VOID (*)(UINT32, UINT32, UINTN)) KernelAddress;
+
+ // Outside BootServices, so can't use Print();
+ DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));
+
+ // jump to kernel with register set
+ Kernel( R0, R1, R2 );
+
+ // Kernel should never exit
+ // After Life services are not provided
+ ASSERT( FALSE );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS BdsBootLinux(
+ IN CONST CHAR16* LinuxKernel,
+ IN CONST CHAR8* ATag,
+ IN CONST CHAR16* Fdt
+) {
+ BDS_FILE LinuxKernelFile;
+ BDS_FILE FdtFile;
+ EFI_STATUS Status;
+ VOID* LinuxImage;
+
+ UINT32 KernelParamsSize;
+ VOID* KernelParamsAddress = NULL;
+ UINTN KernelParamsNewAddress;
+ UINTN *AtagAddress;
+ UINT32 MachineType;
+ BOOLEAN FdtSupported = FALSE;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
+
+ // Load the Linux kernel from a device path
+ Status = BdsLoadFilePath(LinuxKernel, &LinuxKernelFile);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "ERROR: Do not find Linux kernel %s\n",LinuxKernel));
+ return Status;
+ }
+
+ // Copy the Linux Kernel from the raw file to Runtime memory
+ Status = BdsCopyRawFileToRuntimeMemory(&LinuxKernelFile,&LinuxImage,NULL);
+ if (EFI_ERROR(Status)) {
+ goto Exit;
+ }
+
+ // Load the FDT binary from a device path
+ Status = BdsLoadFilePath(Fdt, &FdtFile);
+ if (!EFI_ERROR(Status)) {
+ // Copy the FDT binary from the raw file to Runtime memory
+ Status = BdsCopyRawFileToRuntimeMemory(&FdtFile,&KernelParamsAddress,&KernelParamsSize);
+ if (EFI_ERROR(Status)) {
+ goto Exit;
+ } else {
+ FdtSupported = TRUE;
+ }
+ }
+
+ /**********************************************************
+ * Setup the platform type
+ **********************************************************/
+ Status = GetARMLinuxMachineType(FdtSupported, &MachineType);
+ if(EFI_ERROR(Status))
+ {
+ Print(L"ERROR : Can not prepare ARM Linux machine type. Status=0x%X\n", Status);
+ goto Exit;
+ }
+
+ if (!FdtSupported) {
+ /**********************************************************
+ * Setup the ATAG list
+ **********************************************************/
+ // By setting address=0 we leave the memory allocation to the function
+ AtagAddress = 0;
+ Status = PrepareAtagList( (struct atag **)&AtagAddress, ATag, &KernelParamsSize );
+ KernelParamsAddress = (VOID*)AtagAddress;
+ if(EFI_ERROR(Status))
+ {
+ Print(L"ERROR : Can not prepare ATAG list. Status=0x%X\n", Status);
+ goto Exit;
+ }
+ }
+
+ /**********************************************************
+ * Switch off interrupts, caches, mmu, etc
+ **********************************************************/
+ Status = PreparePlatformHardware();
+ if(EFI_ERROR(Status))
+ {
+ Print(L"ERROR : Can not prepare platform hardware. Status=0x%X\n", Status);
+ goto Exit;
+ }
+
+ // Initialize the ATag destination
+ KernelParamsNewAddress = 0x100;
+
+ // Update the ATag destination by finding the start address of the first System Memory Resource Descriptor Hob
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ while (ResHob != NULL) {
+ if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ KernelParamsNewAddress = (UINTN)ResHob->PhysicalStart + 0x100;
+ break;
+ }
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+ }
+
+ // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on
+ // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.
+ Status = ShutdownUefiBootServices();
+ if(EFI_ERROR(Status))
+ {
+ Print(L"ERROR : Can not shutdown UEFI boot services. Status=0x%X\n", Status);
+ goto Exit;
+ }
+
+ // Move the kernel parameters to any address inside the first 1MB.
+ // This is necessary because the ARM Linux kernel requires
+ // the FTD / ATAG List to reside entirely inside the first 1MB of
+ // physical memory.
+ CopyMem((VOID*)KernelParamsNewAddress, KernelParamsAddress, KernelParamsSize);
+
+ //**********************************************************
+ // * Start the Linux Kernel
+ // **********************************************************
+ // Lift off ...
+ Status = StartLinuxKernel(LinuxImage, (UINTN)0, (UINTN)MachineType, KernelParamsNewAddress );
+
+ // Only be here if we fail to start Linux
+ DEBUG((EFI_D_ERROR, "ERROR : Can not start the kernel. Status=0x%X\n", Status));
+
+Exit:
+ // Free Runtimee Memory (kernel and FDT)
+ return Status;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
new file mode 100644
index 0000000000..2869f652f8
--- /dev/null
+++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
@@ -0,0 +1,165 @@
+/** @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.
+*
+**/
+
+#ifndef __BDSLINUXLOADER_H
+#define __BDSLINUXLOADER_H
+
+#define ATAG_MAX_SIZE 0x4000
+//PcdKernelParamsMaxMemorySize
+
+/* ATAG : list of possible tags */
+#define ATAG_NONE 0x00000000
+#define ATAG_CORE 0x54410001
+#define ATAG_MEM 0x54410002
+#define ATAG_VIDEOTEXT 0x54410003
+#define ATAG_RAMDISK 0x54410004
+#define ATAG_INITRD2 0x54420005
+#define ATAG_SERIAL 0x54410006
+#define ATAG_REVISION 0x54410007
+#define ATAG_VIDEOLFB 0x54410008
+#define ATAG_CMDLINE 0x54410009
+#define ATAG_ARM_MP_CORE 0x5441000A
+
+// Some system addresses
+// These should probably come from the platform header file or from pcd values
+#define DRAM_BASE 0x10000000
+#define ZIMAGE_LOAD_ADDRESS (DRAM_BASE + 0x8000)
+#define INITRD_LOAD_ADDRESS (DRAM_BASE + 0x800000)
+
+#define SIZE_1B 0x00000001
+#define SIZE_2B 0x00000002
+#define SIZE_4B 0x00000004
+#define SIZE_8B 0x00000008
+#define SIZE_16B 0x00000010
+#define SIZE_32B 0x00000020
+#define SIZE_64B 0x00000040
+#define SIZE_128B 0x00000080
+#define SIZE_256B 0x00000100
+#define SIZE_512B 0x00000200
+#define SIZE_1KB 0x00000400
+#define SIZE_2KB 0x00000800
+#define SIZE_4KB 0x00001000
+#define SIZE_8KB 0x00002000
+#define SIZE_16KB 0x00004000
+#define SIZE_32KB 0x00008000
+#define SIZE_64KB 0x00010000
+#define SIZE_128KB 0x00020000
+#define SIZE_256KB 0x00040000
+#define SIZE_512KB 0x00080000
+#define SIZE_1MB 0x00100000
+#define SIZE_2MB 0x00200000
+#define SIZE_4MB 0x00400000
+#define SIZE_8MB 0x00800000
+#define SIZE_16MB 0x01000000
+#define SIZE_32MB 0x02000000
+#define SIZE_64MB 0x04000000
+#define SIZE_100MB 0x06400000
+#define SIZE_128MB 0x08000000
+#define SIZE_256MB 0x10000000
+#define SIZE_512MB 0x20000000
+#define SIZE_1GB 0x40000000
+#define SIZE_2GB 0x80000000
+
+/* structures for each atag */
+struct atag_header {
+ UINT32 size; /* length of tag in words including this header */
+ UINT32 type; /* tag type */
+};
+
+struct atag_core {
+ UINT32 flags;
+ UINT32 pagesize;
+ UINT32 rootdev;
+};
+
+struct atag_mem {
+ UINT32 size;
+ UINTN start;
+};
+
+struct atag_videotext {
+ UINT8 x;
+ UINT8 y;
+ UINT16 video_page;
+ UINT8 video_mode;
+ UINT8 video_cols;
+ UINT16 video_ega_bx;
+ UINT8 video_lines;
+ UINT8 video_isvga;
+ UINT16 video_points;
+};
+
+struct atag_ramdisk {
+ UINT32 flags;
+ UINT32 size;
+ UINTN start;
+};
+
+struct atag_initrd2 {
+ UINT32 start;
+ UINT32 size;
+};
+
+struct atag_serialnr {
+ UINT32 low;
+ UINT32 high;
+};
+
+struct atag_revision {
+ UINT32 rev;
+};
+
+struct atag_videolfb {
+ UINT16 lfb_width;
+ UINT16 lfb_height;
+ UINT16 lfb_depth;
+ UINT16 lfb_linelength;
+ UINT32 lfb_base;
+ UINT32 lfb_size;
+ UINT8 red_size;
+ UINT8 red_pos;
+ UINT8 green_size;
+ UINT8 green_pos;
+ UINT8 blue_size;
+ UINT8 blue_pos;
+ UINT8 rsvd_size;
+ UINT8 rsvd_pos;
+};
+
+struct atag_cmdline {
+ CHAR8 cmdline[1];
+};
+
+struct atag {
+ struct atag_header header;
+ union {
+ struct atag_core core_tag;
+ struct atag_mem mem_tag;
+ struct atag_videotext videotext_tag;
+ struct atag_ramdisk ramdisk_tag;
+ struct atag_initrd2 initrd2_tag;
+ struct atag_serialnr serialnr_tag;
+ struct atag_revision revision_tag;
+ struct atag_videolfb videolfb_tag;
+ struct atag_cmdline cmdline_tag;
+ } body;
+};
+
+#define next_tag_address(t) ((struct atag *)((UINT32)(t) + (((t)->header.size) << 2) ))
+#define tag_size(type) ((UINT32)((sizeof(struct atag_header) + sizeof(struct type)) >> 2))
+
+STATIC struct atag *Params; /* used to point at the current tag */
+
+#endif
+
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S
index 64d0a33c26..101ec677e8 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__ashldi3)
- INTERWORK_FUNC(__ashldi3)
+ GCC_ASM_EXPORT(__ashldi3)
ASM_PFX(__ashldi3):
cmp r2, #31
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S
index 3cb0e68f62..775e288856 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__ashrdi3)
- INTERWORK_FUNC(__ashrdi3)
+ GCC_ASM_EXPORT(__ashrdi3)
ASM_PFX(__ashrdi3):
cmp r2, #31
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.S
index 2f9dcd4297..9fb6f2b3d9 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__clzsi2)
- INTERWORK_FUNC(__clzsi2)
+ GCC_ASM_EXPORT(__clzsi2)
ASM_PFX(__clzsi2):
@ frame_needed = 1, uses_anonymous_args = 0
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.S
index b776ef43e1..287ecd3ad7 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__ctzsi2)
- INTERWORK_FUNC(__ctzsi2)
+ GCC_ASM_EXPORT(__ctzsi2)
ASM_PFX(__ctzsi2):
uxth r3, r0
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S
index c6a889a8b4..d5f05f7eaf 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__divdi3)
- INTERWORK_FUNC(__divdi3)
+ GCC_ASM_EXPORT(__divdi3)
ASM_PFX(__divdi3):
@ args = 0, pretend = 0, frame = 0
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S
index 3d9b78c6b1..d1a7f08747 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__divsi3)
- INTERWORK_FUNC(__divsi3)
+ GCC_ASM_EXPORT(__divsi3)
ASM_PFX(__divsi3):
eor r3, r0, r0, asr #31
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.S
index f8cd1aa9e2..97f9c6ca7c 100755
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.S
@@ -15,8 +15,7 @@
.text
.align 2
- .globl ASM_PFX(__aeabi_ldivmod)
- INTERWORK_FUNC(__aeabi_ldivmod)
+ GCC_ASM_EXPORT(__aeabi_ldivmod)
//
// A pair of (unsigned) long longs is returned in {{r0, r1}, {r2, r3}},
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S
index 8d8c98b602..5800ae12a1 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__lshrdi3)
- INTERWORK_FUNC(__lshrdi3)
+ GCC_ASM_EXPORT(__lshrdi3)
ASM_PFX(__lshrdi3):
cmp r2, #31
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S
index ae20598943..09c0e7a1c0 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(memcpy)
- INTERWORK_FUNC(memcpy)
+ GCC_ASM_EXPORT(memcpy)
ASM_PFX(memcpy):
stmfd sp!, {r7, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S
index 040bbf1fdc..73cb1b2af3 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S
@@ -15,8 +15,7 @@
.text
.align 2
- .globl ASM_PFX(memset)
- INTERWORK_FUNC(memset)
+ GCC_ASM_EXPORT (memset)
ASM_PFX(memset):
@ args = 0, pretend = 0, frame = 0
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S
index c7eb4b5f0e..4b86b83f00 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__moddi3)
- INTERWORK_FUNC(__moddi3)
+ GCC_ASM_EXPORT(__moddi3)
ASM_PFX(__moddi3):
stmfd sp!, {r4, r5, r7, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S
index 93ba234ccb..039688f44c 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__modsi3)
- INTERWORK_FUNC(__modsi3)
+ GCC_ASM_EXPORT(__modsi3)
ASM_PFX(__modsi3):
stmfd sp!, {r4, r5, r7, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S
index 5c9aeef4ab..919d6374e1 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__muldi3)
- INTERWORK_FUNC(__muldi3)
+ GCC_ASM_EXPORT(__muldi3)
ASM_PFX(__muldi3):
stmfd sp!, {r4, r5, r6, r7, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/sourcery.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/sourcery.S
index 68cc974fd9..7938856a9b 100755
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/sourcery.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/sourcery.S
@@ -15,8 +15,7 @@
.text
.align 2
- .globl ASM_PFX(__aeabi_ulcmp)
- INTERWORK_FUNC(__aeabi_ulcmp)
+ GCC_ASM_EXPORT(__aeabi_ulcmp)
ASM_PFX(__aeabi_ulcmp):
stmfd sp!, {r4, r5, r8}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S
index 8c38a7af47..97ebf79351 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S
@@ -16,8 +16,7 @@
.text
.p2align 2
-.globl ASM_PFX(__switch16)
-INTERWORK_FUNC(__switch16)
+GCC_ASM_EXPORT(__switch16)
ASM_PFX(__switch16):
ldrh ip, [lr, #-1]
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S
index d9bf800fd7..e0fd100aa5 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S
@@ -16,8 +16,7 @@
.text
.p2align 2
-.globl ASM_PFX(__switch32)
-INTERWORK_FUNC(__switch32)
+GCC_ASM_EXPORT(__switch32)
ASM_PFX(__switch32):
ldr ip, [lr, #-1]
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S
index 1fbd48aa35..ea3340c9a5 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S
@@ -16,9 +16,7 @@
.text
.p2align 2
-.globl ASM_PFX(__switch8)
-INTERWORK_FUNC(__switch8)
-
+GCC_ASM_EXPORT(__switch8)
ASM_PFX(__switch8):
ldrb ip, [lr, #-1]
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S
index 753d999b5f..83636e1f50 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S
@@ -16,8 +16,7 @@
.text
.p2align 2
-.globl ASM_PFX(__switchu8)
-INTERWORK_FUNC(__switchu8)
+GCC_ASM_EXPORT(__switchu8)
ASM_PFX(__switchu8):
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.S
index 5b7f5b70b7..ae9a703106 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__ucmpdi2)
- INTERWORK_FUNC(__ucmpdi2)
+ GCC_ASM_EXPORT(__ucmpdi2)
ASM_PFX(__ucmpdi2):
stmfd sp!, {r4, r5, r8, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S
index fc9240e135..7b67aeeeab 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__udivdi3)
- INTERWORK_FUNC(__udivdi3)
+ GCC_ASM_EXPORT(__udivdi3)
ASM_PFX(__udivdi3):
stmfd sp!, {r7, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S
index 816e66a12a..c6b823986c 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S
@@ -14,9 +14,8 @@
.text
.align 2
- .globl ASM_PFX(__udivmoddi4)
- INTERWORK_FUNC(__udivmoddi4)
-
+ GCC_ASM_EXPORT(__udivmoddi4)
+
ASM_PFX(__udivmoddi4):
stmfd sp!, {r4, r5, r6, r7, lr}
add r7, sp, #12
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S
index 77cfa726c0..87509941f2 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__udivsi3)
- INTERWORK_FUNC(__udivsi3)
+ GCC_ASM_EXPORT(__udivsi3)
ASM_PFX(__udivsi3):
cmp r1, #0
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.S
index 81e824cc83..4bde15f28d 100755
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.S
@@ -16,8 +16,7 @@
.text
.align 2
- .globl ASM_PFX(__aeabi_uldivmod)
- INTERWORK_FUNC(__aeabi_uldivmod)
+ GCC_ASM_EXPORT(__aeabi_uldivmod)
//
//UINT64
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S
index c801ba06dd..e4374b5789 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__umoddi3)
- INTERWORK_FUNC(__umoddi3)
+ GCC_ASM_EXPORT(__umoddi3)
ASM_PFX(__umoddi3):
stmfd sp!, {r7, lr}
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S
index 30dc55193b..f571a56db6 100644
--- a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S
+++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S
@@ -14,8 +14,7 @@
.text
.align 2
- .globl ASM_PFX(__umodsi3)
- INTERWORK_FUNC(__umodsi3)
+ GCC_ASM_EXPORT(__umodsi3)
ASM_PFX(__umodsi3):
stmfd sp!, {r4, r5, r7, lr}
diff --git a/ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.c b/ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.c
index 5bfa0adc24..5bd1a9d188 100755
--- a/ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.c
+++ b/ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.c
@@ -32,37 +32,33 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
CHAR8 *
DeCygwinPathIfNeeded (
- IN CHAR8 *Name
+ IN CHAR8 *Name,
+ IN CHAR8 *Temp,
+ IN UINTN Size
)
{
CHAR8 *Ptr;
UINTN Index;
- UINTN Len;
+ UINTN Index2;
Ptr = AsciiStrStr (Name, "/cygdrive/");
if (Ptr == NULL) {
return Name;
}
- Len = AsciiStrLen (Ptr);
-
- // convert "/cygdrive" to spaces
- for (Index = 0; Index < 9; Index++) {
- Ptr[Index] = ' ';
+ for (Index = 9, Index2 = 0; (Index < (Size + 9)) && (Ptr[Index] != '\0'); Index++, Index2++) {
+ Temp[Index2] = Ptr[Index];
+ if (Temp[Index2] == '/') {
+ Temp[Index2] = '\\' ;
}
- // convert /c to c:
- Ptr[9] = Ptr[10];
- Ptr[10] = ':';
-
- // switch path seperators
- for (Index = 11; Index < Len; Index++) {
- if (Ptr[Index] == '/') {
- Ptr[Index] = '\\' ;
+ if (Index2 == 1) {
+ Temp[Index2 - 1] = Ptr[Index];
+ Temp[Index2] = ':';
}
}
- return Name;
+ return Temp;
}
@@ -81,12 +77,14 @@ PeCoffLoaderRelocateImageExtraAction (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
{
+ CHAR8 Temp[512];
+
#ifdef __CC_ARM
// Print out the command for the RVD debugger to load symbols for this image
- DEBUG ((EFI_D_ERROR, "load /a /ni /np %a &0x%08x\n", DeCygwinPathIfNeeded (ImageContext->PdbPointer), (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)));
+ DEBUG ((EFI_D_ERROR, "load /a /ni /np %a &0x%08x\n", DeCygwinPathIfNeeded (ImageContext->PdbPointer, Temp, sizeof (Temp)), (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)));
#elif __GNUC__
// This may not work correctly if you generate PE/COFF directlyas then the Offset would not be required
- DEBUG ((EFI_D_ERROR, "add-symbol-file %a 0x%08x\n", DeCygwinPathIfNeeded (ImageContext->PdbPointer), (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)));
+ DEBUG ((EFI_D_ERROR, "add-symbol-file %a 0x%08x\n", DeCygwinPathIfNeeded (ImageContext->PdbPointer, Temp, sizeof (Temp)), (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)));
#else
DEBUG ((EFI_D_ERROR, "Loading driver at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN) ImageContext->ImageAddress, FUNCTION_ENTRY_POINT (ImageContext->EntryPoint)));
#endif
@@ -110,12 +108,16 @@ PeCoffLoaderUnloadImageExtraAction (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
{
+ CHAR8 Temp[512];
+
#ifdef __CC_ARM
+ {
// Print out the command for the RVD debugger to load symbols for this image
- DEBUG ((EFI_D_ERROR, "unload symbols_only %a", DeCygwinPathIfNeeded (ImageContext->PdbPointer)));
+ DEBUG ((EFI_D_ERROR, "unload symbols_only %a", DeCygwinPathIfNeeded (ImageContext->PdbPointer, Temp, sizeof (Temp))));
+ }
#elif __GNUC__
// This may not work correctly if you generate PE/COFF directlyas then the Offset would not be required
- DEBUG ((EFI_D_ERROR, "remove-symbol-file %a 0x%08x\n", DeCygwinPathIfNeeded (ImageContext->PdbPointer), (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)));
+ DEBUG ((EFI_D_ERROR, "remove-symbol-file %a 0x%08x\n", DeCygwinPathIfNeeded (ImageContext->PdbPointer, Temp, sizeof (Temp)), (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)));
#else
DEBUG ((EFI_D_ERROR, "Unloading %a", ImageContext->PdbPointer));
#endif
diff --git a/ArmPkg/Library/L2X0CacheLibNull/L2X0Cache.c b/ArmPkg/Library/L2X0CacheLibNull/L2X0Cache.c
new file mode 100644
index 0000000000..b7d79c3c6e
--- /dev/null
+++ b/ArmPkg/Library/L2X0CacheLibNull/L2X0Cache.c
@@ -0,0 +1,20 @@
+/** @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 <Library/L2X0CacheLib.h>
+
+// Initialize L2X0 Cache Controller
+VOID L2x0CacheInit(UINTN L2x0Base, BOOLEAN CacheEnabled) {
+ //No implementation
+}
diff --git a/ArmPkg/Library/L2X0CacheLibNull/L2X0CacheLibNull.inf b/ArmPkg/Library/L2X0CacheLibNull/L2X0CacheLibNull.inf
new file mode 100644
index 0000000000..f6ff894531
--- /dev/null
+++ b/ArmPkg/Library/L2X0CacheLibNull/L2X0CacheLibNull.inf
@@ -0,0 +1,27 @@
+#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = L2X0CacheLibNull
+ FILE_GUID = 9c76c900-1e8c-11e0-8766-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = L2X0CacheLib
+
+[Sources]
+ L2X0Cache.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
diff --git a/ArmPkg/Universal/MmcDxe/ComponentName.c b/ArmPkg/Universal/MmcDxe/ComponentName.c
new file mode 100644
index 0000000000..030a54f72b
--- /dev/null
+++ b/ArmPkg/Universal/MmcDxe/ComponentName.c
@@ -0,0 +1,162 @@
+/** @file
+ Component Name Protocol implementation for the MMC DXE driver
+
+ 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 "Mmc.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName = {
+ MmcGetDriverName,
+ MmcGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) MmcGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) MmcGetControllerName,
+ "en"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
+mMmcDriverNameTable[] = {
+ {"eng;en", L"MMC/SD Card Interface Driver"},
+ {NULL, NULL}
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+ @param DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+MmcGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mMmcDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gMmcComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+ @param ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+MmcGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/ArmPkg/Universal/MmcDxe/Diagnostics.c b/ArmPkg/Universal/MmcDxe/Diagnostics.c
new file mode 100644
index 0000000000..a477135684
--- /dev/null
+++ b/ArmPkg/Universal/MmcDxe/Diagnostics.c
@@ -0,0 +1,215 @@
+/** @file
+ Diagnostics Protocol implementation for the MMC DXE driver
+
+ 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 <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "Mmc.h"
+
+#define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024
+
+CHAR16* mLogBuffer = NULL;
+UINTN mLogRemainChar = 0;
+
+CHAR16* DiagnosticInitLog(UINTN MaxBufferChar) {
+ mLogRemainChar = MaxBufferChar;
+ mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof(CHAR16));
+ return mLogBuffer;
+}
+
+UINTN DiagnosticLog(CONST CHAR16* Str) {
+ UINTN len = StrLen (Str);
+ if (len <= mLogRemainChar) {
+ mLogRemainChar -= len;
+ StrCpy (mLogBuffer, Str);
+ mLogBuffer += len;
+ return len;
+ } else {
+ return 0;
+ }
+}
+
+VOID GenerateRandomBuffer(VOID* Buffer, UINTN BufferSize) {
+ UINT64 i;
+ UINT64* Buffer64 = (UINT64*)Buffer;
+
+ for (i = 0; i < (BufferSize >> 3); i++) {
+ *Buffer64 = i | (~i << 32);
+ Buffer64++;
+ }
+}
+
+BOOLEAN CompareBuffer(VOID *BufferA, VOID *BufferB, UINTN BufferSize) {
+ UINTN i;
+ UINT64* BufferA64 = (UINT64*)BufferA;
+ UINT64* BufferB64 = (UINT64*)BufferB;
+
+ for (i = 0; i < (BufferSize >> 3); i++) {
+ if (*BufferA64 != *BufferB64) {
+ DEBUG((EFI_D_ERROR, "CompareBuffer: Error at %i", i));
+ DEBUG((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));
+ return FALSE;
+ }
+ BufferA64++;
+ BufferB64++;
+ }
+ return TRUE;
+}
+
+EFI_STATUS MmcReadWriteDataTest(MMC_HOST_INSTANCE *MmcHostInstance, EFI_LBA Lba, UINTN BufferSize) {
+ VOID *BackBuffer;
+ VOID *WriteBuffer;
+ VOID *ReadBuffer;
+ EFI_STATUS Status;
+
+ // Check if a Media is Present
+ if (!MmcHostInstance->BlockIo.Media->MediaPresent) {
+ DiagnosticLog(L"ERROR: No Media Present\n");
+ return EFI_NO_MEDIA;
+ }
+
+ if (MmcHostInstance->State != MmcTransferState) {
+ DiagnosticLog(L"ERROR: Not ready for Transfer state\n");
+ return EFI_NOT_READY;
+ }
+
+ BackBuffer = AllocatePool(BufferSize);
+ WriteBuffer = AllocatePool(BufferSize);
+ ReadBuffer = AllocatePool(BufferSize);
+
+ // Read (and save) buffer at a specific location
+ Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);
+ if (Status != EFI_SUCCESS) {
+ DiagnosticLog(L"ERROR: Fail to Read Block (1)\n");
+ return Status;
+ }
+
+ // Write buffer at the same location
+ GenerateRandomBuffer(WriteBuffer,BufferSize);
+ Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);
+ if (Status != EFI_SUCCESS) {
+ DiagnosticLog(L"ERROR: Fail to Write Block (1)\n");
+ return Status;
+ }
+
+ // Read the buffer at the same location
+ Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);
+ if (Status != EFI_SUCCESS) {
+ DiagnosticLog(L"ERROR: Fail to Read Block (2)\n");
+ return Status;
+ }
+
+ // Check that is conform
+ if (!CompareBuffer(ReadBuffer,WriteBuffer,BufferSize)) {
+ DiagnosticLog(L"ERROR: Fail to Read/Write Block (1)\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Restore content at the original location
+ Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);
+ if (Status != EFI_SUCCESS) {
+ DiagnosticLog(L"ERROR: Fail to Write Block (2)\n");
+ return Status;
+ }
+
+ // Read the restored content
+ Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);
+ if (Status != EFI_SUCCESS) {
+ DiagnosticLog(L"ERROR: Fail to Read Block (3)\n");
+ return Status;
+ }
+
+ // Check the content is correct
+ if (!CompareBuffer(ReadBuffer,BackBuffer,BufferSize)) {
+ DiagnosticLog(L"ERROR: Fail to Read/Write Block (2)\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+MmcDriverDiagnosticsRunDiagnostics (
+ IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
+ IN CHAR8 *Language,
+ OUT EFI_GUID **ErrorType,
+ OUT UINTN *BufferSize,
+ OUT CHAR16 **Buffer
+ )
+{
+ LIST_ENTRY *CurrentLink;
+ MMC_HOST_INSTANCE *MmcHostInstance;
+ EFI_STATUS Status;
+
+ if (Language == NULL ||
+ ErrorType == NULL ||
+ Buffer == NULL ||
+ ControllerHandle == NULL ||
+ BufferSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ *ErrorType = NULL;
+ *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;
+ *Buffer = DiagnosticInitLog(DIAGNOSTIC_LOGBUFFER_MAXCHAR);
+
+ DiagnosticLog(L"MMC Driver Diagnostics\n");
+
+ // For each MMC instance
+ CurrentLink = mMmcHostPool.ForwardLink;
+ while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);
+ ASSERT(MmcHostInstance != NULL);
+
+ // LBA=1 Size=BlockSize
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block\n");
+ Status = MmcReadWriteDataTest(MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);
+
+ // LBA=2 Size=BlockSize
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: Second Block\n");
+ Status = MmcReadWriteDataTest(MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);
+
+ // LBA=10 Size=BlockSize
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: Any Block\n");
+ Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);
+
+ // LBA=LastBlock Size=BlockSize
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: Last Block\n");
+ Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);
+
+ // LBA=1 Size=2*BlockSize
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");
+ Status = MmcReadWriteDataTest(MmcHostInstance, 1, 2*MmcHostInstance->BlockIo.Media->BlockSize);
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return Status;
+}
+
+//
+// EFI Driver Diagnostics 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {
+ (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,
+ "en"
+};
diff --git a/ArmPkg/Universal/MmcDxe/Mmc.c b/ArmPkg/Universal/MmcDxe/Mmc.c
new file mode 100644
index 0000000000..90d1172ffa
--- /dev/null
+++ b/ArmPkg/Universal/MmcDxe/Mmc.c
@@ -0,0 +1,387 @@
+/** @file
+ Main file of the MMC Dxe driver. The driver entrypoint is defined into this 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 <Protocol/DevicePath.h>
+#include <Protocol/MmcHost.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+
+#include "Mmc.h"
+
+EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {
+ SIGNATURE_32('m','m','c','o'), // MediaId
+ TRUE, // RemovableMedia
+ FALSE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching
+ 512, // BlockSize
+ 4, // IoAlign
+ 0, // Pad
+ 0 // LastBlock
+};
+
+//
+// This device structure is serviced as a header.
+// Its next field points to the first root bridge device node.
+//
+LIST_ENTRY mMmcHostPool;
+
+/**
+ Initialize the MMC Host Pool to support multiple MMC devices
+**/
+VOID
+InitializeMmcHostPool (
+ VOID
+ )
+{
+ InitializeListHead (&mMmcHostPool);
+}
+
+/**
+ Insert a new Mmc Host controller to the pool
+**/
+VOID
+InsertMmcHost (
+ IN MMC_HOST_INSTANCE *MmcHostInstance
+ )
+{
+ InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));
+}
+
+/*
+ Remove a new Mmc Host controller to the pool
+*/
+VOID
+RemoveMmcHost (
+ IN MMC_HOST_INSTANCE *MmcHostInstance
+ )
+{
+ RemoveEntryList (&(MmcHostInstance->Link));
+}
+
+MMC_HOST_INSTANCE* CreateMmcHostInstance(
+ IN EFI_MMC_HOST_PROTOCOL* MmcHost
+ )
+{
+ EFI_STATUS Status;
+ MMC_HOST_INSTANCE* MmcHostInstance;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));
+ if (MmcHostInstance == NULL) {
+ return NULL;
+ }
+
+ MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;
+
+ MmcHostInstance->State = MmcHwInitializationState;
+
+ MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);
+ if (MmcHostInstance->BlockIo.Media == NULL) {
+ goto FREE_INSTANCE;
+ }
+
+ MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;
+ MmcHostInstance->BlockIo.Reset = MmcReset;
+ MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;
+ MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;
+ MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;
+
+ MmcHostInstance->MmcHost = MmcHost;
+
+ // Create DevicePath for the new MMC Host
+ Status = MmcHost->BuildDevicePath(&NewDevicePathNode);
+ if (EFI_ERROR (Status)) {
+ goto FREE_MEDIA;
+ }
+
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
+ if (DevicePath == NULL) {
+ goto FREE_MEDIA;
+ }
+
+ SetDevicePathEndNode (DevicePath);
+ MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);
+
+ // Publish BlockIO protocol interface
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &MmcHostInstance->MmcHandle,
+ &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),
+ &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR(Status)) {
+ goto FREE_DEVICE_PATH;
+ }
+
+ return MmcHostInstance;
+
+FREE_DEVICE_PATH:
+ FreePool(DevicePath);
+
+FREE_MEDIA:
+ FreePool(MmcHostInstance->BlockIo.Media);
+
+FREE_INSTANCE:
+ FreePool(MmcHostInstance);
+
+ return NULL;
+}
+
+EFI_STATUS DestroyMmcHostInstance(
+ IN MMC_HOST_INSTANCE* MmcHostInstance
+ )
+{
+ EFI_STATUS Status;
+
+ // Uninstall Protocol Interfaces
+ Status = gBS->UninstallMultipleProtocolInterfaces(
+ &MmcHostInstance->MmcHandle,
+ &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),
+ &gEfiDevicePathProtocolGuid,&(MmcHostInstance->DevicePath),
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Free Memory allocated for the instance
+ if (MmcHostInstance->BlockIo.Media) {
+ FreePool(MmcHostInstance->BlockIo.Media);
+ }
+ FreePool (MmcHostInstance);
+
+ return Status;
+}
+
+/**
+ This function checks if the controller implement the Mmc Host and the Device Path Protocols
+**/
+EFI_STATUS
+EFIAPI
+MmcDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+ EFI_DEV_PATH_PTR Node;
+
+ //
+ // Check RemainingDevicePath validation
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // Check if RemainingDevicePath is the End of Device Path Node,
+ // if yes, go on checking other conditions
+ //
+ if (!IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // check its validation
+ //
+ Node.DevPath = RemainingDevicePath;
+ if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
+ Node.DevPath->SubType != HW_VENDOR_DP ||
+ DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ // Check if Mmc Host protocol is installed by platform
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiMmcHostProtocolGuid,
+ (VOID **) &MmcHost,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close the Mmc Host used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiMmcHostProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+**/
+EFI_STATUS
+EFIAPI
+MmcDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ MMC_HOST_INSTANCE *MmcHostInstance;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+
+ //
+ // Check RemainingDevicePath validation
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // Check if RemainingDevicePath is the End of Device Path Node,
+ // if yes, return EFI_SUCCESS
+ //
+ if (IsDevicePathEnd (RemainingDevicePath)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Get the Mmc Host protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiMmcHostProtocolGuid,
+ (VOID **) &MmcHost,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+ return Status;
+ }
+
+ MmcHostInstance = CreateMmcHostInstance(MmcHost);
+ if (MmcHostInstance != NULL) {
+ // Add the handle to the pool
+ InsertMmcHost (MmcHostInstance);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+**/
+EFI_STATUS
+EFIAPI
+MmcDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ LIST_ENTRY *CurrentLink;
+ MMC_HOST_INSTANCE *MmcHostInstance;
+
+ MMC_TRACE("MmcDriverBindingStop()");
+
+ // For each MMC instance
+ CurrentLink = mMmcHostPool.ForwardLink;
+ while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);
+ ASSERT(MmcHostInstance != NULL);
+
+ // Close gEfiMmcHostProtocolGuid
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,
+ This->DriverBindingHandle
+ );
+
+ // Remove MMC Host Instance from the pool
+ RemoveMmcHost (MmcHostInstance);
+
+ // Destroy MmcHostInstance
+ DestroyMmcHostInstance (MmcHostInstance);
+ }
+
+ return Status;
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {
+ MmcDriverBindingSupported,
+ MmcDriverBindingStart,
+ MmcDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+/**
+
+**/
+EFI_STATUS
+EFIAPI
+MmcDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initializes MMC Host pool
+ //
+ InitializeMmcHostPool ();
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gMmcDriverBinding,
+ ImageHandle,
+ &gMmcComponentName,
+ &gMmcComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Install driver diagnostics
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/ArmPkg/Universal/MmcDxe/Mmc.h b/ArmPkg/Universal/MmcDxe/Mmc.h
new file mode 100644
index 0000000000..dbca991157
--- /dev/null
+++ b/ArmPkg/Universal/MmcDxe/Mmc.h
@@ -0,0 +1,284 @@
+/** @file
+ Main Header file for the MMC DXE driver
+
+ 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.
+
+**/
+
+#ifndef __MMC_H
+#define __MMC_H
+
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/MmcHost.h>
+
+#include <Library/UefiLib.h>
+
+#define MMC_TRACE(txt) DEBUG((EFI_D_BLKIO, "MMC: " txt "\n"))
+
+#define MMC_IOBLOCKS_READ 0
+#define MMC_IOBLOCKS_WRITE 1
+
+#define MMC_OCR_POWERUP 0x80000000
+
+#define MMC_CSD_GET_CCC(Response) (Response[1] >> 20)
+#define MMC_CSD_GET_TRANSPEED(Response) (Response[0] & 0xFF)
+#define MMC_CSD_GET_READBLLEN(Response) ((Response[1] >> 16) & 0xF)
+#define MMC_CSD_GET_WRITEBLLEN(Response) ((Response[3] >> 22) & 0xF)
+#define MMC_CSD_GET_FILEFORMAT(Response) ((Response[3] >> 10) & 0x3)
+#define MMC_CSD_GET_FILEFORMATGRP(Response) ((Response[3] >> 15) & 0x1)
+#define MMC_CSD_GET_DEVICESIZE(csd) (((Response[2] >> 30) & 0x3) | ((Response[1] & 0x3FF) << 2))
+#define MMC_CSD_GET_DEVICESIZEMULT(csd) ((Response[2] >> 15) & 0x7)
+
+#define MMC_R0_CURRENTSTATE(Response) ((Response[0] >> 9) & 0xF)
+
+#define MMC_R0_STATE_IDLE 0
+#define MMC_R0_STATE_READY 1
+#define MMC_R0_STATE_IDENT 2
+#define MMC_R0_STATE_STDBY 3
+#define MMC_R0_STATE_TRAN 4
+#define MMC_R0_STATE_DATA 5
+
+typedef enum {
+ UNKNOWN_CARD,
+ MMC_CARD, //MMC card
+ MMC_CARD_HIGH, //MMC Card with High capacity
+ SD_CARD, //SD 1.1 card
+ SD_CARD_2, //SD 2.0 or above standard card
+ SD_CARD_2_HIGH //SD 2.0 or above high capacity card
+} CARD_TYPE;
+
+typedef struct {
+ UINT32 Reserved0: 7; // 0
+ UINT32 V170_V195: 1; // 1.70V - 1.95V
+ UINT32 V200_V260: 7; // 2.00V - 2.60V
+ UINT32 V270_V360: 9; // 2.70V - 3.60V
+ UINT32 RESERVED_1: 5; // Reserved
+ UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode)
+ UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine
+} OCR;
+
+typedef struct {
+ UINT32 NOT_USED; // 1 [0:0]
+ UINT32 CRC; // CRC7 checksum [7:1]
+ UINT32 MDT; // Manufacturing date [19:8]
+ UINT32 RESERVED_1; // Reserved [23:20]
+ UINT32 PSN; // Product serial number [55:24]
+ UINT8 PRV; // Product revision [63:56]
+ UINT8 PNM[5]; // Product name [64:103]
+ UINT16 OID; // OEM/Application ID [119:104]
+ UINT8 MID; // Manufacturer ID [127:120]
+} CID;
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+
+ UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]
+ UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]
+ UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]
+ UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]
+ UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]
+ UINT32 C_SIZELow2: 2; // Device size [63:62]
+
+ UINT32 C_SIZEHigh10: 10;// Device size [73:64]
+ UINT32 RESERVED_4: 2; // Reserved [75:74]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT32 CCC: 12;// Card command classes [95:84]
+
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+
+ UINT8 RESERVED_5: 6; // Reserved [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+} CSD;
+
+typedef struct {
+ UINT16 RCA;
+ CARD_TYPE CardType;
+ OCR OCRData;
+ CID CIDData;
+ CSD CSDData;
+} CARD_INFO;
+
+typedef struct _MMC_HOST_INSTANCE {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE MmcHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ MMC_STATE State;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ CARD_INFO CardInfo;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+} MMC_HOST_INSTANCE;
+
+#define MMC_HOST_INSTANCE_SIGNATURE SIGNATURE_32('m', 'm', 'c', 'h')
+#define MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(a) CR (a, MMC_HOST_INSTANCE, BlockIo, MMC_HOST_INSTANCE_SIGNATURE)
+#define MMC_HOST_INSTANCE_FROM_LINK(a) CR (a, MMC_HOST_INSTANCE, Link, MMC_HOST_INSTANCE_SIGNATURE)
+
+
+EFI_STATUS
+EFIAPI
+MmcGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+MmcGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+extern EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2;
+
+extern EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2;
+
+extern LIST_ENTRY mMmcHostPool;
+
+/**
+ Reset the block device.
+
+ This function implements EFI_BLOCK_IO_PROTOCOL.Reset().
+ It resets the block device hardware.
+ ExtendedVerification is ignored in this implementation.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ @retval EFI_SUCCESS The block device was reset.
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+MmcReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Reads the requested number of blocks from the device.
+
+ This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
+ It reads the requested number of blocks from the device.
+ All the blocks are read, or an error is returned.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the read request is for.
+ @param Lba The starting logical block address to read from on the device.
+ @param BufferSize The size of the Buffer in bytes.
+ This must be a multiple of the intrinsic block size of the device.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmcReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Writes a specified number of blocks to the device.
+
+ This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
+ It writes a specified number of blocks to the device.
+ All blocks are written, or an error is returned.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written.
+ @param BufferSize The size of the Buffer in bytes.
+ This must be a multiple of the intrinsic block size of the device.
+ @param Buffer Pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data were written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic
+ block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmcWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Flushes all modified data to a physical block device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data were written correctly to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+MmcFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+#endif
diff --git a/ArmPkg/Universal/MmcDxe/MmcBlockIo.c b/ArmPkg/Universal/MmcDxe/MmcBlockIo.c
new file mode 100644
index 0000000000..d8bd2d18b9
--- /dev/null
+++ b/ArmPkg/Universal/MmcDxe/MmcBlockIo.c
@@ -0,0 +1,558 @@
+/** @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 <Protocol/MmcHost.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+
+#include "Mmc.h"
+
+// Untested ...
+//#define USE_STREAM
+
+#define MAX_RETRY_COUNT 200
+
+EFI_STATUS
+MmcNotifyState (
+ MMC_HOST_INSTANCE *MmcHostInstance,
+ MMC_STATE State
+ ) {
+ MmcHostInstance->State = State;
+ return MmcHostInstance->MmcHost->NotifyState(State);
+}
+
+VOID PrintOCR(UINT32 ocr) {
+ float minv, maxv, volts;
+ int loop;
+
+ minv = 3.6;
+ maxv = 2.0;
+ volts = 2.0;
+
+ // The MMC register bits [23:8] indicate the working range of the card
+ for (loop = 8; loop < 24; loop++) {
+ if (ocr & (1 << loop)) {
+ if (minv > volts) minv = volts;
+ if (maxv < volts) maxv = volts + 0.1;
+ }
+ volts = volts + 0.1;
+ }
+
+ DEBUG((EFI_D_ERROR, "- PrintOCR ocr (0x%X)\n",ocr));
+ //DEBUG((EFI_D_ERROR, "\t- Card operating voltage: %fV to %fV\n", minv, maxv));
+ if (((ocr >> 29) & 3) == 0)
+ DEBUG((EFI_D_ERROR, "\t- AccessMode: Byte Mode\n"));
+ else
+ DEBUG((EFI_D_ERROR, "\t- AccessMode: Block Mode (0x%X)\n",((ocr >> 29) & 3)));
+
+ if (ocr & MMC_OCR_POWERUP)
+ DEBUG((EFI_D_ERROR, "\t- PowerUp\n"));
+ else
+ DEBUG((EFI_D_ERROR, "\t- Voltage Not Supported\n"));
+}
+
+VOID PrintCID(UINT32* cid) {
+ DEBUG((EFI_D_ERROR, "- PrintCID\n"));
+ DEBUG((EFI_D_ERROR, "\t- Manufacturing date: %d/%d\n",(cid[0] >> 8) & 0xF,(cid[0] >> 12) & 0xFF));
+ DEBUG((EFI_D_ERROR, "\t- Product serial number: 0x%X%X\n",cid[1] & 0xFFFFFF,(cid[0] >> 24) & 0xFF));
+ DEBUG((EFI_D_ERROR, "\t- Product revision: %d\n",cid[1] >> 24));
+ //DEBUG((EFI_D_ERROR, "\t- Product name: %s\n",(char*)(cid + 2)));
+ DEBUG((EFI_D_ERROR, "\t- OEM ID: %c%c\n",(cid[3] >> 8) & 0xFF,(cid[3] >> 16) & 0xFF));
+}
+
+VOID PrintCSD(UINT32* csd) {
+ UINTN val32;
+ CONST CHAR8* str_unit[] = { "100kbit/s","1Mbit/s","10Mbit/s","100MBit/s","Unkbown","Unkbown","Unkbown","Unkbown" };
+ CONST CHAR8* str_value[] = { "1.0","1.2","1.3","1.5","2.0","2.5","3.0","3.5","4.0","4.5","5.0","Unknown","Unknown","Unknown","Unknown" };
+
+ if (((csd[2] >> 30) & 0x3) == 0)
+ DEBUG((EFI_D_ERROR, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n"));
+ else if (((csd[2] >> 30) & 0x3) == 1)
+ DEBUG((EFI_D_ERROR, "- PrintCSD Version 2.00/High Capacity\n"));
+ else
+ DEBUG((EFI_D_ERROR, "- PrintCSD Version Higher than v3.3\n"));
+
+ DEBUG((EFI_D_ERROR, "\t- Supported card command class: 0x%X\n",MMC_CSD_GET_CCC(csd)));
+ DEBUG((EFI_D_ERROR, "\t- Speed: %a %a\n",str_value[(MMC_CSD_GET_TRANSPEED(csd) >> 3) & 0xF],str_unit[MMC_CSD_GET_TRANSPEED(csd) & 7]));
+ DEBUG((EFI_D_ERROR, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN(csd)-1)));
+ DEBUG((EFI_D_ERROR, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN(csd)-1)));
+
+ if (!MMC_CSD_GET_FILEFORMATGRP(csd)) {
+ val32 = MMC_CSD_GET_FILEFORMAT(csd);
+ if (val32 == 0) DEBUG((EFI_D_ERROR, "\t- Format(0): Hard disk-like file system with partition table\n"));
+ else if (val32 == 1) DEBUG((EFI_D_ERROR, "\t- Format(1): DOS FAT (floppy-like) with boot sector only (no partition table)\n"));
+ else if (val32 == 2) DEBUG((EFI_D_ERROR, "\t- Format(2): Universal File Format\n"));
+ else DEBUG((EFI_D_ERROR, "\t- Format(3): Others/Unknown\n"));
+ } else {
+ DEBUG((EFI_D_ERROR, "\t- Format: Reserved\n"));
+ }
+}
+
+VOID PrintRCA(UINT32 rca) {
+ DEBUG((EFI_D_ERROR, "- PrintRCA: 0x%X\n",rca));
+ DEBUG((EFI_D_ERROR, "\t- Status: 0x%X\n",rca & 0xFFFF));
+ DEBUG((EFI_D_ERROR, "\t- RCA: 0x%X\n",(rca >> 16) & 0xFFFF));
+}
+
+VOID PrintResponseR1(UINT32 response) {
+ DEBUG((EFI_D_ERROR, "Response: 0x%X\n",response));
+ if (response & (1 << 8)) DEBUG((EFI_D_ERROR, "\t- READY_FOR_DATA\n"));
+
+ if (((response >> 9) & 0xF) == 0) DEBUG((EFI_D_ERROR, "\t- State: Idle\n"));
+ else if (((response >> 9) & 0xF) == 1) DEBUG((EFI_D_ERROR, "\t- State: Ready\n"));
+ else if (((response >> 9) & 0xF) == 2) DEBUG((EFI_D_ERROR, "\t- State: Ident\n"));
+ else if (((response >> 9) & 0xF) == 3) DEBUG((EFI_D_ERROR, "\t- State: StandBy\n"));
+ else if (((response >> 9) & 0xF) == 4) DEBUG((EFI_D_ERROR, "\t- State: Tran\n"));
+ else if (((response >> 9) & 0xF) == 5) DEBUG((EFI_D_ERROR, "\t- State: Data\n"));
+ else if (((response >> 9) & 0xF) == 6) DEBUG((EFI_D_ERROR, "\t- State: Rcv\n"));
+ else if (((response >> 9) & 0xF) == 7) DEBUG((EFI_D_ERROR, "\t- State: Prg\n"));
+ else if (((response >> 9) & 0xF) == 8) DEBUG((EFI_D_ERROR, "\t- State: Dis\n"));
+ else DEBUG((EFI_D_ERROR, "\t- State: Reserved\n"));
+}
+
+EFI_STATUS
+EFIAPI
+MmcIdentificationMode (
+ MMC_HOST_INSTANCE *MmcHostInstance
+ ) {
+ EFI_STATUS Status;
+ UINT32 Response[4];
+ UINTN timer;
+ UINTN CmdArg;
+ BOOLEAN bHCS;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+
+ MmcHost = MmcHostInstance->MmcHost;
+ CmdArg = 0;
+ bHCS = FALSE;
+
+ if (MmcHost == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // We can get into this function if we restart the identification mode
+ if (MmcHostInstance->State == MmcHwInitializationState) {
+ // Initialize the MMC Host HW
+ Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));
+ return Status;
+ }
+ } else {
+ //Note: Could even be used in all cases. But it looks this command could put the state machine into inactive for some cards
+ Status = MmcHost->SendCommand(MMC_CMD0, 0);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));
+ return Status;
+ }
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcIdleState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));
+ return Status;
+ }
+
+ // Are we using SDIO ?
+ Status = MmcHost->SendCommand(MMC_CMD5, 0);
+ if (Status == EFI_SUCCESS) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
+ CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
+ Status = MmcHost->SendCommand(MMC_CMD8, CmdArg);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
+ bHCS = TRUE;
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R7,Response);
+ PrintResponseR1(Response[0]);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
+ }
+
+ // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)
+ timer = MAX_RETRY_COUNT;
+ while (timer > 0) {
+ // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
+ Status = MmcHost->SendCommand(MMC_CMD55, 0);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "Card should be SD\n"));
+ if (bHCS) {
+ MmcHostInstance->CardInfo.CardType = SD_CARD_2;
+ } else {
+ MmcHostInstance->CardInfo.CardType = SD_CARD;
+ }
+
+ // Note: The first time CmdArg will be zero
+ CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
+ if (bHCS) {
+ CmdArg |= BIT30;
+ }
+ Status = MmcHost->SendCommand(MMC_ACMD41, CmdArg);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(ACMD41): Error\n"));
+ return Status;
+ }
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
+ ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
+ } else {
+ DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
+ MmcHostInstance->CardInfo.CardType = MMC_CARD;
+
+ Status = MmcHost->SendCommand(MMC_CMD1, 0x800000);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(ACMD41): Error\n"));
+ return Status;
+ }
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
+ ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
+ }
+
+ if (MmcHostInstance->CardInfo.OCRData.Busy == 0) {
+ MicroSecondDelay(10*1000);
+ timer--;
+ } else {
+ if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
+ MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
+ DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
+ }
+ break; // The MMC/SD card is ready. Continue the Identification Mode
+ }
+ }
+
+ if (timer == 0) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
+ ASSERT(0);
+ return EFI_NO_MEDIA;
+ } else {
+ PrintOCR(Response[0]);
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
+ return Status;
+ }
+
+ Status = MmcHost->SendCommand(MMC_CMD2, 0);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
+ ASSERT(0);
+ return Status;
+ }
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CID,Response);
+ PrintCID(Response);
+
+ Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
+ return Status;
+ }
+
+ CmdArg = 0;
+ Status = MmcHost->SendCommand(MMC_CMD3, CmdArg);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
+ return Status;
+ }
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_RCA,Response);
+ PrintRCA(Response[0]);
+
+ // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
+ if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
+ MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
+ } else {
+ MmcHostInstance->CardInfo.RCA = CmdArg;
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+MmcReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ ) {
+ // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
+ // on power and restart Identification mode
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MmcDetectCard (
+ EFI_MMC_HOST_PROTOCOL *MmcHost
+ )
+{
+ if (!MmcHost->IsCardPresent()) {
+ return EFI_NO_MEDIA;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+#define MMCI0_BLOCKLEN 512
+#define MMCI0_TIMEOUT 10000
+
+EFI_STATUS MmcIoBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Transfer,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ ) {
+ UINT32 Response[4];
+ EFI_STATUS Status;
+ UINTN CardSize, NumBlocks, BlockSize, CmdArg;
+ UINTN timer;
+ UINTN Cmd;
+ MMC_HOST_INSTANCE *MmcHostInstance;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+ UINTN BytesRemainingToBeTransfered;
+ UINTN BlockCount = 1;
+
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This);
+ ASSERT(MmcHostInstance != 0);
+ MmcHost = MmcHostInstance->MmcHost;
+ ASSERT(MmcHost);
+
+ if (MmcHost == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if a Card is Present
+ if (!MmcHost->IsCardPresent()) {
+ MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;
+ MmcHostInstance->BlockIo.Media->LastBlock = 0;
+ MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo
+ MmcHostInstance->BlockIo.Media->ReadOnly = FALSE;
+ return EFI_NO_MEDIA;
+ }
+
+ // If the driver has not been initialized yet then go into Iddentification Mode
+ if (MmcHostInstance->State == MmcHwInitializationState) {
+ MmcIdentificationMode (MmcHostInstance);
+
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error\n"));
+ ASSERT(0);
+ return Status;
+ }
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);
+ PrintCSD(Response);
+
+
+ if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
+ ASSERT(0); //TODO: Implementation needed
+ CardSize = MMC_CSD_GET_DEVICESIZE(Response);
+ NumBlocks = ((CardSize + 1) * 1024);;
+ BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);
+ } else {
+ CardSize = MMC_CSD_GET_DEVICESIZE(Response);
+ NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response) + 2));
+ BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);
+ }
+
+ //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
+ if (BlockSize > 512) {
+ NumBlocks = MultU64x32(NumBlocks, BlockSize/512);
+ BlockSize = 512;
+ }
+
+ MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);
+ MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;
+ MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly();
+ MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
+ MmcHostInstance->BlockIo.Media->MediaId++;
+
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error\n"));
+ ASSERT(0);
+ return Status;
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));
+ return Status;
+ }
+ } else {
+ // Maybe test if the card has changed to update gMmcMedia information
+ if (MmcHostInstance->State == MmcTransferState) {
+ //DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcTransferState\n"));
+ } else if (MmcHostInstance->State == MmcStandByState) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcStandByState\n"));
+ } else {
+ ASSERT(0);
+ }
+ }
+
+ if (Lba > This->Media->LastBlock) {
+ ASSERT(0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSize % This->Media->BlockSize) != 0) {
+ ASSERT(0);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ BytesRemainingToBeTransfered = BufferSize;
+ while (BytesRemainingToBeTransfered > 0) {
+ // Set Block Length
+ Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d\n",This->Media->BlockSize));
+ ASSERT(0);
+ return Status;
+ }
+
+ // Block Count (not used). Could return an error for SD card
+ MmcHost->SendCommand(MMC_CMD23, BlockCount);
+
+ //Set command argument based on the card access mode (Byte mode or Block mode)
+ if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
+ CmdArg = Lba;
+ } else {
+ CmdArg = Lba * This->Media->BlockSize;
+ }
+
+ if (Transfer == MMC_IOBLOCKS_READ) {
+#ifndef USE_STREAM
+ // Read a single block
+ Cmd = MMC_CMD17;
+#else
+ //TODO: Should we support read stream (MMC_CMD11)
+#endif
+ } else {
+#ifndef USE_STREAM
+ // Write a single block
+ Cmd = MMC_CMD24;
+#else
+ //TODO: Should we support write stream (MMC_CMD20)
+#endif
+ }
+ Status = MmcHost->SendCommand(Cmd, CmdArg);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD%d): Error\n",Cmd));
+ ASSERT(0);
+ return Status;
+ }
+
+ if (Transfer == MMC_IOBLOCKS_READ) {
+#ifndef USE_STREAM
+ // Read one block of Data
+ Status = MmcHost->ReadBlockData(Lba,This->Media->BlockSize,Buffer);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Read Block Data"));
+ ASSERT(0);
+ return Status;
+ }
+#else
+ //TODO: Read a steam
+ ASSERT(0);
+#endif
+ Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcProgrammingState\n"));
+ return Status;
+ }
+ } else {
+#ifndef USE_STREAM
+ // Write one block of Data
+ Status = MmcHost->WriteBlockData(Lba,This->Media->BlockSize,Buffer);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Write Block Data"));
+ ASSERT(0);
+ return Status;
+ }
+#else
+ //TODO: Write a steam
+ ASSERT(0);
+#endif
+ }
+
+ // Command 12 - Stop transmission (ends read)
+ Status = MmcHost->SendCommand(MMC_CMD12, 0);
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1b,Response);
+
+ // Command 13 - Read status and wait for programming to complete (return to tran)
+ timer = MMCI0_TIMEOUT;
+ while ((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_TRAN) && timer) {
+ MmcHost->SendCommand(MMC_CMD13, 0);
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
+ NanoSecondDelay(100);
+ timer--;
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));
+ return Status;
+ }
+
+ BytesRemainingToBeTransfered -= This->Media->BlockSize;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+MmcReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ ) {
+ return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+MmcWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ ) {
+ return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+MmcFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ ) {
+ return EFI_SUCCESS;
+}
+
diff --git a/ArmPkg/Universal/MmcDxe/MmcDxe.inf b/ArmPkg/Universal/MmcDxe/MmcDxe.inf
new file mode 100644
index 0000000000..dbdd1efe16
--- /dev/null
+++ b/ArmPkg/Universal/MmcDxe/MmcDxe.inf
@@ -0,0 +1,50 @@
+#/** @file
+# Build file for the MMC DXE driver
+#
+# 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MmcDxe
+ FILE_GUID = b6f44cc0-9e45-11df-be21-0002a5d5c51b
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = MmcDxeInitialize
+
+[Sources.common]
+ ComponentName.c
+ Mmc.c
+ MmcBlockIo.c
+ Diagnostics.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ TimerLib
+
+[Protocols]
+ gEfiDiskIoProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiMmcHostProtocolGuid
+ gEfiDriverDiagnostics2ProtocolGuid
+
+[Depex]
+ TRUE \ No newline at end of file