1/*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <autoconf.h>
8#include <elfloader/gen_config.h>
9#ifdef CONFIG_IMAGE_BINARY
10#include <image_start_addr.h>
11#endif
12
13#include <assembler.h>
14
15.extern main
16
17.section ".text.start"
18BEGIN_FUNC(_start)
19    adrp    x19, core_stack_alloc
20    add     x19, x19, #0xff0
21    mov     sp, x19
22#ifdef CONFIG_IMAGE_BINARY
23    stp     x0, x1, [sp, #-16]!
24    bl      clear_bss
25    /*
26     * Binary images may not be loaded in the correct location.
27     * Try and move ourselves so we're in the right place.
28     */
29    bl      fixup_image_base
30    mov     x2, x0
31    /* restore original arguments for next step */
32    ldp     x0, x1, [sp, #-16]!
33    /* fixup_image_base returns 1 if no need to move */
34    cmp     x2, #1
35    beq     1f
36    /* otherwise, jump to the start of the new elfloader */
37
38    br      x2
391:
40#endif
41    b       main
42END_FUNC(_start)
43
44#ifdef CONFIG_IMAGE_BINARY
45BEGIN_FUNC(fixup_image_base)
46    stp     x29, x30, [sp, #-16]!
47    mov     x29, sp
48    ldr     x0, =IMAGE_START_ADDR
49    adr     x1, _start
50    cmp     x0, x1
51    beq     image_ok
52
53    adrp    x2, _end
54    add     x2, x2, #:lo12:_end
55    sub     x2, x2, x1
56
57    /* sanity check: don't want to overwrite ourselves! we assume
58     * everything between _start and _archive_start is important
59     * (i.e. code that might be run while relocating)
60     * but allow overlap for things after _archive_start.
61     */
62    adrp    x3, _archive_start
63    add     x3, x3, #:lo12:_archive_start
64
65    add     x4, x0, x2 /* Dest end */
66
67    /* check: if (end < archive_start && end >= _start) { abort } */
68    cmp     x4, x3
69    bge     1f
70
71    cmp     x4, x1
72    blt     1f
73
74    b       cant_reloc
75
761:
77    /* check: if (dest < archive_start && dest >= _start) { abort } */
78    cmp     x0, x3
79    bge     2f
80
81    cmp     x0, x1
82    blt     2f
83
84cant_reloc:
85    b abort
86
872:
88    /* x0 = desired image base */
89    /* x1 = current image space */
90    /* x2 = image size */
91    bl      memmove
92    /* x0 = dest, save it to a callee-saved register while we invalidate icache */
93    mov     x19, x0
94    bl      flush_dcache
95    bl      invalidate_icache
96    mov     x0, x19
97    b 1f
98
99image_ok:
100    /* already in the right place, just keep booting */
101    mov x0, #1
1021:
103    ldp     x29, x30, [sp], #16
104    ret
105END_FUNC(fixup_image_base)
106#endif
107
108/* Move the elf loader out of the kernel's way */
109BEGIN_FUNC(finish_relocation)
110    /*
111     * On aarch64 the kernel is loaded at a very high address:
112     * at least above 0x0000ff8080000000. We assume that
113     * the ELF loader will never get loaded in a way that overlaps
114     * with the kernel, so reaching this function is an error.
115     */
116    b abort // should never get here!
117END_FUNC(finish_relocation)
118
119/* secondary cpu startup */
120BEGIN_FUNC(secondary_startup)
121    /*
122     * secondary_data is a struct that looks like this:
123     * 0x0 void *entry
124     * 0x8 void *stack
125     */
126    adrp    x19, secondary_data
127    add     x19, x19, #:lo12:secondary_data
128
129    ldr     x0, [x19, #0x8]     // load stack
130    mov     sp, x0
131    ldr     x1, [x19, #0x0]     // load entry point
132
133    br x1
134END_FUNC(secondary_startup)
135