blob: b626f5e5f6d29bf2f64337195972f2f7b0a61232 [file] [log] [blame] [edit]
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file is a barebones, minimal-dependency rootserver (root app) for seL4
// that uses no standard C libraries or startfiles. It prints bootinfo to the
// console using the seL4_DebugPutChar syscall and is intended as a starting
// point for low-level seL4 tests.
#include <stdint.h>
#include <stdarg.h>
#include <sel4/bootinfo.h>
#include <sel4/arch/syscalls.h>
seL4_BootInfo *bootinfo;
__thread seL4_IPCBuffer *__sel4_ipc_buffer;
char minisel_stack[16384] __attribute__((__aligned__(4096)));
char minisel_tls[4096] __attribute__((__aligned__(4096)));
__attribute__((naked)) void _start() {
asm volatile(
".option push \n"
".option norelax \n"
"la gp, __global_pointer$ \n"
"la sp, minisel_stack + 4096 \n"
"la x4, minisel_tls \n"
"la t0, bootinfo \n"
"sw a0, 0(t0) \n"
".option pop \n"
"j main \n"
);
}
// only prints 32-bit "%x" hex values
void minisel_printf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (; *fmt; fmt++) {
if (*fmt == '%') {
fmt++;
if (*fmt == 'x') {
uint32_t arg = va_arg(args, uint32_t);
for (int i = 7; i >= 0; i--) {
int n = (arg >> (4 * i)) & 0xF;
seL4_DebugPutChar(n > 9 ? 'A' + n - 10 : '0' + n);
}
}
} else {
seL4_DebugPutChar(*fmt);
}
}
va_end(args);
}
int main(void) {
minisel_printf("\n");
minisel_printf("########################################\n");
minisel_printf("Minisel startup, bootinfo @ %x\n", bootinfo);
minisel_printf("extraLen %x\n", bootinfo->extraLen);
minisel_printf("nodeID %x\n", bootinfo->nodeID);
minisel_printf("numNodes %x\n", bootinfo->numNodes);
minisel_printf("numIOPTLevels %x\n", bootinfo->numIOPTLevels);
minisel_printf("ipcBuffer %x\n", bootinfo->ipcBuffer);
minisel_printf("initThreadCNodeSizeBits %x\n", bootinfo->initThreadCNodeSizeBits);
minisel_printf("CONFIG_MAX_NUM_BOOTINFO_UNTYPED_CAPS %x\n", CONFIG_MAX_NUM_BOOTINFO_UNTYPED_CAPS);
minisel_printf("\n");
int slot_a = bootinfo->untyped.start;
int slot_b = bootinfo->untyped.end;
minisel_printf("slot_a %x\n", slot_a);
minisel_printf("slot_b %x\n", slot_b);
minisel_printf("\n");
for (int i = 0; i < (slot_b - slot_a); i++) {
seL4_UntypedDesc u = bootinfo->untypedList[i];
uint32_t paddr_a = u.paddr;
uint32_t paddr_b = paddr_a + (1 << u.sizeBits);
minisel_printf("paddr %x:%x isDevice %x\n", paddr_a, paddr_b, u.isDevice);
}
minisel_printf("\n");
minisel_printf("Done, sleeping in WFI loop\n");
while(1) {
asm("wfi");
}
}