From 1bfda055dfbc52678655ab2ded721f9f7c0cd496 Mon Sep 17 00:00:00 2001 From: andrewfish Date: Wed, 2 Feb 2011 22:35:30 +0000 Subject: [PATCH] Sync up ArmPkg with patch from mailing list. Changed name of BdsLib.h to BdsUnixLib.h and fixed a lot of issues with Xcode building. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11293 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/ArmPkg.dec | 65 ++ ArmPkg/ArmPkg.dsc | 59 +- ArmPkg/Drivers/CpuDxe/CpuDxe.inf | 3 + ArmPkg/Drivers/CpuDxe/Exception.c | 104 ++-- .../Drivers/CpuDxe/ExceptionSupport.ARMv6.S | 29 +- .../Drivers/CpuDxe/ExceptionSupport.ARMv6.asm | 10 +- ArmPkg/Drivers/CpuDxe/ExceptionSupport.S | 10 +- ArmPkg/Drivers/CpuDxe/Mmu.c | 302 +++------- ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c | 119 ---- ArmPkg/Drivers/PL180MciDxe/PL180Mci.c | 387 ++++++++++++ ArmPkg/Drivers/PL180MciDxe/PL180Mci.h | 117 ++++ ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf | 51 ++ ArmPkg/Drivers/PL301Axi/PL301Axi.c | 108 ++++ ArmPkg/Drivers/PL301Axi/PL301Axi.inf | 29 + ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c | 130 ++++ .../Drivers/PL310L2Cache/PL310L2CacheSec.inf | 30 + ArmPkg/Drivers/PL34xDmc/PL341Dmc.c | 373 ++++++++++++ ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf | 29 + ArmPkg/Drivers/PL35xSmc/InitializeSMC.S | 189 ++++++ ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm | 183 ++++++ ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf | 30 + ArmPkg/Drivers/PL390Gic/PL390GicDxe.c | 435 ++++++++++++++ .../PL390GicDxe.inf} | 99 ++-- ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c | 97 +++ ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf | 29 + ArmPkg/Drivers/PL390Gic/PL390GicSec.c | 135 +++++ ArmPkg/Drivers/PL390Gic/PL390GicSec.inf | 29 + ArmPkg/Include/Chipset/ARM1176JZ-S.h | 12 +- ArmPkg/Include/Chipset/ArmV7.h | 333 +++++++++-- ArmPkg/Include/Drivers/PL341Dmc.h | 84 +++ ArmPkg/Include/Drivers/PL390Gic.h | 120 ++++ ArmPkg/Include/Library/ArmLib.h | 23 +- ArmPkg/Include/Library/ArmMPCoreMailBoxLib.h | 22 + ArmPkg/Include/Library/ArmTrustZoneLib.h | 69 +++ ArmPkg/Include/Library/BdsUnixLib.h | 38 ++ ArmPkg/Include/Library/L2X0CacheLib.h | 62 ++ ArmPkg/Include/Protocol/MmcHost.h | 112 ++++ ArmPkg/Library/ArmDmaLib/ArmDmaLib.c | 2 +- ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c | 19 +- ArmPkg/Library/ArmLib/Arm11/Arm11Support.S | 63 +- ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c | 9 +- ArmPkg/Library/ArmLib/Arm9/Arm9Support.S | 57 +- ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S | 130 ++-- ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm | 72 ++- ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c | 124 +--- ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.h | 36 ++ ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf | 1 + ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf | 1 + ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf | 40 ++ ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCore.c | 57 ++ .../Library/ArmLib/ArmV7/ArmV7MPCoreHelper.S | 48 ++ .../ArmLib/ArmV7/ArmV7MPCoreHelper.asm | 48 ++ .../Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf | 51 ++ .../ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf | 49 ++ .../ArmLib/ArmV7/ArmV7MPCoreLibSec.inf | 43 ++ ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c | 162 +++++ ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.S | 166 ++++-- ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm | 167 ++++-- ArmPkg/Library/ArmLib/Common/ArmLibSupport.S | 51 +- .../Library/ArmLib/Common/ArmLibSupport.asm | 18 +- .../ArmMPCoreMailBoxLib/ArmMPCoreMailBox.c | 25 + .../ArmMPCoreMailBoxLib.inf | 37 ++ ArmPkg/Library/ArmTrustZoneLib/ArmTrustZone.c | 79 +++ .../ArmTrustZoneLib/ArmTrustZoneLib.inf | 32 + ArmPkg/Library/BaseMemoryLibStm/Arm/CopyMem.S | 3 +- ArmPkg/Library/BaseMemoryLibStm/Arm/SetMem.S | 3 +- .../Library/BaseMemoryLibVstm/Arm/CopyMem.S | 3 +- ArmPkg/Library/BaseMemoryLibVstm/Arm/SetMem.S | 3 +- ArmPkg/Library/BasePeCoffLib/BasePeCoff.c | 2 +- ArmPkg/Library/BdsLib/BdsAppLoader.c | 102 ++++ ArmPkg/Library/BdsLib/BdsFilePath.c | 182 ++++++ ArmPkg/Library/BdsLib/BdsFilePathFs.c | 86 +++ ArmPkg/Library/BdsLib/BdsFilePathFv.c | 136 +++++ ArmPkg/Library/BdsLib/BdsFilePathMem.c | 73 +++ ArmPkg/Library/BdsLib/BdsHelper.c | 183 ++++++ ArmPkg/Library/BdsLib/BdsInternal.h | 136 +++++ ArmPkg/Library/BdsLib/BdsLib.inf | 63 ++ ArmPkg/Library/BdsLib/BdsLinuxLoader.c | 337 +++++++++++ ArmPkg/Library/BdsLib/BdsLinuxLoader.h | 165 ++++++ .../CompilerIntrinsicsLib/Arm/ashldi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/ashrdi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/clzsi2.S | 3 +- .../CompilerIntrinsicsLib/Arm/ctzsi2.S | 3 +- .../CompilerIntrinsicsLib/Arm/divdi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/divsi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/ldivmod.S | 3 +- .../CompilerIntrinsicsLib/Arm/lshrdi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/memcpy.S | 3 +- .../CompilerIntrinsicsLib/Arm/memset.S | 3 +- .../CompilerIntrinsicsLib/Arm/moddi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/modsi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/muldi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/sourcery.S | 3 +- .../CompilerIntrinsicsLib/Arm/switch16.S | 3 +- .../CompilerIntrinsicsLib/Arm/switch32.S | 3 +- .../CompilerIntrinsicsLib/Arm/switch8.S | 4 +- .../CompilerIntrinsicsLib/Arm/switchu8.S | 3 +- .../CompilerIntrinsicsLib/Arm/ucmpdi2.S | 3 +- .../CompilerIntrinsicsLib/Arm/udivdi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/udivmoddi4.S | 5 +- .../CompilerIntrinsicsLib/Arm/udivsi3.S | 3 +- .../Library/CompilerIntrinsicsLib/Arm/uldiv.S | 3 +- .../CompilerIntrinsicsLib/Arm/umoddi3.S | 3 +- .../CompilerIntrinsicsLib/Arm/umodsi3.S | 3 +- .../DebugPeCoffExtraActionLib.c | 42 +- ArmPkg/Library/L2X0CacheLibNull/L2X0Cache.c | 20 + .../L2X0CacheLibNull/L2X0CacheLibNull.inf | 27 + ArmPkg/Universal/MmcDxe/ComponentName.c | 162 +++++ ArmPkg/Universal/MmcDxe/Diagnostics.c | 215 +++++++ ArmPkg/Universal/MmcDxe/Mmc.c | 387 ++++++++++++ ArmPkg/Universal/MmcDxe/Mmc.h | 284 +++++++++ ArmPkg/Universal/MmcDxe/MmcBlockIo.c | 558 ++++++++++++++++++ ArmPkg/Universal/MmcDxe/MmcDxe.inf | 50 ++ 113 files changed, 7979 insertions(+), 964 deletions(-) delete mode 100644 ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c create mode 100644 ArmPkg/Drivers/PL180MciDxe/PL180Mci.c create mode 100644 ArmPkg/Drivers/PL180MciDxe/PL180Mci.h create mode 100644 ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf create mode 100644 ArmPkg/Drivers/PL301Axi/PL301Axi.c create mode 100644 ArmPkg/Drivers/PL301Axi/PL301Axi.inf create mode 100644 ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c create mode 100644 ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf create mode 100644 ArmPkg/Drivers/PL34xDmc/PL341Dmc.c create mode 100644 ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf create mode 100644 ArmPkg/Drivers/PL35xSmc/InitializeSMC.S create mode 100644 ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm create mode 100644 ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf create mode 100644 ArmPkg/Drivers/PL390Gic/PL390GicDxe.c rename ArmPkg/Drivers/{DebugSupportDxe/DebugSupportDxe.inf => PL390Gic/PL390GicDxe.inf} (56%) create mode 100644 ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c create mode 100644 ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf create mode 100644 ArmPkg/Drivers/PL390Gic/PL390GicSec.c create mode 100644 ArmPkg/Drivers/PL390Gic/PL390GicSec.inf create mode 100644 ArmPkg/Include/Drivers/PL341Dmc.h create mode 100644 ArmPkg/Include/Drivers/PL390Gic.h create mode 100644 ArmPkg/Include/Library/ArmMPCoreMailBoxLib.h create mode 100644 ArmPkg/Include/Library/ArmTrustZoneLib.h create mode 100644 ArmPkg/Include/Library/BdsUnixLib.h create mode 100644 ArmPkg/Include/Library/L2X0CacheLib.h create mode 100644 ArmPkg/Include/Protocol/MmcHost.h create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCore.c create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.S create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreHelper.asm create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLib.inf create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibPrePi.inf create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7MPCoreLibSec.inf create mode 100644 ArmPkg/Library/ArmLib/ArmV7/ArmV7Mmu.c create mode 100644 ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBox.c create mode 100644 ArmPkg/Library/ArmMPCoreMailBoxLib/ArmMPCoreMailBoxLib.inf create mode 100644 ArmPkg/Library/ArmTrustZoneLib/ArmTrustZone.c create mode 100644 ArmPkg/Library/ArmTrustZoneLib/ArmTrustZoneLib.inf create mode 100644 ArmPkg/Library/BdsLib/BdsAppLoader.c create mode 100644 ArmPkg/Library/BdsLib/BdsFilePath.c create mode 100644 ArmPkg/Library/BdsLib/BdsFilePathFs.c create mode 100644 ArmPkg/Library/BdsLib/BdsFilePathFv.c create mode 100644 ArmPkg/Library/BdsLib/BdsFilePathMem.c create mode 100644 ArmPkg/Library/BdsLib/BdsHelper.c create mode 100644 ArmPkg/Library/BdsLib/BdsInternal.h create mode 100644 ArmPkg/Library/BdsLib/BdsLib.inf create mode 100644 ArmPkg/Library/BdsLib/BdsLinuxLoader.c create mode 100644 ArmPkg/Library/BdsLib/BdsLinuxLoader.h create mode 100644 ArmPkg/Library/L2X0CacheLibNull/L2X0Cache.c create mode 100644 ArmPkg/Library/L2X0CacheLibNull/L2X0CacheLibNull.inf create mode 100644 ArmPkg/Universal/MmcDxe/ComponentName.c create mode 100644 ArmPkg/Universal/MmcDxe/Diagnostics.c create mode 100644 ArmPkg/Universal/MmcDxe/Mmc.c create mode 100644 ArmPkg/Universal/MmcDxe/Mmc.h create mode 100644 ArmPkg/Universal/MmcDxe/MmcBlockIo.c create mode 100644 ArmPkg/Universal/MmcDxe/MmcDxe.inf 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 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 + /* 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 /* @@ -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 // 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> 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> 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.
- - 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 - -#include -#include -#include - -#include -#include -#include - -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 +#include + +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 + +#include + +#include +#include +#include +#include +#include +#include + +#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 +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include + +// +// 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 + // |====================================== + 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 +#include +#include +#include + +#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 +#include +#include + + 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.
+Portions copyright (c) 2010, Apple Inc. 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. + +Module Name: + + Gic.c + +Abstract: + + Driver implementing the GIC interrupt controller protocol + +--*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// 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< 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 similarity index 56% rename from ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf rename to 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.
-# 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.
+# 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 +#include + + +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 +#include + +/* + * 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 ( @@ -224,6 +234,12 @@ ArmDisableMmu ( VOID ); +VOID +EFIAPI +ArmDisableCachesAndMmu ( + VOID + ); + VOID EFIAPI ArmEnableInterrupts ( @@ -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 + +// 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 + .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 #include #include +#include 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 .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 #include #include -#include -#include +#include #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 +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#.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 +#include +#include +#include +#include + + 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 +#include +#include +#include +#include +#include +#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 + .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 +#include +#include + +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 +#include +#include + +#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 +#include + +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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + + +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 +#include +#include + +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 + +// 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 +#include +#include +#include + +#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 +#include + +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include + +#include + +#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 +#include +#include +#include + +#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 -- 2.39.2