Home | History | Annotate | Download | only in AArch64
      1 //
      2 //  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
      3 //
      4 //  This program and the accompanying materials
      5 //  are licensed and made available under the terms and conditions of the BSD License
      6 //  which accompanies this distribution.  The full text of the license may be found at
      7 //  http://opensource.org/licenses/bsd-license.php
      8 //
      9 //  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 //  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 //
     12 //
     13 
     14 #include <AutoGen.h>
     15 #include <AsmMacroIoLibV8.h>
     16 #include "SecInternal.h"
     17 
     18 .text
     19 .align 3
     20 
     21 GCC_ASM_IMPORT(CEntryPoint)
     22 GCC_ASM_IMPORT(ArmPlatformIsPrimaryCore)
     23 GCC_ASM_IMPORT(ArmPlatformGetCorePosition)
     24 GCC_ASM_IMPORT(ArmPlatformSecBootAction)
     25 GCC_ASM_IMPORT(ArmPlatformSecBootMemoryInit)
     26 GCC_ASM_IMPORT(ArmDisableInterrupts)
     27 GCC_ASM_IMPORT(ArmDisableCachesAndMmu)
     28 GCC_ASM_IMPORT(ArmReadMpidr)
     29 GCC_ASM_IMPORT(ArmCallWFE)
     30 GCC_ASM_EXPORT(_ModuleEntryPoint)
     31 
     32 StartupAddr:        .8byte       ASM_PFX(CEntryPoint)
     33 
     34 ASM_PFX(_ModuleEntryPoint):
     35 
     36 // NOTE: We could be booting from EL3, EL2 or EL1. Need to correctly detect
     37 //       and configure the system accordingly. EL2 is default if possible.
     38 // If we started in EL3 we need to switch and run at EL2.
     39 // If we are running at EL2 stay in EL2
     40 // If we are starting at EL1 stay in EL1.
     41 
     42 // Sec only runs in EL3. Othewise we jump to PEI without changing anything.
     43 // If Sec runs we change to EL2 before switching to PEI.
     44 
     45 // Which EL are we running at? Every EL needs some level of setup...
     46   EL1_OR_EL2_OR_EL3(x0)
     47 1:// If we are at EL1 or EL2 leave SEC for PEI.
     48 2:b     ASM_PFX(JumpToPEI)
     49   // If we are at EL3 we need to configure it and switch to EL2
     50 3:b     ASM_PFX(MainEntryPoint)
     51 
     52 ASM_PFX(MainEntryPoint):
     53   // First ensure all interrupts are disabled
     54   bl    ASM_PFX(ArmDisableInterrupts)
     55 
     56   // Ensure that the MMU and caches are off
     57   bl    ASM_PFX(ArmDisableCachesAndMmu)
     58 
     59   // By default, we are doing a cold boot
     60   mov   x10, #ARM_SEC_COLD_BOOT
     61 
     62   // Jump to Platform Specific Boot Action function
     63   bl    ASM_PFX(ArmPlatformSecBootAction)
     64 
     65 _IdentifyCpu:
     66   // Identify CPU ID
     67   bl    ASM_PFX(ArmReadMpidr)
     68   // Keep a copy of the MpId register value
     69   mov   x5, x0
     70 
     71   // Is it the Primary Core ?
     72   bl    ASM_PFX(ArmPlatformIsPrimaryCore)
     73   cmp   x0, #1
     74   // Only the primary core initialize the memory (SMC)
     75   b.eq  _InitMem
     76 
     77 _WaitInitMem:
     78   // If we are not doing a cold boot in this case we should assume the Initial Memory to be already initialized
     79   // Otherwise we have to wait the Primary Core to finish the initialization
     80   cmp   x10, #ARM_SEC_COLD_BOOT
     81   b.ne  _SetupSecondaryCoreStack
     82 
     83   // Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT)
     84   bl    ASM_PFX(ArmCallWFE)
     85   // Now the Init Mem is initialized, we setup the secondary core stacks
     86   b     _SetupSecondaryCoreStack
     87 
     88 _InitMem:
     89   // If we are not doing a cold boot in this case we should assume the Initial Memory to be already initialized
     90   cmp   x10, #ARM_SEC_COLD_BOOT
     91   b.ne  _SetupPrimaryCoreStack
     92 
     93   // Initialize Init Boot Memory
     94   bl    ASM_PFX(ArmPlatformSecBootMemoryInit)
     95 
     96 _SetupPrimaryCoreStack:
     97   // Get the top of the primary stacks (and the base of the secondary stacks)
     98   LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), x1)
     99   LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), x2)
    100   add   x1, x1, x2
    101 
    102   mov   sp, x1
    103   b     _PrepareArguments
    104 
    105 _SetupSecondaryCoreStack:
    106   // Get the top of the primary stacks (and the base of the secondary stacks)
    107   LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), x1)
    108   LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), x2)
    109   add   x6, x1, x2
    110 
    111   // Get the Core Position
    112   mov   x0, x5
    113   bl    ASM_PFX(ArmPlatformGetCorePosition)
    114   // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack
    115   add   x0, x0, #1
    116 
    117   // StackOffset = CorePos * StackSize
    118   LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecSecondaryStackSize), x2)
    119   mul   x0, x0, x2
    120   // SP = StackBase + StackOffset
    121   add   sp, x6, x0
    122 
    123 _PrepareArguments:
    124   // Move sec startup address into a data register
    125   // Ensure we're jumping to FV version of the code (not boot remapped alias)
    126   ldr   x3, StartupAddr
    127 
    128   // Jump to SEC C code
    129   //    r0 = mp_id
    130   //    r1 = Boot Mode
    131   mov   x0, x5
    132   mov   x1, x10
    133   blr   x3
    134 
    135   ret
    136 
    137 ASM_PFX(JumpToPEI):
    138   LoadConstantToReg (FixedPcdGet32(PcdFvBaseAddress), x0)
    139   blr   x0
    140