This commit is contained in:
2026-04-12 19:31:01 +08:00
parent 138c685de1
commit aa8c0bd8d1
13 changed files with 2188 additions and 29 deletions

View File

@@ -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.*)
}
}
}

View File

@@ -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.*)
}
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}