diff --git a/include/fbos/compiler.h b/include/fbos/compiler.h index b88bb0b..c26c05c 100644 --- a/include/fbos/compiler.h +++ b/include/fbos/compiler.h @@ -19,16 +19,18 @@ #endif /* __KERNEL__ */ /* - * Multiple aliases for 32/64-bit integers which have their definition on the + * Multiple aliases for integer types which have their definition on the * standard library. */ +typedef short int16_t; typedef int int32_t; typedef long ssize_t; typedef long int64_t; -typedef unsigned long size_t; +typedef unsigned short uint16_t; typedef unsigned int uint32_t; +typedef unsigned long size_t; typedef unsigned long uint64_t; typedef unsigned long uintptr_t; diff --git a/include/fbos/init.h b/include/fbos/init.h index c4d0a85..978eebe 100644 --- a/include/fbos/init.h +++ b/include/fbos/init.h @@ -3,11 +3,9 @@ #include -extern struct task_struct init_task; - // Extract the executables from the initrd that is located at `base_addr` and // has the given `size`. -void extract_initrd(const char *const base_addr, uint64_t size); +void extract_initrd(const unsigned char *const base_addr, uint64_t size); // The entry point for the kernel. void start_kernel(void *dtb); diff --git a/include/fbos/sched.h b/include/fbos/sched.h index 5cfc2ba..ff56f32 100644 --- a/include/fbos/sched.h +++ b/include/fbos/sched.h @@ -1,6 +1,8 @@ #ifndef __FBOS_SCHED_H_ #define __FBOS_SCHED_H_ +#include + enum task_id { TASK_UNKNOWN = -1, TASK_INIT = 0, @@ -11,6 +13,10 @@ enum task_id { struct task_struct { void *stack; + const void *addr; + uint64_t entry_offset; }; +extern struct task_struct tasks[4]; + #endif // __FBOS_SCHED_H_ 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 #include -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 diff --git a/test/test_initrd.c b/test/test_initrd.c index 3662eaa..73429b8 100644 --- a/test/test_initrd.c +++ b/test/test_initrd.c @@ -3,6 +3,17 @@ #include #include +#include +#include + +unsigned long init_stack[4][THREAD_SIZE / sizeof(unsigned long)]; + +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] }, +}; int main(void) { @@ -13,7 +24,7 @@ int main(void) long fsize = ftell(fh); rewind(fh); - char *contents = malloc((unsigned long)fsize + 1); + unsigned char *contents = malloc((unsigned long)fsize + 1); fread(contents, (unsigned long)fsize, 1, fh); fclose(fh); diff --git a/usr/src/bar.S b/usr/src/bar.S index 09c68e3..ee86b3e 100644 --- a/usr/src/bar.S +++ b/usr/src/bar.S @@ -2,8 +2,8 @@ .text _start: - li a0, 1 - la a1, bar + li a7, 1 + la a0, bar ecall .Loop: j .Loop diff --git a/usr/src/foo.S b/usr/src/foo.S index 57e82a1..c26b550 100644 --- a/usr/src/foo.S +++ b/usr/src/foo.S @@ -2,8 +2,8 @@ .text _start: - li a0, 1 - la a1, foo + li a7, 1 + la a0, foo ecall .Loop: j .Loop diff --git a/usr/src/foobar.S b/usr/src/foobar.S index 49c9e1d..e3fecb8 100644 --- a/usr/src/foobar.S +++ b/usr/src/foobar.S @@ -2,8 +2,8 @@ .text _start: - li a0, 1 - la a1, foobar + li a7, 1 + la a0, foobar ecall .Loop: j .Loop