Compare commits

...

4 Commits

Author SHA1 Message Date
Leonmmcoset
27a51a0986 doom3 2026-04-20 23:46:16 +08:00
Leonmmcoset
16855e4b98 doom2 2026-04-20 23:09:38 +08:00
Leonmmcoset
dbd88505e6 Merge branch 'main' of https://github.com/Leonmmcoset/cleonos 2026-04-20 21:53:33 +08:00
Leonmmcoset
d7e1cb62ee doom1 2026-04-20 21:53:28 +08:00
20 changed files with 2642 additions and 26 deletions

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "limine"] [submodule "limine"]
path = limine path = limine
url = https://github.com/limine-bootloader/limine.git url = https://github.com/limine-bootloader/limine.git
[submodule "cleonos/third-party/doomgeneric"]
path = cleonos/third-party/doomgeneric
url = https://github.com/ozkl/doomgeneric.git

View File

@@ -337,6 +337,24 @@ set(USER_CFLAGS
"-I${CMAKE_SOURCE_DIR}/cleonos/c/include" "-I${CMAKE_SOURCE_DIR}/cleonos/c/include"
) )
set(USER_CFLAGS_DOOM
-std=c11
-ffreestanding
-fno-stack-protector
-fno-builtin
-Wall
-Wextra
-Wno-error
-Wno-unused-parameter
-Wno-missing-field-initializers
-Wno-sign-compare
-D_DEFAULT_SOURCE
-D_POSIX_C_SOURCE=200809L
"-I${CMAKE_SOURCE_DIR}/cleonos/third-party/doomgeneric/doomgeneric"
"-include"
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/doom/doom_shim.h"
)
set(USER_LDFLAGS set(USER_LDFLAGS
-nostdlib -nostdlib
-z -z
@@ -494,6 +512,23 @@ function(add_user_c_object SRC OUTPUT_VAR)
set(${OUTPUT_VAR} "${OBJ_PATH}" PARENT_SCOPE) set(${OUTPUT_VAR} "${OBJ_PATH}" PARENT_SCOPE)
endfunction() endfunction()
function(add_user_c_object_doom SRC OUTPUT_VAR)
string(REGEX REPLACE "\\.c$" ".o" OBJ_REL "${SRC}")
set(OBJ_PATH "${USER_OBJ_ROOT}/${OBJ_REL}")
get_filename_component(OBJ_DIR "${OBJ_PATH}" DIRECTORY)
set(_deps "${CMAKE_SOURCE_DIR}/${SRC}" ${USER_INC_SOURCES_ABS} ${DOOMGENERIC_DEP_SOURCES_ABS})
add_custom_command(
OUTPUT "${OBJ_PATH}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${OBJ_DIR}"
COMMAND ${USER_CC} ${USER_CFLAGS_DOOM} -c "${CMAKE_SOURCE_DIR}/${SRC}" -o "${OBJ_PATH}"
DEPENDS ${_deps}
VERBATIM
)
set(${OUTPUT_VAR} "${OBJ_PATH}" PARENT_SCOPE)
endfunction()
set(KERNEL_OBJECTS) set(KERNEL_OBJECTS)
foreach(SRC IN LISTS C_SOURCES) foreach(SRC IN LISTS C_SOURCES)
add_kernel_c_object("${SRC}" KERNEL_OBJECTS) add_kernel_c_object("${SRC}" KERNEL_OBJECTS)
@@ -565,6 +600,25 @@ set(RAMDISK_DRIVER_APPS)
set(RAMDISK_SYSTEM_APPS) set(RAMDISK_SYSTEM_APPS)
set(RAMDISK_ROOT_APPS) set(RAMDISK_ROOT_APPS)
set(DOOMGENERIC_DIR "${CMAKE_SOURCE_DIR}/cleonos/third-party/doomgeneric/doomgeneric")
set(DOOMGENERIC_SRC_BASENAMES
dummy am_map doomdef doomstat dstrings d_event d_items d_iwad d_loop d_main d_mode d_net f_finale f_wipe
g_game hu_lib hu_stuff info i_cdmus i_endoom i_joystick i_scale i_sound i_system i_timer memio m_argv
m_bbox m_cheat m_config m_controls m_fixed m_menu m_misc m_random p_ceilng p_doors p_enemy p_floor
p_inter p_lights p_map p_maputl p_mobj p_plats p_pspr p_saveg p_setup p_sight p_spec p_switch p_telept
p_tick p_user r_bsp r_data r_draw r_main r_plane r_segs r_sky r_things sha1 sounds statdump st_lib st_stuff
s_sound tables v_video wi_stuff w_checksum w_file w_main w_wad z_zone w_file_stdc i_input i_video doomgeneric
)
set(DOOMGENERIC_APP_SOURCES)
foreach(_base IN LISTS DOOMGENERIC_SRC_BASENAMES)
list(APPEND DOOMGENERIC_APP_SOURCES "cleonos/third-party/doomgeneric/doomgeneric/${_base}.c")
endforeach()
file(GLOB_RECURSE DOOMGENERIC_DEP_SOURCES_ABS CONFIGURE_DEPENDS
"${CMAKE_SOURCE_DIR}/cleonos/third-party/doomgeneric/doomgeneric/*.h"
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/doom/*.h"
)
list(SORT DOOMGENERIC_DEP_SOURCES_ABS)
set(USER_SHELL_COMMAND_APPS set(USER_SHELL_COMMAND_APPS
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
bg fg jobs kill ps top bg fg jobs kill ps top
@@ -610,6 +664,13 @@ foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/${_app_name}_*.c" "${CMAKE_SOURCE_DIR}/cleonos/c/apps/${_app_name}_*.c"
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/${_app_name}/*.c" "${CMAKE_SOURCE_DIR}/cleonos/c/apps/${_app_name}/*.c"
) )
set(_app_common_objects ${USER_COMMON_OBJECTS})
if(_app_name STREQUAL "doom")
foreach(_doom_src IN LISTS DOOMGENERIC_APP_SOURCES)
list(APPEND _app_specific_abs "${CMAKE_SOURCE_DIR}/${_doom_src}")
endforeach()
endif()
list(FIND USER_SHELL_COMMAND_APPS "${_app_name}" _shell_cmd_idx) list(FIND USER_SHELL_COMMAND_APPS "${_app_name}" _shell_cmd_idx)
if(NOT _shell_cmd_idx EQUAL -1) if(NOT _shell_cmd_idx EQUAL -1)
@@ -626,7 +687,11 @@ foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
continue() continue()
endif() endif()
if(_app_name STREQUAL "doom")
add_user_c_object_doom("${_extra_rel}" _extra_obj)
else()
add_user_c_object("${_extra_rel}" _extra_obj) add_user_c_object("${_extra_rel}" _extra_obj)
endif()
list(APPEND _app_specific_objs "${_extra_obj}") list(APPEND _app_specific_objs "${_extra_obj}")
endforeach() endforeach()
list(REMOVE_DUPLICATES _app_specific_objs) list(REMOVE_DUPLICATES _app_specific_objs)
@@ -635,8 +700,8 @@ foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
add_custom_command( add_custom_command(
OUTPUT "${_app_out}" OUTPUT "${_app_out}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${USER_APP_DIR}" COMMAND ${CMAKE_COMMAND} -E make_directory "${USER_APP_DIR}"
COMMAND ${USER_LD} ${USER_LDFLAGS} -o "${_app_out}" ${USER_COMMON_OBJECTS} "${_user_obj}" ${_app_specific_objs} "${USER_RUST_LIB}" COMMAND ${USER_LD} ${USER_LDFLAGS} -o "${_app_out}" ${_app_common_objects} "${_user_obj}" ${_app_specific_objs} "${USER_RUST_LIB}"
DEPENDS ${USER_COMMON_OBJECTS} "${_user_obj}" ${_app_specific_objs} "${USER_RUST_LIB}" "${USER_LINKER_SCRIPT}" DEPENDS ${_app_common_objects} "${_user_obj}" ${_app_specific_objs} "${USER_RUST_LIB}" "${USER_LINKER_SCRIPT}"
VERBATIM VERBATIM
) )

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
#ifndef CLEONOS_DOOM_SHIM_H
#define CLEONOS_DOOM_SHIM_H
/* Redirect stdio-family APIs that clash with cleonos/c/src/stdio.c signatures. */
#define fopen dg_fopen
#define fclose dg_fclose
#define fread dg_fread
#define fwrite dg_fwrite
#define fseek dg_fseek
#define ftell dg_ftell
#define fflush dg_fflush
#define fgets dg_fgets
#define fprintf dg_fprintf
#define vfprintf dg_vfprintf
#define feof dg_feof
#define fileno dg_fileno
#define perror dg_perror
#define sscanf dg_sscanf
#endif

View File

@@ -0,0 +1,197 @@
#include "doomgeneric.h"
#include "doomkeys.h"
#include "../../include/cleonos_syscall.h"
#define CLEONOS_KEY_LEFT 0x01U
#define CLEONOS_KEY_RIGHT 0x02U
#define CLEONOS_KEY_UP 0x03U
#define CLEONOS_KEY_DOWN 0x04U
#define DG_KEY_QUEUE_CAP 256U
struct dg_key_event {
int pressed;
unsigned char key;
};
static struct dg_key_event g_key_queue[DG_KEY_QUEUE_CAP];
static u64 g_key_r = 0ULL;
static u64 g_key_w = 0ULL;
static cleonos_fb_info g_fb_info;
static cleonos_fb_blit_req g_blit_req;
static u64 g_scale = 1ULL;
static u64 g_dst_x = 0ULL;
static u64 g_dst_y = 0ULL;
static void dg_push_key(int pressed, unsigned char key) {
u64 next = (g_key_w + 1ULL) % DG_KEY_QUEUE_CAP;
if (next == g_key_r) {
return;
}
g_key_queue[g_key_w].pressed = pressed;
g_key_queue[g_key_w].key = key;
g_key_w = next;
}
static int dg_pop_key(int *pressed, unsigned char *key) {
if (g_key_r == g_key_w || pressed == (int *)0 || key == (unsigned char *)0) {
return 0;
}
*pressed = g_key_queue[g_key_r].pressed;
*key = g_key_queue[g_key_r].key;
g_key_r = (g_key_r + 1ULL) % DG_KEY_QUEUE_CAP;
return 1;
}
static unsigned char dg_translate_key(u64 code) {
if (code == (u64)CLEONOS_KEY_LEFT) {
return KEY_LEFTARROW;
}
if (code == (u64)CLEONOS_KEY_RIGHT) {
return KEY_RIGHTARROW;
}
if (code == (u64)CLEONOS_KEY_UP) {
return KEY_UPARROW;
}
if (code == (u64)CLEONOS_KEY_DOWN) {
return KEY_DOWNARROW;
}
if (code == (u64)'\r' || code == (u64)'\n') {
return KEY_ENTER;
}
if (code == (u64)8U || code == (u64)127U) {
return KEY_BACKSPACE;
}
if (code == (u64)27U) {
return KEY_ESCAPE;
}
if (code == (u64)'\t') {
return KEY_TAB;
}
if (code >= 32ULL && code <= 126ULL) {
return (unsigned char)(code & 0xFFULL);
}
return 0U;
}
static void dg_poll_keyboard(void) {
for (;;) {
u64 code = cleonos_sys_kbd_get_char();
unsigned char key;
if (code == (u64)-1) {
break;
}
key = dg_translate_key(code);
if (key == 0U) {
continue;
}
dg_push_key(1, key);
dg_push_key(0, key);
}
}
void DG_Init(void) {
u64 sx;
u64 sy;
g_key_r = 0ULL;
g_key_w = 0ULL;
g_fb_info.width = 0ULL;
g_fb_info.height = 0ULL;
g_fb_info.pitch = 0ULL;
g_fb_info.bpp = 0ULL;
if (cleonos_sys_fb_info(&g_fb_info) == 0ULL || g_fb_info.width == 0ULL || g_fb_info.height == 0ULL ||
g_fb_info.bpp != 32ULL) {
return;
}
sx = g_fb_info.width / (u64)DOOMGENERIC_RESX;
sy = g_fb_info.height / (u64)DOOMGENERIC_RESY;
g_scale = (sx < sy) ? sx : sy;
if (g_scale == 0ULL) {
g_scale = 1ULL;
}
if (g_scale > 4ULL) {
g_scale = 4ULL;
}
g_dst_x = (g_fb_info.width > ((u64)DOOMGENERIC_RESX * g_scale)) ? ((g_fb_info.width - ((u64)DOOMGENERIC_RESX * g_scale)) / 2ULL) : 0ULL;
g_dst_y = (g_fb_info.height > ((u64)DOOMGENERIC_RESY * g_scale)) ? ((g_fb_info.height - ((u64)DOOMGENERIC_RESY * g_scale)) / 2ULL) : 0ULL;
g_blit_req.pixels_ptr = 0ULL;
g_blit_req.src_width = (u64)DOOMGENERIC_RESX;
g_blit_req.src_height = (u64)DOOMGENERIC_RESY;
g_blit_req.src_pitch_bytes = (u64)DOOMGENERIC_RESX * 4ULL;
g_blit_req.dst_x = g_dst_x;
g_blit_req.dst_y = g_dst_y;
g_blit_req.scale = g_scale;
(void)cleonos_sys_fb_clear(0x00000000ULL);
}
void DG_DrawFrame(void) {
dg_poll_keyboard();
if (g_fb_info.width == 0ULL || g_fb_info.height == 0ULL || DG_ScreenBuffer == (pixel_t *)0) {
return;
}
g_blit_req.pixels_ptr = (u64)(void *)DG_ScreenBuffer;
(void)cleonos_sys_fb_blit(&g_blit_req);
}
void DG_SleepMs(uint32_t ms) {
u64 ticks = ((u64)ms + 9ULL) / 10ULL;
if (ticks == 0ULL && ms != 0U) {
ticks = 1ULL;
}
if (ticks > 0ULL) {
(void)cleonos_sys_sleep_ticks(ticks);
}
}
uint32_t DG_GetTicksMs(void) {
return (uint32_t)(cleonos_sys_timer_ticks() * 10ULL);
}
int DG_GetKey(int *pressed, unsigned char *key) {
dg_poll_keyboard();
return dg_pop_key(pressed, key);
}
void DG_SetWindowTitle(const char *title) {
(void)title;
}
int cl_doom_run_main(int argc, char **argv) {
doomgeneric_Create(argc, argv);
for (;;) {
doomgeneric_Tick();
}
}

View File

@@ -0,0 +1,87 @@
#include <stdio.h>
#include <string.h>
#include <cleonos_syscall.h>
int cl_doom_run_main(int argc, char **argv);
static const char *cl_doom_pick_default_wad(void) {
static const char *candidates[] = {
"/doom1.wad",
"/DOOM1.WAD",
"/temp/doom1.wad",
"/temp/DOOM1.WAD",
"/shell/doom1.wad",
"/shell/DOOM1.WAD",
};
u64 i;
for (i = 0ULL; i < (u64)(sizeof(candidates) / sizeof(candidates[0])); i++) {
if (cleonos_sys_fs_stat_size(candidates[i]) != (u64)-1) {
return candidates[i];
}
}
return (const char *)0;
}
int cleonos_app_main(int argc, char **argv, char **envp) {
char *run_argv[32];
int run_argc = 0;
int i;
const char *auto_wad = (const char *)0;
int has_iwad = 0;
(void)envp;
if (argc <= 0 || argv == (char **)0 || argv[0] == (char *)0) {
(void)printf("doom: invalid argv\n");
return 1;
}
for (i = 1; i < argc; i++) {
if (argv[i] != (char *)0 && strcmp(argv[i], "-iwad") == 0) {
has_iwad = 1;
break;
}
}
run_argv[run_argc++] = argv[0];
if (has_iwad == 0) {
if (argc > 1 && argv[1] != (char *)0 && argv[1][0] != '-') {
run_argv[run_argc++] = "-iwad";
run_argv[run_argc++] = argv[1];
for (i = 2; i < argc && run_argc + 1 < (int)(sizeof(run_argv) / sizeof(run_argv[0])); i++) {
run_argv[run_argc++] = argv[i];
}
} else {
auto_wad = cl_doom_pick_default_wad();
if (auto_wad != (const char *)0) {
run_argv[run_argc++] = "-iwad";
run_argv[run_argc++] = (char *)auto_wad;
}
for (i = 1; i < argc && run_argc + 1 < (int)(sizeof(run_argv) / sizeof(run_argv[0])); i++) {
run_argv[run_argc++] = argv[i];
}
}
} else {
for (i = 1; i < argc && run_argc + 1 < (int)(sizeof(run_argv) / sizeof(run_argv[0])); i++) {
run_argv[run_argc++] = argv[i];
}
}
run_argv[run_argc] = (char *)0;
if (has_iwad == 0 && auto_wad == (const char *)0 && (argc <= 1 || argv[1] == (char *)0 || argv[1][0] == '-')) {
(void)printf("doom: no WAD provided\n");
(void)printf("doom: usage: doom /doom1.wad\n");
(void)printf("doom: or: doom -iwad /doom1.wad\n");
return 1;
}
(void)printf("doom: launching doomgeneric\n");
return cl_doom_run_main(run_argc, run_argv);
}

View File

@@ -15,6 +15,7 @@ static int ush_cmd_help(void) {
ush_writeln(" ansi / ansitest / color"); ush_writeln(" ansi / ansitest / color");
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop"); ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
ush_writeln(" fastfetch [--plain]"); ush_writeln(" fastfetch [--plain]");
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");
ush_writeln(" memstat / fsstat / taskstat / userstat / shstat / stats"); ush_writeln(" memstat / fsstat / taskstat / userstat / shstat / stats");
ush_writeln(" tty [index]"); ush_writeln(" tty [index]");
ush_writeln(" dmesg [n]"); ush_writeln(" dmesg [n]");

View File

@@ -137,6 +137,7 @@ static int ush_cmd_help(void) {
ush_writeln(" ansi / ansitest / color"); ush_writeln(" ansi / ansitest / color");
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop"); ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
ush_writeln(" fastfetch [--plain]"); ush_writeln(" fastfetch [--plain]");
ush_writeln(" doom [wad_path] (framebuffer bootstrap renderer)");
ush_writeln(" memstat / fsstat / taskstat / userstat / shstat / stats"); ush_writeln(" memstat / fsstat / taskstat / userstat / shstat / stats");
ush_writeln(" tty [index]"); ush_writeln(" tty [index]");
ush_writeln(" dmesg [n]"); ush_writeln(" dmesg [n]");

View File

@@ -43,6 +43,23 @@ typedef struct cleonos_proc_snapshot {
char path[CLEONOS_PROC_PATH_MAX]; char path[CLEONOS_PROC_PATH_MAX];
} cleonos_proc_snapshot; } cleonos_proc_snapshot;
typedef struct cleonos_fb_info {
u64 width;
u64 height;
u64 pitch;
u64 bpp;
} cleonos_fb_info;
typedef struct cleonos_fb_blit_req {
u64 pixels_ptr;
u64 src_width;
u64 src_height;
u64 src_pitch_bytes;
u64 dst_x;
u64 dst_y;
u64 scale;
} cleonos_fb_blit_req;
#define CLEONOS_SYSCALL_LOG_WRITE 0ULL #define CLEONOS_SYSCALL_LOG_WRITE 0ULL
#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL #define CLEONOS_SYSCALL_TIMER_TICKS 1ULL
#define CLEONOS_SYSCALL_TASK_COUNT 2ULL #define CLEONOS_SYSCALL_TASK_COUNT 2ULL
@@ -124,6 +141,9 @@ typedef struct cleonos_proc_snapshot {
#define CLEONOS_SYSCALL_DL_CLOSE 78ULL #define CLEONOS_SYSCALL_DL_CLOSE 78ULL
#define CLEONOS_SYSCALL_DL_SYM 79ULL #define CLEONOS_SYSCALL_DL_SYM 79ULL
#define CLEONOS_SYSCALL_EXEC_PATHV_IO 80ULL #define CLEONOS_SYSCALL_EXEC_PATHV_IO 80ULL
#define CLEONOS_SYSCALL_FB_INFO 81ULL
#define CLEONOS_SYSCALL_FB_BLIT 82ULL
#define CLEONOS_SYSCALL_FB_CLEAR 83ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length); u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -207,5 +227,8 @@ u64 cleonos_sys_fd_dup(u64 fd);
u64 cleonos_sys_dl_open(const char *path); u64 cleonos_sys_dl_open(const char *path);
u64 cleonos_sys_dl_close(u64 handle); u64 cleonos_sys_dl_close(u64 handle);
u64 cleonos_sys_dl_sym(u64 handle, const char *symbol); u64 cleonos_sys_dl_sym(u64 handle, const char *symbol);
u64 cleonos_sys_fb_info(cleonos_fb_info *out_info);
u64 cleonos_sys_fb_blit(const cleonos_fb_blit_req *req);
u64 cleonos_sys_fb_clear(u64 rgb);
#endif #endif

View File

@@ -196,6 +196,42 @@ static clio_size_t clio_i64_to_dec(long long value, char *out, clio_size_t out_s
return offset + len; return offset + len;
} }
static int clio_is_digit(char ch) {
return (ch >= '0' && ch <= '9') ? 1 : 0;
}
static int clio_emit_repeat(struct clio_sink *sink, char ch, clio_size_t count) {
while (count > 0UL) {
if (clio_sink_emit(sink, &ch, 1UL) == 0) {
return 0;
}
count--;
}
return 1;
}
static int clio_emit_with_width(struct clio_sink *sink, const char *text, clio_size_t text_len, int left_align,
char pad_char, clio_size_t width) {
if (left_align == 0 && width > text_len) {
if (clio_emit_repeat(sink, pad_char, width - text_len) == 0) {
return 0;
}
}
if (text_len > 0UL && clio_sink_emit(sink, text, text_len) == 0) {
return 0;
}
if (left_align != 0 && width > text_len) {
if (clio_emit_repeat(sink, ' ', width - text_len) == 0) {
return 0;
}
}
return 1;
}
static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) {
const char *cursor = fmt; const char *cursor = fmt;
@@ -223,10 +259,43 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) {
} }
{ {
int left_align = 0;
int zero_pad = 0;
clio_size_t width = 0UL;
int has_precision = 0;
clio_size_t precision = 0UL;
int length_mode = 0; /* 0: default, 1: l, 2: ll, 3: z */ int length_mode = 0; /* 0: default, 1: l, 2: ll, 3: z */
char spec = *cursor; char spec = *cursor;
char number_buf[64]; char number_buf[96];
clio_size_t out_len = 0UL;
while (spec == '-' || spec == '0') {
if (spec == '-') {
left_align = 1;
} else if (spec == '0') {
zero_pad = 1;
}
cursor++;
spec = *cursor;
}
while (clio_is_digit(spec) != 0) {
width = (width * 10UL) + (clio_size_t)(unsigned long)(spec - '0');
cursor++;
spec = *cursor;
}
if (spec == '.') {
has_precision = 1;
precision = 0UL;
cursor++;
spec = *cursor;
while (clio_is_digit(spec) != 0) {
precision = (precision * 10UL) + (clio_size_t)(unsigned long)(spec - '0');
cursor++;
spec = *cursor;
}
}
if (spec == 'l') { if (spec == 'l') {
cursor++; cursor++;
@@ -250,24 +319,36 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) {
if (spec == 's') { if (spec == 's') {
const char *text = va_arg(args, const char *); const char *text = va_arg(args, const char *);
clio_size_t text_len;
if (text == (const char *)0) { if (text == (const char *)0) {
text = "(null)"; text = "(null)";
} }
out_len = clio_strlen(text); text_len = clio_strlen(text);
if (has_precision != 0 && precision < text_len) {
text_len = precision;
}
if (clio_sink_emit(sink, text, out_len) == 0) { if (clio_emit_with_width(sink, text, text_len, left_align, ' ', width) == 0) {
return EOF; return EOF;
} }
} else if (spec == 'c') { } else if (spec == 'c') {
char out = (char)va_arg(args, int); char out = (char)va_arg(args, int);
char out_buf[1];
if (clio_sink_emit(sink, &out, 1UL) == 0) { out_buf[0] = out;
if (clio_emit_with_width(sink, out_buf, 1UL, left_align, ' ', width) == 0) {
return EOF; return EOF;
} }
} else if (spec == 'd' || spec == 'i') { } else if (spec == 'd' || spec == 'i') {
long long value; long long value;
char sign_char = '\0';
const char *digits = number_buf;
clio_size_t digits_len;
clio_size_t leading_zeros = 0UL;
clio_size_t core_len;
int sign_emitted = 0;
if (length_mode == 2) { if (length_mode == 2) {
value = va_arg(args, long long); value = va_arg(args, long long);
@@ -279,14 +360,72 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) {
value = (long long)va_arg(args, int); value = (long long)va_arg(args, int);
} }
out_len = clio_i64_to_dec(value, number_buf, (clio_size_t)sizeof(number_buf)); digits_len = clio_i64_to_dec(value, number_buf, (clio_size_t)sizeof(number_buf));
if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) { if (digits_len == 0UL) {
return EOF; return EOF;
} }
if (number_buf[0] == '-') {
sign_char = '-';
digits = number_buf + 1;
digits_len--;
}
if (has_precision != 0 && precision == 0UL && value == 0LL) {
digits_len = 0UL;
}
if (has_precision != 0 && precision > digits_len) {
leading_zeros = precision - digits_len;
}
core_len = digits_len + leading_zeros + ((sign_char != '\0') ? 1UL : 0UL);
if (left_align == 0 && width > core_len) {
if (zero_pad != 0 && has_precision == 0) {
if (sign_char != '\0') {
if (clio_sink_emit(sink, &sign_char, 1UL) == 0) {
return EOF;
}
sign_emitted = 1;
}
if (clio_emit_repeat(sink, '0', width - core_len) == 0) {
return EOF;
}
} else {
if (clio_emit_repeat(sink, ' ', width - core_len) == 0) {
return EOF;
}
}
}
if (sign_char != '\0' && sign_emitted == 0) {
if (clio_sink_emit(sink, &sign_char, 1UL) == 0) {
return EOF;
}
}
if (clio_emit_repeat(sink, '0', leading_zeros) == 0) {
return EOF;
}
if (digits_len > 0UL && clio_sink_emit(sink, digits, digits_len) == 0) {
return EOF;
}
if (left_align != 0 && width > core_len) {
if (clio_emit_repeat(sink, ' ', width - core_len) == 0) {
return EOF;
}
}
} else if (spec == 'u' || spec == 'x' || spec == 'X') { } else if (spec == 'u' || spec == 'x' || spec == 'X') {
unsigned long long value; unsigned long long value;
unsigned int base = (spec == 'u') ? 10U : 16U; unsigned int base = (spec == 'u') ? 10U : 16U;
int upper = (spec == 'X') ? 1 : 0; int upper = (spec == 'X') ? 1 : 0;
clio_size_t digits_len;
clio_size_t leading_zeros = 0UL;
clio_size_t core_len;
char pad_char = ' ';
if (length_mode == 2) { if (length_mode == 2) {
value = va_arg(args, unsigned long long); value = va_arg(args, unsigned long long);
@@ -298,22 +437,98 @@ static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) {
value = (unsigned long long)va_arg(args, unsigned int); value = (unsigned long long)va_arg(args, unsigned int);
} }
out_len = clio_u64_to_base(value, base, upper, number_buf, (clio_size_t)sizeof(number_buf)); digits_len = clio_u64_to_base(value, base, upper, number_buf, (clio_size_t)sizeof(number_buf));
if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) { if (digits_len == 0UL) {
return EOF; return EOF;
} }
if (has_precision != 0 && precision == 0UL && value == 0ULL) {
digits_len = 0UL;
}
if (has_precision != 0 && precision > digits_len) {
leading_zeros = precision - digits_len;
}
core_len = digits_len + leading_zeros;
if (zero_pad != 0 && has_precision == 0 && left_align == 0) {
pad_char = '0';
}
if (left_align == 0 && width > core_len) {
if (clio_emit_repeat(sink, pad_char, width - core_len) == 0) {
return EOF;
}
}
if (clio_emit_repeat(sink, '0', leading_zeros) == 0) {
return EOF;
}
if (digits_len > 0UL && clio_sink_emit(sink, number_buf, digits_len) == 0) {
return EOF;
}
if (left_align != 0 && width > core_len) {
if (clio_emit_repeat(sink, ' ', width - core_len) == 0) {
return EOF;
}
}
} else if (spec == 'p') { } else if (spec == 'p') {
const void *ptr = va_arg(args, const void *); const void *ptr = va_arg(args, const void *);
unsigned long long value = (unsigned long long)(unsigned long)ptr; unsigned long long value = (unsigned long long)(unsigned long)ptr;
clio_size_t digits_len;
clio_size_t leading_zeros = 0UL;
clio_size_t core_len;
digits_len = clio_u64_to_base(value, 16U, 0, number_buf, (clio_size_t)sizeof(number_buf));
if (digits_len == 0UL) {
return EOF;
}
if (has_precision != 0 && precision == 0UL && value == 0ULL) {
digits_len = 0UL;
}
if (has_precision != 0 && precision > digits_len) {
leading_zeros = precision - digits_len;
}
core_len = 2UL + leading_zeros + digits_len;
if (left_align == 0 && width > core_len) {
if (clio_emit_repeat(sink, ' ', width - core_len) == 0) {
return EOF;
}
}
if (clio_sink_emit(sink, "0x", 2UL) == 0) { if (clio_sink_emit(sink, "0x", 2UL) == 0) {
return EOF; return EOF;
} }
out_len = clio_u64_to_base(value, 16U, 0, number_buf, (clio_size_t)sizeof(number_buf)); if (clio_emit_repeat(sink, '0', leading_zeros) == 0) {
if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) {
return EOF; return EOF;
} }
if (digits_len > 0UL && clio_sink_emit(sink, number_buf, digits_len) == 0) {
return EOF;
}
if (left_align != 0 && width > core_len) {
if (clio_emit_repeat(sink, ' ', width - core_len) == 0) {
return EOF;
}
}
} else if (spec == 'n') {
int *out_count = va_arg(args, int *);
if (out_count != (int *)0) {
if (sink->count > 0x7FFFFFFFUL) {
*out_count = 0x7FFFFFFF;
} else {
*out_count = (int)sink->count;
}
}
} else { } else {
char fallback[2]; char fallback[2];
fallback[0] = spec; fallback[0] = spec;

View File

@@ -355,3 +355,15 @@ u64 cleonos_sys_dl_close(u64 handle) {
u64 cleonos_sys_dl_sym(u64 handle, const char *symbol) { u64 cleonos_sys_dl_sym(u64 handle, const char *symbol) {
return cleonos_syscall(CLEONOS_SYSCALL_DL_SYM, handle, (u64)symbol, 0ULL); return cleonos_syscall(CLEONOS_SYSCALL_DL_SYM, handle, (u64)symbol, 0ULL);
} }
u64 cleonos_sys_fb_info(cleonos_fb_info *out_info) {
return cleonos_syscall(CLEONOS_SYSCALL_FB_INFO, (u64)out_info, 0ULL, 0ULL);
}
u64 cleonos_sys_fb_blit(const cleonos_fb_blit_req *req) {
return cleonos_syscall(CLEONOS_SYSCALL_FB_BLIT, (u64)req, 0ULL, 0ULL);
}
u64 cleonos_sys_fb_clear(u64 rgb) {
return cleonos_syscall(CLEONOS_SYSCALL_FB_CLEAR, rgb, 0ULL, 0ULL);
}

View File

@@ -74,5 +74,7 @@ u64 clks_exec_request_count(void);
u64 clks_exec_success_count(void); u64 clks_exec_success_count(void);
clks_bool clks_exec_is_running(void); clks_bool clks_exec_is_running(void);
clks_bool clks_exec_current_path_is_user(void); clks_bool clks_exec_current_path_is_user(void);
clks_bool clks_exec_current_user_ptr_readable(u64 addr, u64 size);
clks_bool clks_exec_current_user_ptr_writable(u64 addr, u64 size);
#endif #endif

View File

@@ -84,6 +84,9 @@
#define CLKS_SYSCALL_DL_CLOSE 78ULL #define CLKS_SYSCALL_DL_CLOSE 78ULL
#define CLKS_SYSCALL_DL_SYM 79ULL #define CLKS_SYSCALL_DL_SYM 79ULL
#define CLKS_SYSCALL_EXEC_PATHV_IO 80ULL #define CLKS_SYSCALL_EXEC_PATHV_IO 80ULL
#define CLKS_SYSCALL_FB_INFO 81ULL
#define CLKS_SYSCALL_FB_BLIT 82ULL
#define CLKS_SYSCALL_FB_CLEAR 83ULL
void clks_syscall_init(void); void clks_syscall_init(void);
u64 clks_syscall_dispatch(void *frame_ptr); u64 clks_syscall_dispatch(void *frame_ptr);

View File

@@ -2,7 +2,11 @@
#include <clks/string.h> #include <clks/string.h>
#include <clks/types.h> #include <clks/types.h>
#define CLKS_HEAP_ARENA_SIZE (1024ULL * 1024ULL) #ifndef CLKS_CFG_HEAP_ARENA_SIZE
#define CLKS_CFG_HEAP_ARENA_SIZE (64ULL * 1024ULL * 1024ULL)
#endif
#define CLKS_HEAP_ARENA_SIZE CLKS_CFG_HEAP_ARENA_SIZE
#define CLKS_HEAP_ALIGN 16ULL #define CLKS_HEAP_ALIGN 16ULL
#define CLKS_HEAP_MAGIC 0x434C454F4E4F534FULL #define CLKS_HEAP_MAGIC 0x434C454F4E4F534FULL

View File

@@ -1,5 +1,6 @@
#include <clks/elf64.h> #include <clks/elf64.h>
#include <clks/heap.h> #include <clks/heap.h>
#include <clks/log.h>
#include <clks/string.h> #include <clks/string.h>
#include <clks/types.h> #include <clks/types.h>
@@ -17,6 +18,8 @@
#define CLKS_ELF64_EM_X86_64 62U #define CLKS_ELF64_EM_X86_64 62U
#define CLKS_ELF64_PF_X 0x1U
struct clks_elf64_ehdr { struct clks_elf64_ehdr {
u8 e_ident[16]; u8 e_ident[16];
u16 e_type; u16 e_type;
@@ -90,6 +93,42 @@ static clks_bool clks_elf64_range_ok(u64 off, u64 len, u64 total) {
return CLKS_TRUE; return CLKS_TRUE;
} }
static void clks_elf64_rebase_exec_pointers(struct clks_elf64_loaded_image *loaded, u64 old_base, u64 old_end,
u64 delta) {
u16 seg_index;
if (loaded == CLKS_NULL || delta == 0ULL || old_end <= old_base) {
return;
}
for (seg_index = 0U; seg_index < loaded->segment_count; seg_index++) {
struct clks_elf64_loaded_segment *seg = &loaded->segments[seg_index];
u64 scan_len;
u64 off;
/* Skip executable segments to avoid patching instruction bytes. */
if ((seg->flags & CLKS_ELF64_PF_X) != 0U) {
continue;
}
scan_len = seg->filesz;
if (scan_len < sizeof(u64)) {
continue;
}
scan_len -= (scan_len % sizeof(u64));
for (off = 0ULL; off < scan_len; off += sizeof(u64)) {
u64 *slot = (u64 *)((u8 *)seg->base + (usize)off);
u64 value = *slot;
if (value >= old_base && value < old_end) {
*slot = value + delta;
}
}
}
}
clks_bool clks_elf64_validate(const void *image, u64 size) { clks_bool clks_elf64_validate(const void *image, u64 size) {
const struct clks_elf64_ehdr *eh; const struct clks_elf64_ehdr *eh;
u64 ph_table_size; u64 ph_table_size;
@@ -230,6 +269,10 @@ clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_
image_base = clks_kmalloc((usize)span); image_base = clks_kmalloc((usize)span);
if (image_base == CLKS_NULL) { if (image_base == CLKS_NULL) {
clks_log(CLKS_LOG_WARN, "ELF", "LOAD ALLOC FAILED");
clks_log_hex(CLKS_LOG_WARN, "ELF", "SPAN", span);
clks_log_hex(CLKS_LOG_WARN, "ELF", "MIN_VADDR", min_vaddr);
clks_log_hex(CLKS_LOG_WARN, "ELF", "MAX_VADDR_END", max_vaddr_end);
return CLKS_FALSE; return CLKS_FALSE;
} }
@@ -273,6 +316,17 @@ clks_bool clks_elf64_load(const void *image, u64 size, struct clks_elf64_loaded_
out_loaded->segment_count++; out_loaded->segment_count++;
} }
if (eh->e_type == CLKS_ELF64_ET_EXEC) {
u64 new_base = (u64)(usize)image_base;
u64 old_base = min_vaddr;
u64 old_end = max_vaddr_end;
if (new_base != old_base) {
u64 delta = new_base - old_base;
clks_elf64_rebase_exec_pointers(out_loaded, old_base, old_end, delta);
}
}
return CLKS_TRUE; return CLKS_TRUE;
} }

View File

@@ -13,7 +13,7 @@
typedef u64 (*clks_exec_entry_fn)(void); typedef u64 (*clks_exec_entry_fn)(void);
#define CLKS_EXEC_RUN_STACK_BYTES (64ULL * 1024ULL) #define CLKS_EXEC_RUN_STACK_BYTES (1024ULL * 1024ULL)
#define CLKS_EXEC_MAX_PROCS 64U #define CLKS_EXEC_MAX_PROCS 64U
#define CLKS_EXEC_MAX_DEPTH 16U #define CLKS_EXEC_MAX_DEPTH 16U
#define CLKS_EXEC_PATH_MAX 192U #define CLKS_EXEC_PATH_MAX 192U
@@ -160,6 +160,11 @@ struct clks_exec_dynlib_slot {
#if defined(CLKS_ARCH_X86_64) #if defined(CLKS_ARCH_X86_64)
extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top); extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top);
extern void clks_exec_abort_to_caller_x86_64(void); extern void clks_exec_abort_to_caller_x86_64(void);
static u64 clks_exec_read_cr2(void) {
u64 value = 0ULL;
__asm__ volatile("mov %%cr2, %0" : "=r"(value));
return value;
}
#endif #endif
static u64 clks_exec_requests = 0ULL; static u64 clks_exec_requests = 0ULL;
@@ -178,6 +183,10 @@ static u64 clks_exec_unwind_slot_stack[CLKS_EXEC_MAX_DEPTH];
static clks_bool clks_exec_unwind_slot_valid_stack[CLKS_EXEC_MAX_DEPTH]; static clks_bool clks_exec_unwind_slot_valid_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_begin_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_image_begin_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_end_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_image_end_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_vaddr_begin_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_vaddr_end_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_stack_begin_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_stack_end_stack[CLKS_EXEC_MAX_DEPTH];
static u32 clks_exec_pid_stack_depth = 0U; static u32 clks_exec_pid_stack_depth = 0U;
static struct clks_exec_dynlib_slot clks_exec_dynlib_table[CLKS_EXEC_DYNLIB_MAX]; static struct clks_exec_dynlib_slot clks_exec_dynlib_table[CLKS_EXEC_DYNLIB_MAX];
static u64 clks_exec_next_dynlib_handle = 1ULL; static u64 clks_exec_next_dynlib_handle = 1ULL;
@@ -315,6 +324,48 @@ static clks_bool clks_exec_rip_is_current_user_context(u64 rip) {
return (rip >= image_begin && rip < image_end) ? CLKS_TRUE : CLKS_FALSE; return (rip >= image_begin && rip < image_end) ? CLKS_TRUE : CLKS_FALSE;
} }
static clks_bool clks_exec_translate_legacy_user_rip(u64 rip, u64 *out_rip) {
i32 depth_index;
u64 vaddr_begin;
u64 vaddr_end;
u64 image_begin;
u64 image_end;
u64 off;
u64 translated;
if (out_rip == CLKS_NULL || clks_exec_pid_stack_depth == 0U) {
return CLKS_FALSE;
}
depth_index = (i32)(clks_exec_pid_stack_depth - 1U);
vaddr_begin = clks_exec_image_vaddr_begin_stack[(u32)depth_index];
vaddr_end = clks_exec_image_vaddr_end_stack[(u32)depth_index];
image_begin = clks_exec_image_begin_stack[(u32)depth_index];
image_end = clks_exec_image_end_stack[(u32)depth_index];
if (vaddr_begin == 0ULL || vaddr_end <= vaddr_begin || image_begin == 0ULL || image_end <= image_begin) {
return CLKS_FALSE;
}
if (rip < vaddr_begin || rip >= vaddr_end) {
return CLKS_FALSE;
}
off = rip - vaddr_begin;
if (off >= (image_end - image_begin)) {
return CLKS_FALSE;
}
translated = image_begin + off;
if (translated < image_begin || translated >= image_end) {
return CLKS_FALSE;
}
*out_rip = translated;
return CLKS_TRUE;
}
static void clks_exec_copy_path(char *dst, usize dst_size, const char *src) { static void clks_exec_copy_path(char *dst, usize dst_size, const char *src) {
usize i = 0U; usize i = 0U;
@@ -362,6 +413,26 @@ static clks_bool clks_exec_range_ok(u64 off, u64 len, u64 total) {
return CLKS_TRUE; return CLKS_TRUE;
} }
static clks_bool clks_exec_addr_range_in_window(u64 addr, u64 size, u64 begin, u64 end) {
if (begin == 0ULL || end <= begin) {
return CLKS_FALSE;
}
if (size == 0ULL) {
return CLKS_FALSE;
}
if (addr < begin || addr >= end) {
return CLKS_FALSE;
}
if (size > (end - addr)) {
return CLKS_FALSE;
}
return CLKS_TRUE;
}
static i32 clks_exec_dynlib_alloc_slot(void) { static i32 clks_exec_dynlib_alloc_slot(void) {
u32 i; u32 i;
@@ -1179,6 +1250,8 @@ static clks_bool clks_exec_invoke_entry(void *entry_ptr, u32 depth_index, u64 *o
} }
stack_top = (void *)((u8 *)stack_base + (usize)CLKS_EXEC_RUN_STACK_BYTES); stack_top = (void *)((u8 *)stack_base + (usize)CLKS_EXEC_RUN_STACK_BYTES);
clks_exec_stack_begin_stack[depth_index] = (u64)stack_base;
clks_exec_stack_end_stack[depth_index] = (u64)stack_top;
unwind_slot = (((u64)stack_top) & ~0xFULL) - CLKS_EXEC_UNWIND_CTX_BYTES; unwind_slot = (((u64)stack_top) & ~0xFULL) - CLKS_EXEC_UNWIND_CTX_BYTES;
clks_exec_unwind_slot_stack[depth_index] = unwind_slot; clks_exec_unwind_slot_stack[depth_index] = unwind_slot;
clks_exec_unwind_slot_valid_stack[depth_index] = CLKS_TRUE; clks_exec_unwind_slot_valid_stack[depth_index] = CLKS_TRUE;
@@ -1192,6 +1265,8 @@ static clks_bool clks_exec_invoke_entry(void *entry_ptr, u32 depth_index, u64 *o
/* Close unwind window immediately after call returns to avoid IRQ race. */ /* Close unwind window immediately after call returns to avoid IRQ race. */
clks_exec_unwind_slot_valid_stack[depth_index] = CLKS_FALSE; clks_exec_unwind_slot_valid_stack[depth_index] = CLKS_FALSE;
clks_exec_unwind_slot_stack[depth_index] = 0ULL; clks_exec_unwind_slot_stack[depth_index] = 0ULL;
clks_exec_stack_begin_stack[depth_index] = 0ULL;
clks_exec_stack_end_stack[depth_index] = 0ULL;
clks_exec_restore_interrupt_window(restore_irq_disable); clks_exec_restore_interrupt_window(restore_irq_disable);
*out_ret = call_ret; *out_ret = call_ret;
@@ -1254,6 +1329,10 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) {
clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE;
clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_image_end_stack[(u32)depth_index] = 0ULL; clks_exec_image_end_stack[(u32)depth_index] = 0ULL;
clks_exec_image_vaddr_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_image_vaddr_end_stack[(u32)depth_index] = 0ULL;
clks_exec_stack_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_stack_end_stack[(u32)depth_index] = 0ULL;
clks_exec_pid_stack_depth++; clks_exec_pid_stack_depth++;
depth_pushed = CLKS_TRUE; depth_pushed = CLKS_TRUE;
@@ -1300,6 +1379,8 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) {
clks_exec_image_begin_stack[(u32)depth_index] = image_begin; clks_exec_image_begin_stack[(u32)depth_index] = image_begin;
clks_exec_image_end_stack[(u32)depth_index] = image_end; clks_exec_image_end_stack[(u32)depth_index] = image_end;
clks_exec_image_vaddr_begin_stack[(u32)depth_index] = loaded.image_vaddr_base;
clks_exec_image_vaddr_end_stack[(u32)depth_index] = loaded.image_vaddr_base + loaded.image_size;
} }
clks_exec_log_info_serial("EXEC RUN START"); clks_exec_log_info_serial("EXEC RUN START");
@@ -1348,6 +1429,10 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) {
clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE;
clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_image_end_stack[(u32)depth_index] = 0ULL; clks_exec_image_end_stack[(u32)depth_index] = 0ULL;
clks_exec_image_vaddr_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_image_vaddr_end_stack[(u32)depth_index] = 0ULL;
clks_exec_stack_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_stack_end_stack[(u32)depth_index] = 0ULL;
clks_exec_pid_stack_depth--; clks_exec_pid_stack_depth--;
depth_pushed = CLKS_FALSE; depth_pushed = CLKS_FALSE;
} }
@@ -1374,6 +1459,10 @@ fail:
clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE; clks_exec_stop_requested_stack[(u32)depth_index] = CLKS_FALSE;
clks_exec_image_begin_stack[(u32)depth_index] = 0ULL; clks_exec_image_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_image_end_stack[(u32)depth_index] = 0ULL; clks_exec_image_end_stack[(u32)depth_index] = 0ULL;
clks_exec_image_vaddr_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_image_vaddr_end_stack[(u32)depth_index] = 0ULL;
clks_exec_stack_begin_stack[(u32)depth_index] = 0ULL;
clks_exec_stack_end_stack[(u32)depth_index] = 0ULL;
clks_exec_pid_stack_depth--; clks_exec_pid_stack_depth--;
} }
@@ -1484,6 +1573,10 @@ void clks_exec_init(void) {
clks_memset(clks_exec_unwind_slot_valid_stack, 0, sizeof(clks_exec_unwind_slot_valid_stack)); clks_memset(clks_exec_unwind_slot_valid_stack, 0, sizeof(clks_exec_unwind_slot_valid_stack));
clks_memset(clks_exec_image_begin_stack, 0, sizeof(clks_exec_image_begin_stack)); clks_memset(clks_exec_image_begin_stack, 0, sizeof(clks_exec_image_begin_stack));
clks_memset(clks_exec_image_end_stack, 0, sizeof(clks_exec_image_end_stack)); clks_memset(clks_exec_image_end_stack, 0, sizeof(clks_exec_image_end_stack));
clks_memset(clks_exec_image_vaddr_begin_stack, 0, sizeof(clks_exec_image_vaddr_begin_stack));
clks_memset(clks_exec_image_vaddr_end_stack, 0, sizeof(clks_exec_image_vaddr_end_stack));
clks_memset(clks_exec_stack_begin_stack, 0, sizeof(clks_exec_stack_begin_stack));
clks_memset(clks_exec_stack_end_stack, 0, sizeof(clks_exec_stack_end_stack));
clks_memset(clks_exec_proc_table, 0, sizeof(clks_exec_proc_table)); clks_memset(clks_exec_proc_table, 0, sizeof(clks_exec_proc_table));
clks_memset(clks_exec_dynlib_table, 0, sizeof(clks_exec_dynlib_table)); clks_memset(clks_exec_dynlib_table, 0, sizeof(clks_exec_dynlib_table));
clks_exec_next_dynlib_handle = 1ULL; clks_exec_next_dynlib_handle = 1ULL;
@@ -2419,6 +2512,20 @@ clks_bool clks_exec_handle_exception(u64 vector, u64 error_code, u64 rip, u64 *i
return CLKS_FALSE; return CLKS_FALSE;
} }
#if defined(CLKS_ARCH_X86_64)
if (vector == 14ULL && (error_code & 0x10ULL) != 0ULL && io_rip != CLKS_NULL) {
u64 translated_rip = 0ULL;
if (clks_exec_translate_legacy_user_rip(rip, &translated_rip) == CLKS_TRUE) {
*io_rip = translated_rip;
clks_exec_log_info_serial("USER RIP LEGACY REBASE");
clks_exec_log_hex_serial("RIP_OLD", rip);
clks_exec_log_hex_serial("RIP_NEW", translated_rip);
return CLKS_TRUE;
}
}
#endif
signal = clks_exec_signal_from_vector(vector); signal = clks_exec_signal_from_vector(vector);
status = clks_exec_encode_signal_status(signal, vector, error_code); status = clks_exec_encode_signal_status(signal, vector, error_code);
@@ -2437,6 +2544,11 @@ clks_bool clks_exec_handle_exception(u64 vector, u64 error_code, u64 rip, u64 *i
clks_exec_log_hex_serial("VECTOR", vector); clks_exec_log_hex_serial("VECTOR", vector);
clks_exec_log_hex_serial("ERROR", error_code); clks_exec_log_hex_serial("ERROR", error_code);
clks_exec_log_hex_serial("RIP", rip); clks_exec_log_hex_serial("RIP", rip);
#if defined(CLKS_ARCH_X86_64)
if (vector == 14ULL) {
clks_exec_log_hex_serial("CR2", clks_exec_read_cr2());
}
#endif
#if defined(CLKS_ARCH_X86_64) #if defined(CLKS_ARCH_X86_64)
if (io_rip == CLKS_NULL || io_rdi == CLKS_NULL || io_rsi == CLKS_NULL) { if (io_rip == CLKS_NULL || io_rdi == CLKS_NULL || io_rsi == CLKS_NULL) {
@@ -2526,3 +2638,39 @@ clks_bool clks_exec_current_path_is_user(void) {
proc = &clks_exec_proc_table[(u32)slot]; proc = &clks_exec_proc_table[(u32)slot];
return clks_exec_path_is_user_program(proc->path); return clks_exec_path_is_user_program(proc->path);
} }
clks_bool clks_exec_current_user_ptr_readable(u64 addr, u64 size) {
i32 depth_index;
u64 image_begin;
u64 image_end;
u64 stack_begin;
u64 stack_end;
if (clks_exec_is_running() == CLKS_FALSE || clks_exec_current_path_is_user() == CLKS_FALSE) {
return CLKS_FALSE;
}
if (size == 0ULL || clks_exec_pid_stack_depth == 0U) {
return CLKS_FALSE;
}
depth_index = (i32)(clks_exec_pid_stack_depth - 1U);
image_begin = clks_exec_image_begin_stack[(u32)depth_index];
image_end = clks_exec_image_end_stack[(u32)depth_index];
stack_begin = clks_exec_stack_begin_stack[(u32)depth_index];
stack_end = clks_exec_stack_end_stack[(u32)depth_index];
if (clks_exec_addr_range_in_window(addr, size, image_begin, image_end) == CLKS_TRUE) {
return CLKS_TRUE;
}
if (clks_exec_addr_range_in_window(addr, size, stack_begin, stack_end) == CLKS_TRUE) {
return CLKS_TRUE;
}
return CLKS_FALSE;
}
clks_bool clks_exec_current_user_ptr_writable(u64 addr, u64 size) {
return clks_exec_current_user_ptr_readable(addr, size);
}

View File

@@ -1,6 +1,7 @@
#include <clks/cpu.h> #include <clks/cpu.h>
#include <clks/audio.h> #include <clks/audio.h>
#include <clks/exec.h> #include <clks/exec.h>
#include <clks/framebuffer.h>
#include <clks/fs.h> #include <clks/fs.h>
#include <clks/heap.h> #include <clks/heap.h>
#include <clks/interrupts.h> #include <clks/interrupts.h>
@@ -32,7 +33,7 @@
#define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL) #define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL)
#define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym" #define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym"
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL #define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_EXEC_PATHV_IO #define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_FB_CLEAR
#define CLKS_SYSCALL_STATS_RING_SIZE 256U #define CLKS_SYSCALL_STATS_RING_SIZE 256U
#define CLKS_SYSCALL_USC_MAX_ALLOWED_APPS 64U #define CLKS_SYSCALL_USC_MAX_ALLOWED_APPS 64U
@@ -131,6 +132,23 @@ struct clks_syscall_exec_io_req {
u64 stderr_fd; u64 stderr_fd;
}; };
struct clks_syscall_fb_info_user {
u64 width;
u64 height;
u64 pitch;
u64 bpp;
};
struct clks_syscall_fb_blit_req {
u64 pixels_ptr;
u64 src_width;
u64 src_height;
u64 src_pitch_bytes;
u64 dst_x;
u64 dst_y;
u64 scale;
};
static clks_bool clks_syscall_ready = CLKS_FALSE; static clks_bool clks_syscall_ready = CLKS_FALSE;
static clks_bool clks_syscall_user_trace_active = CLKS_FALSE; static clks_bool clks_syscall_user_trace_active = CLKS_FALSE;
static u64 clks_syscall_user_trace_budget = 0ULL; static u64 clks_syscall_user_trace_budget = 0ULL;
@@ -160,16 +178,55 @@ static inline void clks_syscall_outw(u16 port, u16 value) {
} }
#endif #endif
static clks_bool clks_syscall_in_user_exec_context(void) {
return (clks_exec_is_running() == CLKS_TRUE && clks_exec_current_path_is_user() == CLKS_TRUE) ? CLKS_TRUE
: CLKS_FALSE;
}
static clks_bool clks_syscall_user_ptr_readable(u64 addr, u64 size) {
if (addr == 0ULL || size == 0ULL) {
return CLKS_FALSE;
}
if (clks_syscall_in_user_exec_context() == CLKS_FALSE) {
return CLKS_TRUE;
}
return clks_exec_current_user_ptr_readable(addr, size);
}
static clks_bool clks_syscall_user_ptr_writable(u64 addr, u64 size) {
if (addr == 0ULL || size == 0ULL) {
return CLKS_FALSE;
}
if (clks_syscall_in_user_exec_context() == CLKS_FALSE) {
return CLKS_TRUE;
}
return clks_exec_current_user_ptr_writable(addr, size);
}
static clks_bool clks_syscall_copy_user_string(u64 src_addr, char *dst, usize dst_size) { 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; usize i = 0U;
if (src == CLKS_NULL || dst == CLKS_NULL || dst_size == 0U) { if (src_addr == 0ULL || dst == CLKS_NULL || dst_size == 0U) {
return CLKS_FALSE; return CLKS_FALSE;
} }
while (i + 1U < dst_size) { while (i + 1U < dst_size) {
char ch = src[i]; u64 char_addr = src_addr + (u64)i;
char ch;
if (char_addr < src_addr) {
return CLKS_FALSE;
}
if (clks_syscall_user_ptr_readable(char_addr, 1ULL) == CLKS_FALSE) {
return CLKS_FALSE;
}
ch = *(const char *)(usize)char_addr;
dst[i] = ch; dst[i] = ch;
if (ch == '\0') { if (ch == '\0') {
@@ -209,6 +266,10 @@ static u64 clks_syscall_copy_text_to_user(u64 dst_addr, u64 dst_size, const char
copy_len = (usize)dst_size - 1U; copy_len = (usize)dst_size - 1U;
} }
if (clks_syscall_user_ptr_writable(dst_addr, (u64)copy_len + 1ULL) == CLKS_FALSE) {
return 0ULL;
}
clks_memcpy((void *)dst_addr, src, copy_len); clks_memcpy((void *)dst_addr, src, copy_len);
((char *)dst_addr)[copy_len] = '\0'; ((char *)dst_addr)[copy_len] = '\0';
return (u64)copy_len; return (u64)copy_len;
@@ -228,6 +289,10 @@ static u64 clks_syscall_log_write(u64 arg0, u64 arg1) {
len = CLKS_SYSCALL_LOG_MAX_LEN; len = CLKS_SYSCALL_LOG_MAX_LEN;
} }
if (clks_syscall_user_ptr_readable((u64)(usize)src, len) == CLKS_FALSE) {
return 0ULL;
}
for (i = 0ULL; i < len; i++) { for (i = 0ULL; i < len; i++) {
buf[i] = src[i]; buf[i] = src[i];
} }
@@ -252,6 +317,10 @@ static u64 clks_syscall_tty_write(u64 arg0, u64 arg1) {
len = CLKS_SYSCALL_TTY_MAX_LEN; len = CLKS_SYSCALL_TTY_MAX_LEN;
} }
if (clks_syscall_user_ptr_readable((u64)(usize)src, len) == CLKS_FALSE) {
return 0ULL;
}
for (i = 0ULL; i < len; i++) { for (i = 0ULL; i < len; i++) {
buf[i] = src[i]; buf[i] = src[i];
} }
@@ -277,6 +346,127 @@ static u64 clks_syscall_kbd_get_char(void) {
return (u64)(u8)ch; return (u64)(u8)ch;
} }
static u64 clks_syscall_fb_info(u64 arg0) {
struct clks_syscall_fb_info_user *out_info = (struct clks_syscall_fb_info_user *)arg0;
struct clks_framebuffer_info fb_info;
if (arg0 == 0ULL || clks_fb_ready() == CLKS_FALSE) {
return 0ULL;
}
if (clks_syscall_user_ptr_writable(arg0, (u64)sizeof(*out_info)) == CLKS_FALSE) {
return 0ULL;
}
fb_info = clks_fb_info();
out_info->width = (u64)fb_info.width;
out_info->height = (u64)fb_info.height;
out_info->pitch = (u64)fb_info.pitch;
out_info->bpp = (u64)fb_info.bpp;
return 1ULL;
}
static u64 clks_syscall_fb_clear(u64 arg0) {
if (clks_fb_ready() == CLKS_FALSE) {
return 0ULL;
}
clks_fb_clear((u32)(arg0 & 0xFFFFFFFFULL));
return 1ULL;
}
static u64 clks_syscall_fb_blit(u64 arg0) {
struct clks_syscall_fb_blit_req req;
const u8 *src_base;
struct clks_framebuffer_info fb_info;
u64 src_width;
u64 src_height;
u64 src_pitch_bytes;
u64 dst_x;
u64 dst_y;
u64 scale;
u64 y;
u64 x;
if (arg0 == 0ULL || clks_fb_ready() == CLKS_FALSE) {
return 0ULL;
}
if (clks_syscall_user_ptr_readable(arg0, (u64)sizeof(req)) == CLKS_FALSE) {
return 0ULL;
}
clks_memcpy(&req, (const void *)(usize)arg0, sizeof(req));
if (req.pixels_ptr == 0ULL) {
return 0ULL;
}
src_width = req.src_width;
src_height = req.src_height;
src_pitch_bytes = req.src_pitch_bytes;
dst_x = req.dst_x;
dst_y = req.dst_y;
scale = req.scale;
if (src_width == 0ULL || src_height == 0ULL || scale == 0ULL) {
return 0ULL;
}
if (src_width > 4096ULL || src_height > 4096ULL || scale > 8ULL) {
return 0ULL;
}
if (src_pitch_bytes == 0ULL) {
src_pitch_bytes = src_width * 4ULL;
}
if (src_pitch_bytes < (src_width * 4ULL)) {
return 0ULL;
}
if (src_pitch_bytes != 0ULL && src_height > (((u64)-1) / src_pitch_bytes)) {
return 0ULL;
}
if (clks_syscall_user_ptr_readable(req.pixels_ptr, src_pitch_bytes * src_height) == CLKS_FALSE) {
return 0ULL;
}
src_base = (const u8 *)(usize)req.pixels_ptr;
fb_info = clks_fb_info();
if (dst_x >= (u64)fb_info.width || dst_y >= (u64)fb_info.height) {
return 0ULL;
}
for (y = 0ULL; y < src_height; y++) {
const u32 *src_row = (const u32 *)(const void *)(src_base + (usize)(y * src_pitch_bytes));
u64 draw_y = dst_y + (y * scale);
if (draw_y >= (u64)fb_info.height) {
break;
}
for (x = 0ULL; x < src_width; x++) {
u32 color = src_row[x];
u64 draw_x = dst_x + (x * scale);
if (draw_x >= (u64)fb_info.width) {
break;
}
if (scale == 1ULL) {
clks_fb_draw_pixel((u32)draw_x, (u32)draw_y, color);
} else {
clks_fb_fill_rect((u32)draw_x, (u32)draw_y, (u32)scale, (u32)scale, color);
}
}
}
return 1ULL;
}
static u64 clks_syscall_fd_open(u64 arg0, u64 arg1, u64 arg2) { static u64 clks_syscall_fd_open(u64 arg0, u64 arg1, u64 arg2) {
char path[CLKS_SYSCALL_PATH_MAX]; char path[CLKS_SYSCALL_PATH_MAX];
@@ -292,6 +482,10 @@ static u64 clks_syscall_fd_read(u64 arg0, u64 arg1, u64 arg2) {
return (u64)-1; return (u64)-1;
} }
if (arg2 > 0ULL && clks_syscall_user_ptr_writable(arg1, arg2) == CLKS_FALSE) {
return (u64)-1;
}
return clks_exec_fd_read(arg0, (void *)arg1, arg2); return clks_exec_fd_read(arg0, (void *)arg1, arg2);
} }
@@ -300,6 +494,10 @@ static u64 clks_syscall_fd_write(u64 arg0, u64 arg1, u64 arg2) {
return (u64)-1; return (u64)-1;
} }
if (arg2 > 0ULL && clks_syscall_user_ptr_readable(arg1, arg2) == CLKS_FALSE) {
return (u64)-1;
}
return clks_exec_fd_write(arg0, (const void *)arg1, arg2); return clks_exec_fd_write(arg0, (const void *)arg1, arg2);
} }
@@ -878,6 +1076,10 @@ static u64 clks_syscall_kdbg_bt(u64 arg0) {
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_readable(arg0, (u64)sizeof(req)) == CLKS_FALSE) {
return 0ULL;
}
clks_memcpy(&req, (const void *)arg0, sizeof(req)); clks_memcpy(&req, (const void *)arg0, sizeof(req));
if (req.out_ptr == 0ULL || req.out_size == 0ULL) { if (req.out_ptr == 0ULL || req.out_size == 0ULL) {
@@ -1144,6 +1346,10 @@ static u64 clks_syscall_fs_get_child_name(u64 arg0, u64 arg1, u64 arg2) {
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_writable(arg2, CLKS_SYSCALL_NAME_MAX) == CLKS_FALSE) {
return 0ULL;
}
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) { if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
return 0ULL; return 0ULL;
} }
@@ -1215,6 +1421,10 @@ static u64 clks_syscall_fs_read(u64 arg0, u64 arg1, u64 arg2) {
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_writable(arg1, arg2) == CLKS_FALSE) {
return 0ULL;
}
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) { if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
return 0ULL; return 0ULL;
} }
@@ -1309,6 +1519,10 @@ static u64 clks_syscall_exec_pathv_io(u64 arg0, u64 arg1, u64 arg2) {
return (u64)-1; return (u64)-1;
} }
if (clks_syscall_user_ptr_readable(arg2, (u64)sizeof(req)) == CLKS_FALSE) {
return (u64)-1;
}
clks_memcpy(&req, (const void *)arg2, sizeof(req)); clks_memcpy(&req, (const void *)arg2, sizeof(req));
if (clks_syscall_copy_user_optional_string(req.env_line_ptr, env_line, sizeof(env_line)) == CLKS_FALSE) { if (clks_syscall_copy_user_optional_string(req.env_line_ptr, env_line, sizeof(env_line)) == CLKS_FALSE) {
@@ -1372,6 +1586,9 @@ static u64 clks_syscall_waitpid(u64 arg0, u64 arg1) {
u64 wait_ret = clks_exec_wait_pid(arg0, &status); u64 wait_ret = clks_exec_wait_pid(arg0, &status);
if (wait_ret == 1ULL && arg1 != 0ULL) { if (wait_ret == 1ULL && arg1 != 0ULL) {
if (clks_syscall_user_ptr_writable(arg1, (u64)sizeof(status)) == CLKS_FALSE) {
return (u64)-1;
}
clks_memcpy((void *)arg1, &status, sizeof(status)); clks_memcpy((void *)arg1, &status, sizeof(status));
} }
@@ -1391,6 +1608,10 @@ static u64 clks_syscall_proc_argv(u64 arg0, u64 arg1, u64 arg2) {
arg2 = CLKS_SYSCALL_ITEM_MAX; arg2 = CLKS_SYSCALL_ITEM_MAX;
} }
if (clks_syscall_user_ptr_writable(arg1, arg2) == CLKS_FALSE) {
return 0ULL;
}
return (clks_exec_copy_current_argv(arg0, (char *)arg1, (usize)arg2) == CLKS_TRUE) ? 1ULL : 0ULL; return (clks_exec_copy_current_argv(arg0, (char *)arg1, (usize)arg2) == CLKS_TRUE) ? 1ULL : 0ULL;
} }
@@ -1407,6 +1628,10 @@ static u64 clks_syscall_proc_env(u64 arg0, u64 arg1, u64 arg2) {
arg2 = CLKS_SYSCALL_ITEM_MAX; arg2 = CLKS_SYSCALL_ITEM_MAX;
} }
if (clks_syscall_user_ptr_writable(arg1, arg2) == CLKS_FALSE) {
return 0ULL;
}
return (clks_exec_copy_current_env(arg0, (char *)arg1, (usize)arg2) == CLKS_TRUE) ? 1ULL : 0ULL; return (clks_exec_copy_current_env(arg0, (char *)arg1, (usize)arg2) == CLKS_TRUE) ? 1ULL : 0ULL;
} }
@@ -1437,6 +1662,10 @@ static u64 clks_syscall_proc_pid_at(u64 arg0, u64 arg1) {
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_writable(arg1, (u64)sizeof(pid)) == CLKS_FALSE) {
return 0ULL;
}
if (clks_exec_proc_pid_at(arg0, &pid) == CLKS_FALSE) { if (clks_exec_proc_pid_at(arg0, &pid) == CLKS_FALSE) {
return 0ULL; return 0ULL;
} }
@@ -1452,6 +1681,10 @@ static u64 clks_syscall_proc_snapshot(u64 arg0, u64 arg1, u64 arg2) {
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_writable(arg1, (u64)sizeof(snap)) == CLKS_FALSE) {
return 0ULL;
}
if (clks_exec_proc_snapshot(arg0, &snap) == CLKS_FALSE) { if (clks_exec_proc_snapshot(arg0, &snap) == CLKS_FALSE) {
return 0ULL; return 0ULL;
} }
@@ -1602,6 +1835,10 @@ static u64 clks_syscall_fs_write_common(u64 arg0, u64 arg1, u64 arg2, clks_bool
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_readable(arg1, arg2) == CLKS_FALSE) {
return 0ULL;
}
while (remaining > 0ULL) { while (remaining > 0ULL) {
u64 chunk_len = remaining; u64 chunk_len = remaining;
void *heap_copy; void *heap_copy;
@@ -1668,6 +1905,10 @@ static u64 clks_syscall_log_journal_read(u64 arg0, u64 arg1, u64 arg2) {
return 0ULL; return 0ULL;
} }
if (clks_syscall_user_ptr_writable(arg1, arg2) == CLKS_FALSE) {
return 0ULL;
}
if (clks_log_journal_read(arg0, line, sizeof(line)) == CLKS_FALSE) { if (clks_log_journal_read(arg0, line, sizeof(line)) == CLKS_FALSE) {
return 0ULL; return 0ULL;
} }
@@ -2266,6 +2507,12 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_syscall_dl_close(frame->rbx); return clks_syscall_dl_close(frame->rbx);
case CLKS_SYSCALL_DL_SYM: case CLKS_SYSCALL_DL_SYM:
return clks_syscall_dl_sym(frame->rbx, frame->rcx); return clks_syscall_dl_sym(frame->rbx, frame->rcx);
case CLKS_SYSCALL_FB_INFO:
return clks_syscall_fb_info(frame->rbx);
case CLKS_SYSCALL_FB_BLIT:
return clks_syscall_fb_blit(frame->rbx);
case CLKS_SYSCALL_FB_CLEAR:
return clks_syscall_fb_clear(frame->rbx);
default: default:
return (u64)-1; return (u64)-1;
} }

