blob: f918a98e33a39bbecaa868f2fea06028c7524a17 [file] [log] [blame] [edit]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sel4/sel4.h>
#include <sel4runtime/start.h>
#include <sel4runtime/stdint.h>
#include <sel4runtime/stddef.h>
/*
* As this file is only included when we are running a root server,
* these symbols must exist and be provided for this file to function
* properly.
*
* This will generate a link time error if this function is used outside
* of a root server.
*/
extern unsigned int _tdata_start[];
extern unsigned int _tdata_end[];
extern unsigned int _tbss_end[];
long sel4_vsyscall(long sysnum, ...);
/*
* The entrypoint into a root task is somewhat different to the
* entrypoint into a regular process. The kernel does not provide a
* stack to the root task nor does it conform to System-V ABI; instead
* it simply starts execution at the entrypoint with the first argument
* being the pointer to the seL4_BootInfo.
*
* This is invoked by _sel4_start, which simply sets up a static stack
* and passes the argument to us.
*/
void __sel4_start_root(seL4_BootInfo *boot_info)
{
sel4runtime_uintptr_t tdata_start = (sel4runtime_uintptr_t) &_tdata_start[0];
sel4runtime_uintptr_t tdata_end = (sel4runtime_uintptr_t) &_tdata_end[0];
sel4runtime_uintptr_t tbss_end = (sel4runtime_uintptr_t) &_tbss_end[0];
Elf_Phdr tls_header = {
.p_type = PT_TLS,
.p_offset = 0,
.p_vaddr = (Elf_Addr) tdata_start,
.p_paddr = 0,
.p_filesz = tdata_end - tdata_start,
.p_memsz = tbss_end - tdata_start,
.p_align = sizeof(seL4_Word),
};
struct {
char const *const argv[2];
char const *const envp[2];
auxv_t auxv[8];
} info = {
.argv = {
"rootserver",
SEL4RUNTIME_NULL,
},
.envp = {
"seL4=1",
SEL4RUNTIME_NULL,
},
.auxv = {
{
.a_type = AT_PHENT,
.a_un.a_val = sizeof(Elf32_Phdr),
}, {
.a_type = AT_PHNUM,
.a_un.a_val = 1,
}, {
.a_type = AT_PHDR,
.a_un.a_ptr = &tls_header,
}, {
.a_type = AT_SYSINFO,
.a_un.a_ptr = &sel4_vsyscall,
}, {
.a_type = AT_SEL4_BOOT_INFO,
.a_un.a_ptr = boot_info,
}, {
.a_type = AT_SEL4_IPC_BUFFER_PTR,
.a_un.a_ptr = boot_info->ipcBuffer,
}, {
.a_type = AT_SEL4_TCB,
.a_un.a_val = seL4_CapInitThreadTCB,
}, {
// Null terminating entry
.a_type = AT_NULL,
.a_un.a_val = 0
},
},
};
__sel4runtime_start_main(main, ARRAY_LENGTH(info.argv) - 1, info.argv, info.envp, info.auxv);
}