mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
Stage 28
This commit is contained in:
@@ -398,12 +398,16 @@ static int ush_cmd_exit(ush_state *sh, const char *arg) {
|
||||
}
|
||||
|
||||
static int ush_cmd_clear(void) {
|
||||
u64 i;
|
||||
|
||||
for (i = 0ULL; i < USH_CLEAR_LINES; i++) {
|
||||
ush_write_char('\n');
|
||||
}
|
||||
ush_write("\x1B[2J\x1B[H");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ush_cmd_ansi(void) {
|
||||
ush_writeln("\x1B[1;36mansi color demo\x1B[0m");
|
||||
ush_writeln(" \x1B[30mblack\x1B[0m \x1B[31mred\x1B[0m \x1B[32mgreen\x1B[0m \x1B[33myellow\x1B[0m");
|
||||
ush_writeln(" \x1B[34mblue\x1B[0m \x1B[35mmagenta\x1B[0m \x1B[36mcyan\x1B[0m \x1B[37mwhite\x1B[0m");
|
||||
ush_writeln(" \x1B[90mbright-black\x1B[0m \x1B[91mbright-red\x1B[0m \x1B[92mbright-green\x1B[0m \x1B[93mbright-yellow\x1B[0m");
|
||||
ush_writeln(" \x1B[94mbright-blue\x1B[0m \x1B[95mbright-magenta\x1B[0m \x1B[96mbright-cyan\x1B[0m \x1B[97mbright-white\x1B[0m");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -874,6 +878,8 @@ void ush_execute_line(ush_state *sh, const char *line) {
|
||||
success = ush_cmd_exit(sh, arg);
|
||||
} else if (ush_streq(cmd, "clear") != 0 || ush_streq(cmd, "cls") != 0) {
|
||||
success = ush_cmd_clear();
|
||||
} else if (ush_streq(cmd, "ansi") != 0 || ush_streq(cmd, "color") != 0) {
|
||||
success = ush_cmd_ansi();
|
||||
} else if (ush_streq(cmd, "memstat") != 0) {
|
||||
success = ush_cmd_memstat();
|
||||
} else if (ush_streq(cmd, "fsstat") != 0) {
|
||||
|
||||
@@ -246,13 +246,14 @@ void ush_writeln(const char *text) {
|
||||
|
||||
void ush_prompt(const ush_state *sh) {
|
||||
if (sh == (const ush_state *)0) {
|
||||
ush_write("cleonos(user)> ");
|
||||
ush_write("\x1B[96mcleonos\x1B[0m(\x1B[92muser\x1B[0m)> ");
|
||||
return;
|
||||
}
|
||||
|
||||
ush_write("cleonos(user:");
|
||||
ush_write("\x1B[96mcleonos\x1B[0m(\x1B[92muser\x1B[0m:");
|
||||
ush_write("\x1B[93m");
|
||||
ush_write(sh->cwd);
|
||||
ush_write(")> ");
|
||||
ush_write("\x1B[0m)> ");
|
||||
}
|
||||
|
||||
void ush_write_hex_u64(u64 value) {
|
||||
|
||||
@@ -5,10 +5,12 @@ int cleonos_app_main(void) {
|
||||
char line[USH_LINE_MAX];
|
||||
|
||||
ush_init_state(&sh);
|
||||
ush_writeln("[USER][SHELL] interactive framework online");
|
||||
ush_writeln("\x1B[92m[USER][SHELL]\x1B[0m interactive framework online");
|
||||
|
||||
if (ush_run_script_file(&sh, "/shell/init.cmd") == 0) {
|
||||
ush_writeln("[USER][SHELL] /shell/init.cmd missing");
|
||||
if (ush_run_script_file(&sh, "/shell/init.cmd") == 0 &&
|
||||
ush_run_script_file(&sh, "/shell/INIT.CMD") == 0 &&
|
||||
ush_run_script_file(&sh, "/SHELL/INIT.CMD") == 0) {
|
||||
ush_writeln("\x1B[33m[USER][SHELL]\x1B[0m init script not found, continue interactive mode");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
@@ -14,5 +14,6 @@ u64 clks_exec_yield(void);
|
||||
u64 clks_exec_request_count(void);
|
||||
u64 clks_exec_success_count(void);
|
||||
clks_bool clks_exec_is_running(void);
|
||||
clks_bool clks_exec_current_path_is_user(void);
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,7 @@ clks_bool clks_userland_init(void);
|
||||
void clks_userland_tick(u64 tick);
|
||||
clks_bool clks_userland_shell_ready(void);
|
||||
clks_bool clks_userland_shell_exec_requested(void);
|
||||
clks_bool clks_userland_shell_auto_exec_enabled(void);
|
||||
u64 clks_userland_launch_attempts(void);
|
||||
u64 clks_userland_launch_success(void);
|
||||
u64 clks_userland_launch_failures(void);
|
||||
|
||||
@@ -47,6 +47,69 @@ static clks_bool clks_exec_exit_requested_stack[CLKS_EXEC_MAX_DEPTH];
|
||||
static u64 clks_exec_exit_status_stack[CLKS_EXEC_MAX_DEPTH];
|
||||
static u32 clks_exec_pid_stack_depth = 0U;
|
||||
|
||||
static clks_bool clks_exec_has_prefix(const char *text, const char *prefix) {
|
||||
usize i = 0U;
|
||||
|
||||
if (text == CLKS_NULL || prefix == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
while (prefix[i] != '\0') {
|
||||
if (text[i] != prefix[i]) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_exec_has_suffix(const char *text, const char *suffix) {
|
||||
usize text_len;
|
||||
usize suffix_len;
|
||||
usize i;
|
||||
|
||||
if (text == CLKS_NULL || suffix == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
text_len = clks_strlen(text);
|
||||
suffix_len = clks_strlen(suffix);
|
||||
|
||||
if (suffix_len > text_len) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0U; i < suffix_len; i++) {
|
||||
if (text[text_len - suffix_len + i] != suffix[i]) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_exec_path_is_user_program(const char *path) {
|
||||
if (path == CLKS_NULL || path[0] != '/') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_exec_has_prefix(path, "/system/") == CLKS_TRUE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_exec_has_prefix(path, "/driver/") == CLKS_TRUE) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_exec_has_prefix(path, "/shell/") == CLKS_TRUE) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
return clks_exec_has_suffix(path, ".elf");
|
||||
}
|
||||
|
||||
static void clks_exec_copy_path(char *dst, usize dst_size, const char *src) {
|
||||
usize i = 0U;
|
||||
|
||||
@@ -395,3 +458,24 @@ u64 clks_exec_success_count(void) {
|
||||
clks_bool clks_exec_is_running(void) {
|
||||
return (clks_exec_running_depth > 0U) ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_bool clks_exec_current_path_is_user(void) {
|
||||
i32 depth_index;
|
||||
i32 slot;
|
||||
const struct clks_exec_proc_record *proc;
|
||||
|
||||
depth_index = clks_exec_current_depth_index();
|
||||
|
||||
if (depth_index < 0) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
slot = clks_exec_proc_find_slot_by_pid(clks_exec_pid_stack[(u32)depth_index]);
|
||||
|
||||
if (slot < 0) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
proc = &clks_exec_proc_table[(u32)slot];
|
||||
return clks_exec_path_is_user_program(proc->path);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ void clks_kernel_main(void) {
|
||||
clks_tty_init();
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS Stage25 START");
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS Stage28 START");
|
||||
|
||||
if (boot_fb == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||
@@ -224,7 +224,12 @@ void clks_kernel_main(void) {
|
||||
clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks);
|
||||
|
||||
clks_shell_init();
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "KERNEL SHELL ACTIVE");
|
||||
|
||||
if (clks_userland_shell_auto_exec_enabled() == CLKS_TRUE) {
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "DEFAULT ENTER USER SHELL MODE");
|
||||
} else {
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "KERNEL SHELL ACTIVE");
|
||||
}
|
||||
|
||||
clks_log_hex(CLKS_LOG_INFO, "TTY", "COUNT", (u64)clks_tty_count());
|
||||
clks_log_hex(CLKS_LOG_INFO, "TTY", "ACTIVE", (u64)clks_tty_active());
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define CLKS_SYSCALL_TTY_MAX_LEN 512U
|
||||
#define CLKS_SYSCALL_FS_IO_MAX_LEN 65536U
|
||||
#define CLKS_SYSCALL_JOURNAL_MAX_LEN 256U
|
||||
#define CLKS_SYSCALL_USER_TRACE_BUDGET 128ULL
|
||||
|
||||
struct clks_syscall_frame {
|
||||
u64 rax;
|
||||
@@ -46,6 +47,8 @@ struct clks_syscall_frame {
|
||||
};
|
||||
|
||||
static clks_bool clks_syscall_ready = CLKS_FALSE;
|
||||
static clks_bool clks_syscall_user_trace_active = CLKS_FALSE;
|
||||
static u64 clks_syscall_user_trace_budget = 0ULL;
|
||||
|
||||
static clks_bool clks_syscall_copy_user_string(u64 src_addr, char *dst, usize dst_size) {
|
||||
const char *src = (const char *)src_addr;
|
||||
@@ -375,8 +378,43 @@ static u64 clks_syscall_log_journal_read(u64 arg0, u64 arg1, u64 arg2) {
|
||||
return 1ULL;
|
||||
}
|
||||
|
||||
static void clks_syscall_trace_user_program(u64 id) {
|
||||
clks_bool user_program_running =
|
||||
(clks_exec_is_running() == CLKS_TRUE && clks_exec_current_path_is_user() == CLKS_TRUE)
|
||||
? CLKS_TRUE
|
||||
: CLKS_FALSE;
|
||||
|
||||
if (user_program_running == CLKS_FALSE) {
|
||||
if (clks_syscall_user_trace_active == CLKS_TRUE) {
|
||||
clks_log(CLKS_LOG_DEBUG, "SYSCALL", "USER_TRACE_END");
|
||||
}
|
||||
|
||||
clks_syscall_user_trace_active = CLKS_FALSE;
|
||||
clks_syscall_user_trace_budget = 0ULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_syscall_user_trace_active == CLKS_FALSE) {
|
||||
clks_syscall_user_trace_active = CLKS_TRUE;
|
||||
clks_syscall_user_trace_budget = CLKS_SYSCALL_USER_TRACE_BUDGET;
|
||||
clks_log(CLKS_LOG_DEBUG, "SYSCALL", "USER_TRACE_BEGIN");
|
||||
clks_log_hex(CLKS_LOG_DEBUG, "SYSCALL", "PID", clks_exec_current_pid());
|
||||
}
|
||||
|
||||
if (clks_syscall_user_trace_budget > 0ULL) {
|
||||
clks_log_hex(CLKS_LOG_DEBUG, "SYSCALL", "USER_ID", id);
|
||||
clks_syscall_user_trace_budget--;
|
||||
|
||||
if (clks_syscall_user_trace_budget == 0ULL) {
|
||||
clks_log(CLKS_LOG_DEBUG, "SYSCALL", "USER_TRACE_BUDGET_EXHAUSTED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clks_syscall_init(void) {
|
||||
clks_syscall_ready = CLKS_TRUE;
|
||||
clks_syscall_user_trace_active = CLKS_FALSE;
|
||||
clks_syscall_user_trace_budget = 0ULL;
|
||||
clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE");
|
||||
}
|
||||
|
||||
@@ -389,6 +427,7 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
||||
}
|
||||
|
||||
id = frame->rax;
|
||||
clks_syscall_trace_user_program(id);
|
||||
|
||||
switch (id) {
|
||||
case CLKS_SYSCALL_LOG_WRITE:
|
||||
|
||||
@@ -12,10 +12,24 @@
|
||||
#define CLKS_TTY_CURSOR_BLINK_INTERVAL_TICKS 5ULL
|
||||
#define CLKS_TTY_BLINK_TICK_UNSET 0xFFFFFFFFFFFFFFFFULL
|
||||
#define CLKS_TTY_DESKTOP_INDEX 1U
|
||||
#define CLKS_TTY_ANSI_MAX_LEN 31U
|
||||
|
||||
typedef struct clks_tty_ansi_state {
|
||||
clks_bool in_escape;
|
||||
clks_bool saw_csi;
|
||||
clks_bool bold;
|
||||
u32 len;
|
||||
char params[CLKS_TTY_ANSI_MAX_LEN + 1U];
|
||||
} clks_tty_ansi_state;
|
||||
|
||||
static char clks_tty_cells[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS];
|
||||
static u32 clks_tty_cell_fg[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS];
|
||||
static u32 clks_tty_cell_bg[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS];
|
||||
static u32 clks_tty_cursor_row[CLKS_TTY_COUNT];
|
||||
static u32 clks_tty_cursor_col[CLKS_TTY_COUNT];
|
||||
static u32 clks_tty_current_fg[CLKS_TTY_COUNT];
|
||||
static u32 clks_tty_current_bg[CLKS_TTY_COUNT];
|
||||
static clks_tty_ansi_state clks_tty_ansi[CLKS_TTY_COUNT];
|
||||
|
||||
static u32 clks_tty_rows = 0;
|
||||
static u32 clks_tty_cols = 0;
|
||||
@@ -27,24 +41,71 @@ static clks_bool clks_tty_cursor_visible = CLKS_FALSE;
|
||||
static clks_bool clks_tty_blink_enabled = CLKS_TRUE;
|
||||
static u64 clks_tty_blink_last_tick = CLKS_TTY_BLINK_TICK_UNSET;
|
||||
|
||||
static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) {
|
||||
u32 col;
|
||||
static u32 clks_tty_ansi_palette(u32 index) {
|
||||
static const u32 palette[16] = {
|
||||
0x00000000U, 0x00CD3131U, 0x000DBC79U, 0x00E5E510U,
|
||||
0x002472C8U, 0x00BC3FBCU, 0x0011A8CDU, 0x00E5E5E5U,
|
||||
0x00666666U, 0x00F14C4CU, 0x0023D18BU, 0x00F5F543U,
|
||||
0x003B8EEAU, 0x00D670D6U, 0x0029B8DBU, 0x00FFFFFFU
|
||||
};
|
||||
|
||||
for (col = 0; col < clks_tty_cols; col++) {
|
||||
clks_tty_cells[tty_index][row][col] = ch;
|
||||
if (index < 16U) {
|
||||
return palette[index];
|
||||
}
|
||||
|
||||
return CLKS_TTY_FG;
|
||||
}
|
||||
|
||||
static void clks_tty_reset_blink_timer(void) {
|
||||
clks_tty_blink_last_tick = CLKS_TTY_BLINK_TICK_UNSET;
|
||||
}
|
||||
|
||||
static void clks_tty_draw_cell_with_colors(u32 row, u32 col, char ch, u32 fg, u32 bg) {
|
||||
clks_fb_draw_char(col * clks_tty_cell_width, row * clks_tty_cell_height, ch, fg, bg);
|
||||
}
|
||||
|
||||
static void clks_tty_draw_cell(u32 row, u32 col, char ch) {
|
||||
clks_tty_draw_cell_with_colors(row, col, ch, CLKS_TTY_FG, CLKS_TTY_BG);
|
||||
static void clks_tty_draw_cell(u32 tty_index, u32 row, u32 col) {
|
||||
clks_tty_draw_cell_with_colors(
|
||||
row,
|
||||
col,
|
||||
clks_tty_cells[tty_index][row][col],
|
||||
clks_tty_cell_fg[tty_index][row][col],
|
||||
clks_tty_cell_bg[tty_index][row][col]
|
||||
);
|
||||
}
|
||||
|
||||
static void clks_tty_reset_blink_timer(void) {
|
||||
clks_tty_blink_last_tick = CLKS_TTY_BLINK_TICK_UNSET;
|
||||
static void clks_tty_reset_color_state(u32 tty_index) {
|
||||
clks_tty_current_fg[tty_index] = CLKS_TTY_FG;
|
||||
clks_tty_current_bg[tty_index] = CLKS_TTY_BG;
|
||||
clks_tty_ansi[tty_index].bold = CLKS_FALSE;
|
||||
}
|
||||
|
||||
static void clks_tty_reset_ansi_state(u32 tty_index) {
|
||||
clks_tty_ansi[tty_index].in_escape = CLKS_FALSE;
|
||||
clks_tty_ansi[tty_index].saw_csi = CLKS_FALSE;
|
||||
clks_tty_ansi[tty_index].len = 0U;
|
||||
clks_tty_ansi[tty_index].params[0] = '\0';
|
||||
}
|
||||
|
||||
static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) {
|
||||
u32 col;
|
||||
|
||||
for (col = 0; col < clks_tty_cols; col++) {
|
||||
clks_tty_cells[tty_index][row][col] = ch;
|
||||
clks_tty_cell_fg[tty_index][row][col] = CLKS_TTY_FG;
|
||||
clks_tty_cell_bg[tty_index][row][col] = CLKS_TTY_BG;
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_tty_clear_tty(u32 tty_index) {
|
||||
u32 row;
|
||||
|
||||
for (row = 0; row < clks_tty_rows; row++) {
|
||||
clks_tty_fill_row(tty_index, row, ' ');
|
||||
}
|
||||
|
||||
clks_tty_cursor_row[tty_index] = 0U;
|
||||
clks_tty_cursor_col[tty_index] = 0U;
|
||||
}
|
||||
|
||||
static void clks_tty_hide_cursor(void) {
|
||||
@@ -59,7 +120,7 @@ static void clks_tty_hide_cursor(void) {
|
||||
col = clks_tty_cursor_col[clks_tty_active_index];
|
||||
|
||||
if (row < clks_tty_rows && col < clks_tty_cols) {
|
||||
clks_tty_draw_cell(row, col, clks_tty_cells[clks_tty_active_index][row][col]);
|
||||
clks_tty_draw_cell(clks_tty_active_index, row, col);
|
||||
}
|
||||
|
||||
clks_tty_cursor_visible = CLKS_FALSE;
|
||||
@@ -68,6 +129,9 @@ static void clks_tty_hide_cursor(void) {
|
||||
static void clks_tty_draw_cursor(void) {
|
||||
u32 row;
|
||||
u32 col;
|
||||
u32 fg;
|
||||
u32 bg;
|
||||
char ch;
|
||||
|
||||
if (clks_tty_is_ready == CLKS_FALSE) {
|
||||
return;
|
||||
@@ -86,14 +150,11 @@ static void clks_tty_draw_cursor(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
clks_tty_draw_cell_with_colors(
|
||||
row,
|
||||
col,
|
||||
clks_tty_cells[clks_tty_active_index][row][col],
|
||||
CLKS_TTY_BG,
|
||||
CLKS_TTY_FG
|
||||
);
|
||||
ch = clks_tty_cells[clks_tty_active_index][row][col];
|
||||
fg = clks_tty_cell_fg[clks_tty_active_index][row][col];
|
||||
bg = clks_tty_cell_bg[clks_tty_active_index][row][col];
|
||||
|
||||
clks_tty_draw_cell_with_colors(row, col, ch, bg, fg);
|
||||
clks_tty_cursor_visible = CLKS_TRUE;
|
||||
}
|
||||
|
||||
@@ -106,7 +167,7 @@ static void clks_tty_redraw_active(void) {
|
||||
|
||||
for (row = 0; row < clks_tty_rows; row++) {
|
||||
for (col = 0; col < clks_tty_cols; col++) {
|
||||
clks_tty_draw_cell(row, col, clks_tty_cells[clks_tty_active_index][row][col]);
|
||||
clks_tty_draw_cell(clks_tty_active_index, row, col);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,14 +178,20 @@ static void clks_tty_scroll_up(u32 tty_index) {
|
||||
u32 row;
|
||||
|
||||
for (row = 1; row < clks_tty_rows; row++) {
|
||||
clks_memcpy(clks_tty_cells[tty_index][row - 1U], clks_tty_cells[tty_index][row], clks_tty_cols);
|
||||
clks_memcpy(
|
||||
clks_tty_cells[tty_index][row - 1],
|
||||
clks_tty_cells[tty_index][row],
|
||||
clks_tty_cols
|
||||
clks_tty_cell_fg[tty_index][row - 1U],
|
||||
clks_tty_cell_fg[tty_index][row],
|
||||
(usize)clks_tty_cols * sizeof(u32)
|
||||
);
|
||||
clks_memcpy(
|
||||
clks_tty_cell_bg[tty_index][row - 1U],
|
||||
clks_tty_cell_bg[tty_index][row],
|
||||
(usize)clks_tty_cols * sizeof(u32)
|
||||
);
|
||||
}
|
||||
|
||||
clks_tty_fill_row(tty_index, clks_tty_rows - 1, ' ');
|
||||
clks_tty_fill_row(tty_index, clks_tty_rows - 1U, ' ');
|
||||
|
||||
if (tty_index == clks_tty_active_index) {
|
||||
u32 col;
|
||||
@@ -132,16 +199,18 @@ static void clks_tty_scroll_up(u32 tty_index) {
|
||||
clks_fb_scroll_up(clks_tty_cell_height, CLKS_TTY_BG);
|
||||
|
||||
for (col = 0U; col < clks_tty_cols; col++) {
|
||||
clks_tty_draw_cell(clks_tty_rows - 1U, col, clks_tty_cells[tty_index][clks_tty_rows - 1U][col]);
|
||||
clks_tty_draw_cell(tty_index, clks_tty_rows - 1U, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_tty_put_visible(u32 tty_index, u32 row, u32 col, char ch) {
|
||||
clks_tty_cells[tty_index][row][col] = ch;
|
||||
clks_tty_cell_fg[tty_index][row][col] = clks_tty_current_fg[tty_index];
|
||||
clks_tty_cell_bg[tty_index][row][col] = clks_tty_current_bg[tty_index];
|
||||
|
||||
if (tty_index == clks_tty_active_index) {
|
||||
clks_tty_draw_cell(row, col, ch);
|
||||
clks_tty_draw_cell(tty_index, row, col);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,10 +275,163 @@ static void clks_tty_put_char_raw(u32 tty_index, char ch) {
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_tty_ansi_apply_sgr_code(u32 tty_index, u32 code) {
|
||||
if (code == 0U) {
|
||||
clks_tty_reset_color_state(tty_index);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == 1U) {
|
||||
clks_tty_ansi[tty_index].bold = CLKS_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == 22U) {
|
||||
clks_tty_ansi[tty_index].bold = CLKS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == 39U) {
|
||||
clks_tty_current_fg[tty_index] = CLKS_TTY_FG;
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == 49U) {
|
||||
clks_tty_current_bg[tty_index] = CLKS_TTY_BG;
|
||||
return;
|
||||
}
|
||||
|
||||
if (code >= 30U && code <= 37U) {
|
||||
u32 idx = code - 30U;
|
||||
|
||||
if (clks_tty_ansi[tty_index].bold == CLKS_TRUE) {
|
||||
idx += 8U;
|
||||
}
|
||||
|
||||
clks_tty_current_fg[tty_index] = clks_tty_ansi_palette(idx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code >= 90U && code <= 97U) {
|
||||
clks_tty_current_fg[tty_index] = clks_tty_ansi_palette((code - 90U) + 8U);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code >= 40U && code <= 47U) {
|
||||
clks_tty_current_bg[tty_index] = clks_tty_ansi_palette(code - 40U);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code >= 100U && code <= 107U) {
|
||||
clks_tty_current_bg[tty_index] = clks_tty_ansi_palette((code - 100U) + 8U);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_tty_ansi_apply_sgr_params(u32 tty_index, const char *params, u32 len) {
|
||||
u32 i;
|
||||
u32 value = 0U;
|
||||
clks_bool has_digit = CLKS_FALSE;
|
||||
|
||||
if (len == 0U) {
|
||||
clks_tty_ansi_apply_sgr_code(tty_index, 0U);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0U; i <= len; i++) {
|
||||
char ch = (i < len) ? params[i] : ';';
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
has_digit = CLKS_TRUE;
|
||||
value = (value * 10U) + (u32)(ch - '0');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == ';') {
|
||||
if (has_digit == CLKS_TRUE) {
|
||||
clks_tty_ansi_apply_sgr_code(tty_index, value);
|
||||
} else {
|
||||
clks_tty_ansi_apply_sgr_code(tty_index, 0U);
|
||||
}
|
||||
|
||||
value = 0U;
|
||||
has_digit = CLKS_FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static clks_bool clks_tty_ansi_process_byte(u32 tty_index, char ch) {
|
||||
clks_tty_ansi_state *state = &clks_tty_ansi[tty_index];
|
||||
|
||||
if (state->in_escape == CLKS_FALSE) {
|
||||
if ((u8)ch == 0x1BU) {
|
||||
state->in_escape = CLKS_TRUE;
|
||||
state->saw_csi = CLKS_FALSE;
|
||||
state->len = 0U;
|
||||
state->params[0] = '\0';
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (state->saw_csi == CLKS_FALSE) {
|
||||
if (ch == '[') {
|
||||
state->saw_csi = CLKS_TRUE;
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
clks_tty_reset_ansi_state(tty_index);
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if ((ch >= '0' && ch <= '9') || ch == ';') {
|
||||
if (state->len < CLKS_TTY_ANSI_MAX_LEN) {
|
||||
state->params[state->len++] = ch;
|
||||
state->params[state->len] = '\0';
|
||||
} else {
|
||||
clks_tty_reset_ansi_state(tty_index);
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (ch == 'm') {
|
||||
clks_tty_ansi_apply_sgr_params(tty_index, state->params, state->len);
|
||||
clks_tty_reset_ansi_state(tty_index);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (ch == 'J') {
|
||||
if (state->len == 0U || (state->len == 1U && state->params[0] == '2')) {
|
||||
clks_tty_clear_tty(tty_index);
|
||||
|
||||
if (tty_index == clks_tty_active_index) {
|
||||
clks_tty_redraw_active();
|
||||
}
|
||||
}
|
||||
|
||||
clks_tty_reset_ansi_state(tty_index);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (ch == 'H') {
|
||||
clks_tty_cursor_row[tty_index] = 0U;
|
||||
clks_tty_cursor_col[tty_index] = 0U;
|
||||
clks_tty_reset_ansi_state(tty_index);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
clks_tty_reset_ansi_state(tty_index);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
void clks_tty_init(void) {
|
||||
struct clks_framebuffer_info info;
|
||||
u32 tty;
|
||||
u32 row;
|
||||
|
||||
if (clks_fb_ready() == CLKS_FALSE) {
|
||||
clks_tty_is_ready = CLKS_FALSE;
|
||||
@@ -244,16 +466,15 @@ void clks_tty_init(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (tty = 0; tty < CLKS_TTY_COUNT; tty++) {
|
||||
clks_tty_cursor_row[tty] = 0;
|
||||
clks_tty_cursor_col[tty] = 0;
|
||||
|
||||
for (row = 0; row < clks_tty_rows; row++) {
|
||||
clks_tty_fill_row(tty, row, ' ');
|
||||
}
|
||||
for (tty = 0U; tty < CLKS_TTY_COUNT; tty++) {
|
||||
clks_tty_cursor_row[tty] = 0U;
|
||||
clks_tty_cursor_col[tty] = 0U;
|
||||
clks_tty_reset_color_state(tty);
|
||||
clks_tty_reset_ansi_state(tty);
|
||||
clks_tty_clear_tty(tty);
|
||||
}
|
||||
|
||||
clks_tty_active_index = 0;
|
||||
clks_tty_active_index = 0U;
|
||||
clks_tty_is_ready = CLKS_TRUE;
|
||||
clks_tty_cursor_visible = CLKS_FALSE;
|
||||
clks_tty_blink_enabled = CLKS_TRUE;
|
||||
@@ -271,7 +492,10 @@ void clks_tty_write_char(char ch) {
|
||||
clks_tty_hide_cursor();
|
||||
|
||||
tty_index = clks_tty_active_index;
|
||||
clks_tty_put_char_raw(tty_index, ch);
|
||||
|
||||
if (clks_tty_ansi_process_byte(tty_index, ch) == CLKS_FALSE) {
|
||||
clks_tty_put_char_raw(tty_index, ch);
|
||||
}
|
||||
|
||||
clks_tty_draw_cursor();
|
||||
clks_tty_reset_blink_timer();
|
||||
@@ -289,7 +513,10 @@ void clks_tty_write(const char *text) {
|
||||
tty_index = clks_tty_active_index;
|
||||
|
||||
while (text[i] != '\0') {
|
||||
clks_tty_put_char_raw(tty_index, text[i]);
|
||||
if (clks_tty_ansi_process_byte(tty_index, text[i]) == CLKS_FALSE) {
|
||||
clks_tty_put_char_raw(tty_index, text[i]);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ static u64 clks_user_launch_attempt_count = 0ULL;
|
||||
static u64 clks_user_launch_success_count = 0ULL;
|
||||
static u64 clks_user_launch_fail_count = 0ULL;
|
||||
static u64 clks_user_last_try_tick = 0ULL;
|
||||
static clks_bool clks_user_first_try_pending = CLKS_FALSE;
|
||||
|
||||
static clks_bool clks_userland_probe_elf(const char *path, const char *tag) {
|
||||
const void *image;
|
||||
@@ -83,11 +84,12 @@ clks_bool clks_userland_init(void) {
|
||||
|
||||
clks_user_shell_ready = CLKS_FALSE;
|
||||
clks_user_shell_exec_requested_flag = CLKS_FALSE;
|
||||
clks_user_shell_exec_enabled = CLKS_FALSE;
|
||||
clks_user_shell_exec_enabled = CLKS_TRUE;
|
||||
clks_user_launch_attempt_count = 0ULL;
|
||||
clks_user_launch_success_count = 0ULL;
|
||||
clks_user_launch_fail_count = 0ULL;
|
||||
clks_user_last_try_tick = 0ULL;
|
||||
clks_user_first_try_pending = CLKS_TRUE;
|
||||
|
||||
if (clks_userland_probe_elf("/shell/shell.elf", "SHELL ELF READY") == CLKS_FALSE) {
|
||||
return CLKS_FALSE;
|
||||
@@ -105,7 +107,7 @@ clks_bool clks_userland_init(void) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "USER", "USER SHELL EXEC DISABLED (KERNEL SHELL MODE)");
|
||||
clks_log(CLKS_LOG_INFO, "USER", "USER SHELL AUTO EXEC ENABLED");
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
@@ -116,6 +118,13 @@ void clks_userland_tick(u64 tick) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_user_first_try_pending == CLKS_TRUE) {
|
||||
clks_user_first_try_pending = CLKS_FALSE;
|
||||
clks_user_last_try_tick = tick;
|
||||
(void)clks_userland_request_shell_exec();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tick - clks_user_last_try_tick < CLKS_USERLAND_RETRY_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
@@ -132,6 +141,10 @@ clks_bool clks_userland_shell_exec_requested(void) {
|
||||
return clks_user_shell_exec_requested_flag;
|
||||
}
|
||||
|
||||
clks_bool clks_userland_shell_auto_exec_enabled(void) {
|
||||
return clks_user_shell_exec_enabled;
|
||||
}
|
||||
|
||||
u64 clks_userland_launch_attempts(void) {
|
||||
return clks_user_launch_attempt_count;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
- `stage24.md`
|
||||
- `stage25.md`
|
||||
- `stage26.md`
|
||||
- `stage27.md`
|
||||
- `stage28.md`
|
||||
|
||||
- `syscall.md` (syscall ABI reference)
|
||||
|
||||
## Notes
|
||||
- Stage docs use a fixed template: goal, implementation, acceptance criteria, build targets, QEMU command, and debugging notes.
|
||||
- Stages 16~19 are currently not documented in this folder; add them later using the same template to keep history continuous.
|
||||
|
||||
|
||||
|
||||
34
docs/stage27.md
Normal file
34
docs/stage27.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Stage 27 - User Shell/Wine Split and Syscall Expansion
|
||||
|
||||
## Goal
|
||||
- Expand user shell capability toward kernel-shell parity.
|
||||
- Extend syscall ABI for richer process/runtime operations.
|
||||
- Split CLeonOS-Wine implementation into maintainable modules.
|
||||
|
||||
## Implementation
|
||||
- Added more user-facing commands in user shell around process/runtime control (`spawn`, `wait`, `sleep`, `yield`, `pid`, file ops under `/temp`).
|
||||
- Extended syscall surface (process and runtime related IDs) and kept kernel/user syscall ID tables aligned.
|
||||
- Updated user runtime syscall wrappers to cover newly added syscall IDs.
|
||||
- Refactored Wine codebase from single-file implementation into modular structure for CLI, ELF loader, syscall bridge, and runtime helpers.
|
||||
|
||||
## Acceptance Criteria
|
||||
- User shell can complete process and temp-file workflows without falling back to kernel shell.
|
||||
- New syscall IDs are available consistently in:
|
||||
- `clks/include/clks/syscall.h`
|
||||
- `cleonos/c/include/cleonos_syscall.h`
|
||||
- `cleonos/c/src/syscall.c`
|
||||
- Wine entry remains runnable after split (`python cleonos_wine.py ...`).
|
||||
|
||||
## Build Targets
|
||||
- `make userapps`
|
||||
- `make ramdisk`
|
||||
- `make iso`
|
||||
- `make run`
|
||||
|
||||
## QEMU Command
|
||||
- `make run`
|
||||
|
||||
## Debug Notes
|
||||
- If a user command reports `request failed`, verify syscall ID mapping first.
|
||||
- If `wait`/`spawn` behavior is wrong, check `clks/kernel/exec.c` process table and pid stack.
|
||||
- If Wine import fails after split, check package/module import paths and `__init__.py` exports.
|
||||
43
docs/stage28.md
Normal file
43
docs/stage28.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Stage 28 - ANSI TTY + Default User Shell Entry + User Syscall Trace
|
||||
|
||||
## Goal
|
||||
- Add ANSI color control support to TTY.
|
||||
- Introduce ANSI-colored experience in user shell.
|
||||
- Default to entering user shell after kernel is ready.
|
||||
- Add serial log tracing for syscalls while user programs are running.
|
||||
|
||||
## Implementation
|
||||
- TTY:
|
||||
- Added ANSI CSI/SGR parsing (`ESC[...m`) for standard foreground/background colors.
|
||||
- Added support for reset/default color behavior (`0`, `39`, `49`) and bright color range (`90..97`, `100..107`).
|
||||
- Added per-cell color buffers so scrolling/redraw keeps color attributes.
|
||||
- User shell:
|
||||
- Colored prompt and startup text now use ANSI sequences.
|
||||
- Added `ansi`/`color` command to preview palette.
|
||||
- `clear` now uses ANSI clear/home sequence.
|
||||
- Boot behavior:
|
||||
- Enabled user shell auto-exec by default in userland manager.
|
||||
- Boot log now reports default user-shell mode when auto-exec is enabled.
|
||||
- Syscall tracing:
|
||||
- Added bounded debug trace in `clks/kernel/syscall.c` for syscalls issued while a user-path program is active.
|
||||
- Trace emits begin/end markers and syscall IDs with budget guard to avoid log flooding.
|
||||
|
||||
## Acceptance Criteria
|
||||
- User shell prompt/output can display ANSI colors correctly on TTY.
|
||||
- Boot enters default user-shell flow (auto launch enabled).
|
||||
- Serial logs include syscall trace lines while user programs execute.
|
||||
- Stage27 and Stage28 docs are present and indexed in `docs/README.md`.
|
||||
|
||||
## Build Targets
|
||||
- `make userapps`
|
||||
- `make ramdisk`
|
||||
- `make iso`
|
||||
- `make run`
|
||||
|
||||
## QEMU Command
|
||||
- `make run`
|
||||
|
||||
## Debug Notes
|
||||
- If ANSI text shows raw escape chars, verify `clks/kernel/tty.c` ANSI parser path is compiled.
|
||||
- If user shell does not auto launch, check `clks/kernel/userland.c` auto-exec flags and retry tick flow.
|
||||
- If syscall trace is missing, confirm `clks_exec_current_path_is_user()` is true during the target run.
|
||||
Reference in New Issue
Block a user