| // 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"); |
| } |
| } |