1// 2// Copyright (c) 2011-2013, ARM Limited. All rights reserved. 3// Copyright (c) 2015, Linaro Limited. All rights reserved. 4// 5// This program and the accompanying materials 6// are licensed and made available under the terms and conditions of the BSD License 7// which accompanies this distribution. The full text of the license may be found at 8// http://opensource.org/licenses/bsd-license.php 9// 10// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12// 13// 14 15#include <AsmMacroIoLibV8.h> 16#include <Base.h> 17#include <Library/PcdLib.h> 18#include <AutoGen.h> 19 20.text 21.align 3 22 23GCC_ASM_IMPORT(ArmPlatformIsPrimaryCore) 24GCC_ASM_IMPORT(ArmReadMpidr) 25GCC_ASM_IMPORT(ArmPlatformPeiBootAction) 26GCC_ASM_IMPORT(ArmPlatformStackSet) 27GCC_ASM_EXPORT(_ModuleEntryPoint) 28ASM_GLOBAL ASM_PFX(mSystemMemoryEnd) 29 30StartupAddr: .8byte ASM_PFX(CEntryPoint) 31ASM_PFX(mSystemMemoryEnd): .8byte 0 32 33ASM_PFX(_ModuleEntryPoint): 34 // 35 // We are built as a ET_DYN PIE executable, so we need to process all 36 // relative relocations regardless of whether or not we are executing from 37 // the same offset we were linked at. This is only possible if we are 38 // running from RAM. 39 // 40 adr x8, __reloc_base 41 adr x9, __reloc_start 42 adr x10, __reloc_end 43 44.Lreloc_loop: 45 cmp x9, x10 46 bhs .Lreloc_done 47 48 // 49 // AArch64 uses the ELF64 RELA format, which means each entry in the 50 // relocation table consists of 51 // 52 // UINT64 offset : the relative offset of the value that needs to 53 // be relocated 54 // UINT64 info : relocation type and symbol index (the latter is 55 // not used for R_AARCH64_RELATIVE relocations) 56 // UINT64 addend : value to be added to the value being relocated 57 // 58 ldp x11, x12, [x9], #24 // read offset into x11 and info into x12 59 cmp x12, #0x403 // check info == R_AARCH64_RELATIVE? 60 bne .Lreloc_loop // not a relative relocation? then skip 61 62 ldr x12, [x9, #-8] // read addend into x12 63 add x12, x12, x8 // add reloc base to addend to get relocated value 64 str x12, [x11, x8] // write relocated value at offset 65 b .Lreloc_loop 66.Lreloc_done: 67 68 // Do early platform specific actions 69 bl ASM_PFX(ArmPlatformPeiBootAction) 70 71 // Get ID of this CPU in Multicore system 72 bl ASM_PFX(ArmReadMpidr) 73 // Keep a copy of the MpId register value 74 mov x10, x0 75 76// Check if we can install the stack at the top of the System Memory or if we need 77// to install the stacks at the bottom of the Firmware Device (case the FD is located 78// at the top of the DRAM) 79_SetupStackPosition: 80 // Compute Top of System Memory 81 ldr x1, PcdGet64 (PcdSystemMemoryBase) 82 ldr x2, PcdGet64 (PcdSystemMemorySize) 83 sub x2, x2, #1 84 add x1, x1, x2 // x1 = SystemMemoryTop = PcdSystemMemoryBase + PcdSystemMemorySize 85 adr x2, mSystemMemoryEnd 86 str x1, [x2] 87 88 // Calculate Top of the Firmware Device 89 ldr x2, PcdGet64 (PcdFdBaseAddress) 90 ldr w3, PcdGet32 (PcdFdSize) 91 sub x3, x3, #1 92 add x3, x3, x2 // x3 = FdTop = PcdFdBaseAddress + PcdFdSize 93 94 // UEFI Memory Size (stacks are allocated in this region) 95 LoadConstantToReg (FixedPcdGet32(PcdSystemMemoryUefiRegionSize), x4) 96 97 // 98 // Reserve the memory for the UEFI region (contain stacks on its top) 99 // 100 101 // Calculate how much space there is between the top of the Firmware and the Top of the System Memory 102 subs x0, x1, x3 // x0 = SystemMemoryTop - FdTop 103 b.mi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM 104 cmp x0, x4 105 b.ge _SetupStack 106 107 // Case the top of stacks is the FdBaseAddress 108 mov x1, x2 109 110_SetupStack: 111 // x1 contains the top of the stack (and the UEFI Memory) 112 113 // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment 114 // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the 115 // top of the memory space) 116 adds x11, x1, #1 117 b.cs _SetupOverflowStack 118 119_SetupAlignedStack: 120 mov x1, x11 121 b _GetBaseUefiMemory 122 123_SetupOverflowStack: 124 // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE 125 // aligned (4KB) 126 LoadConstantToReg (EFI_PAGE_MASK, x11) 127 and x11, x11, x1 128 sub x1, x1, x11 129 130_GetBaseUefiMemory: 131 // Calculate the Base of the UEFI Memory 132 sub x11, x1, x4 133 134_GetStackBase: 135 // r1 = The top of the Mpcore Stacks 136 // Stack for the primary core = PrimaryCoreStack 137 LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2) 138 sub x12, x1, x2 139 140 // Stack for the secondary core = Number of Cores - 1 141 LoadConstantToReg (FixedPcdGet32(PcdCoreCount), x0) 142 sub x0, x0, #1 143 LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x1) 144 mul x1, x1, x0 145 sub x12, x12, x1 146 147 // x12 = The base of the MpCore Stacks (primary stack & secondary stacks) 148 mov x0, x12 149 mov x1, x10 150 //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize) 151 LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2) 152 LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x3) 153 bl ASM_PFX(ArmPlatformStackSet) 154 155 // Is it the Primary Core ? 156 mov x0, x10 157 bl ASM_PFX(ArmPlatformIsPrimaryCore) 158 cmp x0, #1 159 bne _PrepareArguments 160 161_PrepareArguments: 162 mov x0, x10 163 mov x1, x11 164 mov x2, x12 165 166 // Move sec startup address into a data register 167 // Ensure we're jumping to FV version of the code (not boot remapped alias) 168 ldr x4, StartupAddr 169 170 // Jump to PrePiCore C code 171 // x0 = MpId 172 // x1 = UefiMemoryBase 173 // x2 = StacksBase 174 blr x4 175 176_NeverReturn: 177 b _NeverReturn 178