1// 2// Copyright (c) 2011-2013, ARM Limited. All rights reserved. 3// Copyright (c) 2015-2016, 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 <AsmMacroIoLib.h> 16 17ASM_FUNC(_ModuleEntryPoint) 18 // 19 // We are built as a ET_DYN PIE executable, so we need to process all 20 // relative relocations if we are executing from a different offset than we 21 // were linked at. This is only possible if we are running from RAM. 22 // 23 ADRL (r4, __reloc_base) 24 ADRL (r5, __reloc_start) 25 ADRL (r6, __reloc_end) 26 27.Lreloc_loop: 28 cmp r5, r6 29 bhs .Lreloc_done 30 31 // 32 // AArch32 uses the ELF32 REL format, which means each entry in the 33 // relocation table consists of 34 // 35 // UINT32 offset : the relative offset of the value that needs to 36 // be relocated 37 // UINT32 info : relocation type and symbol index (the latter is 38 // not used for R_ARM_RELATIVE relocations) 39 // 40 ldrd r8, r9, [r5], #8 // read offset into r8 and info into r9 41 cmp r9, #23 // check info == R_ARM_RELATIVE? 42 bne .Lreloc_loop // not a relative relocation? then skip 43 44 ldr r9, [r8, r4] // read addend into r9 45 add r9, r9, r1 // add image base to addend to get relocated value 46 str r9, [r8, r4] // write relocated value at offset 47 b .Lreloc_loop 48.Lreloc_done: 49 50 // Do early platform specific actions 51 bl ASM_PFX(ArmPlatformPeiBootAction) 52 53 // Get ID of this CPU in Multicore system 54 bl ASM_PFX(ArmReadMpidr) 55 // Keep a copy of the MpId register value 56 mov r10, r0 57 58// Check if we can install the stack at the top of the System Memory or if we need 59// to install the stacks at the bottom of the Firmware Device (case the FD is located 60// at the top of the DRAM) 61_SetupStackPosition: 62 // Compute Top of System Memory 63 LDRL (r1, PcdGet64 (PcdSystemMemoryBase)) 64 ADRL (r12, PcdGet64 (PcdSystemMemorySize)) 65 ldrd r2, r3, [r12] 66 67 // calculate the top of memory 68 adds r2, r2, r1 69 sub r2, r2, #1 70 addcs r3, r3, #1 71 72 // truncate the memory used by UEFI to 4 GB range 73 teq r3, #0 74 movne r1, #-1 75 moveq r1, r2 76 77 // Calculate Top of the Firmware Device 78 LDRL (r2, PcdGet64 (PcdFdBaseAddress)) 79 MOV32 (r3, FixedPcdGet32 (PcdFdSize) - 1) 80 add r3, r3, r2 // r3 = FdTop = PcdFdBaseAddress + PcdFdSize 81 82 // UEFI Memory Size (stacks are allocated in this region) 83 MOV32 (r4, FixedPcdGet32(PcdSystemMemoryUefiRegionSize)) 84 85 // 86 // Reserve the memory for the UEFI region (contain stacks on its top) 87 // 88 89 // Calculate how much space there is between the top of the Firmware and the Top of the System Memory 90 subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop 91 bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM 92 cmp r0, r4 93 bge _SetupStack 94 95 // Case the top of stacks is the FdBaseAddress 96 mov r1, r2 97 98_SetupStack: 99 // r1 contains the top of the stack (and the UEFI Memory) 100 101 // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment 102 // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the 103 // top of the memory space) 104 adds r11, r1, #1 105 bcs _SetupOverflowStack 106 107_SetupAlignedStack: 108 mov r1, r11 109 b _GetBaseUefiMemory 110 111_SetupOverflowStack: 112 // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE 113 // aligned (4KB) 114 MOV32 (r11, (~EFI_PAGE_MASK) & 0xffffffff) 115 and r1, r1, r11 116 117_GetBaseUefiMemory: 118 // Calculate the Base of the UEFI Memory 119 sub r11, r1, r4 120 121_GetStackBase: 122 // r1 = The top of the Mpcore Stacks 123 // Stack for the primary core = PrimaryCoreStack 124 MOV32 (r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize)) 125 sub r9, r1, r2 126 127 // Stack for the secondary core = Number of Cores - 1 128 MOV32 (r1, (FixedPcdGet32(PcdCoreCount) - 1) * FixedPcdGet32(PcdCPUCoreSecondaryStackSize)) 129 sub r9, r9, r1 130 131 // r9 = The base of the MpCore Stacks (primary stack & secondary stacks) 132 mov r0, r9 133 mov r1, r10 134 //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize) 135 MOV32 (r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize)) 136 MOV32 (r3, FixedPcdGet32(PcdCPUCoreSecondaryStackSize)) 137 bl ASM_PFX(ArmPlatformStackSet) 138 139 // Is it the Primary Core ? 140 mov r0, r10 141 bl ASM_PFX(ArmPlatformIsPrimaryCore) 142 cmp r0, #1 143 bne _PrepareArguments 144 145_PrepareArguments: 146 mov r0, r10 147 mov r1, r11 148 mov r2, r9 149 150 // Jump to PrePiCore C code 151 // r0 = MpId 152 // r1 = UefiMemoryBase 153 // r2 = StacksBase 154 bl ASM_PFX(CEntryPoint) 155 156_NeverReturn: 157 b _NeverReturn 158