View File

@@ -28,7 +28,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
内核分发位置: 内核分发位置:
- `clks/kernel/syscall.c` - `clks/kernel/runtime/syscall.c`
## 2. 全局返回规则 ## 2. 全局返回规则
@@ -61,10 +61,10 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
## 3. 当前实现中的长度/路径限制 ## 3. 当前实现中的长度/路径限制
以下限制由内核 `clks/kernel/syscall.c` 当前实现决定: 以下限制由内核 `clks/kernel/runtime/syscall.c` 当前实现决定:
- 日志写入 `LOG_WRITE`:最大拷贝 `191` 字节。 - 日志写入 `LOG_WRITE`:最大拷贝 `191` 字节。
- TTY 文本写入 `TTY_WRITE`:最大拷贝 `512` 字节。 - TTY 文本写入 `TTY_WRITE`:最大拷贝 `2048` 字节。
- 文件读取 `FS_READ`:最多读取 `min(file_size, buffer_size)` 字节。 - 文件读取 `FS_READ`:最多读取 `min(file_size, buffer_size)` 字节。
- 文件写入 `FS_WRITE` / `FS_APPEND`:内核按 `65536` 字节分块搬运;这是实现分块大小,不是文件大小上限。 - 文件写入 `FS_WRITE` / `FS_APPEND`:内核按 `65536` 字节分块搬运;这是实现分块大小,不是文件大小上限。
- log journal 行读取缓冲:`256` 字节。 - log journal 行读取缓冲:`256` 字节。
@@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `/proc/<pid>`:指定 PID 快照文本 - `/proc/<pid>`:指定 PID 快照文本
- `/proc` 为只读;写入类 syscall 不支持。 - `/proc` 为只读;写入类 syscall 不支持。
## 4. Syscall 列表0~76 ## 4. Syscall 列表0~83
### 0 `CLEONOS_SYSCALL_LOG_WRITE` ### 0 `CLEONOS_SYSCALL_LOG_WRITE`
@@ -604,6 +604,61 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- 返回:新 fd失败 `-1` - 返回:新 fd失败 `-1`
- 说明:当前为“按值复制”语义(复制 flags/offset/目标对象)。 - 说明:当前为“按值复制”语义(复制 flags/offset/目标对象)。
### 77 `CLEONOS_SYSCALL_DL_OPEN`
- 参数:
- `arg0`: `const char *path`
- 返回:动态库句柄(`handle`);失败 `-1`
- 说明将用户态动态库ELF加载到当前进程地址空间`DL_SYM` 查询符号。
### 78 `CLEONOS_SYSCALL_DL_CLOSE`
- 参数:
- `arg0`: `u64 handle`
- 返回:成功 `0`,失败 `-1`
- 说明:关闭/释放由 `DL_OPEN` 返回的动态库句柄。
### 79 `CLEONOS_SYSCALL_DL_SYM`
- 参数:
- `arg0`: `u64 handle`
- `arg1`: `const char *symbol`
- 返回:符号地址(`u64`);失败返回 `0`
- 说明:用于查询库导出符号入口地址。
### 80 `CLEONOS_SYSCALL_EXEC_PATHV_IO`
- 参数:
- `arg0`: `const char *path`
- `arg1`: `const char *argv_line`(可为 `0`
- `arg2`: `struct { u64 env_line_ptr; u64 stdin_fd; u64 stdout_fd; u64 stderr_fd; } *req`
- 返回:与 `EXEC_PATHV` 一致(成功返回子进程退出状态,失败 `-1`
- 说明:在 `EXEC_PATHV` 基础上增加 I/O 句柄重定向(用于管道与重定向)。
### 81 `CLEONOS_SYSCALL_FB_INFO`
- 参数:
- `arg0`: `cleonos_fb_info *out_info`
- 返回:成功 `1`,失败 `0`
- 说明:获取 framebuffer 信息(`width/height/pitch/bpp`)。`out_info` 为空或 framebuffer 未就绪时失败。
### 82 `CLEONOS_SYSCALL_FB_BLIT`
- 参数:
- `arg0`: `const cleonos_fb_blit_req *req`
- 返回:成功 `1`,失败 `0`
- 说明:
- 从用户态 `pixels_ptr` 指向的 32bpp 源缓冲拷贝到 framebuffer。
- `src_pitch_bytes=0` 时按 `src_width*4` 推导。
- 当前实现限制:`src_width<=4096``src_height<=4096``scale<=8`,且目标坐标需落在屏幕内。
### 83 `CLEONOS_SYSCALL_FB_CLEAR`
- 参数:
- `arg0`: `u64 rgb`(低 32 位有效)
- 返回:成功 `1`,失败 `0`
- 说明:用纯色清屏。
## 5. 用户态封装函数 ## 5. 用户态封装函数
用户态封装位于: 用户态封装位于:
@@ -629,6 +684,9 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `cleonos_sys_kdbg_sym()` / `cleonos_sys_kdbg_bt()` / `cleonos_sys_kdbg_regs()` - `cleonos_sys_kdbg_sym()` / `cleonos_sys_kdbg_bt()` / `cleonos_sys_kdbg_regs()`
- `cleonos_sys_stats_total()` / `cleonos_sys_stats_id_count()` / `cleonos_sys_stats_recent_window()` / `cleonos_sys_stats_recent_id()` - `cleonos_sys_stats_total()` / `cleonos_sys_stats_id_count()` / `cleonos_sys_stats_recent_window()` / `cleonos_sys_stats_recent_id()`
- `cleonos_sys_fd_open()` / `cleonos_sys_fd_read()` / `cleonos_sys_fd_write()` / `cleonos_sys_fd_close()` / `cleonos_sys_fd_dup()` - `cleonos_sys_fd_open()` / `cleonos_sys_fd_read()` / `cleonos_sys_fd_write()` / `cleonos_sys_fd_close()` / `cleonos_sys_fd_dup()`
- `cleonos_sys_dl_open()` / `cleonos_sys_dl_close()` / `cleonos_sys_dl_sym()`
- `cleonos_sys_exec_pathv_io()`
- `cleonos_sys_fb_info()` / `cleonos_sys_fb_blit()` / `cleonos_sys_fb_clear()`
## 6. 开发注意事项 ## 6. 开发注意事项
@@ -639,6 +697,8 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
## 7. Wine 兼容说明 ## 7. Wine 兼容说明
- `wine/cleonos_wine_lib/runner.py` 目前以 syscall `0..67` 为主;`68..76`stats/fd需同步适配后才能完整覆盖 - `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..80`(含 `stats/fd/exec_pathv_io`
- `DL_*``77..79`)在 Wine 中当前为占位实现:`DL_OPEN=-1``DL_CLOSE=0``DL_SYM=0`
- framebuffer 相关 syscall`81..83`)尚未在 Wine 中实现(会返回未支持路径)。
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。 - Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0``AUDIO_PLAY_TONE=0``AUDIO_STOP=1` - Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0``AUDIO_PLAY_TONE=0``AUDIO_STOP=1`

BIN
ramdisk/doom1.wad Normal file

Binary file not shown.