diff --git a/cleonos/c/include/cleonos_syscall.h b/cleonos/c/include/cleonos_syscall.h index fceaf9f..4eb7e74 100644 --- a/cleonos/c/include/cleonos_syscall.h +++ b/cleonos/c/include/cleonos_syscall.h @@ -18,6 +18,13 @@ typedef unsigned long long usize; #define CLEONOS_SIGCONT 18ULL #define CLEONOS_SIGSTOP 19ULL +#define CLEONOS_O_RDONLY 0x0000ULL +#define CLEONOS_O_WRONLY 0x0001ULL +#define CLEONOS_O_RDWR 0x0002ULL +#define CLEONOS_O_CREAT 0x0040ULL +#define CLEONOS_O_TRUNC 0x0200ULL +#define CLEONOS_O_APPEND 0x0400ULL + typedef struct cleonos_proc_snapshot { u64 pid; u64 ppid; @@ -107,6 +114,11 @@ typedef struct cleonos_proc_snapshot { #define CLEONOS_SYSCALL_STATS_ID_COUNT 69ULL #define CLEONOS_SYSCALL_STATS_RECENT_WINDOW 70ULL #define CLEONOS_SYSCALL_STATS_RECENT_ID 71ULL +#define CLEONOS_SYSCALL_FD_OPEN 72ULL +#define CLEONOS_SYSCALL_FD_READ 73ULL +#define CLEONOS_SYSCALL_FD_WRITE 74ULL +#define CLEONOS_SYSCALL_FD_CLOSE 75ULL +#define CLEONOS_SYSCALL_FD_DUP 76ULL u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); u64 cleonos_sys_log_write(const char *message, u64 length); @@ -180,5 +192,10 @@ u64 cleonos_sys_stats_total(void); u64 cleonos_sys_stats_id_count(u64 id); u64 cleonos_sys_stats_recent_window(void); u64 cleonos_sys_stats_recent_id(u64 id); +u64 cleonos_sys_fd_open(const char *path, u64 flags, u64 mode); +u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size); +u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size); +u64 cleonos_sys_fd_close(u64 fd); +u64 cleonos_sys_fd_dup(u64 fd); #endif diff --git a/cleonos/c/src/syscall.c b/cleonos/c/src/syscall.c index f4bd7a1..96059fa 100644 --- a/cleonos/c/src/syscall.c +++ b/cleonos/c/src/syscall.c @@ -310,3 +310,23 @@ u64 cleonos_sys_stats_recent_window(void) { u64 cleonos_sys_stats_recent_id(u64 id) { return cleonos_syscall(CLEONOS_SYSCALL_STATS_RECENT_ID, id, 0ULL, 0ULL); } + +u64 cleonos_sys_fd_open(const char *path, u64 flags, u64 mode) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_OPEN, (u64)path, flags, mode); +} + +u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_READ, fd, (u64)out_buffer, size); +} + +u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_WRITE, fd, (u64)buffer, size); +} + +u64 cleonos_sys_fd_close(u64 fd) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_CLOSE, fd, 0ULL, 0ULL); +} + +u64 cleonos_sys_fd_dup(u64 fd) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_DUP, fd, 0ULL, 0ULL); +} diff --git a/clks/include/clks/exec.h b/clks/include/clks/exec.h index 76f1c75..2a98644 100644 --- a/clks/include/clks/exec.h +++ b/clks/include/clks/exec.h @@ -40,6 +40,11 @@ clks_bool clks_exec_spawn_path(const char *path, u64 *out_pid); clks_bool clks_exec_spawn_pathv(const char *path, const char *argv_line, const char *env_line, u64 *out_pid); u64 clks_exec_wait_pid(u64 pid, u64 *out_status); clks_bool clks_exec_request_exit(u64 status); +u64 clks_exec_fd_open(const char *path, u64 flags, u64 mode); +u64 clks_exec_fd_read(u64 fd, void *out_buffer, u64 size); +u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size); +u64 clks_exec_fd_close(u64 fd); +u64 clks_exec_fd_dup(u64 fd); u64 clks_exec_current_pid(void); u32 clks_exec_current_tty(void); u64 clks_exec_current_argc(void); diff --git a/clks/include/clks/syscall.h b/clks/include/clks/syscall.h index 1808165..219491a 100644 --- a/clks/include/clks/syscall.h +++ b/clks/include/clks/syscall.h @@ -75,6 +75,11 @@ #define CLKS_SYSCALL_STATS_ID_COUNT 69ULL #define CLKS_SYSCALL_STATS_RECENT_WINDOW 70ULL #define CLKS_SYSCALL_STATS_RECENT_ID 71ULL +#define CLKS_SYSCALL_FD_OPEN 72ULL +#define CLKS_SYSCALL_FD_READ 73ULL +#define CLKS_SYSCALL_FD_WRITE 74ULL +#define CLKS_SYSCALL_FD_CLOSE 75ULL +#define CLKS_SYSCALL_FD_DUP 76ULL void clks_syscall_init(void); u64 clks_syscall_dispatch(void *frame_ptr); diff --git a/clks/kernel/exec.c b/clks/kernel/exec.c index 33afe23..a3b7f0d 100644 --- a/clks/kernel/exec.c +++ b/clks/kernel/exec.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ typedef u64 (*clks_exec_entry_fn)(void); #define CLKS_EXEC_PATH_MAX 192U #define CLKS_EXEC_ARG_LINE_MAX 256U #define CLKS_EXEC_ENV_LINE_MAX 512U +#define CLKS_EXEC_FD_MAX 32U #define CLKS_EXEC_MAX_ARGS 24U #define CLKS_EXEC_MAX_ENVS 24U #define CLKS_EXEC_ITEM_MAX 128U @@ -25,6 +27,19 @@ typedef u64 (*clks_exec_entry_fn)(void); #define CLKS_EXEC_DEFAULT_KILL_SIGNAL CLKS_EXEC_SIGNAL_TERM #define CLKS_EXEC_KERNEL_ADDR_BASE 0xFFFF800000000000ULL #define CLKS_EXEC_UNWIND_CTX_BYTES 56ULL +#define CLKS_EXEC_FD_ACCESS_MASK 0x3ULL +#define CLKS_EXEC_O_RDONLY 0x0000ULL +#define CLKS_EXEC_O_WRONLY 0x0001ULL +#define CLKS_EXEC_O_RDWR 0x0002ULL +#define CLKS_EXEC_O_CREAT 0x0040ULL +#define CLKS_EXEC_O_TRUNC 0x0200ULL +#define CLKS_EXEC_O_APPEND 0x0400ULL + +enum clks_exec_fd_kind { + CLKS_EXEC_FD_KIND_NONE = 0, + CLKS_EXEC_FD_KIND_TTY = 1, + CLKS_EXEC_FD_KIND_FILE = 2, +}; enum clks_exec_proc_state { CLKS_EXEC_PROC_UNUSED = 0, @@ -34,6 +49,15 @@ enum clks_exec_proc_state { CLKS_EXEC_PROC_STOPPED = 4, }; +struct clks_exec_fd_entry { + clks_bool used; + enum clks_exec_fd_kind kind; + u64 flags; + u64 offset; + u32 tty_index; + char path[CLKS_EXEC_PATH_MAX]; +}; + struct clks_exec_proc_record { clks_bool used; enum clks_exec_proc_state state; @@ -57,6 +81,7 @@ struct clks_exec_proc_record { u64 last_fault_vector; u64 last_fault_error; u64 last_fault_rip; + struct clks_exec_fd_entry fds[CLKS_EXEC_FD_MAX]; }; #if defined(CLKS_ARCH_X86_64) @@ -81,6 +106,8 @@ static u64 clks_exec_image_begin_stack[CLKS_EXEC_MAX_DEPTH]; static u64 clks_exec_image_end_stack[CLKS_EXEC_MAX_DEPTH]; static u32 clks_exec_pid_stack_depth = 0U; +static struct clks_exec_proc_record *clks_exec_current_proc(void); + static void clks_exec_serial_write_hex64(u64 value) { int nibble; @@ -424,6 +451,188 @@ static u64 clks_exec_alloc_pid(void) { return pid; } +static clks_bool clks_exec_fd_access_mode_valid(u64 flags) { + u64 mode = flags & CLKS_EXEC_FD_ACCESS_MASK; + return (mode == CLKS_EXEC_O_RDONLY || mode == CLKS_EXEC_O_WRONLY || mode == CLKS_EXEC_O_RDWR) ? CLKS_TRUE + : CLKS_FALSE; +} + +static clks_bool clks_exec_fd_can_read(u64 flags) { + u64 mode = flags & CLKS_EXEC_FD_ACCESS_MASK; + return (mode == CLKS_EXEC_O_RDONLY || mode == CLKS_EXEC_O_RDWR) ? CLKS_TRUE : CLKS_FALSE; +} + +static clks_bool clks_exec_fd_can_write(u64 flags) { + u64 mode = flags & CLKS_EXEC_FD_ACCESS_MASK; + return (mode == CLKS_EXEC_O_WRONLY || mode == CLKS_EXEC_O_RDWR) ? CLKS_TRUE : CLKS_FALSE; +} + +static clks_bool clks_exec_path_is_dev_tty(const char *path) { + return (path != CLKS_NULL && clks_strcmp(path, "/dev/tty") == 0) ? CLKS_TRUE : CLKS_FALSE; +} + +static void clks_exec_fd_init_defaults(struct clks_exec_proc_record *proc) { + if (proc == CLKS_NULL) { + return; + } + + clks_memset(proc->fds, 0, sizeof(proc->fds)); + + proc->fds[0].used = CLKS_TRUE; + proc->fds[0].kind = CLKS_EXEC_FD_KIND_TTY; + proc->fds[0].flags = CLKS_EXEC_O_RDONLY; + proc->fds[0].offset = 0ULL; + proc->fds[0].tty_index = proc->tty_index; + proc->fds[0].path[0] = '\0'; + + proc->fds[1].used = CLKS_TRUE; + proc->fds[1].kind = CLKS_EXEC_FD_KIND_TTY; + proc->fds[1].flags = CLKS_EXEC_O_WRONLY; + proc->fds[1].offset = 0ULL; + proc->fds[1].tty_index = proc->tty_index; + proc->fds[1].path[0] = '\0'; + + proc->fds[2].used = CLKS_TRUE; + proc->fds[2].kind = CLKS_EXEC_FD_KIND_TTY; + proc->fds[2].flags = CLKS_EXEC_O_WRONLY; + proc->fds[2].offset = 0ULL; + proc->fds[2].tty_index = proc->tty_index; + proc->fds[2].path[0] = '\0'; +} + +static i32 clks_exec_fd_find_free(struct clks_exec_proc_record *proc) { + u32 i; + + if (proc == CLKS_NULL) { + return -1; + } + + for (i = 0U; i < CLKS_EXEC_FD_MAX; i++) { + if (proc->fds[i].used == CLKS_FALSE) { + return (i32)i; + } + } + + return -1; +} + +static struct clks_exec_fd_entry *clks_exec_fd_lookup(struct clks_exec_proc_record *proc, u64 fd) { + if (proc == CLKS_NULL || fd >= CLKS_EXEC_FD_MAX) { + return CLKS_NULL; + } + + if (proc->fds[(u32)fd].used == CLKS_FALSE) { + return CLKS_NULL; + } + + return &proc->fds[(u32)fd]; +} + +static u64 clks_exec_fd_file_read(struct clks_exec_fd_entry *entry, void *out_buffer, u64 size) { + const void *file_data; + u64 file_size = 0ULL; + u64 read_len; + + if (entry == CLKS_NULL || out_buffer == CLKS_NULL || size == 0ULL) { + return 0ULL; + } + + file_data = clks_fs_read_all(entry->path, &file_size); + + if (file_data == CLKS_NULL) { + return (u64)-1; + } + + if (entry->offset >= file_size) { + return 0ULL; + } + + read_len = file_size - entry->offset; + + if (read_len > size) { + read_len = size; + } + + clks_memcpy(out_buffer, (const u8 *)file_data + (usize)entry->offset, (usize)read_len); + entry->offset += read_len; + return read_len; +} + +static u64 clks_exec_fd_file_write(struct clks_exec_fd_entry *entry, const void *buffer, u64 size) { + const void *old_data = CLKS_NULL; + u64 old_size = 0ULL; + u64 write_pos; + u64 new_size; + void *merged = CLKS_NULL; + clks_bool ok; + + if (entry == CLKS_NULL) { + return (u64)-1; + } + + if (size == 0ULL) { + return 0ULL; + } + + if (buffer == CLKS_NULL) { + return (u64)-1; + } + + if ((entry->flags & CLKS_EXEC_O_APPEND) != 0ULL) { + if (clks_fs_append(entry->path, buffer, size) == CLKS_FALSE) { + return (u64)-1; + } + + entry->offset += size; + return size; + } + + old_data = clks_fs_read_all(entry->path, &old_size); + + if (old_data == CLKS_NULL) { + return (u64)-1; + } + + write_pos = entry->offset; + + if (write_pos > (0xFFFFFFFFFFFFFFFFULL - size)) { + return (u64)-1; + } + + new_size = write_pos + size; + + if (new_size < old_size) { + new_size = old_size; + } + + if (new_size == 0ULL) { + return 0ULL; + } + + merged = clks_kmalloc((usize)new_size); + + if (merged == CLKS_NULL) { + return (u64)-1; + } + + clks_memset(merged, 0, (usize)new_size); + + if (old_size > 0ULL) { + clks_memcpy(merged, old_data, (usize)old_size); + } + + clks_memcpy((u8 *)merged + (usize)write_pos, buffer, (usize)size); + ok = clks_fs_write_all(entry->path, merged, new_size); + clks_kfree(merged); + + if (ok == CLKS_FALSE) { + return (u64)-1; + } + + entry->offset = write_pos + size; + return size; +} + static struct clks_exec_proc_record *clks_exec_prepare_proc_record(i32 slot, u64 pid, const char *path, @@ -461,6 +670,7 @@ static struct clks_exec_proc_record *clks_exec_prepare_proc_record(i32 slot, proc->last_fault_vector = 0ULL; proc->last_fault_error = 0ULL; proc->last_fault_rip = 0ULL; + clks_exec_fd_init_defaults(proc); if (proc->argc < CLKS_EXEC_MAX_ARGS) { clks_exec_copy_path(proc->argv_items[proc->argc], CLKS_EXEC_ITEM_MAX, path); @@ -965,6 +1175,215 @@ clks_bool clks_exec_request_exit(u64 status) { return CLKS_TRUE; } +u64 clks_exec_fd_open(const char *path, u64 flags, u64 mode) { + struct clks_exec_proc_record *proc = clks_exec_current_proc(); + struct clks_fs_node_info info; + i32 fd_slot; + u8 empty_payload = 0U; + + (void)mode; + + if (proc == CLKS_NULL || path == CLKS_NULL || path[0] != '/') { + return (u64)-1; + } + + if (clks_strlen(path) >= CLKS_EXEC_PATH_MAX) { + return (u64)-1; + } + + if (clks_exec_fd_access_mode_valid(flags) == CLKS_FALSE) { + return (u64)-1; + } + + if (((flags & CLKS_EXEC_O_TRUNC) != 0ULL || (flags & CLKS_EXEC_O_APPEND) != 0ULL) && + clks_exec_fd_can_write(flags) == CLKS_FALSE) { + return (u64)-1; + } + + fd_slot = clks_exec_fd_find_free(proc); + + if (fd_slot < 0) { + return (u64)-1; + } + + if (clks_exec_path_is_dev_tty(path) == CLKS_TRUE) { + struct clks_exec_fd_entry *entry = &proc->fds[(u32)fd_slot]; + + clks_memset(entry, 0, sizeof(*entry)); + entry->used = CLKS_TRUE; + entry->kind = CLKS_EXEC_FD_KIND_TTY; + entry->flags = flags; + entry->offset = 0ULL; + entry->tty_index = proc->tty_index; + entry->path[0] = '\0'; + return (u64)fd_slot; + } + + if (clks_fs_stat(path, &info) == CLKS_FALSE) { + if ((flags & CLKS_EXEC_O_CREAT) == 0ULL || clks_exec_fd_can_write(flags) == CLKS_FALSE) { + return (u64)-1; + } + + if (clks_fs_write_all(path, &empty_payload, 0ULL) == CLKS_FALSE || clks_fs_stat(path, &info) == CLKS_FALSE) { + return (u64)-1; + } + } + + if (info.type != CLKS_FS_NODE_FILE) { + return (u64)-1; + } + + if ((flags & CLKS_EXEC_O_TRUNC) != 0ULL) { + if (clks_fs_write_all(path, &empty_payload, 0ULL) == CLKS_FALSE || clks_fs_stat(path, &info) == CLKS_FALSE) { + return (u64)-1; + } + } + + { + struct clks_exec_fd_entry *entry = &proc->fds[(u32)fd_slot]; + + clks_memset(entry, 0, sizeof(*entry)); + entry->used = CLKS_TRUE; + entry->kind = CLKS_EXEC_FD_KIND_FILE; + entry->flags = flags; + entry->offset = ((flags & CLKS_EXEC_O_APPEND) != 0ULL) ? info.size : 0ULL; + entry->tty_index = proc->tty_index; + clks_exec_copy_path(entry->path, sizeof(entry->path), path); + } + + return (u64)fd_slot; +} + +u64 clks_exec_fd_read(u64 fd, void *out_buffer, u64 size) { + struct clks_exec_proc_record *proc = clks_exec_current_proc(); + struct clks_exec_fd_entry *entry; + + if (proc == CLKS_NULL) { + return (u64)-1; + } + + if (size == 0ULL) { + return 0ULL; + } + + if (out_buffer == CLKS_NULL) { + return (u64)-1; + } + + entry = clks_exec_fd_lookup(proc, fd); + + if (entry == CLKS_NULL || clks_exec_fd_can_read(entry->flags) == CLKS_FALSE) { + return (u64)-1; + } + + if (entry->kind == CLKS_EXEC_FD_KIND_TTY) { + u64 count = 0ULL; + char *dst = (char *)out_buffer; + + while (count < size) { + char ch; + + if (clks_keyboard_pop_char_for_tty(entry->tty_index, &ch) == CLKS_FALSE) { + break; + } + + dst[count] = ch; + count++; + } + + return count; + } + + if (entry->kind == CLKS_EXEC_FD_KIND_FILE) { + return clks_exec_fd_file_read(entry, out_buffer, size); + } + + return (u64)-1; +} + +u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size) { + struct clks_exec_proc_record *proc = clks_exec_current_proc(); + struct clks_exec_fd_entry *entry; + + if (proc == CLKS_NULL) { + return (u64)-1; + } + + if (size == 0ULL) { + return 0ULL; + } + + if (buffer == CLKS_NULL) { + return (u64)-1; + } + + entry = clks_exec_fd_lookup(proc, fd); + + if (entry == CLKS_NULL || clks_exec_fd_can_write(entry->flags) == CLKS_FALSE) { + return (u64)-1; + } + + if (entry->kind == CLKS_EXEC_FD_KIND_TTY) { + u64 i; + const char *src = (const char *)buffer; + + for (i = 0ULL; i < size; i++) { + clks_tty_write_char(src[i]); + } + + return size; + } + + if (entry->kind == CLKS_EXEC_FD_KIND_FILE) { + return clks_exec_fd_file_write(entry, buffer, size); + } + + return (u64)-1; +} + +u64 clks_exec_fd_close(u64 fd) { + struct clks_exec_proc_record *proc = clks_exec_current_proc(); + struct clks_exec_fd_entry *entry; + + if (proc == CLKS_NULL) { + return (u64)-1; + } + + entry = clks_exec_fd_lookup(proc, fd); + + if (entry == CLKS_NULL) { + return (u64)-1; + } + + clks_memset(entry, 0, sizeof(*entry)); + return 0ULL; +} + +u64 clks_exec_fd_dup(u64 fd) { + struct clks_exec_proc_record *proc = clks_exec_current_proc(); + struct clks_exec_fd_entry *entry; + i32 fd_slot; + + if (proc == CLKS_NULL) { + return (u64)-1; + } + + entry = clks_exec_fd_lookup(proc, fd); + + if (entry == CLKS_NULL) { + return (u64)-1; + } + + fd_slot = clks_exec_fd_find_free(proc); + + if (fd_slot < 0) { + return (u64)-1; + } + + proc->fds[(u32)fd_slot] = *entry; + return (u64)fd_slot; +} + u64 clks_exec_current_pid(void) { i32 depth_index = clks_exec_current_depth_index(); diff --git a/clks/kernel/syscall.c b/clks/kernel/syscall.c index 6d0e493..c0cc5fb 100644 --- a/clks/kernel/syscall.c +++ b/clks/kernel/syscall.c @@ -32,7 +32,7 @@ #define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL) #define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym" #define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL -#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_STATS_RECENT_ID +#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_FD_DUP #define CLKS_SYSCALL_STATS_RING_SIZE 256U struct clks_syscall_frame { @@ -210,6 +210,40 @@ static u64 clks_syscall_kbd_get_char(void) { return (u64)(u8)ch; } +static u64 clks_syscall_fd_open(u64 arg0, u64 arg1, u64 arg2) { + char path[CLKS_SYSCALL_PATH_MAX]; + + if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) { + return (u64)-1; + } + + return clks_exec_fd_open(path, arg1, arg2); +} + +static u64 clks_syscall_fd_read(u64 arg0, u64 arg1, u64 arg2) { + if (arg2 > 0ULL && arg1 == 0ULL) { + return (u64)-1; + } + + return clks_exec_fd_read(arg0, (void *)arg1, arg2); +} + +static u64 clks_syscall_fd_write(u64 arg0, u64 arg1, u64 arg2) { + if (arg2 > 0ULL && arg1 == 0ULL) { + return (u64)-1; + } + + return clks_exec_fd_write(arg0, (const void *)arg1, arg2); +} + +static u64 clks_syscall_fd_close(u64 arg0) { + return clks_exec_fd_close(arg0); +} + +static u64 clks_syscall_fd_dup(u64 arg0) { + return clks_exec_fd_dup(arg0); +} + static clks_bool clks_syscall_procfs_is_root(const char *path) { return (path != CLKS_NULL && clks_strcmp(path, "/proc") == 0) ? CLKS_TRUE : CLKS_FALSE; } @@ -1786,6 +1820,16 @@ u64 clks_syscall_dispatch(void *frame_ptr) { return clks_syscall_stats_recent_window(); case CLKS_SYSCALL_STATS_RECENT_ID: return clks_syscall_stats_recent_id(frame->rbx); + case CLKS_SYSCALL_FD_OPEN: + return clks_syscall_fd_open(frame->rbx, frame->rcx, frame->rdx); + case CLKS_SYSCALL_FD_READ: + return clks_syscall_fd_read(frame->rbx, frame->rcx, frame->rdx); + case CLKS_SYSCALL_FD_WRITE: + return clks_syscall_fd_write(frame->rbx, frame->rcx, frame->rdx); + case CLKS_SYSCALL_FD_CLOSE: + return clks_syscall_fd_close(frame->rbx); + case CLKS_SYSCALL_FD_DUP: + return clks_syscall_fd_dup(frame->rbx); default: return (u64)-1; } diff --git a/docs/syscall.md b/docs/syscall.md index 7251117..bffabd0 100644 --- a/docs/syscall.md +++ b/docs/syscall.md @@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `/proc/`:指定 PID 快照文本 - `/proc` 为只读;写入类 syscall 不支持。 -## 4. Syscall 列表(0~71) +## 4. Syscall 列表(0~76) ### 0 `CLEONOS_SYSCALL_LOG_WRITE` @@ -557,6 +557,53 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `arg0`: `u64 id` - 返回:指定 syscall ID 在“最近窗口”中的出现次数(ID 越界返回 `0`) +### 72 `CLEONOS_SYSCALL_FD_OPEN` + +- 参数: +- `arg0`: `const char *path` +- `arg1`: `u64 flags` +- `arg2`: `u64 mode`(当前保留) +- 返回:成功返回 `fd`,失败返回 `-1` +- 说明: +- 当前支持普通文件与 `/dev/tty`。 +- 默认进程会预置 `fd 0/1/2`(stdin/stdout/stderr)。 +- 标志位兼容子集:`O_RDONLY/O_WRONLY/O_RDWR/O_CREAT/O_TRUNC/O_APPEND`。 + +### 73 `CLEONOS_SYSCALL_FD_READ` + +- 参数: +- `arg0`: `u64 fd` +- `arg1`: `void *out_buffer` +- `arg2`: `u64 size` +- 返回:读取字节数;错误返回 `-1` +- 说明: +- 对 `tty fd`(如 stdin)为非阻塞读取:无输入时返回 `0`。 +- 对文件 fd 为顺序读取,内部维护偏移。 + +### 74 `CLEONOS_SYSCALL_FD_WRITE` + +- 参数: +- `arg0`: `u64 fd` +- `arg1`: `const void *buffer` +- `arg2`: `u64 size` +- 返回:写入字节数;错误返回 `-1` +- 说明: +- `tty fd` 输出到终端。 +- 文件 fd 支持顺序写;`O_APPEND` 下始终追加。 + +### 75 `CLEONOS_SYSCALL_FD_CLOSE` + +- 参数: +- `arg0`: `u64 fd` +- 返回:成功 `0`,失败 `-1` + +### 76 `CLEONOS_SYSCALL_FD_DUP` + +- 参数: +- `arg0`: `u64 oldfd` +- 返回:新 fd;失败 `-1` +- 说明:当前为“按值复制”语义(复制 flags/offset/目标对象)。 + ## 5. 用户态封装函数 用户态封装位于: @@ -581,6 +628,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `cleonos_sys_proc_count()` / `cleonos_sys_proc_pid_at()` / `cleonos_sys_proc_snapshot()` / `cleonos_sys_proc_kill()` - `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_fd_open()` / `cleonos_sys_fd_read()` / `cleonos_sys_fd_write()` / `cleonos_sys_fd_close()` / `cleonos_sys_fd_dup()` ## 6. 开发注意事项 @@ -591,6 +639,6 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); ## 7. Wine 兼容说明 -- `wine/cleonos_wine_lib/runner.py` 目前以 syscall `0..67` 为主,新增 ID 需同步适配后才能完整观测统计类接口。 +- `wine/cleonos_wine_lib/runner.py` 目前以 syscall `0..67` 为主;`68..76`(stats/fd)需同步适配后才能完整覆盖。 - Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。 - Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。