Home | History | Annotate | Download | only in Sec
      1 /** @file
      2 *  Main file supporting the SEC Phase on ARM Platforms
      3 *
      4 *  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
      5 *
      6 *  This program and the accompanying materials
      7 *  are licensed and made available under the terms and conditions of the BSD License
      8 *  which accompanies this distribution.  The full text of the license may be found at
      9 *  http://opensource.org/licenses/bsd-license.php
     10 *
     11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 *
     14 **/
     15 
     16 #include <Library/ArmTrustedMonitorLib.h>
     17 #include <Library/DebugAgentLib.h>
     18 #include <Library/PrintLib.h>
     19 #include <Library/BaseMemoryLib.h>
     20 #include <Library/SerialPortLib.h>
     21 #include <Library/ArmGicLib.h>
     22 #include <Library/ArmPlatformLib.h>
     23 
     24 #include "SecInternal.h"
     25 
     26 #define SerialPrint(txt)  SerialPortWrite ((UINT8*)txt, AsciiStrLen(txt)+1);
     27 
     28 VOID
     29 CEntryPoint (
     30   IN  UINTN                     MpId,
     31   IN  UINTN                     SecBootMode
     32   )
     33 {
     34   CHAR8           Buffer[100];
     35   UINTN           CharCount;
     36   UINTN           JumpAddress;
     37 
     38   // Invalidate the data cache. Doesn't have to do the Data cache clean.
     39   ArmInvalidateDataCache ();
     40 
     41   // Invalidate Instruction Cache
     42   ArmInvalidateInstructionCache ();
     43 
     44   // Invalidate I & D TLBs
     45   ArmInvalidateTlb ();
     46 
     47   // CPU specific settings
     48   ArmCpuSetup (MpId);
     49 
     50   // Enable Floating Point Coprocessor if supported by the platform
     51   if (FixedPcdGet32 (PcdVFPEnabled)) {
     52     ArmEnableVFP ();
     53   }
     54 
     55   // Initialize peripherals that must be done at the early stage
     56   // Example: Some L2 controller, interconnect, clock, DMC, etc
     57   ArmPlatformSecInitialize (MpId);
     58 
     59   // Primary CPU clears out the SCU tag RAMs, secondaries wait
     60   if (ArmPlatformIsPrimaryCore (MpId) && (SecBootMode == ARM_SEC_COLD_BOOT)) {
     61     if (ArmIsMpCore()) {
     62       // Signal for the initial memory is configured (event: BOOT_MEM_INIT)
     63       ArmCallSEV ();
     64     }
     65 
     66     // SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib
     67     // In non SEC modules the init call is in autogenerated code.
     68     SerialPortInitialize ();
     69 
     70     // Start talking
     71     if (FixedPcdGetBool (PcdTrustzoneSupport)) {
     72       CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Secure firmware (version %s built at %a on %a)\n\r",
     73           (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
     74     } else {
     75       CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Boot firmware (version %s built at %a on %a)\n\r",
     76           (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
     77     }
     78     SerialPortWrite ((UINT8 *) Buffer, CharCount);
     79 
     80     // Initialize the Debug Agent for Source Level Debugging
     81     InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL);
     82     SaveAndSetDebugTimerInterrupt (TRUE);
     83 
     84     // Enable the GIC distributor and CPU Interface
     85     // - no other Interrupts are enabled,  doesn't have to worry about the priority.
     86     // - all the cores are in secure state, use secure SGI's
     87     ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase));
     88     ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
     89   } else {
     90     // Enable the GIC CPU Interface
     91     ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
     92   }
     93 
     94   // Enable Full Access to CoProcessors
     95   ArmWriteCpacr (CPACR_CP_FULL_ACCESS);
     96 
     97   // Test if Trustzone is supported on this platform
     98   if (FixedPcdGetBool (PcdTrustzoneSupport)) {
     99     if (ArmIsMpCore ()) {
    100       // Setup SMP in Non Secure world
    101       ArmCpuSetupSmpNonSecure (GET_CORE_ID(MpId));
    102     }
    103 
    104     // Either we use the Secure Stacks for Secure Monitor (in this case (Base == 0) && (Size == 0))
    105     // Or we use separate Secure Monitor stacks (but (Base != 0) && (Size != 0))
    106     ASSERT (((PcdGet32(PcdCPUCoresSecMonStackBase) == 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) == 0)) ||
    107             ((PcdGet32(PcdCPUCoresSecMonStackBase) != 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) != 0)));
    108 
    109     // Enter Monitor Mode
    110     enter_monitor_mode (
    111       (UINTN)TrustedWorldInitialization, MpId, SecBootMode,
    112       (VOID*) (PcdGet32 (PcdCPUCoresSecMonStackBase) +
    113           (PcdGet32 (PcdCPUCoreSecMonStackSize) * (ArmPlatformGetCorePosition (MpId) + 1)))
    114       );
    115   } else {
    116     if (ArmPlatformIsPrimaryCore (MpId)) {
    117       SerialPrint ("Trust Zone Configuration is disabled\n\r");
    118     }
    119 
    120     // With Trustzone support the transition from Sec to Normal world is done by return_from_exception().
    121     // If we want to keep this function call we need to ensure the SVC's SPSR point to the same Program
    122     // Status Register as the the current one (CPSR).
    123     copy_cpsr_into_spsr ();
    124 
    125     // Call the Platform specific function to execute additional actions if required
    126     JumpAddress = PcdGet64 (PcdFvBaseAddress);
    127     ArmPlatformSecExtraAction (MpId, &JumpAddress);
    128 
    129     NonTrustedWorldTransition (MpId, JumpAddress);
    130   }
    131   ASSERT (0); // We must never return from the above function
    132 }
    133 
    134 VOID
    135 TrustedWorldInitialization (
    136   IN  UINTN                     MpId,
    137   IN  UINTN                     SecBootMode
    138   )
    139 {
    140   UINTN   JumpAddress;
    141 
    142   //-------------------- Monitor Mode ---------------------
    143 
    144   // Set up Monitor World (Vector Table, etc)
    145   ArmSecureMonitorWorldInitialize ();
    146 
    147   // Transfer the interrupt to Non-secure World
    148   ArmGicSetupNonSecure (MpId, PcdGet32(PcdGicDistributorBase), PcdGet32(PcdGicInterruptInterfaceBase));
    149 
    150   // Initialize platform specific security policy
    151   ArmPlatformSecTrustzoneInit (MpId);
    152 
    153   // Setup the Trustzone Chipsets
    154   if (SecBootMode == ARM_SEC_COLD_BOOT) {
    155     if (ArmPlatformIsPrimaryCore (MpId)) {
    156       if (ArmIsMpCore()) {
    157         // Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT)
    158         ArmCallSEV ();
    159       }
    160     } else {
    161       // The secondary cores need to wait until the Trustzone chipsets configuration is done
    162       // before switching to Non Secure World
    163 
    164       // Wait for the Primary Core to finish the initialization of the Secure World (event: EVENT_SECURE_INIT)
    165       ArmCallWFE ();
    166     }
    167   }
    168 
    169   // Call the Platform specific function to execute additional actions if required
    170   JumpAddress = PcdGet64 (PcdFvBaseAddress);
    171   ArmPlatformSecExtraAction (MpId, &JumpAddress);
    172 
    173   // Initialize architecture specific security policy
    174   ArmSecArchTrustzoneInit ();
    175 
    176   // CP15 Secure Configuration Register
    177   ArmWriteScr (PcdGet32 (PcdArmScr));
    178 
    179   NonTrustedWorldTransition (MpId, JumpAddress);
    180 }
    181 
    182 VOID
    183 NonTrustedWorldTransition (
    184   IN  UINTN                     MpId,
    185   IN  UINTN                     JumpAddress
    186   )
    187 {
    188   // If PcdArmNonSecModeTransition is defined then set this specific mode to CPSR before the transition
    189   // By not set, the mode for Non Secure World is SVC
    190   if (PcdGet32 (PcdArmNonSecModeTransition) != 0) {
    191     set_non_secure_mode ((ARM_PROCESSOR_MODE)PcdGet32 (PcdArmNonSecModeTransition));
    192   }
    193 
    194   return_from_exception (JumpAddress);
    195   //-------------------- Non Secure Mode ---------------------
    196 
    197   // PEI Core should always load and never return
    198   ASSERT (FALSE);
    199 }
    200 
    201