source: mainline/boot/arch/arm64/src/asm.S

Last change on this file was 95b7d4df, checked in by Martin Decky <martin@…>, 4 years ago

Improve boot loader versatility

Add support for booting from EL3 and EL2, make sure instruction and
data caches are coherent on real hardware.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2015 Petr Pavlu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <abi/asmtool.h>
30#include <arch/arch.h>
31#include <arch/regutils.h>
32
33.section BOOTSTRAP
34
35#define DIRECTORY_ENTRIES 16
36
37/* MS-DOS stub */
38msdos_stub:
39 .ascii "MZ" /* MS-DOS signature */
40 .space 0x3a /* Ignore fields up to byte at 0x3c */
41 .long pe_header - msdos_stub /* Offset to the PE header */
42
43/* Portable Executable header */
44pe_header:
45 /* PE signature */
46 .ascii "PE\x0\x0"
47
48 /* COFF File Header */
49 .short 0xaa64 /* Machine = IMAGE_FILE_MACHINE_ARM64 */
50 .short 1 /* Number of sections */
51 .long 0 /* Time date stamp */
52 .long 0 /* Pointer to symbol table */
53 .long 0 /* Number of symbols */
54 .short sec_table - opt_header /* Size of optional header */
55 /*
56 * Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE |
57 * IMAGE_FILE_LARGE_ADDRESS_AWARE
58 */
59 .short 0x22
60
61 /* Optional header standard fields */
62opt_header:
63 .short 0x20b /* Magic = PE32+ */
64 .byte 0 /* Major linker version */
65 .byte 0 /* Minor linker version */
66 .long payload_end - msdos_stub /* Size of code */
67 .long 0 /* Size of initialized data */
68 .long 0 /* Size of uninitialized data */
69 .long start - msdos_stub /* Address of entry point */
70 .long start - msdos_stub /* Base of code */
71
72 /* Optional header Windows-specific fields */
73 .quad 0 /* Image base */
74 .long 4 /* Section alignment */
75 .long 4 /* File alignment */
76 .short 0 /* Major operating system version */
77 .short 0 /* Minor operating system version */
78 .short 0 /* Major image version */
79 .short 0 /* Minor image version */
80 .short 0 /* Major subsystem version */
81 .short 0 /* Minor subsystem version */
82 .long 0 /* Win32 version value */
83 .long payload_end - msdos_stub /* Size of image */
84 .long start - msdos_stub /* Size of headers */
85 .long 0 /* Checksum */
86 .short 10 /* Subsystem = EFI application */
87 .short 0 /* DLL characteristics */
88 .quad 0 /* Size of stack reserve */
89 .quad 0 /* Size of stack commit */
90 .quad 0 /* Size of heap reserve */
91 .quad 0 /* Size of heap commit */
92 .long 0 /* Loader flags */
93 .long DIRECTORY_ENTRIES /* Number of RVA and sizes */
94 .space DIRECTORY_ENTRIES * 8 /* Directory entries */
95
96sec_table:
97 .ascii ".text\x0\x0\x0" /* Name */
98 .long payload_end - start /* Virtual size */
99 .long start - msdos_stub /* Virtual address */
100 .long payload_end - start /* Size of raw data */
101 .long start - msdos_stub /* Pointer to raw data */
102 .long 0 /* Pointer to relocations */
103 .long 0 /* Pointer to line numbers */
104 .short 0 /* Number of relocations */
105 .short 0 /* Number of line numbers */
106 /*
107 * Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE |
108 * IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
109 */
110 .long 0xe0000020
111
112/** Boot loader entry point
113 *
114 * @param x0 UEFI image handle.
115 * @param x1 Pointer to the UEFI system table.
116 *
117 */
118SYMBOL(start)
119 .hidden start
120
121 /*
122 * Stay on the UEFI stack. Its size is at least 128 KiB, plenty for this
123 * boot loader.
124 */
125 stp x29, x30, [sp, #-32]!
126 mov x29, sp
127 stp x0, x1, [sp, #16]
128
129 /*
130 * Self-relocate the image. Pass a load address of the image (x0) and a
131 * pointer to the dynamic array (x1).
132 */
133 adr x0, msdos_stub
134 adrp x1, _DYNAMIC
135 add x1, x1, #:lo12:_DYNAMIC
136 bl self_relocate
137 cbnz x0, __uefi_exit
138
139 /*
140 * Flush the instruction cache of the relocated boot loader image.
141 */
142 adr x0, msdos_stub
143 adrp x1, payload_end
144 sub x1, x1, x0
145 bl smc_coherence
146
147 /*
148 * Pass the image handle (x0), a pointer to the UEFI system table (x1),
149 * and the image load address (x2) to the boostrap function.
150 */
151 ldp x0, x1, [sp, #16]
152 adr x2, msdos_stub
153 bl bootstrap
154
155 __uefi_exit:
156 ldp x29, x30, [sp], #32
157 ret
158
159FUNCTION_BEGIN(halt)
160 .hidden halt
161
162 b halt
163FUNCTION_END(halt)
164
165/** Flush instruction caches
166 *
167 * @param x0 Starting address of the flushing.
168 * @param x1 Number of bytes to flush.
169 *
170 */
171FUNCTION_BEGIN(smc_coherence)
172 .hidden smc_coherence
173
174 /* Initialize loop */
175 mov x9, x0
176 mov x10, xzr
177
178 __dc_loop:
179 /* Data or Unified Cache Line Clean */
180 dc cvau, x9
181 add x9, x9, #4
182 add x10, x10, #4
183 cmp x10, x1
184 blo __dc_loop
185
186 dsb ish
187
188 /* Initialize loop */
189 mov x9, x0
190 mov x10, xzr
191
192 __ic_loop:
193 /* Instruction Cache Line Invalidate */
194 ic ivau, x9
195 add x9, x9, #4
196 add x10, x10, #4
197 cmp x10, x1
198 blo __ic_loop
199
200 dsb ish
201 isb
202 ret
203FUNCTION_END(smc_coherence)
204
205/** Flush data caches
206 *
207 * @param x0 Starting address of the flushing.
208 * @param x1 Number of bytes to flush.
209 *
210 */
211FUNCTION_BEGIN(dcache_flush)
212 .hidden dcache_flush
213
214 mov x9, x0
215 mov x10, xzr
216
217 __dc_flush_loop:
218 /* Data or Unified Cache Line Clean */
219 dc cvau, x9
220 add x9, x9, #4
221 add x10, x10, #4
222 cmp x10, x1
223 blo __dc_flush_loop
224
225 dsb ish
226 isb
227 ret
228FUNCTION_END(dcache_flush)
229
230/** Kernel entry
231 *
232 * @param x0 Kernel entry point.
233 * @param x1 Pointer to the bootinfo structure.
234 *
235 */
236FUNCTION_BEGIN(jump_to_kernel)
237 .hidden jump_to_kernel
238
239 mrs x9, CurrentEL
240 lsr x9, x9, 2
241
242 cmp x9, #3
243 b.eq __el3
244
245 cmp x9, #2
246 b.eq __el2
247
248 cmp x9, #1
249 b.eq __el1
250
251 b halt
252
253 __el3:
254 msr sctlr_el2, xzr
255 msr hcr_el2, xzr
256 isb
257
258 /* EL2 is AArch64, EL1 is Non-secure World */
259 mov x9, #(1 << 10)
260 orr x9, x9, #(1 << 0)
261 msr scr_el3, x9
262 isb
263
264 /* EL2h */
265 mov x9, #0x9
266 msr spsr_el3, x9
267 isb
268
269 adr x9, __el2
270 msr elr_el3, x9
271 isb
272
273 /* Switch to EL2 */
274 eret
275
276 __el2:
277 msr sctlr_el1, xzr
278 isb
279
280 /* EL1 is AArch64 */
281 mov x9, #(1 << 31)
282 msr hcr_el2, x9
283 isb
284
285 /* EL1h */
286 mov x9, #0x5
287 msr spsr_el2, x9
288 isb
289
290 adr x9, __el1
291 msr elr_el2, x9
292 isb
293
294 /* Switch to EL1 */
295 eret
296
297 __el1:
298 /* Do not trap on FPU instructions */
299 mrs x9, cpacr_el1
300 orr x9, x9, #(3 << 20)
301 msr cpacr_el1, x9
302 dmb ish
303
304 /* Disable MMU (removes the identity mapping provided by UEFI) */
305 mrs x9, sctlr_el1
306 bic x9, x9, #SCTLR_M_FLAG
307 msr sctlr_el1, x9
308 isb
309
310 br x0
311FUNCTION_END(jump_to_kernel)
Note: See TracBrowser for help on using the repository browser.