First version of Minisel, a minimalist seL4 rootserver app for testing.

Change-Id: I0dff1e7d2a74a16a748c60cc37a8c2d13b505892
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b5c73e8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+SRC_LIBSEL4 ?= $(ROOTDIR)/kata/kernel/libsel4
+OUT_KATA    ?= $(OUT)/kata/riscv32-unknown-elf/release
+OUT_MINISEL ?= $(OUT)/tmp/minisel
+
+INCLUDES += -I$(SRC_LIBSEL4)/arch_include/riscv
+INCLUDES += -I$(SRC_LIBSEL4)/include
+INCLUDES += -I$(SRC_LIBSEL4)/mode_include/32
+INCLUDES += -I$(SRC_LIBSEL4)/sel4_arch_include/riscv32/
+INCLUDES += -I$(OUT_KATA)/kernel/gen_config
+INCLUDES += -I$(OUT_KATA)/libsel4/autoconf
+INCLUDES += -I$(OUT_KATA)/libsel4/gen_config/
+INCLUDES += -I$(OUT_KATA)/libsel4/include
+INCLUDES += -I$(OUT_KATA)/libsel4/sel4_arch_include/riscv32
+
+OPT=-O0
+DBG=-g
+
+all: $(OUT_MINISEL)/minisel.elf
+
+$(OUT_MINISEL)/minisel.elf:
+	mkdir -p $(OUT_MINISEL)
+	riscv32-unknown-elf-gcc $(DBG) $(OPT) $(INCLUDES) -march=rv32imac -mabi=ilp32 -std=gnu11 -c minisel.c -o $(OUT_MINISEL)/minisel.o
+	riscv32-unknown-elf-gcc $(DBG) -static -nostdlib $(OUT_MINISEL)/minisel.o -o $(OUT_MINISEL)/minisel.elf
diff --git a/minisel.c b/minisel.c
new file mode 100644
index 0000000..3d92285
--- /dev/null
+++ b/minisel.c
@@ -0,0 +1,85 @@
+// 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");
+  }
+}