summaryrefslogtreecommitdiff
path: root/tools/src/startup.c
blob: 105270706f65b18188d6f75153d8392ad2385aa5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* SPDX-License-Identifier: MIT */

#include "chickens.h"
#include "exception.h"
#include "smp.h"
#include "string.h"
#include "types.h"
#include "uart.h"
#include "utils.h"
#include "xnuboot.h"

u64 boot_args_addr;
struct boot_args cur_boot_args;
void *adt;

struct rela_entry {
    uint64_t off, type, addend;
};

void debug_putc(char c);
void m1n1_main(void);

extern char _bss_start[0];
extern char _bss_end[0];

#define R_AARCH64_RELATIVE 1027

void apply_rela(uint64_t base, struct rela_entry *rela_start, struct rela_entry *rela_end)
{
    struct rela_entry *e = rela_start;

    while (e < rela_end) {
        switch (e->type) {
            case R_AARCH64_RELATIVE:
                *(u64 *)(base + e->off) = base + e->addend;
                break;
            default:
                debug_putc('R');
                debug_putc('!');
                while (1)
                    ;
        }
        e++;
    }
}

void dump_boot_args(struct boot_args *ba)
{
    printf("  revision:     %d\n", ba->revision);
    printf("  version:      %d\n", ba->version);
    printf("  virt_base:    0x%lx\n", ba->virt_base);
    printf("  phys_base:    0x%lx\n", ba->phys_base);
    printf("  mem_size:     0x%lx\n", ba->mem_size);
    printf("  top_of_kdata: 0x%lx\n", ba->top_of_kernel_data);
    printf("  video:\n");
    printf("    base:       0x%lx\n", ba->video.base);
    printf("    display:    0x%lx\n", ba->video.display);
    printf("    stride:     0x%lx\n", ba->video.stride);
    printf("    width:      %lu\n", ba->video.width);
    printf("    height:     %lu\n", ba->video.height);
    printf("    depth:      %lubpp\n", ba->video.depth & 0xff);
    printf("    density:    %lu\n", ba->video.depth >> 16);
    printf("  machine_type: %d\n", ba->machine_type);
    printf("  devtree:      %p\n", ba->devtree);
    printf("  devtree_size: 0x%x\n", ba->devtree_size);
    printf("  cmdline:      %s\n", ba->cmdline);
    printf("  boot_flags:   0x%lx\n", ba->boot_flags);
    printf("  mem_size_act: 0x%lx\n", ba->mem_size_actual);
}

void _start_c(void *boot_args, void *base)
{
    UNUSED(base);

    if (in_el2())
        msr(TPIDR_EL2, 0);
    else
        msr(TPIDR_EL1, 0);

    memset64(_bss_start, 0, _bss_end - _bss_start);
    boot_args_addr = (u64)boot_args;
    memcpy(&cur_boot_args, boot_args, sizeof(cur_boot_args));

    adt =
        (void *)(((u64)cur_boot_args.devtree) - cur_boot_args.virt_base + cur_boot_args.phys_base);

    int ret = uart_init();
    if (ret < 0) {
        debug_putc('!');
    }

    uart_puts("Initializing");
    printf("CPU init (MIDR: 0x%lx)...\n", mrs(MIDR_EL1));
    const char *type = init_cpu();
    printf("  CPU: %s\n\n", type);

    printf("boot_args at %p\n", boot_args);

    dump_boot_args(&cur_boot_args);
    printf("\n");

    exception_initialize();
    m1n1_main();
}

/* Secondary SMP core boot */
void _cpu_reset_c(void *stack)
{
    if (mrs(MPIDR_EL1) & 0xffffff)
        uart_puts("RVBAR entry on secondary CPU");
    else
        uart_puts("RVBAR entry on primary CPU");

    printf("\n  Stack base: %p\n", stack);
    printf("  MPIDR: 0x%lx\n", mrs(MPIDR_EL1));
    const char *type = init_cpu();
    printf("  CPU: %s\n", type);

    exception_initialize();
    smp_secondary_entry();
}