1// 2// Copyright (c) 2011-2015, 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 <AsmMacroIoLib.h> 15#include <Base.h> 16#include <Library/PcdLib.h> 17#include <AutoGen.h> 18 19#include <Chipset/ArmV7.h> 20 21.text 22.align 3 23 24GCC_ASM_IMPORT(CEntryPoint) 25GCC_ASM_IMPORT(ArmPlatformIsPrimaryCore) 26GCC_ASM_IMPORT(ArmReadMpidr) 27GCC_ASM_IMPORT(ArmPlatformPeiBootAction) 28GCC_ASM_IMPORT(ArmPlatformStackSet) 29GCC_ASM_EXPORT(_ModuleEntryPoint) 30GCC_ASM_EXPORT(mSystemMemoryEnd) 31 32StartupAddr: .word CEntryPoint 33mSystemMemoryEnd: .8byte 0 34 35 36ASM_PFX(_ModuleEntryPoint): 37 // Do early platform specific actions 38 bl ASM_PFX(ArmPlatformPeiBootAction) 39 40 // Get ID of this CPU in Multicore system 41 bl ASM_PFX(ArmReadMpidr) 42 // Keep a copy of the MpId register value 43 mov r8, r0 44 45_SetSVCMode: 46 // Enter SVC mode, Disable FIQ and IRQ 47 mov r1, #(CPSR_MODE_SVC | CPSR_IRQ | CPSR_FIQ) 48 msr CPSR_c, r1 49 50// Check if we can install the stack at the top of the System Memory or if we need 51// to install the stacks at the bottom of the Firmware Device (case the FD is located 52// at the top of the DRAM) 53_SystemMemoryEndInit: 54 ldr r1, mSystemMemoryEnd 55 56 // Is mSystemMemoryEnd initialized? 57 cmp r1, #0 58 bne _SetupStackPosition 59 60 LoadConstantToReg (FixedPcdGet32(PcdSystemMemoryBase), r1) 61 LoadConstantToReg (FixedPcdGet32(PcdSystemMemorySize), r2) 62 sub r2, r2, #1 63 add r1, r1, r2 64 // Update the global variable 65 adr r2, mSystemMemoryEnd 66 str r1, [r2] 67 68_SetupStackPosition: 69 // r1 = SystemMemoryTop 70 71 // Calculate Top of the Firmware Device 72 LoadConstantToReg (FixedPcdGet32(PcdFdBaseAddress), r2) 73 LoadConstantToReg (FixedPcdGet32(PcdFdSize), r3) 74 sub r3, r3, #1 75 add r3, r3, r2 // r3 = FdTop = PcdFdBaseAddress + PcdFdSize 76 77 // UEFI Memory Size (stacks are allocated in this region) 78 LoadConstantToReg (FixedPcdGet32(PcdSystemMemoryUefiRegionSize), r4) 79 80 // 81 // Reserve the memory for the UEFI region (contain stacks on its top) 82 // 83 84 // Calculate how much space there is between the top of the Firmware and the Top of the System Memory 85 subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop 86 bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM 87 cmp r0, r4 88 bge _SetupStack 89 90 // Case the top of stacks is the FdBaseAddress 91 mov r1, r2 92 93_SetupStack: 94 // r1 contains the top of the stack (and the UEFI Memory) 95 96 // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment 97 // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the 98 // top of the memory space) 99 adds r9, r1, #1 100 bcs _SetupOverflowStack 101 102_SetupAlignedStack: 103 mov r1, r9 104 b _GetBaseUefiMemory 105 106_SetupOverflowStack: 107 // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE 108 // aligned (4KB) 109 LoadConstantToReg (EFI_PAGE_MASK, r9) 110 and r9, r9, r1 111 sub r1, r1, r9 112 113_GetBaseUefiMemory: 114 // Calculate the Base of the UEFI Memory 115 sub r9, r1, r4 116 117_GetStackBase: 118 // r1 = The top of the Mpcore Stacks 119 // Stack for the primary core = PrimaryCoreStack 120 LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r2) 121 sub r10, r1, r2 122 123 // Stack for the secondary core = Number of Cores - 1 124 LoadConstantToReg (FixedPcdGet32(PcdCoreCount), r0) 125 sub r0, r0, #1 126 LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), r1) 127 mul r1, r1, r0 128 sub r10, r10, r1 129 130 // r10 = The base of the MpCore Stacks (primary stack & secondary stacks) 131 mov r0, r10 132 mov r1, r8 133 //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize) 134 LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r2) 135 LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), r3) 136 bl ASM_PFX(ArmPlatformStackSet) 137 138 // Is it the Primary Core ? 139 mov r0, r8 140 bl ASM_PFX(ArmPlatformIsPrimaryCore) 141 cmp r0, #1 142 bne _PrepareArguments 143 144_PrepareArguments: 145 mov r0, r8 146 mov r1, r9 147 mov r2, r10 148 mov r3, sp 149 150 // Move sec startup address into a data register 151 // Ensure we're jumping to FV version of the code (not boot remapped alias) 152 ldr r4, StartupAddr 153 154 // Jump to PrePiCore C code 155 // r0 = MpId 156 // r1 = UefiMemoryBase 157 // r2 = StacksBase 158 blx r4 159 160_NeverReturn: 161 b _NeverReturn 162 163