aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/head.S4
-rw-r--r--kernel/initrd.c40
-rw-r--r--kernel/main.c15
3 files changed, 50 insertions, 9 deletions
diff --git a/kernel/head.S b/kernel/head.S
index de7852b..9018a8e 100644
--- a/kernel/head.S
+++ b/kernel/head.S
@@ -43,8 +43,8 @@ _start:
csrw sscratch, 0
// Point tp and sp to the init task.
- la tp, init_task
- la sp, init_task + THREAD_SIZE
+ la tp, tasks
+ la sp, tasks + THREAD_SIZE
// The `start_kernel` function requires an argument to be passed, which is
// the pointer to the `fdt` blob. The bootloader puts this on the `a1`
diff --git a/kernel/initrd.c b/kernel/initrd.c
index c05e77d..4706fe8 100644
--- a/kernel/initrd.c
+++ b/kernel/initrd.c
@@ -63,16 +63,48 @@ __kernel int get_task_id_from_name(const char *const name)
return TASK_UNKNOWN;
}
-__kernel void extract_elf(int task_id, const char *const addr, size_t size)
+__kernel void ensure_elf_format(const unsigned char *const addr)
+{
+ if (addr[0] != 0x7F || memcmp(&addr[1], "ELF", 3) != 0) {
+ die("Bad ELF format\n");
+ }
+ if (addr[4] != 2) {
+ die("64-bit format is mandatory\n");
+ }
+ if (addr[5] != 1) {
+ die("Little-endian only\n");
+ }
+}
+
+struct exec_header {
+ uint64_t e_entry;
+ uint64_t e_phoff;
+ uint16_t e_phnum;
+ uint16_t e_phentsize;
+};
+
+// TODO
+__kernel void extract_elf(int task_id, const unsigned char *const addr, size_t size)
{
__unused(task_id);
- __unused(addr);
__unused(size);
- // TODO
+ ensure_elf_format(addr);
+
+ /* struct exec_header header = { */
+ /* .e_entry = (unsigned long long)addr[0x18], */
+ /* .e_phoff = (uint64_t)addr[0x20], */
+ /* .e_phentsize = (uint16_t)addr[0x36], */
+ /* .e_phnum = (uint16_t)addr[0x38], */
+ /* }; */
+
+#ifdef __KERNEL__
+ tasks[task_id].addr = (const void *)addr;
+ tasks[task_id].entry_offset = (uint64_t)addr[0x18];
+#endif
}
-__kernel void extract_initrd(const char *const initrd_addr, uint64_t size)
+__kernel void extract_initrd(const unsigned char *const initrd_addr, uint64_t size)
{
char buffer[BUFFER_SIZE];
uint64_t name_size, file_size, padding, base = 0;
diff --git a/kernel/main.c b/kernel/main.c
index 7eb2ef6..089614f 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -4,9 +4,14 @@
#include <fbos/sched.h>
#include <fbos/dt.h>
-unsigned long init_stack[THREAD_SIZE / sizeof(unsigned long)];
+unsigned long init_stack[4][THREAD_SIZE / sizeof(unsigned long)];
-struct task_struct init_task = { .stack = init_stack };
+struct task_struct tasks[4] = {
+ [0] = { .stack = init_stack[0] },
+ [1] = { .stack = init_stack[1] },
+ [2] = { .stack = init_stack[2] },
+ [3] = { .stack = init_stack[3] },
+};
/*
* This is the main entry point of the kernel after head.S is done. This
@@ -21,7 +26,11 @@ __noreturn __kernel void start_kernel(void *dtb)
struct initrd_addr addr = find_dt_initrd_addr(dtb);
- extract_initrd((char *)addr.start, addr.end - addr.start);
+ extract_initrd((unsigned char *)addr.start, addr.end - addr.start);
+
+ // TODO: this is the jump address for the first task.
+ const char *ddr = (const char *)tasks[1].addr + tasks[1].entry_offset;
+ __unused(ddr);
// TODO: reenable stuff