.global __aarch64_entry
.global __aarch64_ap_entry
.global __aarch64_ap_spin_table_entry

.macro ADR_WIDE reg, sym
    adrp \reg, \sym
    add \reg, \reg, :lo12:\sym
.endm

.pushsection .text.entry
__aarch64_entry:
    // Image header
    ccmp	x18, #0, #0xd, pl               // "MZ" magic
    b       __aarch64_real_entry            // Jump to real entry
    .quad   0x80000                         // Image load offset from start of RAM
    .quad   __kernel_size                   // Kernel size
    .quad   0                               // Kernel flags
    .quad   0                               // reserved
    .quad   0                               // reserved
    .quad   0                               // reserved
    .ascii  "ARM\x64"
    .long   0

// x0 -- dtb physical address
__aarch64_real_entry:
    adr x29, __aarch64_entry
    mov x30, x0

    //// Halt non-BSP cores
    mrs x0, mpidr_el1
    ands x0, x0, #0xF
    bne .ap_spin_loop

    //// Zero .bss
    adrp x0, __bss_start
    adrp x1, __bss_end
1:
    cmp x0, x1
    beq 2f
    stp xzr, xzr, [x0], #16
    b 1b
2:

    //// Setup a stack
    ADR_WIDE x0, {bsp_stack_bottom} + {bsp_stack_size}
    mov sp, x0

    //// Store boot parameters
    ADR_WIDE x0, {kernel_load_base}
    str x29, [x0]
    ADR_WIDE x0, {dtb_physical_address}
    str x30, [x0]

    //// Relocate the kernel
    mov x0, x29
    ADR_WIDE x1, __rela_start
    ADR_WIDE x2, __rela_end
    bl {relocate_kernel}

    //// Branch to appropriate ELn code
    mrs x0, currentel
    adr x1, .bsp_el_branch_table
    add x0, x0, x1
    br x0

.bsp_el_branch_table:
    b . // EL0 impossible
    b {bsp_entry_el1}
    b {bsp_entry_el2}
    b . // TODO: EL3

.ap_spin_loop:
    wfe
    b .ap_spin_loop

.popsection // .text.entry

.pushsection .text
__aarch64_ap_entry:
    // x0 - physical stack pointer
    mov sp, x0

    mrs x2, currentel
    adr x1, .ap_el_branch_table
    add x1, x1, x2
    br x1

// TODO
__aarch64_ap_spin_table_entry:
    b .

.ap_el_branch_table:
    b .
    b {ap_entry_el1}
    b {ap_entry_el2}
    b .
.popsection // .text
