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#include <assembler.h>
10#include <armv/assembler.h>
11
12.extern main
13.extern non_boot_main
14
15.section ".text.start"
16
17BEGIN_FUNC(_start)
18#ifdef CONFIG_ELFLOADER_ARMV8_LEAVE_AARCH64
19    /* Include an Aarch64 preamble that switches to aarch32 */
20    .incbin "crt0_64.bin"
21BEGIN_FUNC(_start32)
22#endif // CONFIG_ELFLOADER_ARMV8_LEAVE_AARCH64
23
24    /* If we're not booting under EFI, r2 will contain a pointer to the DTB */
25    mov r0, r2
26
27    /* Disable Async aborts that might be pending from bootloader */
28    cpsid   ifa
29
30    /* r0 contains the FDT address from the bootloader */
31#if CONFIG_MAX_NUM_NODES > 1
32    /* Enable SMP */
33    mrc     ACTLR(r1)
34    orr     r1, r1, #(1 << 6)       /* enable SMP bit   */
35#ifdef CONFIG_ARM_CORTEX_A9
36    orr     r1, r1, #1              /* enable FW bit    */
37#endif
38    mcr     ACTLR(r1)
39#endif /* CONFIG_MAX_NUM_NODES > 1 */
40
41    ldr sp, =core_stack_alloc + 0xff0
42
43#ifndef CONFIG_IMAGE_EFI
44    /*
45     * clear the BSS section, since it may not be clear yet.
46     * Under EFI, this is done earlier in the boot process.
47     */
48    push    {r0}
49    bl      clear_bss
50    pop     {r0}
51#endif
52
53    b       main
54END_FUNC(_start)
55
56/* Move the elf loader out of the kernel's way */
57BEGIN_FUNC(finish_relocation)
58#if CONFIG_IMAGE_EFI
59    // r0 = offset between current base address and new base address
60    // r1 = _DYNAMIC pointer (current base address)
61    // r2 = total offset (new_base)
62    mov r8, r1 // move to r8
63
64    // figure out relocated address of continue_boot
65    adr r1, LC2
66    ldmia r1, {r3, r4, r5}
67
68    // r3 = stack pointer (in current program)
69    // r4 = continue_boot (in current program)
70    // r5 = current base address (_text, the start of the binary)
71
72    sub sp, r3, r0                  // point sp to new stack
73    sub r4, r4, r0                  // continue_boot address in relocated elfloader
74
75    // self_reloc expects:
76    // r0 = current base address
77    // r1 = dynamic section pointer
78    // r2 = new base address
79    // r3 = 0
80
81    mov r0, r5                      // current base address
82    mov r1, r8                      // put _DYNAMIC back
83    // r2 is new base address, passed from relocate_below_kernel()
84    mov r3, #0                      // NULL r3
85
86    push {r4}                       // save continue_boot address
87
88    bl _relocate
89
90    pop {r4}
91    mov r0, #1
92    blx r4
93    b abort // should never get here!
94#else
95    /* On non-EFI, the image cannot be relocated.
96     * If you hit this, you probably need to modify the ELF loader
97     * load address.
98     */
99    mov pc, lr
100#endif
101END_FUNC(finish_relocation)
102.align 2
103.type LC2, #object
104LC2:
105.word core_stack_alloc + 0xff0  // r3
106.word continue_boot             // r4
107.word _text                     // r5
108.size LC2, . - LC2
109
110#if CONFIG_MAX_NUM_NODES > 1
111BEGIN_FUNC(secondary_startup)
112    /* Invalidate caches before proceeding... */
113    mov     r0, #0
114    mcr     IIALL(r0)
115    dcache  isw
116
117    /* Disable Async aborts that might be pending from bootloader */
118    cpsid   ifa
119
120    /* Enable SMP */
121    mrc     ACTLR(r0)
122    orr     r0, r0, #(1 << 6)       /* enable SMP bit   */
123#ifdef CONFIG_ARM_CORTEX_A9
124    orr     r0, r0, #1              /* enable FW bit    */
125#endif
126    mcr     ACTLR(r0)
127
128    /*
129     * secondary_data is a struct like this:
130     * 0x0 void *entry
131     * 0x4 void *stack
132     */
133    ldr     r0, =secondary_data
134    ldr     r1, [r0, #0x4]         /* load stack */
135    mov     sp, r1
136
137    ldr     r2, [r0]               /* load entry point */
138
139    /* core_entry expects sp as its first argument */
140    mov     r0, r1
141    bx r2
142END_FUNC(secondary_startup)
143#endif /* CONFIG_MAX_NUM_NODES */
144
145/*
146 * Symbols required for libgcc.
147 */
148.global raise
149.global __aeabi_unwind_cpp_pr0
150.global __aeabi_unwind_cpp_pr1
151.global __aeabi_unwind_cpp_pr2
152raise:
153__aeabi_unwind_cpp_pr0:
154__aeabi_unwind_cpp_pr1:
155__aeabi_unwind_cpp_pr2:
156    b       raise
157