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