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