aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2024-11-22 07:58:15 +0100
committerMiquel Sabaté Solà <mikisabate@gmail.com>2024-11-22 07:58:15 +0100
commit8231af9d8d759ae89c8214ca2410b0feab9dfb8c (patch)
treef679c721ad1dd3daa5830da6c10425d2d3b699ab
parent40ffc517e20c381ce8fdb3a881726a26a52e35db (diff)
downloadfbos-8231af9d8d759ae89c8214ca2410b0feab9dfb8c.tar.gz
fbos-8231af9d8d759ae89c8214ca2410b0feab9dfb8c.zip
Add basic parsing for underlying ELF executables
The given initrd is a CPIO archive of multiple ELF executables. We are already able to parse the CPIO archive to detect where each file is located, this commit adds the mapping for each ELF executable to the corresponding task_struct. Note that this is still heavily under construction, since we cannot simply jump into the entry point of an executable as we have not yet setup the proper layout from performing context switches. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
-rw-r--r--include/fbos/compiler.h6
-rw-r--r--include/fbos/init.h4
-rw-r--r--include/fbos/sched.h6
-rw-r--r--kernel/head.S4
-rw-r--r--kernel/initrd.c40
-rw-r--r--kernel/main.c15
-rw-r--r--test/test_initrd.c13
-rw-r--r--usr/src/bar.S4
-rw-r--r--usr/src/foo.S4
-rw-r--r--usr/src/foobar.S4
10 files changed, 79 insertions, 21 deletions
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 <fbos/compiler.h>
-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 <fbos/compiler.h>
+
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 <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
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 <assert.h>
#include <fbos/init.h>
+#include <fbos/sched.h>
+#include <fbos/mm.h>
+
+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