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