1/*
2 * Copyright 2019, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#include <sel4/sel4.h>
13#include <sel4runtime/start.h>
14#include <sel4runtime/stdint.h>
15#include <sel4runtime/stddef.h>
16
17/*
18 * As this file is only included when we are running a root server,
19 * these symbols must exist and be provided for this file to function
20 * properly.
21 *
22 * This will generate a link time error if this function is used outside
23 * of a root server.
24 */
25
26extern unsigned int _tdata_start[];
27extern unsigned int _tdata_end[];
28extern unsigned int _tbss_end[];
29
30long sel4_vsyscall(long sysnum, ...);
31
32/*
33 * The entrypoint into a root task is somewhat different to the
34 * entrypoint into a regular process. The kernel does not provide a
35 * stack to the root task nor does it conform to System-V ABI; instead
36 * it simply starts execution at the entrypoint with the first argument
37 * being the pointer to the seL4_BootInfo.
38 *
39 * This is invoked by _sel4_start, which simply sets up a static stack
40 * and passes the argument to us.
41 */
42void __sel4_start_root(seL4_BootInfo *boot_info)
43{
44    sel4runtime_uintptr_t tdata_start = (sel4runtime_uintptr_t) &_tdata_start[0];
45    sel4runtime_uintptr_t tdata_end = (sel4runtime_uintptr_t) &_tdata_end[0];
46    sel4runtime_uintptr_t tbss_end = (sel4runtime_uintptr_t) &_tbss_end[0];
47
48    Elf_Phdr tls_header = {
49        .p_type   = PT_TLS,
50        .p_offset = 0,
51        .p_vaddr  = (Elf_Addr) tdata_start,
52        .p_paddr  = 0,
53        .p_filesz = tdata_end - tdata_start,
54        .p_memsz  = tbss_end - tdata_start,
55        .p_align = sizeof(seL4_Word),
56    };
57
58    struct {
59        char const *const argv[2];
60        char const *const envp[2];
61        auxv_t auxv[7];
62    } info = {
63        .argv = {
64            "rootserver",
65            SEL4RUNTIME_NULL,
66        },
67        .envp = {
68            "seL4=1",
69            SEL4RUNTIME_NULL,
70        },
71        .auxv = {
72            {
73                .a_type = AT_PHENT,
74                .a_un.a_val = sizeof(Elf32_Phdr),
75            }, {
76                .a_type = AT_PHNUM,
77                .a_un.a_val = 1,
78            }, {
79                .a_type = AT_PHDR,
80                .a_un.a_ptr = &tls_header,
81            }, {
82                .a_type = AT_SYSINFO,
83                .a_un.a_ptr = &sel4_vsyscall,
84            }, {
85                .a_type = AT_SEL4_BOOT_INFO,
86                .a_un.a_ptr = boot_info,
87            }, {
88                .a_type = AT_SEL4_TCB,
89                .a_un.a_val = seL4_CapInitThreadTCB,
90            }, {
91                // Null terminating entry
92                .a_type = AT_NULL,
93                .a_un.a_val = 0
94            },
95        },
96    };
97
98    __sel4runtime_start_main(main, ARRAY_LENGTH(info.argv) - 1, info.argv, info.envp, info.auxv);
99}
100