mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Stage 26
This commit is contained in:
@@ -345,6 +345,7 @@ set(USER_APP_NAMES)
|
|||||||
set(RAMDISK_SHELL_APPS)
|
set(RAMDISK_SHELL_APPS)
|
||||||
set(RAMDISK_DRIVER_APPS)
|
set(RAMDISK_DRIVER_APPS)
|
||||||
set(RAMDISK_SYSTEM_APPS)
|
set(RAMDISK_SYSTEM_APPS)
|
||||||
|
set(RAMDISK_ROOT_APPS)
|
||||||
|
|
||||||
foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
|
foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
|
||||||
get_filename_component(_stem "${SRC}" NAME_WE)
|
get_filename_component(_stem "${SRC}" NAME_WE)
|
||||||
@@ -375,6 +376,8 @@ foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
|
|||||||
list(APPEND USER_APP_OUTPUTS "${_app_out}")
|
list(APPEND USER_APP_OUTPUTS "${_app_out}")
|
||||||
if(_app_name MATCHES ".*drv$")
|
if(_app_name MATCHES ".*drv$")
|
||||||
list(APPEND RAMDISK_DRIVER_APPS "${_app_out}")
|
list(APPEND RAMDISK_DRIVER_APPS "${_app_out}")
|
||||||
|
elseif(_app_name STREQUAL "hello")
|
||||||
|
list(APPEND RAMDISK_ROOT_APPS "${_app_out}")
|
||||||
else()
|
else()
|
||||||
list(APPEND RAMDISK_SHELL_APPS "${_app_out}")
|
list(APPEND RAMDISK_SHELL_APPS "${_app_out}")
|
||||||
endif()
|
endif()
|
||||||
@@ -427,6 +430,10 @@ foreach(_app IN LISTS RAMDISK_SHELL_APPS)
|
|||||||
get_filename_component(_app_file "${_app}" NAME)
|
get_filename_component(_app_file "${_app}" NAME)
|
||||||
list(APPEND RAMDISK_COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy "${_app}" "${RAMDISK_ROOT}/shell/${_app_file}")
|
list(APPEND RAMDISK_COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy "${_app}" "${RAMDISK_ROOT}/shell/${_app_file}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
foreach(_app IN LISTS RAMDISK_ROOT_APPS)
|
||||||
|
get_filename_component(_app_file "${_app}" NAME)
|
||||||
|
list(APPEND RAMDISK_COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy "${_app}" "${RAMDISK_ROOT}/${_app_file}")
|
||||||
|
endforeach()
|
||||||
foreach(_app IN LISTS RAMDISK_DRIVER_APPS)
|
foreach(_app IN LISTS RAMDISK_DRIVER_APPS)
|
||||||
get_filename_component(_app_file "${_app}" NAME)
|
get_filename_component(_app_file "${_app}" NAME)
|
||||||
list(APPEND RAMDISK_COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy "${_app}" "${RAMDISK_ROOT}/driver/${_app_file}")
|
list(APPEND RAMDISK_COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy "${_app}" "${RAMDISK_ROOT}/driver/${_app_file}")
|
||||||
@@ -616,3 +623,4 @@ add_custom_target(cleonos-help
|
|||||||
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target run"
|
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target run"
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target debug"
|
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target debug"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
7
cleonos/c/apps/hello_main.c
Normal file
7
cleonos/c/apps/hello_main.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <cleonos_syscall.h>
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
static const char msg[] = "[USER][HELLO] Hello world from /hello.elf\n";
|
||||||
|
(void)cleonos_sys_tty_write(msg, (u64)(sizeof(msg) - 1U));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -4,13 +4,9 @@ typedef int (*cleonos_entry_fn)(void);
|
|||||||
|
|
||||||
extern int cleonos_app_main(void);
|
extern int cleonos_app_main(void);
|
||||||
|
|
||||||
void _start(void) {
|
u64 _start(void) {
|
||||||
volatile int code;
|
int code;
|
||||||
|
|
||||||
code = ((cleonos_entry_fn)cleonos_app_main)();
|
code = ((cleonos_entry_fn)cleonos_app_main)();
|
||||||
(void)code;
|
return (u64)code;
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
__asm__ volatile("pause");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ ENTRY(_start)
|
|||||||
PHDRS {
|
PHDRS {
|
||||||
text PT_LOAD FLAGS(5);
|
text PT_LOAD FLAGS(5);
|
||||||
rodata PT_LOAD FLAGS(4);
|
rodata PT_LOAD FLAGS(4);
|
||||||
data PT_LOAD FLAGS(6);
|
data PT_LOAD FLAGS(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
@@ -35,4 +35,4 @@ SECTIONS {
|
|||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ ENTRY(_start)
|
|||||||
PHDRS {
|
PHDRS {
|
||||||
text PT_LOAD FLAGS(5);
|
text PT_LOAD FLAGS(5);
|
||||||
rodata PT_LOAD FLAGS(4);
|
rodata PT_LOAD FLAGS(4);
|
||||||
data PT_LOAD FLAGS(6);
|
data PT_LOAD FLAGS(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
@@ -39,4 +39,4 @@ SECTIONS {
|
|||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ struct clks_elf64_loaded_segment {
|
|||||||
|
|
||||||
struct clks_elf64_loaded_image {
|
struct clks_elf64_loaded_image {
|
||||||
u64 entry;
|
u64 entry;
|
||||||
|
void *image_base;
|
||||||
|
u64 image_size;
|
||||||
|
u64 image_vaddr_base;
|
||||||
u16 segment_count;
|
u16 segment_count;
|
||||||
struct clks_elf64_loaded_segment segments[CLKS_ELF64_MAX_SEGMENTS];
|
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_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_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);
|
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) {
|
clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_image *out_loaded) {
|
||||||
const struct clks_elf64_ehdr *eh;
|
const struct clks_elf64_ehdr *eh;
|
||||||
u16 i;
|
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) {
|
if (out_loaded == CLKS_NULL) {
|
||||||
return CLKS_FALSE;
|
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;
|
eh = (const struct clks_elf64_ehdr *)image;
|
||||||
out_loaded->entry = eh->e_entry;
|
|
||||||
|
|
||||||
for (i = 0; i < eh->e_phnum; i++) {
|
for (i = 0; i < eh->e_phnum; i++) {
|
||||||
const struct clks_elf64_phdr *ph =
|
const struct clks_elf64_phdr *ph =
|
||||||
(const struct clks_elf64_phdr *)((const u8 *)image + eh->e_phoff + ((u64)i * eh->e_phentsize));
|
(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) {
|
if (ph->p_type != CLKS_ELF64_PT_LOAD || ph->p_memsz == 0ULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_loaded->segment_count >= CLKS_ELF64_MAX_SEGMENTS) {
|
if (out_loaded->segment_count >= CLKS_ELF64_MAX_SEGMENTS) {
|
||||||
|
clks_elf64_unload(out_loaded);
|
||||||
return CLKS_FALSE;
|
return CLKS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst = clks_kmalloc((usize)ph->p_memsz);
|
seg_off = ph->p_vaddr - min_vaddr;
|
||||||
|
if (seg_off > span || ph->p_memsz > (span - seg_off)) {
|
||||||
if (dst == CLKS_NULL) {
|
clks_elf64_unload(out_loaded);
|
||||||
return CLKS_FALSE;
|
return CLKS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_memset(dst, 0, (usize)ph->p_memsz);
|
seg_dst = (u8 *)image_base + (usize)seg_off;
|
||||||
clks_memcpy(dst, (const void *)((const u8 *)image + ph->p_offset), (usize)ph->p_filesz);
|
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].vaddr = ph->p_vaddr;
|
||||||
out_loaded->segments[out_loaded->segment_count].memsz = ph->p_memsz;
|
out_loaded->segments[out_loaded->segment_count].memsz = ph->p_memsz;
|
||||||
out_loaded->segments[out_loaded->segment_count].filesz = ph->p_filesz;
|
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;
|
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/exec.h>
|
||||||
#include <clks/fs.h>
|
#include <clks/fs.h>
|
||||||
#include <clks/log.h>
|
#include <clks/log.h>
|
||||||
|
#include <clks/string.h>
|
||||||
#include <clks/types.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_requests = 0ULL;
|
||||||
static u64 clks_exec_success = 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) {
|
void clks_exec_init(void) {
|
||||||
clks_exec_requests = 0ULL;
|
clks_exec_requests = 0ULL;
|
||||||
clks_exec_success = 0ULL;
|
clks_exec_success = 0ULL;
|
||||||
@@ -17,6 +34,9 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
|
|||||||
const void *image;
|
const void *image;
|
||||||
u64 image_size = 0ULL;
|
u64 image_size = 0ULL;
|
||||||
struct clks_elf64_info info;
|
struct clks_elf64_info info;
|
||||||
|
struct clks_elf64_loaded_image loaded;
|
||||||
|
void *entry_ptr;
|
||||||
|
u64 run_ret;
|
||||||
|
|
||||||
clks_exec_requests++;
|
clks_exec_requests++;
|
||||||
|
|
||||||
@@ -29,6 +49,17 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
|
|||||||
return CLKS_FALSE;
|
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);
|
image = clks_fs_read_all(path, &image_size);
|
||||||
|
|
||||||
if (image == CLKS_NULL || image_size == 0ULL) {
|
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;
|
return CLKS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_exec_success++;
|
if (clks_elf64_load(image, image_size, &loaded) == CLKS_FALSE) {
|
||||||
|
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF LOAD FAILED");
|
||||||
if (out_status != CLKS_NULL) {
|
clks_log(CLKS_LOG_WARN, "EXEC", path);
|
||||||
*out_status = 0ULL;
|
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(CLKS_LOG_INFO, "EXEC", path);
|
||||||
clks_log_hex(CLKS_LOG_INFO, "EXEC", "ENTRY", info.entry);
|
clks_log_hex(CLKS_LOG_INFO, "EXEC", "ENTRY", info.entry);
|
||||||
clks_log_hex(CLKS_LOG_INFO, "EXEC", "PHNUM", (u64)info.phnum);
|
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;
|
return CLKS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,4 +115,4 @@ u64 clks_exec_request_count(void) {
|
|||||||
|
|
||||||
u64 clks_exec_success_count(void) {
|
u64 clks_exec_success_count(void) {
|
||||||
return clks_exec_success;
|
return clks_exec_success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <clks/exec.h>
|
#include <clks/exec.h>
|
||||||
#include <clks/fs.h>
|
#include <clks/fs.h>
|
||||||
|
#include <clks/elf64.h>
|
||||||
#include <clks/heap.h>
|
#include <clks/heap.h>
|
||||||
#include <clks/keyboard.h>
|
#include <clks/keyboard.h>
|
||||||
#include <clks/log.h>
|
#include <clks/log.h>
|
||||||
@@ -699,6 +700,7 @@ static clks_bool clks_shell_cmd_help(void) {
|
|||||||
clks_shell_writeln(" rusttest");
|
clks_shell_writeln(" rusttest");
|
||||||
clks_shell_writeln(" panic");
|
clks_shell_writeln(" panic");
|
||||||
clks_shell_writeln(" exec <path|name>");
|
clks_shell_writeln(" exec <path|name>");
|
||||||
|
clks_shell_writeln(" elfloader [path] (kernel builtin, default /hello.elf)");
|
||||||
clks_shell_writeln(" clear");
|
clks_shell_writeln(" clear");
|
||||||
clks_shell_writeln(" kbdstat");
|
clks_shell_writeln(" kbdstat");
|
||||||
clks_shell_writeln("edit keys: Left/Right, Home/End, Up/Down history");
|
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;
|
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) {
|
static clks_bool clks_shell_cmd_exec(const char *arg) {
|
||||||
char path[CLKS_SHELL_PATH_MAX];
|
char path[CLKS_SHELL_PATH_MAX];
|
||||||
u64 status = (u64)-1;
|
u64 status = (u64)-1;
|
||||||
@@ -1280,6 +1331,8 @@ static void clks_shell_execute_line(const char *line) {
|
|||||||
success = clks_shell_cmd_rusttest();
|
success = clks_shell_cmd_rusttest();
|
||||||
} else if (clks_shell_streq(cmd, "panic") == CLKS_TRUE) {
|
} else if (clks_shell_streq(cmd, "panic") == CLKS_TRUE) {
|
||||||
success = clks_shell_cmd_panic();
|
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) {
|
} else if (clks_shell_streq(cmd, "exec") == CLKS_TRUE || clks_shell_streq(cmd, "run") == CLKS_TRUE) {
|
||||||
success = clks_shell_cmd_exec(arg);
|
success = clks_shell_cmd_exec(arg);
|
||||||
} else if (clks_shell_streq(cmd, "clear") == CLKS_TRUE) {
|
} 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 clks_shell_tick(u64 tick) {
|
||||||
(void)tick;
|
(void)tick;
|
||||||
clks_shell_drain_input(CLKS_SHELL_INPUT_BUDGET);
|
clks_shell_drain_input(CLKS_SHELL_INPUT_BUDGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
- `stage23.md`
|
- `stage23.md`
|
||||||
- `stage24.md`
|
- `stage24.md`
|
||||||
- `stage25.md`
|
- `stage25.md`
|
||||||
|
- `stage26.md`
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
- Stage docs use a fixed template: goal, implementation, acceptance criteria, build targets, QEMU command, and debugging notes.
|
- Stage docs use a fixed template: goal, implementation, acceptance criteria, build targets, QEMU command, and debugging notes.
|
||||||
|
|||||||
37
docs/stage26.md
Normal file
37
docs/stage26.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Stage 26 - Kernel Builtin ELF Loader + Root Hello ELF
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
- Move `elfloader` from standalone user ELF into a kernel builtin command.
|
||||||
|
- Keep `hello.elf` as root-level user ELF test payload.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
- Removed standalone user app `elfloader_main.c`.
|
||||||
|
- Added kernel shell builtin command: `elfloader [path]`.
|
||||||
|
- Default target path: `/hello.elf`.
|
||||||
|
- Builtin flow: `fs_read -> elf64 inspect -> exec load -> entry call -> return status`.
|
||||||
|
- Updated CMake ramdisk placement rules:
|
||||||
|
- `hello.elf` -> `/hello.elf`
|
||||||
|
- Simplified user Rust library back to shared helper export (`cleonos_rust_guarded_len`).
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- No `elfloader.elf` is generated or packed.
|
||||||
|
- Ramdisk root contains `/hello.elf`.
|
||||||
|
- In kernel shell:
|
||||||
|
- `elfloader` loads and executes `/hello.elf`, then returns status.
|
||||||
|
- `elfloader /path/to/app.elf` works for other absolute/relative paths.
|
||||||
|
|
||||||
|
## Build Targets
|
||||||
|
- `make userapps`
|
||||||
|
- `make ramdisk`
|
||||||
|
- `make iso`
|
||||||
|
- `make run`
|
||||||
|
|
||||||
|
## QEMU Command
|
||||||
|
- `make run`
|
||||||
|
|
||||||
|
## Debug Notes
|
||||||
|
- If `elfloader` reports `file missing`, check ramdisk root packaging for `/hello.elf`.
|
||||||
|
- If it reports `invalid elf64`, verify user app link script and ELF output format.
|
||||||
|
- If it reports `exec failed`, inspect `EXEC` channel logs for load/entry/return status.
|
||||||
|
- `hello.elf` is supported in current synchronous exec mode.
|
||||||
|
- `/shell/shell.elf` is intentionally blocked in synchronous mode (interactive loop requires process/task context switching stage).
|
||||||
@@ -3,4 +3,7 @@ CLeonOS ramdisk root layout
|
|||||||
/system : kernel-mode ELF apps and core system components
|
/system : kernel-mode ELF apps and core system components
|
||||||
/shell : user shell and command ELF apps
|
/shell : user shell and command ELF apps
|
||||||
/temp : runtime temp/cache files
|
/temp : runtime temp/cache files
|
||||||
/driver : hardware and peripheral drivers
|
/driver : hardware and peripheral drivers
|
||||||
|
|
||||||
|
Root ELF demos:
|
||||||
|
/hello.elf : Hello world user ELF
|
||||||
|
|||||||
Reference in New Issue
Block a user