mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
Stage 26
This commit is contained in:
@@ -4,7 +4,7 @@ ENTRY(_start)
|
||||
PHDRS {
|
||||
text PT_LOAD FLAGS(5);
|
||||
rodata PT_LOAD FLAGS(4);
|
||||
data PT_LOAD FLAGS(6);
|
||||
data PT_LOAD FLAGS(7);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
@@ -35,4 +35,4 @@ SECTIONS {
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ ENTRY(_start)
|
||||
PHDRS {
|
||||
text PT_LOAD FLAGS(5);
|
||||
rodata PT_LOAD FLAGS(4);
|
||||
data PT_LOAD FLAGS(6);
|
||||
data PT_LOAD FLAGS(7);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
@@ -39,4 +39,4 @@ SECTIONS {
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ struct clks_elf64_loaded_segment {
|
||||
|
||||
struct clks_elf64_loaded_image {
|
||||
u64 entry;
|
||||
void *image_base;
|
||||
u64 image_size;
|
||||
u64 image_vaddr_base;
|
||||
u16 segment_count;
|
||||
struct clks_elf64_loaded_segment segments[CLKS_ELF64_MAX_SEGMENTS];
|
||||
};
|
||||
@@ -31,5 +34,7 @@ struct clks_elf64_loaded_image {
|
||||
clks_bool clks_elf64_validate(const void *image, u64 size);
|
||||
clks_bool clks_elf64_inspect(const void *image, u64 size, struct clks_elf64_info *out_info);
|
||||
clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_image *out_loaded);
|
||||
void clks_elf64_unload(struct clks_elf64_loaded_image *loaded);
|
||||
void *clks_elf64_entry_pointer(const struct clks_elf64_loaded_image *loaded, u64 entry);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -174,6 +174,11 @@ clks_bool clks_elf64_inspect(const void *image, u64 size, struct clks_elf64_info
|
||||
clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_image *out_loaded) {
|
||||
const struct clks_elf64_ehdr *eh;
|
||||
u16 i;
|
||||
u16 load_count = 0U;
|
||||
u64 min_vaddr = 0ULL;
|
||||
u64 max_vaddr_end = 0ULL;
|
||||
u64 span;
|
||||
void *image_base;
|
||||
|
||||
if (out_loaded == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
@@ -186,31 +191,83 @@ clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_
|
||||
}
|
||||
|
||||
eh = (const struct clks_elf64_ehdr *)image;
|
||||
out_loaded->entry = eh->e_entry;
|
||||
|
||||
for (i = 0; i < eh->e_phnum; i++) {
|
||||
const struct clks_elf64_phdr *ph =
|
||||
(const struct clks_elf64_phdr *)((const u8 *)image + eh->e_phoff + ((u64)i * eh->e_phentsize));
|
||||
void *dst;
|
||||
u64 seg_end;
|
||||
|
||||
if (ph->p_type != CLKS_ELF64_PT_LOAD || ph->p_memsz == 0ULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (load_count == 0U || ph->p_vaddr < min_vaddr) {
|
||||
min_vaddr = ph->p_vaddr;
|
||||
}
|
||||
|
||||
seg_end = ph->p_vaddr + ph->p_memsz;
|
||||
if (seg_end < ph->p_vaddr) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (load_count == 0U || seg_end > max_vaddr_end) {
|
||||
max_vaddr_end = seg_end;
|
||||
}
|
||||
|
||||
load_count++;
|
||||
}
|
||||
|
||||
if (load_count == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (load_count > CLKS_ELF64_MAX_SEGMENTS) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
span = max_vaddr_end - min_vaddr;
|
||||
if (span == 0ULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
image_base = clks_kmalloc((usize)span);
|
||||
if (image_base == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memset(image_base, 0, (usize)span);
|
||||
|
||||
out_loaded->entry = eh->e_entry;
|
||||
out_loaded->image_base = image_base;
|
||||
out_loaded->image_size = span;
|
||||
out_loaded->image_vaddr_base = min_vaddr;
|
||||
out_loaded->segment_count = 0U;
|
||||
|
||||
for (i = 0; i < eh->e_phnum; i++) {
|
||||
const struct clks_elf64_phdr *ph =
|
||||
(const struct clks_elf64_phdr *)((const u8 *)image + eh->e_phoff + ((u64)i * eh->e_phentsize));
|
||||
u64 seg_off;
|
||||
u8 *seg_dst;
|
||||
|
||||
if (ph->p_type != CLKS_ELF64_PT_LOAD || ph->p_memsz == 0ULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (out_loaded->segment_count >= CLKS_ELF64_MAX_SEGMENTS) {
|
||||
clks_elf64_unload(out_loaded);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
dst = clks_kmalloc((usize)ph->p_memsz);
|
||||
|
||||
if (dst == CLKS_NULL) {
|
||||
seg_off = ph->p_vaddr - min_vaddr;
|
||||
if (seg_off > span || ph->p_memsz > (span - seg_off)) {
|
||||
clks_elf64_unload(out_loaded);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memset(dst, 0, (usize)ph->p_memsz);
|
||||
clks_memcpy(dst, (const void *)((const u8 *)image + ph->p_offset), (usize)ph->p_filesz);
|
||||
seg_dst = (u8 *)image_base + (usize)seg_off;
|
||||
clks_memcpy(seg_dst, (const void *)((const u8 *)image + ph->p_offset), (usize)ph->p_filesz);
|
||||
|
||||
out_loaded->segments[out_loaded->segment_count].base = dst;
|
||||
out_loaded->segments[out_loaded->segment_count].base = seg_dst;
|
||||
out_loaded->segments[out_loaded->segment_count].vaddr = ph->p_vaddr;
|
||||
out_loaded->segments[out_loaded->segment_count].memsz = ph->p_memsz;
|
||||
out_loaded->segments[out_loaded->segment_count].filesz = ph->p_filesz;
|
||||
@@ -219,4 +276,36 @@ clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void clks_elf64_unload(struct clks_elf64_loaded_image *loaded) {
|
||||
if (loaded == CLKS_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loaded->image_base != CLKS_NULL) {
|
||||
clks_kfree(loaded->image_base);
|
||||
}
|
||||
|
||||
clks_memset(loaded, 0, sizeof(*loaded));
|
||||
}
|
||||
|
||||
void *clks_elf64_entry_pointer(const struct clks_elf64_loaded_image *loaded, u64 entry) {
|
||||
u64 off;
|
||||
|
||||
if (loaded == CLKS_NULL || loaded->image_base == CLKS_NULL) {
|
||||
return CLKS_NULL;
|
||||
}
|
||||
|
||||
if (entry < loaded->image_vaddr_base) {
|
||||
return CLKS_NULL;
|
||||
}
|
||||
|
||||
off = entry - loaded->image_vaddr_base;
|
||||
|
||||
if (off >= loaded->image_size) {
|
||||
return CLKS_NULL;
|
||||
}
|
||||
|
||||
return (void *)((u8 *)loaded->image_base + (usize)off);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,28 @@
|
||||
#include <clks/exec.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/string.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
typedef u64 (*clks_exec_entry_fn)(void);
|
||||
|
||||
#define CLKS_EXEC_STATUS_UNSUPPORTED 0xFFFFFFFFFFFFFFFEULL
|
||||
|
||||
static u64 clks_exec_requests = 0ULL;
|
||||
static u64 clks_exec_success = 0ULL;
|
||||
|
||||
static clks_bool clks_exec_is_sync_unsupported(const char *path) {
|
||||
if (path == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_strcmp(path, "/shell/shell.elf") == 0) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
void clks_exec_init(void) {
|
||||
clks_exec_requests = 0ULL;
|
||||
clks_exec_success = 0ULL;
|
||||
@@ -17,6 +34,9 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
|
||||
const void *image;
|
||||
u64 image_size = 0ULL;
|
||||
struct clks_elf64_info info;
|
||||
struct clks_elf64_loaded_image loaded;
|
||||
void *entry_ptr;
|
||||
u64 run_ret;
|
||||
|
||||
clks_exec_requests++;
|
||||
|
||||
@@ -29,6 +49,17 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_exec_is_sync_unsupported(path) == CLKS_TRUE) {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "SYNC EXEC UNSUPPORTED FOR INTERACTIVE ELF");
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", path);
|
||||
|
||||
if (out_status != CLKS_NULL) {
|
||||
*out_status = CLKS_EXEC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
image = clks_fs_read_all(path, &image_size);
|
||||
|
||||
if (image == CLKS_NULL || image_size == 0ULL) {
|
||||
@@ -43,17 +74,38 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_exec_success++;
|
||||
|
||||
if (out_status != CLKS_NULL) {
|
||||
*out_status = 0ULL;
|
||||
if (clks_elf64_load(image, image_size, &loaded) == CLKS_FALSE) {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF LOAD FAILED");
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", path);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "EXEC REQUEST ACCEPTED");
|
||||
entry_ptr = clks_elf64_entry_pointer(&loaded, info.entry);
|
||||
if (entry_ptr == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "ENTRY POINTER RESOLVE FAILED");
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", path);
|
||||
clks_elf64_unload(&loaded);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "EXEC RUN START");
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", path);
|
||||
clks_log_hex(CLKS_LOG_INFO, "EXEC", "ENTRY", info.entry);
|
||||
clks_log_hex(CLKS_LOG_INFO, "EXEC", "PHNUM", (u64)info.phnum);
|
||||
|
||||
run_ret = ((clks_exec_entry_fn)entry_ptr)();
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "RUN RETURNED");
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", path);
|
||||
clks_log_hex(CLKS_LOG_INFO, "EXEC", "RET", run_ret);
|
||||
|
||||
clks_exec_success++;
|
||||
|
||||
if (out_status != CLKS_NULL) {
|
||||
*out_status = run_ret;
|
||||
}
|
||||
|
||||
clks_elf64_unload(&loaded);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
@@ -63,4 +115,4 @@ u64 clks_exec_request_count(void) {
|
||||
|
||||
u64 clks_exec_success_count(void) {
|
||||
return clks_exec_success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <clks/exec.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/elf64.h>
|
||||
#include <clks/heap.h>
|
||||
#include <clks/keyboard.h>
|
||||
#include <clks/log.h>
|
||||
@@ -699,6 +700,7 @@ static clks_bool clks_shell_cmd_help(void) {
|
||||
clks_shell_writeln(" rusttest");
|
||||
clks_shell_writeln(" panic");
|
||||
clks_shell_writeln(" exec <path|name>");
|
||||
clks_shell_writeln(" elfloader [path] (kernel builtin, default /hello.elf)");
|
||||
clks_shell_writeln(" clear");
|
||||
clks_shell_writeln(" kbdstat");
|
||||
clks_shell_writeln("edit keys: Left/Right, Home/End, Up/Down history");
|
||||
@@ -1057,6 +1059,55 @@ static clks_bool clks_shell_cmd_rm(const char *arg) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_cmd_elfloader(const char *arg) {
|
||||
const char *target = arg;
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
const void *image;
|
||||
u64 size = 0ULL;
|
||||
struct clks_elf64_info info;
|
||||
u64 status = (u64)-1;
|
||||
|
||||
if (target == CLKS_NULL || target[0] == '\0') {
|
||||
target = "/hello.elf";
|
||||
}
|
||||
|
||||
if (target[0] == '/') {
|
||||
clks_shell_copy_line(path, sizeof(path), target);
|
||||
} else if (clks_shell_resolve_path(target, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("elfloader: invalid path");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
image = clks_fs_read_all(path, &size);
|
||||
|
||||
if (image == CLKS_NULL || size == 0ULL) {
|
||||
clks_shell_writeln("elfloader: file missing");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_elf64_inspect(image, size, &info) == CLKS_FALSE) {
|
||||
clks_shell_writeln("elfloader: invalid elf64");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_shell_writeln("elfloader: kernel builtin");
|
||||
clks_shell_write(" PATH: ");
|
||||
clks_shell_writeln(path);
|
||||
clks_shell_print_kv_hex(" ELF_SIZE", size);
|
||||
clks_shell_print_kv_hex(" ENTRY", info.entry);
|
||||
clks_shell_print_kv_hex(" PHNUM", (u64)info.phnum);
|
||||
clks_shell_print_kv_hex(" LOAD_SEGMENTS", (u64)info.loadable_segments);
|
||||
clks_shell_print_kv_hex(" TOTAL_MEMSZ", info.total_load_memsz);
|
||||
|
||||
if (clks_exec_run_path(path, &status) == CLKS_TRUE && status == 0ULL) {
|
||||
clks_shell_writeln("elfloader: exec accepted");
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
clks_shell_writeln("elfloader: exec failed");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_cmd_exec(const char *arg) {
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
u64 status = (u64)-1;
|
||||
@@ -1280,6 +1331,8 @@ static void clks_shell_execute_line(const char *line) {
|
||||
success = clks_shell_cmd_rusttest();
|
||||
} else if (clks_shell_streq(cmd, "panic") == CLKS_TRUE) {
|
||||
success = clks_shell_cmd_panic();
|
||||
} else if (clks_shell_streq(cmd, "elfloader") == CLKS_TRUE) {
|
||||
success = clks_shell_cmd_elfloader(arg);
|
||||
} else if (clks_shell_streq(cmd, "exec") == CLKS_TRUE || clks_shell_streq(cmd, "run") == CLKS_TRUE) {
|
||||
success = clks_shell_cmd_exec(arg);
|
||||
} else if (clks_shell_streq(cmd, "clear") == CLKS_TRUE) {
|
||||
@@ -1486,4 +1539,5 @@ void clks_shell_pump_input(u32 max_chars) {
|
||||
void clks_shell_tick(u64 tick) {
|
||||
(void)tick;
|
||||
clks_shell_drain_input(CLKS_SHELL_INPUT_BUDGET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user