diff options
Diffstat (limited to 'SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c')
-rw-r--r-- | SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c new file mode 100644 index 000000000..3c4f4983f --- /dev/null +++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c @@ -0,0 +1,222 @@ +/** @file +* Main file supporting the SEC Phase on ARM Platforms +* +* Copyright (c) 2011-2012, 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/ArmTrustedMonitorLib.h> +#include <Library/DebugAgentLib.h> +#include <Library/PrintLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/SerialPortLib.h> +#include <Library/ArmGicLib.h> +#include <Library/ArmCpuLib.h> +#include <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include "SecInternal.h" +#include "Smc.h" + +#define SerialPrint(txt) SerialPortWrite ((UINT8*)txt, AsciiStrLen(txt)+1); + +extern VOID *monitor_vector_table; + +#define ISRAM_ADDRESS 0x02020000 +#define EXTERNAL_FUNC_ADDRESS (ISRAM_ADDRESS + 0x0030) +#define MSH_ReadFromFIFO_eMMC_ADDRESS (EXTERNAL_FUNC_ADDRESS + 0x14) +#define MSH_EndBootOp_eMMC_ADDRESS (EXTERNAL_FUNC_ADDRESS + 0x18) + +#define SDMMC_ReadBlocks(uStartBlk, uNumOfBlks, uDstAddr) \ + (((VOID(*)(UINT32, UINT32, UINT32*))(*((UINT32 *)EXTERNAL_FUNC_ADDRESS)))(uStartBlk, uNumOfBlks, uDstAddr)) + +#define EMMC_ReadBlocks(uNumOfBlks, uDstAddr) \ + (((VOID(*)(UINT32, UINT32*))(*((UINT32 *)MSH_ReadFromFIFO_eMMC_ADDRESS)))(uNumOfBlks, uDstAddr)) + +#define EMMC_EndBootOp() \ + (((VOID(*)())(*((UINT32 *)MSH_EndBootOp_eMMC_ADDRESS)))()) + +VOID CopyFirmwareFromSDMMC(VOID) +{ + SDMMC_ReadBlocks(49, ((1536*1024)/512), (UINT32 *)0x40000000); +} + +VOID CopyFirmwareFromEMMC(VOID) +{ + if (FixedPcdGetBool (PcdTrustzoneSupport)) { + load_uefi_image(EMMC); + } else { + EMMC_ReadBlocks(((1536*1024)/512), (UINT32 *)0x40000000); + EMMC_EndBootOp(); + } +} + +VOID ColdBootForTzsw(UINT32 StartupAddr) +{ + coldboot(EMMC, StartupAddr); +} + +VOID +CEntryPoint ( + IN UINTN MpId + ) +{ + CHAR8 Buffer[100]; + UINTN CharCount; + UINTN JumpAddress; + + if (!FixedPcdGetBool (PcdTrustzoneSupport)) { + // Invalidate the data cache. Doesn't have to do the Data cache clean. + ArmInvalidateDataCache(); + + // Invalidate Instruction Cache + ArmInvalidateInstructionCache(); + + // Invalidate I & D TLBs + ArmInvalidateInstructionAndDataTlb(); + + // CPU specific settings + ArmCpuSetup (MpId); + + // Enable Floating Point Coprocessor if supported by the platform + if (FixedPcdGet32 (PcdVFPEnabled)) { + ArmEnableVFP(); + } + // Initialize peripherals that must be done at the early stage + // Example: Some L2 controller, interconnect, clock, DMC, etc + ArmPlatformSecInitialize (MpId); + } + + // Primary CPU clears out the SCU tag RAMs, secondaries wait + if (ArmPlatformIsPrimaryCore (MpId)) { + if (ArmIsMpCore()) { + // Is UEFI built as it is assumed that TZSW is running? + // PcdTrustzoneSupport==1: YES. + // PcdTrustzoneSupport==1: NO. UEFI is built as it is assumed that TZSW is not needed. + if (FixedPcdGetBool (PcdTrustzoneSupport)) { + // IS UEFI executed after TZSW ran? (In other words, UEFI is fuzed and running? + // ArmReadNsacr()==1: YES. + // ArmReadNsacr()!=1: No. UEFI(assumed TZSW is running) is executed after uploaded with T32(not fuzed) + if(ArmReadNsacr()) { + exynos_smc(SMC_CMD_CPU1BOOT, 0, 0, 0); + } + } + } + + // 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 + if (FixedPcdGetBool (PcdTrustzoneSupport)) { + CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Secure firmware (version %s built at %a on %a)\n\r", + (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); + } else { + CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Boot firmware (version %s built at %a on %a)\n\r", + (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); + } + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + // Initialize the Debug Agent for Source Level Debugging + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL); + SaveAndSetDebugTimerInterrupt (TRUE); + + // Enable the GIC distributor and CPU Interface + // - no other Interrupts are enabled, doesn't have to worry about the priority. + // - all the cores are in secure state, use secure SGI's + ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase)); + ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); + + } else { + // Enable the GIC CPU Interface + ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); + } + + // Enable Full Access to CoProcessors + ArmWriteCpacr (CPACR_CP_FULL_ACCESS); + + // 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 (); + + // Call the Platform specific function to execute additional actions if required + JumpAddress = PcdGet32 (PcdFvBaseAddress); + ArmPlatformSecExtraAction (MpId, &JumpAddress); + + NonTrustedWorldTransition (MpId, JumpAddress); + + ASSERT (0); // We must never return from the above function +} + +VOID +TrustedWorldInitialization ( + IN UINTN MpId + ) +{ + UINTN JumpAddress; + + //-------------------- Monitor Mode --------------------- + + // Set up Monitor World (Vector Table, etc) + ArmSecureMonitorWorldInitialize (); + + // Transfer the interrupt to Non-secure World + ArmGicSetupNonSecure (MpId, PcdGet32(PcdGicDistributorBase), PcdGet32(PcdGicInterruptInterfaceBase)); + + // Initialize platform specific security policy + ArmPlatformSecTrustzoneInit (MpId); + + // Setup the Trustzone Chipsets + if (ArmPlatformIsPrimaryCore (MpId)) { + if (ArmIsMpCore()) { + // Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT) + ArmCallSEV (); + } + } else { + // The secondary cores need to wait until the Trustzone chipsets configuration is done + // before switching to Non Secure World + + // Wait for the Primary Core to finish the initialization of the Secure World (event: EVENT_SECURE_INIT) + ArmCallWFE (); + } + + // Call the Platform specific function to execute additional actions if required + JumpAddress = PcdGet32 (PcdFvBaseAddress); + ArmPlatformSecExtraAction (MpId, &JumpAddress); + + // Write to CP15 Non-secure Access Control Register + ArmWriteNsacr (PcdGet32 (PcdArmNsacr)); + + // CP15 Secure Configuration Register + ArmWriteScr (PcdGet32 (PcdArmScr)); + + NonTrustedWorldTransition (MpId, JumpAddress); +} + +VOID +NonTrustedWorldTransition ( + IN UINTN MpId, + IN UINTN JumpAddress + ) +{ + // If PcdArmNonSecModeTransition is defined then set this specific mode to CPSR before the transition + // By not set, the mode for Non Secure World is SVC + if (PcdGet32 (PcdArmNonSecModeTransition) != 0) { + set_non_secure_mode ((ARM_PROCESSOR_MODE)PcdGet32 (PcdArmNonSecModeTransition)); + } + + return_from_exception (JumpAddress); + //-------------------- Non Secure Mode --------------------- + + // PEI Core should always load and never return + ASSERT (FALSE); +} + |