Skip to content

Commit

Permalink
Add basic parsing for underlying ELF executables
Browse files Browse the repository at this point in the history
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à <[email protected]>
  • Loading branch information
mssola committed Nov 22, 2024
1 parent 40ffc51 commit 8231af9
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 21 deletions.
6 changes: 4 additions & 2 deletions include/fbos/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 1 addition & 3 deletions include/fbos/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions include/fbos/sched.h
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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_
4 changes: 2 additions & 2 deletions kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
40 changes: 36 additions & 4 deletions kernel/initrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 12 additions & 3 deletions kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
13 changes: 12 additions & 1 deletion test/test_initrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions usr/src/bar.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
.text

_start:
li a0, 1
la a1, bar
li a7, 1
la a0, bar
ecall
.Loop:
j .Loop
Expand Down
4 changes: 2 additions & 2 deletions usr/src/foo.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
.text

_start:
li a0, 1
la a1, foo
li a7, 1
la a0, foo
ecall
.Loop:
j .Loop
Expand Down
4 changes: 2 additions & 2 deletions usr/src/foobar.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
.text

_start:
li a0, 1
la a1, foobar
li a7, 1
la a0, foobar
ecall
.Loop:
j .Loop
Expand Down

0 comments on commit 8231af9

Please sign in to comment.