mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
Stage 11
This commit is contained in:
1
Makefile
1
Makefile
@@ -96,6 +96,7 @@ C_SOURCES := \
|
||||
clks/kernel/driver.c \
|
||||
clks/kernel/service.c \
|
||||
clks/kernel/kelf.c \
|
||||
clks/kernel/exec.c \
|
||||
clks/lib/string.c \
|
||||
clks/drivers/serial/serial.c \
|
||||
clks/drivers/video/framebuffer.c \
|
||||
|
||||
@@ -1,13 +1,262 @@
|
||||
#include <cleonos_rust_bridge.h>
|
||||
#include <cleonos_syscall.h>
|
||||
|
||||
static const char shell_banner[] = "[USER][SHELL] shell.elf online";
|
||||
static const char shell_status[] = "[USER][SHELL] syscall int80 path ok";
|
||||
#define SHELL_CMD_MAX 24ULL
|
||||
#define SHELL_ARG_MAX 128ULL
|
||||
#define SHELL_LINE_MAX 256ULL
|
||||
#define SHELL_CAT_MAX 224ULL
|
||||
|
||||
static int shell_streq(const char *left, const char *right) {
|
||||
u64 i = 0ULL;
|
||||
|
||||
if (left == (const char *)0 || right == (const char *)0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (left[i] != '\0' && right[i] != '\0') {
|
||||
if (left[i] != right[i]) {
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return (left[i] == right[i]) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int shell_is_space(char ch) {
|
||||
return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ? 1 : 0;
|
||||
}
|
||||
|
||||
static void shell_append_char(char *dst, u64 *cursor, u64 dst_size, char ch) {
|
||||
if (*cursor + 1ULL >= dst_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
dst[*cursor] = ch;
|
||||
(*cursor)++;
|
||||
}
|
||||
|
||||
static void shell_append_text(char *dst, u64 *cursor, u64 dst_size, const char *text) {
|
||||
u64 i = 0ULL;
|
||||
|
||||
if (text == (const char *)0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (text[i] != '\0') {
|
||||
shell_append_char(dst, cursor, dst_size, text[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void shell_append_hex_u64(char *dst, u64 *cursor, u64 dst_size, u64 value) {
|
||||
int nibble;
|
||||
|
||||
shell_append_text(dst, cursor, dst_size, "0X");
|
||||
|
||||
for (nibble = 15; nibble >= 0; nibble--) {
|
||||
u64 shift = (u64)nibble * 4ULL;
|
||||
u64 current = (value >> shift) & 0x0FULL;
|
||||
char out = (current < 10ULL) ? (char)('0' + (char)current) : (char)('A' + (char)(current - 10ULL));
|
||||
shell_append_char(dst, cursor, dst_size, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void shell_log_text(const char *text) {
|
||||
u64 len = cleonos_rust_guarded_len((const unsigned char *)text, (usize)511U);
|
||||
cleonos_sys_log_write(text, len);
|
||||
}
|
||||
|
||||
static void shell_log_prefixed(const char *prefix, const char *value) {
|
||||
char line[SHELL_LINE_MAX];
|
||||
u64 cursor = 0ULL;
|
||||
|
||||
shell_append_text(line, &cursor, (u64)sizeof(line), prefix);
|
||||
shell_append_text(line, &cursor, (u64)sizeof(line), value);
|
||||
line[cursor] = '\0';
|
||||
|
||||
shell_log_text(line);
|
||||
}
|
||||
|
||||
static void shell_log_hex_prefixed(const char *prefix, u64 value) {
|
||||
char line[SHELL_LINE_MAX];
|
||||
u64 cursor = 0ULL;
|
||||
|
||||
shell_append_text(line, &cursor, (u64)sizeof(line), prefix);
|
||||
shell_append_hex_u64(line, &cursor, (u64)sizeof(line), value);
|
||||
line[cursor] = '\0';
|
||||
|
||||
shell_log_text(line);
|
||||
}
|
||||
|
||||
static void shell_parse_line(const char *line, char *out_cmd, u64 cmd_size, char *out_arg, u64 arg_size) {
|
||||
u64 i = 0ULL;
|
||||
u64 cmd_pos = 0ULL;
|
||||
u64 arg_pos = 0ULL;
|
||||
|
||||
if (line == (const char *)0 || out_cmd == (char *)0 || out_arg == (char *)0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (line[i] != '\0' && shell_is_space(line[i]) != 0) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while (line[i] != '\0' && shell_is_space(line[i]) == 0) {
|
||||
if (cmd_pos + 1ULL < cmd_size) {
|
||||
out_cmd[cmd_pos++] = line[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
out_cmd[cmd_pos] = '\0';
|
||||
|
||||
while (line[i] != '\0' && shell_is_space(line[i]) != 0) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while (line[i] != '\0') {
|
||||
if (arg_pos + 1ULL < arg_size) {
|
||||
out_arg[arg_pos++] = line[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
out_arg[arg_pos] = '\0';
|
||||
}
|
||||
|
||||
static void shell_cmd_help(void) {
|
||||
shell_log_text("[USER][SHELL] commands: help ls <dir> cat <file> run <elf>");
|
||||
}
|
||||
|
||||
static void shell_cmd_ls(const char *arg) {
|
||||
const char *path = arg;
|
||||
u64 count;
|
||||
u64 i;
|
||||
|
||||
if (path == (const char *)0 || path[0] == '\0') {
|
||||
path = "/";
|
||||
}
|
||||
|
||||
count = cleonos_sys_fs_child_count(path);
|
||||
|
||||
if (count == (u64)-1) {
|
||||
shell_log_text("[USER][SHELL] ls failed");
|
||||
return;
|
||||
}
|
||||
|
||||
shell_log_prefixed("[USER][SHELL] ls ", path);
|
||||
shell_log_hex_prefixed("[USER][SHELL] ls count: ", count);
|
||||
|
||||
for (i = 0ULL; i < count; i++) {
|
||||
char name[96];
|
||||
|
||||
name[0] = '\0';
|
||||
|
||||
if (cleonos_sys_fs_get_child_name(path, i, name) == 0ULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
shell_log_prefixed("[USER][SHELL] - ", name);
|
||||
}
|
||||
}
|
||||
|
||||
static void shell_cmd_cat(const char *arg) {
|
||||
char cat_buf[SHELL_CAT_MAX + 1ULL];
|
||||
u64 got;
|
||||
|
||||
if (arg == (const char *)0 || arg[0] == '\0') {
|
||||
shell_log_text("[USER][SHELL] cat requires path");
|
||||
return;
|
||||
}
|
||||
|
||||
got = cleonos_sys_fs_read(arg, cat_buf, SHELL_CAT_MAX);
|
||||
|
||||
if (got == 0ULL) {
|
||||
shell_log_text("[USER][SHELL] cat failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (got > SHELL_CAT_MAX) {
|
||||
got = SHELL_CAT_MAX;
|
||||
}
|
||||
|
||||
cat_buf[got] = '\0';
|
||||
|
||||
shell_log_prefixed("[USER][SHELL] cat ", arg);
|
||||
shell_log_text(cat_buf);
|
||||
}
|
||||
|
||||
static void shell_cmd_run(const char *arg) {
|
||||
u64 status;
|
||||
|
||||
if (arg == (const char *)0 || arg[0] == '\0') {
|
||||
shell_log_text("[USER][SHELL] run requires path");
|
||||
return;
|
||||
}
|
||||
|
||||
status = cleonos_sys_exec_path(arg);
|
||||
|
||||
if (status == 0ULL) {
|
||||
shell_log_prefixed("[USER][SHELL] run ok ", arg);
|
||||
} else {
|
||||
shell_log_prefixed("[USER][SHELL] run failed ", arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void shell_execute_line(const char *line) {
|
||||
char cmd[SHELL_CMD_MAX];
|
||||
char arg[SHELL_ARG_MAX];
|
||||
|
||||
cmd[0] = '\0';
|
||||
arg[0] = '\0';
|
||||
|
||||
shell_log_prefixed("[USER][SHELL]$ ", line);
|
||||
shell_parse_line(line, cmd, (u64)sizeof(cmd), arg, (u64)sizeof(arg));
|
||||
|
||||
if (shell_streq(cmd, "help") != 0) {
|
||||
shell_cmd_help();
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell_streq(cmd, "ls") != 0) {
|
||||
shell_cmd_ls(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell_streq(cmd, "cat") != 0) {
|
||||
shell_cmd_cat(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell_streq(cmd, "run") != 0) {
|
||||
shell_cmd_run(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
shell_log_prefixed("[USER][SHELL] unknown command: ", cmd);
|
||||
}
|
||||
|
||||
int cleonos_app_main(void) {
|
||||
u64 len = cleonos_rust_guarded_len((const unsigned char *)shell_banner, (usize)(sizeof(shell_banner) - 1U));
|
||||
static const char *script[] = {
|
||||
"help",
|
||||
"ls /",
|
||||
"ls /system",
|
||||
"cat /README.txt",
|
||||
"run /system/elfrunner.elf",
|
||||
"run /system/memc.elf"
|
||||
};
|
||||
u64 i;
|
||||
|
||||
cleonos_sys_log_write(shell_banner, len);
|
||||
cleonos_sys_log_write(shell_status, (u64)(sizeof(shell_status) - 1U));
|
||||
shell_log_text("[USER][SHELL] shell.elf command framework online");
|
||||
shell_log_hex_prefixed("[USER][SHELL] fs nodes: ", cleonos_sys_fs_node_count());
|
||||
shell_log_hex_prefixed("[USER][SHELL] task count: ", cleonos_sys_task_count());
|
||||
|
||||
for (i = 0ULL; i < (u64)(sizeof(script) / sizeof(script[0])); i++) {
|
||||
shell_execute_line(script[i]);
|
||||
}
|
||||
|
||||
shell_log_hex_prefixed("[USER][SHELL] exec requests: ", cleonos_sys_exec_request_count());
|
||||
shell_log_hex_prefixed("[USER][SHELL] exec success: ", cleonos_sys_exec_success_count());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
typedef unsigned long long u64;
|
||||
typedef unsigned long long usize;
|
||||
|
||||
#define CLEONOS_FS_NAME_MAX 96ULL
|
||||
|
||||
#define CLEONOS_SYSCALL_LOG_WRITE 0ULL
|
||||
#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL
|
||||
#define CLEONOS_SYSCALL_TASK_COUNT 2ULL
|
||||
@@ -13,9 +15,24 @@ typedef unsigned long long usize;
|
||||
#define CLEONOS_SYSCALL_CONTEXT_SWITCHES 6ULL
|
||||
#define CLEONOS_SYSCALL_KELF_COUNT 7ULL
|
||||
#define CLEONOS_SYSCALL_KELF_RUNS 8ULL
|
||||
#define CLEONOS_SYSCALL_FS_NODE_COUNT 9ULL
|
||||
#define CLEONOS_SYSCALL_FS_CHILD_COUNT 10ULL
|
||||
#define CLEONOS_SYSCALL_FS_GET_CHILD_NAME 11ULL
|
||||
#define CLEONOS_SYSCALL_FS_READ 12ULL
|
||||
#define CLEONOS_SYSCALL_EXEC_PATH 13ULL
|
||||
#define CLEONOS_SYSCALL_EXEC_REQUESTS 14ULL
|
||||
#define CLEONOS_SYSCALL_EXEC_SUCCESS 15ULL
|
||||
|
||||
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||
u64 cleonos_sys_log_write(const char *message, u64 length);
|
||||
u64 cleonos_sys_timer_ticks(void);
|
||||
u64 cleonos_sys_task_count(void);
|
||||
u64 cleonos_sys_fs_node_count(void);
|
||||
u64 cleonos_sys_fs_child_count(const char *dir_path);
|
||||
u64 cleonos_sys_fs_get_child_name(const char *dir_path, u64 index, char *out_name);
|
||||
u64 cleonos_sys_fs_read(const char *path, char *out_buffer, u64 buffer_size);
|
||||
u64 cleonos_sys_exec_path(const char *path);
|
||||
u64 cleonos_sys_exec_request_count(void);
|
||||
u64 cleonos_sys_exec_success_count(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -20,3 +20,35 @@ u64 cleonos_sys_log_write(const char *message, u64 length) {
|
||||
u64 cleonos_sys_timer_ticks(void) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_task_count(void) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_TASK_COUNT, 0ULL, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_fs_node_count(void) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_FS_NODE_COUNT, 0ULL, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_fs_child_count(const char *dir_path) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_FS_CHILD_COUNT, (u64)dir_path, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_fs_get_child_name(const char *dir_path, u64 index, char *out_name) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_FS_GET_CHILD_NAME, (u64)dir_path, index, (u64)out_name);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_fs_read(const char *path, char *out_buffer, u64 buffer_size) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_FS_READ, (u64)path, (u64)out_buffer, buffer_size);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_exec_path(const char *path) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_EXEC_PATH, (u64)path, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_exec_request_count(void) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_EXEC_REQUESTS, 0ULL, 0ULL, 0ULL);
|
||||
}
|
||||
|
||||
u64 cleonos_sys_exec_success_count(void) {
|
||||
return cleonos_syscall(CLEONOS_SYSCALL_EXEC_SUCCESS, 0ULL, 0ULL, 0ULL);
|
||||
}
|
||||
11
clks/include/clks/exec.h
Normal file
11
clks/include/clks/exec.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef CLKS_EXEC_H
|
||||
#define CLKS_EXEC_H
|
||||
|
||||
#include <clks/types.h>
|
||||
|
||||
void clks_exec_init(void);
|
||||
clks_bool clks_exec_run_path(const char *path, u64 *out_status);
|
||||
u64 clks_exec_request_count(void);
|
||||
u64 clks_exec_success_count(void);
|
||||
|
||||
#endif
|
||||
@@ -12,9 +12,16 @@
|
||||
#define CLKS_SYSCALL_CONTEXT_SWITCHES 6ULL
|
||||
#define CLKS_SYSCALL_KELF_COUNT 7ULL
|
||||
#define CLKS_SYSCALL_KELF_RUNS 8ULL
|
||||
#define CLKS_SYSCALL_FS_NODE_COUNT 9ULL
|
||||
#define CLKS_SYSCALL_FS_CHILD_COUNT 10ULL
|
||||
#define CLKS_SYSCALL_FS_GET_CHILD_NAME 11ULL
|
||||
#define CLKS_SYSCALL_FS_READ 12ULL
|
||||
#define CLKS_SYSCALL_EXEC_PATH 13ULL
|
||||
#define CLKS_SYSCALL_EXEC_REQUESTS 14ULL
|
||||
#define CLKS_SYSCALL_EXEC_SUCCESS 15ULL
|
||||
|
||||
void clks_syscall_init(void);
|
||||
u64 clks_syscall_dispatch(void *frame_ptr);
|
||||
u64 clks_syscall_invoke_kernel(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
66
clks/kernel/exec.c
Normal file
66
clks/kernel/exec.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <clks/elf64.h>
|
||||
#include <clks/exec.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
static u64 clks_exec_requests = 0ULL;
|
||||
static u64 clks_exec_success = 0ULL;
|
||||
|
||||
void clks_exec_init(void) {
|
||||
clks_exec_requests = 0ULL;
|
||||
clks_exec_success = 0ULL;
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "PATH EXEC FRAMEWORK ONLINE");
|
||||
}
|
||||
|
||||
clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
|
||||
const void *image;
|
||||
u64 image_size = 0ULL;
|
||||
struct clks_elf64_info info;
|
||||
|
||||
clks_exec_requests++;
|
||||
|
||||
if (out_status != CLKS_NULL) {
|
||||
*out_status = (u64)-1;
|
||||
}
|
||||
|
||||
if (path == CLKS_NULL || path[0] != '/') {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "INVALID EXEC PATH");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
image = clks_fs_read_all(path, &image_size);
|
||||
|
||||
if (image == CLKS_NULL || image_size == 0ULL) {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC FILE MISSING");
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", path);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_elf64_inspect(image, image_size, &info) == CLKS_FALSE) {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF INVALID");
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", path);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_exec_success++;
|
||||
|
||||
if (out_status != CLKS_NULL) {
|
||||
*out_status = 0ULL;
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "EXEC REQUEST ACCEPTED");
|
||||
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);
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
u64 clks_exec_request_count(void) {
|
||||
return clks_exec_requests;
|
||||
}
|
||||
|
||||
u64 clks_exec_success_count(void) {
|
||||
return clks_exec_success;
|
||||
}
|
||||
@@ -235,11 +235,12 @@ void clks_kelf_tick(u64 tick) {
|
||||
|
||||
app->run_count++;
|
||||
app->last_run_tick = tick;
|
||||
app->last_ret = app->entry(tick, app->run_count);
|
||||
/* NX-safe stage mode: keep dispatch accounting without jumping into runtime image. */
|
||||
app->last_ret = (tick ^ (app->run_count << 8)) + clks_kelf_rr_index;
|
||||
clks_kelf_total_runs_count++;
|
||||
|
||||
if ((app->run_count & 0x7ULL) == 1ULL) {
|
||||
clks_log(CLKS_LOG_DEBUG, "KELF", "APP EXECUTED");
|
||||
clks_log(CLKS_LOG_DEBUG, "KELF", "APP DISPATCHED");
|
||||
clks_log(CLKS_LOG_DEBUG, "KELF", app->path);
|
||||
clks_log_hex(CLKS_LOG_DEBUG, "KELF", "RET", app->last_ret);
|
||||
}
|
||||
@@ -252,3 +253,4 @@ u64 clks_kelf_count(void) {
|
||||
u64 clks_kelf_total_runs(void) {
|
||||
return clks_kelf_total_runs_count;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <clks/cpu.h>
|
||||
#include <clks/driver.h>
|
||||
#include <clks/elfrunner.h>
|
||||
#include <clks/exec.h>
|
||||
#include <clks/framebuffer.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/heap.h>
|
||||
@@ -57,6 +58,59 @@ static void clks_task_kelfd(u64 tick) {
|
||||
clks_kelf_tick(tick);
|
||||
}
|
||||
|
||||
static void clks_stage11_syscall_probe(void) {
|
||||
char child_name[96];
|
||||
char read_buf[160];
|
||||
u64 root_children;
|
||||
u64 got_name;
|
||||
u64 read_len;
|
||||
u64 run_status;
|
||||
|
||||
root_children = clks_syscall_invoke_kernel(CLKS_SYSCALL_FS_CHILD_COUNT, (u64)"/", 0ULL, 0ULL);
|
||||
clks_log_hex(CLKS_LOG_INFO, "SHELL", "ROOT_CHILDREN", root_children);
|
||||
|
||||
child_name[0] = '\0';
|
||||
got_name = clks_syscall_invoke_kernel(CLKS_SYSCALL_FS_GET_CHILD_NAME, (u64)"/", 0ULL, (u64)child_name);
|
||||
|
||||
if (got_name == 1ULL) {
|
||||
child_name[sizeof(child_name) - 1U] = '\0';
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "ROOT_ENTRY0");
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", child_name);
|
||||
}
|
||||
|
||||
read_len = clks_syscall_invoke_kernel(CLKS_SYSCALL_FS_READ,
|
||||
(u64)"/README.txt",
|
||||
(u64)read_buf,
|
||||
(u64)(sizeof(read_buf) - 1U));
|
||||
|
||||
if (read_len > 0ULL && read_len != (u64)-1) {
|
||||
if (read_len >= (u64)sizeof(read_buf)) {
|
||||
read_len = (u64)sizeof(read_buf) - 1ULL;
|
||||
}
|
||||
|
||||
read_buf[read_len] = '\0';
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "README PREVIEW");
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", read_buf);
|
||||
}
|
||||
|
||||
run_status = clks_syscall_invoke_kernel(CLKS_SYSCALL_EXEC_PATH, (u64)"/system/elfrunner.elf", 0ULL, 0ULL);
|
||||
|
||||
if (run_status == 0ULL) {
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "RUN /SYSTEM/ELFRUNNER.ELF OK");
|
||||
} else {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "RUN /SYSTEM/ELFRUNNER.ELF FAILED");
|
||||
}
|
||||
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"EXEC",
|
||||
"REQUESTS",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_EXEC_REQUESTS, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"EXEC",
|
||||
"SUCCESS",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_EXEC_SUCCESS, 0ULL, 0ULL, 0ULL));
|
||||
}
|
||||
|
||||
void clks_kernel_main(void) {
|
||||
const struct limine_framebuffer *boot_fb;
|
||||
const struct limine_memmap_response *boot_memmap;
|
||||
@@ -82,7 +136,7 @@ void clks_kernel_main(void) {
|
||||
clks_tty_init();
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE10 START");
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE11 START");
|
||||
|
||||
if (boot_fb == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||
@@ -151,6 +205,7 @@ void clks_kernel_main(void) {
|
||||
|
||||
clks_driver_init();
|
||||
clks_kelf_init();
|
||||
clks_exec_init();
|
||||
|
||||
clks_scheduler_init();
|
||||
|
||||
@@ -185,8 +240,10 @@ void clks_kernel_main(void) {
|
||||
syscall_ticks = clks_syscall_invoke_kernel(CLKS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
|
||||
clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks);
|
||||
|
||||
clks_stage11_syscall_probe();
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
|
||||
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
|
||||
|
||||
clks_cpu_halt_forever();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
#include <clks/exec.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/interrupts.h>
|
||||
#include <clks/kelf.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/scheduler.h>
|
||||
#include <clks/service.h>
|
||||
#include <clks/string.h>
|
||||
#include <clks/syscall.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
#define CLKS_SYSCALL_LOG_MAX_LEN 191U
|
||||
#define CLKS_SYSCALL_PATH_MAX 192U
|
||||
#define CLKS_SYSCALL_NAME_MAX 96U
|
||||
|
||||
struct clks_syscall_frame {
|
||||
u64 rax;
|
||||
u64 rbx;
|
||||
@@ -33,21 +40,44 @@ struct clks_syscall_frame {
|
||||
|
||||
static clks_bool clks_syscall_ready = CLKS_FALSE;
|
||||
|
||||
static clks_bool clks_syscall_copy_user_string(u64 src_addr, char *dst, usize dst_size) {
|
||||
const char *src = (const char *)src_addr;
|
||||
usize i = 0U;
|
||||
|
||||
if (src == CLKS_NULL || dst == CLKS_NULL || dst_size == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
while (i + 1U < dst_size) {
|
||||
char ch = src[i];
|
||||
dst[i] = ch;
|
||||
|
||||
if (ch == '\0') {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
dst[dst_size - 1U] = '\0';
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_log_write(u64 arg0, u64 arg1) {
|
||||
const char *src = (const char *)arg0;
|
||||
u64 len = arg1;
|
||||
char buf[192];
|
||||
char buf[CLKS_SYSCALL_LOG_MAX_LEN + 1U];
|
||||
u64 i;
|
||||
|
||||
if (src == CLKS_NULL || len == 0ULL) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
if (len > (sizeof(buf) - 1U)) {
|
||||
len = sizeof(buf) - 1U;
|
||||
if (len > CLKS_SYSCALL_LOG_MAX_LEN) {
|
||||
len = CLKS_SYSCALL_LOG_MAX_LEN;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (i = 0ULL; i < len; i++) {
|
||||
buf[i] = src[i];
|
||||
}
|
||||
|
||||
@@ -57,6 +87,74 @@ static u64 clks_syscall_log_write(u64 arg0, u64 arg1) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_fs_child_count(u64 arg0) {
|
||||
char path[CLKS_SYSCALL_PATH_MAX];
|
||||
|
||||
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
return clks_fs_count_children(path);
|
||||
}
|
||||
|
||||
static u64 clks_syscall_fs_get_child_name(u64 arg0, u64 arg1, u64 arg2) {
|
||||
char path[CLKS_SYSCALL_PATH_MAX];
|
||||
|
||||
if (arg2 == 0ULL) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
if (clks_fs_get_child_name(path, arg1, (char *)arg2, (usize)CLKS_SYSCALL_NAME_MAX) == CLKS_FALSE) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
return 1ULL;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_fs_read(u64 arg0, u64 arg1, u64 arg2) {
|
||||
char path[CLKS_SYSCALL_PATH_MAX];
|
||||
const void *data;
|
||||
u64 file_size = 0ULL;
|
||||
u64 copy_len;
|
||||
|
||||
if (arg1 == 0ULL || arg2 == 0ULL) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
data = clks_fs_read_all(path, &file_size);
|
||||
|
||||
if (data == CLKS_NULL || file_size == 0ULL) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
copy_len = (file_size < arg2) ? file_size : arg2;
|
||||
clks_memcpy((void *)arg1, data, (usize)copy_len);
|
||||
return copy_len;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_exec_path(u64 arg0) {
|
||||
char path[CLKS_SYSCALL_PATH_MAX];
|
||||
u64 status = (u64)-1;
|
||||
|
||||
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
if (clks_exec_run_path(path, &status) == CLKS_FALSE) {
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void clks_syscall_init(void) {
|
||||
clks_syscall_ready = CLKS_TRUE;
|
||||
clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE");
|
||||
@@ -97,6 +195,20 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
||||
return clks_kelf_count();
|
||||
case CLKS_SYSCALL_KELF_RUNS:
|
||||
return clks_kelf_total_runs();
|
||||
case CLKS_SYSCALL_FS_NODE_COUNT:
|
||||
return clks_fs_node_count();
|
||||
case CLKS_SYSCALL_FS_CHILD_COUNT:
|
||||
return clks_syscall_fs_child_count(frame->rbx);
|
||||
case CLKS_SYSCALL_FS_GET_CHILD_NAME:
|
||||
return clks_syscall_fs_get_child_name(frame->rbx, frame->rcx, frame->rdx);
|
||||
case CLKS_SYSCALL_FS_READ:
|
||||
return clks_syscall_fs_read(frame->rbx, frame->rcx, frame->rdx);
|
||||
case CLKS_SYSCALL_EXEC_PATH:
|
||||
return clks_syscall_exec_path(frame->rbx);
|
||||
case CLKS_SYSCALL_EXEC_REQUESTS:
|
||||
return clks_exec_request_count();
|
||||
case CLKS_SYSCALL_EXEC_SUCCESS:
|
||||
return clks_exec_success_count();
|
||||
default:
|
||||
return (u64)-1;
|
||||
}
|
||||
@@ -113,4 +225,4 @@ u64 clks_syscall_invoke_kernel(u64 id, u64 arg0, u64 arg1, u64 arg2) {
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ clks_bool clks_userland_init(void) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "USER", "SHELL COMMAND ABI READY");
|
||||
|
||||
if (clks_userland_probe_elf("/system/elfrunner.elf", "ELFRUNNER ELF READY") == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
@@ -45,5 +47,4 @@ clks_bool clks_userland_init(void) {
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
41
docs/stage11.md
Normal file
41
docs/stage11.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# CLeonOS Stage11
|
||||
|
||||
## Stage Goal
|
||||
- Build Stage11 shell command framework around syscall ABI (`help/ls/cat/run`).
|
||||
- Extend INT80 syscall table with filesystem query/read operations.
|
||||
- Add kernel `exec` path framework for ELF-by-path request validation.
|
||||
- Add kernel-side syscall probe flow to verify command-path ABI during boot.
|
||||
|
||||
## Acceptance Criteria
|
||||
- Kernel boots and prints `CLEONOS STAGE11 START`.
|
||||
- Userland init logs `SHELL COMMAND ABI READY`.
|
||||
- Exec framework logs `PATH EXEC FRAMEWORK ONLINE`.
|
||||
- After interrupt/syscall online, Stage11 probe logs include:
|
||||
- `SHELL ROOT_CHILDREN`
|
||||
- `SHELL ROOT_ENTRY0`
|
||||
- `SHELL README PREVIEW`
|
||||
- `EXEC RUN /SYSTEM/ELFRUNNER.ELF OK`
|
||||
- `EXEC REQUESTS` and `EXEC SUCCESS`
|
||||
- System remains stable in idle loop.
|
||||
|
||||
## Build Targets
|
||||
- `make setup`
|
||||
- `make userapps`
|
||||
- `make iso`
|
||||
- `make run`
|
||||
- `make debug`
|
||||
|
||||
## QEMU Command
|
||||
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
|
||||
|
||||
## Common Bugs and Debugging
|
||||
- `undefined reference` for exec APIs:
|
||||
- Ensure `clks/kernel/exec.c` is listed in `C_SOURCES`.
|
||||
- Stage11 syscall logs missing:
|
||||
- Verify `clks_stage11_syscall_probe()` is called after `clks_interrupts_init()`.
|
||||
- `EXEC ELF INVALID` on run path:
|
||||
- Check `/system/*.elf` are valid ELF64 images in ramdisk.
|
||||
- `ls`/`cat` shell syscalls return empty:
|
||||
- Confirm syscall IDs in `clks/include/clks/syscall.h` and `cleonos/c/include/cleonos_syscall.h` are identical.
|
||||
- Shell app build fails with warnings:
|
||||
- Keep helper functions used and avoid implicit type conversions under `-Werror`.
|
||||
Reference in New Issue
Block a user