• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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