diff options
author | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-02-01 05:41:42 +0000 |
---|---|---|
committer | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-02-01 05:41:42 +0000 |
commit | 1d5d0ae92d95410f20bc6daab7a47e129fb2547a (patch) | |
tree | 8679c57c5f85cadad47d4604450c1c3702276cf1 /ArmPlatformPkg/Sec | |
parent | fb334ef6c543b1babc9d8a613ad5d1ce6fe536e1 (diff) | |
download | edk2-platforms-1d5d0ae92d95410f20bc6daab7a47e129fb2547a.tar.xz |
Add ArmPlatformPkg from ARM Ltd. patch.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11291 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPlatformPkg/Sec')
-rw-r--r-- | ArmPlatformPkg/Sec/Exception.S | 106 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/Exception.asm | 94 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/Helper.S | 74 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/Helper.asm | 66 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/Sec.c | 275 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/Sec.inf | 66 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/SecEntryPoint.S | 112 | ||||
-rw-r--r-- | ArmPlatformPkg/Sec/SecEntryPoint.asm | 104 |
8 files changed, 897 insertions, 0 deletions
diff --git a/ArmPlatformPkg/Sec/Exception.S b/ArmPlatformPkg/Sec/Exception.S new file mode 100644 index 0000000000..81e2659c1b --- /dev/null +++ b/ArmPlatformPkg/Sec/Exception.S @@ -0,0 +1,106 @@ +// +// 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 <AutoGen.h> + +#start of the code section +.text +.align 5
+
+# IMPORT +GCC_ASM_IMPORT(SecCommonExceptionEntry) + +# EXPORT +GCC_ASM_EXPORT(SecVectorTable) +
+//============================================================ +//Default Exception Handlers +//============================================================ + +//FIXME: One of the EDK2 tool is broken. It does not look to respect the alignment. Even, if we specify 32-byte alignment for this file. +Dummy1: .word 0
+Dummy2: .word 0
+ +ASM_PFX(SecVectorTable): + b _DefaultResetHandler + b _DefaultUndefined + b _DefaultSWI + b _DefaultPrefetchAbort + b _DefaultDataAbort + b _DefaultReserved + b _DefaultIrq + b _DefaultFiq + +// +// Default Exception handlers: There is no plan to return from any of these exceptions. +// No context saving at all. +// +_DefaultResetHandler: + mov r1, lr + # Switch to SVC for common stack + cps #0x13 + mov r0, #0 + blx ASM_PFX(SecCommonExceptionEntry) + +_DefaultUndefined: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #1 + blx ASM_PFX(SecCommonExceptionEntry) + +_DefaultSWI: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #2 + blx ASM_PFX(SecCommonExceptionEntry) + +_DefaultPrefetchAbort: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #3 + blx ASM_PFX(SecCommonExceptionEntry) + +_DefaultDataAbort: + sub r1, LR, #8 + # Switch to SVC for common stack + cps #0x13 + mov r0, #4 + blx ASM_PFX(SecCommonExceptionEntry) + +_DefaultReserved: + mov r1, lr + # Switch to SVC for common stack + cps #0x13 + mov r0, #5 + blx SecCommonExceptionEntry + +_DefaultIrq: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #6 + blx SecCommonExceptionEntry + +_DefaultFiq: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #7 + blx SecCommonExceptionEntry +
+.end
diff --git a/ArmPlatformPkg/Sec/Exception.asm b/ArmPlatformPkg/Sec/Exception.asm new file mode 100644 index 0000000000..dcf2cf93b4 --- /dev/null +++ b/ArmPlatformPkg/Sec/Exception.asm @@ -0,0 +1,94 @@ +//
+// 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 <AutoGen.h>
+
+ IMPORT SecCommonExceptionEntry
+ EXPORT SecVectorTable
+
+ PRESERVE8
+ AREA SecException, CODE, READONLY, CODEALIGN, ALIGN=5
+
+//============================================================ +//Default Exception Handlers +//============================================================ + +//FIXME: One of the EDK2 tool is broken. It does not look to respect the alignment. Even, if we specify 32-byte alignment for this file. +Dummy1 DCD 0
+Dummy2 DCD 0
+ +SecVectorTable + b _DefaultResetHandler + b _DefaultUndefined + b _DefaultSWI + b _DefaultPrefetchAbort + b _DefaultDataAbort + b _DefaultReserved + b _DefaultIrq + b _DefaultFiq +
+// +// Default Exception handlers: There is no plan to return from any of these exceptions.
+// No context saving at all.
+// +_DefaultResetHandler + mov r1, lr
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #0 + blx SecCommonExceptionEntry + +_DefaultUndefined + sub r1, LR
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #1 + blx SecCommonExceptionEntry + +_DefaultSWI + sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #2 + blx SecCommonExceptionEntry + +_DefaultPrefetchAbort + sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #3 + blx SecCommonExceptionEntry + +_DefaultDataAbort + sub r1, LR, #8
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #4 + blx SecCommonExceptionEntry + +_DefaultReserved + mov r1, lr
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #5 + blx SecCommonExceptionEntry + +_DefaultIrq + sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #6 + blx SecCommonExceptionEntry + +_DefaultFiq + sub r1, LR, #4
+ cps #0x13 ; Switch to SVC for common stack + mov r0, #7 + blx SecCommonExceptionEntry +
+ END
diff --git a/ArmPlatformPkg/Sec/Helper.S b/ArmPlatformPkg/Sec/Helper.S new file mode 100644 index 0000000000..94bd68f8bc --- /dev/null +++ b/ArmPlatformPkg/Sec/Helper.S @@ -0,0 +1,74 @@ +#========================================================================================
+# 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.
+#
+#=======================================================================================
+
+#start of the code section
+.text
+.align 3
+
+GCC_ASM_EXPORT(monitor_vector_table)
+GCC_ASM_EXPORT(return_from_exception)
+GCC_ASM_EXPORT(enter_monitor_mode)
+GCC_ASM_EXPORT(copy_cpsr_into_spsr)
+
+ASM_PFX(monitor_vector_table):
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+
+# arg0: Secure Monitor mode stack
+ASM_PFX(enter_monitor_mode):
+ mov r2, lr @ Save current lr
+
+ mrs r1, cpsr @ Save current mode (SVC) in r1
+ bic r3, r1, #0x1f @ Clear all mode bits
+ orr r3, r3, #0x16 @ Set bits for Monitor mode
+ msr cpsr_cxsf, r3 @ We are now in Monitor Mode
+
+ mov sp, r0 @ Use the passed sp
+ mov lr, r2 @ Use the same lr as before
+
+ msr spsr_cxsf, r1 @ Use saved mode for the MOVS jump to the kernel
+ bx lr
+
+# We cannot use the instruction 'movs pc, lr' because the caller can be written either in ARM or Thumb2 assembler.
+# When we will jump into this function, we will set the CPSR flag to ARM assembler. By copying directly 'lr' into
+# 'pc'; we will not change the CPSR flag and it will crash.
+# The way to fix this limitation is to do the movs into the ARM assmbler code and then do a 'bx'.
+ASM_PFX(return_from_exception):
+ ldr lr, returned_exception
+
+ #The following instruction breaks the code.
+ #movs pc, lr
+ mrs r2, cpsr
+ bic r2, r2, #0x1f
+ orr r2, r2, #0x13
+ msr cpsr_c, r2
+
+returned_exception: @ We are now in non-secure state
+ bx r0
+
+# Save the current Program Status Register (PSR) into the Saved PSR
+ASM_PFX(copy_cpsr_into_spsr):
+ mrs r0, cpsr
+ msr spsr_cxsf, r0
+ bx lr
+
+dead:
+ B dead
+
+.end
diff --git a/ArmPlatformPkg/Sec/Helper.asm b/ArmPlatformPkg/Sec/Helper.asm new file mode 100644 index 0000000000..43a0749138 --- /dev/null +++ b/ArmPlatformPkg/Sec/Helper.asm @@ -0,0 +1,66 @@ +//
+// 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.
+//
+//
+
+ EXPORT monitor_vector_table
+ EXPORT return_from_exception
+ EXPORT enter_monitor_mode
+ EXPORT copy_cpsr_into_spsr
+
+ AREA Helper, CODE, READONLY
+
+ ALIGN 32
+monitor_vector_table
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+ ldr pc, dead
+
+// arg0: Secure Monitor mode stack
+enter_monitor_mode
+ mov r2, lr // Save current lr
+
+ mrs r1, cpsr // Save current mode (SVC) in r1
+ bic r3, r1, #0x1f // Clear all mode bits
+ orr r3, r3, #0x16 // Set bits for Monitor mode
+ msr cpsr_cxsf, r3 // We are now in Monitor Mode
+
+ mov sp, r0 // Use the passed sp
+ mov lr, r2 // Use the same lr as before
+
+ msr spsr_cxsf, r1 // Use saved mode for the MOVS jump to the kernel
+ bx lr
+
+// We cannot use the instruction 'movs pc, lr' because the caller can be written either in ARM or Thumb2 assembler.
+// When we will jump into this function, we will set the CPSR flag to ARM assembler. By copying directly 'lr' into
+// 'pc'; we will not change the CPSR flag and it will crash.
+// The way to fix this limitation is to do the movs into the ARM assmbler code and then do a 'bx'.
+return_from_exception
+ adr lr, returned_exception
+ movs pc, lr
+returned_exception // We are now in non-secure state
+ bx r0
+
+// Save the current Program Status Register (PSR) into the Saved PSR
+copy_cpsr_into_spsr
+ mrs r0, cpsr
+ msr spsr_cxsf, r0
+ bx lr
+
+dead
+ B dead
+
+ END
diff --git a/ArmPlatformPkg/Sec/Sec.c b/ArmPlatformPkg/Sec/Sec.c new file mode 100644 index 0000000000..2ae01d8e54 --- /dev/null +++ b/ArmPlatformPkg/Sec/Sec.c @@ -0,0 +1,275 @@ +/** @file +* Main file supporting the SEC Phase for Versatile Express +* +* 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/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/ArmLib.h> +#include <Chipset/ArmV7.h> +#include <Drivers/PL390Gic.h> +#include <Library/L2X0CacheLib.h> +#include <Library/SerialPortLib.h> +#include <Library/ArmPlatformLib.h> + +extern VOID *monitor_vector_table; + +VOID ArmSetupGicNonSecure ( + IN INTN GicDistributorBase, + IN INTN GicInterruptInterfaceBase +); + +// Vector Table for Sec Phase +VOID SecVectorTable (VOID); + +VOID NonSecureWaitForFirmware ( + VOID + ); + +VOID +enter_monitor_mode( + IN VOID* Stack + ); + +VOID +return_from_exception ( + IN UINTN NonSecureBase + ); + +VOID +copy_cpsr_into_spsr ( + VOID + ); + +VOID +CEntryPoint ( + IN UINTN CoreId + ) +{ + // Primary CPU clears out the SCU tag RAMs, secondaries wait + if (CoreId == 0) { + if (FixedPcdGet32(PcdMPCoreSupport)) { + ArmInvalidScu(); + } + + // SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib + // In non SEC modules the init call is in autogenerated code. + SerialPortInitialize (); + // Start talking + DEBUG ((EFI_D_ERROR, "UART Enabled\n")); + + // Now we've got UART, make the check: + // - The Vector table must be 32-byte aligned + ASSERT(((UINT32)SecVectorTable & ((1 << 5)-1)) == 0); + } + + // Invalidate the data cache. Doesn't have to do the Data cache clean. + ArmInvalidateDataCache(); + + //Invalidate Instruction Cache + ArmInvalidateInstructionCache(); + + //Invalidate I & D TLBs + ArmInvalidateInstructionAndDataTlb(); + + // Enable Full Access to CoProcessors + ArmWriteCPACR (CPACR_CP_FULL_ACCESS); + + // Enable SWP instructions + ArmEnableSWPInstruction(); + + // Enable program flow prediction, if supported. + ArmEnableBranchPrediction(); + + if (FixedPcdGet32(PcdVFPEnabled)) { + ArmEnableVFP(); + } + + if (CoreId == 0) { + // Initialize L2X0 but not enabled + L2x0CacheInit(PcdGet32(PcdL2x0ControllerBase), FALSE); + + // If we skip the PEI Core we could want to initialize the DRAM in the SEC phase. + // If we are in standalone, we need the initialization to copy the UEFI firmware into DRAM + if (FeaturePcdGet(PcdSkipPeiCore) || !FeaturePcdGet(PcdStandalone)) { + // Initialize system memory (DRAM) + ArmPlatformInitializeSystemMemory(); + } + + // Turn Off NOR flash remapping to 0. We can will now see DRAM in low memory + ArmPlatformBootRemapping(); + } + + // Test if Trustzone is supported on this platform + if (ArmPlatformTrustzoneSupported()) { + if (FixedPcdGet32(PcdMPCoreSupport)) { + // Setup SMP in Non Secure world + ArmSetupSmpNonSecure(CoreId); + } + + // Enter Monitor Mode + enter_monitor_mode((VOID*)(PcdGet32(PcdCPUCoresSecMonStackBase) + (PcdGet32(PcdCPUCoreSecMonStackSize) * CoreId))); + + //Write the monitor mode vector table address + ArmWriteVMBar((UINT32) &monitor_vector_table); + + //-------------------- Monitor Mode --------------------- + // setup the Trustzone Chipsets + if (CoreId == 0) { + ArmPlatformTrustzoneInit(); + + // Wake up the secondary cores by sending a interrupt to everyone else + // NOTE 1: The Software Generated Interrupts are always enabled on Cortex-A9 + // MPcore test chip on Versatile Express board, So the Software doesn't have to + // enable SGI's explicitly. + // 2: As no other Interrupts are enabled, doesn't have to worry about the priority. + // 3: As all the cores are in secure state, use secure SGI's + // + + PL390GicEnableDistributor (PcdGet32(PcdGicDistributorBase)); + PL390GicEnableInterruptInterface(PcdGet32(PcdGicInterruptInterfaceBase)); + + // Send SGI to all Secondary core to wake them up from WFI state. + PL390GicSendSgiTo (PcdGet32(PcdGicDistributorBase), GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E); + } else { + // The secondary cores need to wait until the Trustzone chipsets configuration is done + // before swtching to Non Secure World + + // Enabled GIC CPU Interface + PL390GicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); + + // Waiting for the SGI from the primary core + ArmCallWFI(); + + //Acknowledge the interrupt and send End of Interrupt signal. + PL390GicAcknowledgeSgiFrom(PcdGet32(PcdGicInterruptInterfaceBase),0/*CoreId*/); + } + + // Transfer the interrupt to Non-secure World + PL390GicSetupNonSecure(PcdGet32(PcdGicDistributorBase),PcdGet32(PcdGicInterruptInterfaceBase)); + + // Write to CP15 Non-secure Access Control Register : + // - Enable CP10 and CP11 accesses in NS World + // - Enable Access to Preload Engine in NS World + // - Enable lockable TLB entries allocation in NS world + // - Enable R/W access to SMP bit of Auxiliary Control Register in NS world + ArmWriteNsacr(NSACR_NS_SMP | NSACR_TL | NSACR_PLE | NSACR_CP(10) | NSACR_CP(11)); + + // CP15 Secure Configuration Register with Non Secure bit (SCR_NS), CPSR.A modified in any + // security state (SCR_AW), CPSR.F modified in any security state (SCR_FW) + ArmWriteScr(SCR_NS | SCR_FW | SCR_AW); + } else { + if(0 == CoreId){ + DEBUG ((EFI_D_ERROR, "Trust Zone Configuration is disabled\n")); + } + + //Trustzone is not enabled, just enable the Distributor and CPU interface + PL390GicEnableInterruptInterface(PcdGet32(PcdGicInterruptInterfaceBase)); + + // With Trustzone support the transition from Sec to Normal world is done by return_from_exception(). + // If we want to keep this function call we need to ensure the SVC's SPSR point to the same Program + // Status Register as the the current one (CPSR). + copy_cpsr_into_spsr(); + } + + // If ArmVe has not been built as Standalone then we need to patch the DRAM to add an infinite loop at the start address + if (FeaturePcdGet(PcdStandalone) == FALSE) { + if (CoreId == 0) { + UINTN* StartAddress = (UINTN*)PcdGet32(PcdEmbeddedFdBaseAddress); + + DEBUG ((EFI_D_ERROR, "Waiting for firmware at 0x%08X ...\n",StartAddress)); + + // Patch the DRAM to make an infinite loop at the start address + *StartAddress = 0xEAFFFFFE; // opcode for while(1) + + // To enter into Non Secure state, we need to make a return from exception + return_from_exception(PcdGet32(PcdEmbeddedFdBaseAddress)); + } else { + // When the primary core is stopped by the hardware debugger to copy the firmware + // into DRAM. The secondary cores are still running. As soon as the first bytes of + // the firmware are written into DRAM, the secondary cores will start to execute the + // code even if the firmware is not entirely written into the memory. + // That's why the secondary cores need to be parked in WFI and wake up once the + // firmware is ready. + + // Enter Secondary Cores into non Secure State. To enter into Non Secure state, we need to make a return from exception + return_from_exception((UINTN)NonSecureWaitForFirmware); + } + } else { + if (CoreId == 0) { + DEBUG ((EFI_D_ERROR, "Standalone Firmware\n")); + } + + // To enter into Non Secure state, we need to make a return from exception + return_from_exception(PcdGet32(PcdEmbeddedFdBaseAddress)); + } + //-------------------- Non Secure Mode --------------------- + + // PEI Core should always load and never return + ASSERT (FALSE); +} + +// When the firmware is built as not Standalone, the secondary cores need to wait the firmware +// entirely written into DRAM. It is the firmware from DRAM which will wake up the secondary cores. +VOID NonSecureWaitForFirmware() { + VOID (*secondary_start)(VOID); + + // The secondary cores will execute the fimrware once wake from WFI. + secondary_start = (VOID (*)())PcdGet32(PcdEmbeddedFdBaseAddress); + + ArmCallWFI(); + + //Acknowledge the interrupt and send End of Interrupt signal. + PL390GicAcknowledgeSgiFrom(PcdGet32(PcdGicInterruptInterfaceBase),0/*CoreId*/); + + //Jump to secondary core entry point. + secondary_start(); + + // PEI Core should always load and never return + ASSERT (FALSE); +} + +VOID SecCommonExceptionEntry(UINT32 Entry, UINT32 LR) { + switch (Entry) { + case 0: + DEBUG((EFI_D_ERROR,"Reset Exception at 0x%X\n",LR)); + break; + case 1: + DEBUG((EFI_D_ERROR,"Undefined Exception at 0x%X\n",LR)); + break; + case 2: + DEBUG((EFI_D_ERROR,"SWI Exception at 0x%X\n",LR)); + break; + case 3: + DEBUG((EFI_D_ERROR,"PrefetchAbort Exception at 0x%X\n",LR)); + break; + case 4: + DEBUG((EFI_D_ERROR,"DataAbort Exception at 0x%X\n",LR)); + break; + case 5: + DEBUG((EFI_D_ERROR,"Reserved Exception at 0x%X\n",LR)); + break; + case 6: + DEBUG((EFI_D_ERROR,"IRQ Exception at 0x%X\n",LR)); + break; + case 7: + DEBUG((EFI_D_ERROR,"FIQ Exception at 0x%X\n",LR)); + break; + default: + DEBUG((EFI_D_ERROR,"Unknown Exception at 0x%X\n",LR)); + break; + } + while(1); +} diff --git a/ArmPlatformPkg/Sec/Sec.inf b/ArmPlatformPkg/Sec/Sec.inf new file mode 100644 index 0000000000..7180e1a5ad --- /dev/null +++ b/ArmPlatformPkg/Sec/Sec.inf @@ -0,0 +1,66 @@ +#/** @file +# SEC - Reset vector code that jumps to C and loads DXE core +# +# 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 = ArmPlatformSec + FILE_GUID = c536bbfe-c813-4e48-9f90-01fe1ecf9d54 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +[Sources.ARM] + Helper.asm | RVCT + Helper.S | GCC + Sec.c + SecEntryPoint.S | GCC + SecEntryPoint.asm | RVCT + Exception.asm | RVCT + Exception.S | GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + ArmLib + ArmPlatformLib + L2X0CacheLib + PL390GicSecLib + +[FeaturePcd] + gArmPlatformTokenSpaceGuid.PcdStandalone + gArmTokenSpaceGuid.PcdSkipPeiCore + +[FixedPcd] + gArmTokenSpaceGuid.PcdVFPEnabled + gArmPlatformTokenSpaceGuid.PcdMPCoreSupport + + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize + + gArmTokenSpaceGuid.PcdL2x0ControllerBase + + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase diff --git a/ArmPlatformPkg/Sec/SecEntryPoint.S b/ArmPlatformPkg/Sec/SecEntryPoint.S new file mode 100644 index 0000000000..e7d7160b87 --- /dev/null +++ b/ArmPlatformPkg/Sec/SecEntryPoint.S @@ -0,0 +1,112 @@ +#------------------------------------------------------------------------------ +# +# ARM VE Entry point. Reset vector in FV header will brach to +# _ModuleEntryPoint. +# +# 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 <Library/ArmPlatformLib.h> +#include <AutoGen.h> + +#Start of Code section +.text +.align 3 + +#make _ModuleEntryPoint as global +GCC_ASM_EXPORT(_ModuleEntryPoint) + +#global functions referenced by this module +GCC_ASM_IMPORT(CEntryPoint) +GCC_ASM_IMPORT(ArmPlatformIsMemoryInitialized) +GCC_ASM_IMPORT(ArmPlatformInitializeBootMemory) +GCC_ASM_IMPORT(ArmDisableInterrupts) +GCC_ASM_IMPORT(ArmDisableCachesAndMmu) +GCC_ASM_IMPORT(ArmWriteVBar) +GCC_ASM_IMPORT(SecVectorTable) + +#if (FixedPcdGet32(PcdMPCoreSupport)) +GCC_ASM_IMPORT(ArmIsScuEnable) +#endif + +StartupAddr: .word CEntryPoint +SecVectorTableAddr: .word SecVectorTable + +ASM_PFX(_ModuleEntryPoint): + #Set VBAR to the start of the exception vectors in Secure Mode + ldr r0, SecVectorTableAddr + bl ASM_PFX(ArmWriteVBar) + + # First ensure all interrupts are disabled + bl ASM_PFX(ArmDisableInterrupts) + + # Ensure that the MMU and caches are off + bl ASM_PFX(ArmDisableCachesAndMmu) + +_IdentifyCpu: + # Identify CPU ID + bl ASM_PFX(ArmReadMpidr) + and r5, r0, #0xf + + #get ID of this CPU in Multicore system + cmp r5, #0 + # Only the primary core initialize the memory (SMC) + beq _InitMem + +#if (FixedPcdGet32(PcdMPCoreSupport)) + # ... The secondary cores wait for SCU to be enabled +_WaitForEnabledScu: + bl ASM_PFX(ArmIsScuEnable) + tst r1, #1 + beq _WaitForEnabledScu + b _SetupStack +#endif + +_InitMem: + bl ASM_PFX(ArmPlatformIsMemoryInitialized) + bne _SetupStack + + # Initialize Init Memory + bl ASM_PFX(ArmPlatformInitializeBootMemory) + + # Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack) + mov r5, #0 + +_SetupStack: + # Setup Stack for the 4 CPU cores + #Read Stack Base address from PCD + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase) ,r1) + + #read Stack size from PCD + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecStackSize) ,r2) + + #calcuate Stack Pointer reg value using Stack size and CPU ID. + mov r3,r5 @ r3 = core_id + mul r3,r3,r2 @ r3 = core_id * stack_size = offset from the stack base + add r3,r3,r1 @ r3 ldr= stack_base + offset + mov sp, r3 + + # move sec startup address into a data register + # ensure we're jumping to FV version of the code (not boot remapped alias) + ldr r3, StartupAddr + + # Move the CoreId in r0 to be the first argument of the SEC Entry Point + mov r0, r5 + + # jump to SEC C code + # r0 = core_id + blx r3 + +.end diff --git a/ArmPlatformPkg/Sec/SecEntryPoint.asm b/ArmPlatformPkg/Sec/SecEntryPoint.asm new file mode 100644 index 0000000000..794a8c02d1 --- /dev/null +++ b/ArmPlatformPkg/Sec/SecEntryPoint.asm @@ -0,0 +1,104 @@ +// +// 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 <AutoGen.h> +#include <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/PcdLib.h> +#include <Library/ArmPlatformLib.h> + + INCLUDE AsmMacroIoLib.inc + + IMPORT CEntryPoint + IMPORT ArmPlatformIsMemoryInitialized + IMPORT ArmPlatformInitializeBootMemory + IMPORT ArmDisableInterrupts + IMPORT ArmDisableCachesAndMmu + IMPORT ArmWriteVBar + IMPORT ArmReadMpidr + IMPORT SecVectorTable + EXPORT _ModuleEntryPoint + +#if (FixedPcdGet32(PcdMPCoreSupport)) + IMPORT ArmIsScuEnable +#endif + + PRESERVE8 + AREA SecEntryPoint, CODE, READONLY + +StartupAddr DCD CEntryPoint + +_ModuleEntryPoint + //Set VBAR to the start of the exception vectors in Secure Mode + ldr r0, =SecVectorTable + blx ArmWriteVBar + + // First ensure all interrupts are disabled + blx ArmDisableInterrupts + + // Ensure that the MMU and caches are off + blx ArmDisableCachesAndMmu + +_IdentifyCpu + // Identify CPU ID + bl ArmReadMpidr + and r5, r0, #0xf + + //get ID of this CPU in Multicore system + cmp r5, #0 + // Only the primary core initialize the memory (SMC) + beq _InitMem + +#if (FixedPcdGet32(PcdMPCoreSupport)) + // ... The secondary cores wait for SCU to be enabled +_WaitForEnabledScu + bl ArmIsScuEnable + tst r1, #1 + beq _WaitForEnabledScu + b _SetupStack +#endif + +_InitMem + bl ArmPlatformIsMemoryInitialized + bne _SetupStack + + // Initialize Init Memory + bl ArmPlatformInitializeBootMemory + + // Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack) + mov r5, #0 + +_SetupStack + // Setup Stack for the 4 CPU cores + //Read Stack Base address from PCD + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1) + + // Read Stack size from PCD + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecStackSize), r2) + + // Calcuate Stack Pointer reg value using Stack size and CPU ID. + mov r3,r5 // r3 = core_id + mul r3,r3,r2 // r3 = core_id * stack_size = offset from the stack base + add r3,r3,r1 // r3 = stack_base + offset + mov sp, r3 + + // Move sec startup address into a data register + // ensure we're jumping to FV version of the code (not boot remapped alias) + ldr r3, StartupAddr + + // Jump to SEC C code + // r0 = core_id + mov r0, r5 + blx r3 + + END |