mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
terminal fixes
This commit is contained in:
parent
3fbcf3d4fd
commit
b40d3c050d
12 changed files with 149 additions and 28 deletions
BIN
boredos.iso
BIN
boredos.iso
Binary file not shown.
BIN
build/cmd.o
BIN
build/cmd.o
Binary file not shown.
|
|
@ -871,10 +871,12 @@ void cmd_screen_clear() {
|
||||||
for(int c=0; c<terminal_cols; c++) {
|
for(int c=0; c<terminal_cols; c++) {
|
||||||
screen_buffer[r * terminal_cols + c].c = ' ';
|
screen_buffer[r * terminal_cols + c].c = ' ';
|
||||||
screen_buffer[r * terminal_cols + c].color = COLOR_DARK_TEXT;
|
screen_buffer[r * terminal_cols + c].color = COLOR_DARK_TEXT;
|
||||||
|
screen_buffer[r * terminal_cols + c].attrs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor_row = 0;
|
cursor_row = 0;
|
||||||
cursor_col = 0;
|
cursor_col = 0;
|
||||||
|
wm_mark_dirty(win_cmd.x, win_cmd.y, win_cmd.w, win_cmd.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public for CLI apps to use - exit/close the terminal window
|
// Public for CLI apps to use - exit/close the terminal window
|
||||||
|
|
@ -1159,8 +1161,6 @@ void cmd_process_finished(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int cursor_col;
|
|
||||||
void cmd_putchar(char c);
|
|
||||||
if (cursor_col > 0) {
|
if (cursor_col > 0) {
|
||||||
cmd_putchar('\n');
|
cmd_putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
@ -2000,6 +2000,21 @@ void cmd_handle_click(Window *win, int x, int y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmd_handle_close(Window *win) {
|
||||||
|
if (!win) return;
|
||||||
|
|
||||||
|
extern process_t* process_get_by_ui_window(void *win);
|
||||||
|
extern void process_terminate(process_t *proc);
|
||||||
|
|
||||||
|
// Find any process associated with this terminal window and terminate it
|
||||||
|
process_t *proc = process_get_by_ui_window(win);
|
||||||
|
if (proc) {
|
||||||
|
process_terminate(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
win->visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
void cmd_set_raw_mode(bool enabled) {
|
void cmd_set_raw_mode(bool enabled) {
|
||||||
terminal_raw_mode = enabled;
|
terminal_raw_mode = enabled;
|
||||||
}
|
}
|
||||||
|
|
@ -2470,6 +2485,7 @@ void cmd_init(void) {
|
||||||
win_cmd.handle_key = cmd_key;
|
win_cmd.handle_key = cmd_key;
|
||||||
win_cmd.handle_click = cmd_handle_click;
|
win_cmd.handle_click = cmd_handle_click;
|
||||||
win_cmd.handle_right_click = NULL;
|
win_cmd.handle_right_click = NULL;
|
||||||
|
win_cmd.handle_close = cmd_handle_close;
|
||||||
win_cmd.handle_resize = cmd_handle_resize;
|
win_cmd.handle_resize = cmd_handle_resize;
|
||||||
win_cmd.resizable = true;
|
win_cmd.resizable = true;
|
||||||
|
|
||||||
|
|
|
||||||
BIN
src/kernel/images/.DS_Store
vendored
BIN
src/kernel/images/.DS_Store
vendored
Binary file not shown.
|
|
@ -272,6 +272,27 @@ int network_tcp_recv(void *buf, size_t max_len) {
|
||||||
return (int)copied;
|
return (int)copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int network_tcp_recv_nb(void *buf, size_t max_len) {
|
||||||
|
if (network_processing) return -1;
|
||||||
|
network_processing = 1;
|
||||||
|
|
||||||
|
if (!tcp_recv_queue) {
|
||||||
|
network_processing = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t to_copy = max_len;
|
||||||
|
if (to_copy > tcp_recv_queue->tot_len) to_copy = tcp_recv_queue->tot_len;
|
||||||
|
if (to_copy > 0xFFFF) to_copy = 0xFFFF; // pbuf_copy_partial limit
|
||||||
|
|
||||||
|
size_t copied = pbuf_copy_partial(tcp_recv_queue, buf, (u16_t)to_copy, 0);
|
||||||
|
struct pbuf *remainder = pbuf_free_header(tcp_recv_queue, (u16_t)copied);
|
||||||
|
if (current_tcp_pcb) tcp_recved(current_tcp_pcb, (u16_t)copied);
|
||||||
|
tcp_recv_queue = remainder;
|
||||||
|
network_processing = 0;
|
||||||
|
return (int)copied;
|
||||||
|
}
|
||||||
|
|
||||||
int network_tcp_close(void) {
|
int network_tcp_close(void) {
|
||||||
if (network_processing) return 0;
|
if (network_processing) return 0;
|
||||||
network_processing = 1;
|
network_processing = 1;
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,13 @@ int network_dhcp_acquire(void);
|
||||||
int network_get_gateway_ip(ipv4_address_t* ip);
|
int network_get_gateway_ip(ipv4_address_t* ip);
|
||||||
int network_get_dns_ip(ipv4_address_t *ip);
|
int network_get_dns_ip(ipv4_address_t *ip);
|
||||||
int network_icmp_single_ping(ipv4_address_t *dest);
|
int network_icmp_single_ping(ipv4_address_t *dest);
|
||||||
|
int network_tcp_connect(const ipv4_address_t *ip, uint16_t port);
|
||||||
|
int network_tcp_send(const void *data, size_t len);
|
||||||
|
int network_tcp_recv(void *buf, size_t max_len);
|
||||||
|
int network_tcp_recv_nb(void *buf, size_t max_len);
|
||||||
|
int network_tcp_close(void);
|
||||||
|
int network_dns_lookup(const char *name, ipv4_address_t *out_ip);
|
||||||
|
int network_set_dns_server(const ipv4_address_t *ip);
|
||||||
void network_cleanup(void);
|
void network_cleanup(void);
|
||||||
void network_force_unlock(void);
|
void network_force_unlock(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,72 @@ uint64_t process_schedule(uint64_t current_rsp) {
|
||||||
return current_process->rsp;
|
return current_process->rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void process_cleanup_inner(process_t *proc) {
|
||||||
|
if (!proc || proc->pid == 0xFFFFFFFF) return;
|
||||||
|
|
||||||
|
// 1. Cleanup side effects
|
||||||
|
extern Window win_cmd;
|
||||||
|
if (proc->ui_window && (proc->ui_window != &win_cmd)) {
|
||||||
|
wm_remove_window((Window *)proc->ui_window);
|
||||||
|
proc->ui_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void fat32_close(struct FAT32_FileHandle *fh);
|
||||||
|
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
||||||
|
if (proc->fds[i]) {
|
||||||
|
fat32_close(proc->fds[i]);
|
||||||
|
proc->fds[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void cmd_process_finished(void);
|
||||||
|
cmd_process_finished();
|
||||||
|
|
||||||
|
extern void network_cleanup_pcb(void *pcb);
|
||||||
|
// TODO: We need per-process PCB tracking to call this safely
|
||||||
|
// For now, let's NOT call global network_cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_terminate(process_t *to_delete) {
|
||||||
|
if (!to_delete || to_delete->pid == 0xFFFFFFFF) return;
|
||||||
|
|
||||||
|
uint64_t rflags;
|
||||||
|
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||||
|
|
||||||
|
process_cleanup_inner(to_delete);
|
||||||
|
|
||||||
|
// 2. Find previous process in circular list
|
||||||
|
process_t *prev = to_delete;
|
||||||
|
while (prev->next != to_delete) {
|
||||||
|
prev = prev->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev == to_delete) {
|
||||||
|
// Only one process (should be kernel), cannot terminate.
|
||||||
|
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Remove current from list
|
||||||
|
prev->next = to_delete->next;
|
||||||
|
|
||||||
|
if (to_delete == current_process) {
|
||||||
|
current_process = to_delete->next;
|
||||||
|
// WARNING: If this was called as a regular function and not via a task switch,
|
||||||
|
// the stack might be in a weird state. But usually we call this via window manager
|
||||||
|
// or other external triggers.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark slot as free
|
||||||
|
to_delete->pid = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
|
||||||
|
to_delete->user_stack_alloc = NULL;
|
||||||
|
to_delete->kernel_stack_alloc = NULL;
|
||||||
|
|
||||||
|
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t process_terminate_current(void) {
|
uint64_t process_terminate_current(void) {
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||||
|
|
@ -338,26 +404,7 @@ uint64_t process_terminate_current(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Cleanup side effects
|
process_cleanup_inner(current_process);
|
||||||
extern Window win_cmd;
|
|
||||||
if (current_process->ui_window && (current_process->ui_window != &win_cmd)) {
|
|
||||||
wm_remove_window((Window *)current_process->ui_window);
|
|
||||||
current_process->ui_window = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void fat32_close(struct FAT32_FileHandle *fh);
|
|
||||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
|
||||||
if (current_process->fds[i]) {
|
|
||||||
fat32_close(current_process->fds[i]);
|
|
||||||
current_process->fds[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void cmd_process_finished(void);
|
|
||||||
cmd_process_finished();
|
|
||||||
|
|
||||||
extern void network_cleanup(void);
|
|
||||||
network_cleanup();
|
|
||||||
|
|
||||||
// 2. Find previous process in circular list
|
// 2. Find previous process in circular list
|
||||||
process_t *prev = current_process;
|
process_t *prev = current_process;
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str);
|
||||||
process_t* process_get_current(void);
|
process_t* process_get_current(void);
|
||||||
uint64_t process_schedule(uint64_t current_rsp);
|
uint64_t process_schedule(uint64_t current_rsp);
|
||||||
uint64_t process_terminate_current(void);
|
uint64_t process_terminate_current(void);
|
||||||
|
void process_terminate(process_t *proc);
|
||||||
|
|
||||||
void process_push_gui_event(process_t *proc, gui_event_t *ev);
|
void process_push_gui_event(process_t *proc, gui_event_t *ev);
|
||||||
process_t* process_get_by_ui_window(void* win);
|
process_t* process_get_by_ui_window(void* win);
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,14 @@ static void user_window_resize(Window *win, int w, int h) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
static uint64_t syscall_handler_inner(registers_t *regs) {
|
||||||
|
uint64_t syscall_num = regs->rax;
|
||||||
|
uint64_t arg1 = regs->rdi;
|
||||||
|
uint64_t arg2 = regs->rsi;
|
||||||
|
uint64_t arg3 = regs->rdx;
|
||||||
|
uint64_t arg4 = regs->r10;
|
||||||
|
uint64_t arg5 = regs->r8;
|
||||||
|
|
||||||
extern void cmd_write(const char *str);
|
extern void cmd_write(const char *str);
|
||||||
extern void serial_write(const char *str);
|
extern void serial_write(const char *str);
|
||||||
|
|
||||||
|
|
@ -561,7 +568,7 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6
|
||||||
} else if (cmd == GUI_CMD_GET_EVENT) {
|
} else if (cmd == GUI_CMD_GET_EVENT) {
|
||||||
Window *win = (Window *)arg2;
|
Window *win = (Window *)arg2;
|
||||||
gui_event_t *ev_out = (gui_event_t *)arg3;
|
gui_event_t *ev_out = (gui_event_t *)arg3;
|
||||||
if (!win || !ev_out) return 0;
|
if (!ev_out) return 0;
|
||||||
if (proc->gui_event_head != proc->gui_event_tail) {
|
if (proc->gui_event_head != proc->gui_event_tail) {
|
||||||
*ev_out = proc->gui_events[proc->gui_event_head];
|
*ev_out = proc->gui_events[proc->gui_event_head];
|
||||||
proc->gui_event_head = (proc->gui_event_head + 1) % MAX_GUI_EVENTS;
|
proc->gui_event_head = (proc->gui_event_head + 1) % MAX_GUI_EVENTS;
|
||||||
|
|
@ -1056,6 +1063,11 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6
|
||||||
extern void cmd_set_raw_mode(bool enabled);
|
extern void cmd_set_raw_mode(bool enabled);
|
||||||
cmd_set_raw_mode((bool)arg2);
|
cmd_set_raw_mode((bool)arg2);
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (cmd == 42) { // SYSTEM_CMD_TCP_RECV_NB
|
||||||
|
void *buf = (void *)arg2;
|
||||||
|
size_t max_len = (size_t)arg3;
|
||||||
|
extern int network_tcp_recv_nb(void *buf, size_t max_len);
|
||||||
|
return (uint64_t)network_tcp_recv_nb(buf, max_len);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1071,8 +1083,14 @@ uint64_t syscall_handler_c(registers_t *regs) {
|
||||||
return process_terminate_current();
|
return process_terminate_current();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (syscall_num == 5 && regs->rdi == 43) { // SYSTEM_CMD_YIELD
|
||||||
|
extern uint64_t process_schedule(uint64_t current_rsp);
|
||||||
|
regs->rax = 0;
|
||||||
|
return process_schedule((uint64_t)regs);
|
||||||
|
}
|
||||||
|
|
||||||
// Normal syscalls
|
// Normal syscalls
|
||||||
regs->rax = syscall_handler_inner(regs->rax, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8);
|
regs->rax = syscall_handler_inner(regs);
|
||||||
|
|
||||||
// Return current RSP to assembly wrapper
|
// Return current RSP to assembly wrapper
|
||||||
return (uint64_t)regs;
|
return (uint64_t)regs;
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,10 @@ int sys_tcp_recv(void *buf, size_t max_len) {
|
||||||
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_TCP_RECV, (uint64_t)buf, (uint64_t)max_len);
|
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_TCP_RECV, (uint64_t)buf, (uint64_t)max_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sys_tcp_recv_nb(void *buf, size_t max_len) {
|
||||||
|
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_TCP_RECV_NB, (uint64_t)buf, (uint64_t)max_len);
|
||||||
|
}
|
||||||
|
|
||||||
int sys_tcp_close(void) {
|
int sys_tcp_close(void) {
|
||||||
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_TCP_CLOSE, 0);
|
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_TCP_CLOSE, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -223,3 +227,7 @@ void sys_network_force_unlock(void) {
|
||||||
syscall2(SYS_SYSTEM, SYSTEM_CMD_NET_UNLOCK, 0);
|
syscall2(SYS_SYSTEM, SYSTEM_CMD_NET_UNLOCK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sys_yield(void) {
|
||||||
|
syscall1(SYS_SYSTEM, SYSTEM_CMD_YIELD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@
|
||||||
#define SYSTEM_CMD_SET_DNS 38
|
#define SYSTEM_CMD_SET_DNS 38
|
||||||
#define SYSTEM_CMD_NET_UNLOCK 39
|
#define SYSTEM_CMD_NET_UNLOCK 39
|
||||||
#define SYSTEM_CMD_SET_RAW_MODE 41
|
#define SYSTEM_CMD_SET_RAW_MODE 41
|
||||||
|
#define SYSTEM_CMD_TCP_RECV_NB 42
|
||||||
|
#define SYSTEM_CMD_YIELD 43
|
||||||
|
|
||||||
// Internal assembly entry into Ring 0
|
// Internal assembly entry into Ring 0
|
||||||
extern uint64_t syscall0(uint64_t sys_num);
|
extern uint64_t syscall0(uint64_t sys_num);
|
||||||
|
|
@ -133,10 +135,12 @@ void sys_set_text_color(uint32_t color);
|
||||||
int sys_tcp_connect(const net_ipv4_address_t *ip, uint16_t port);
|
int sys_tcp_connect(const net_ipv4_address_t *ip, uint16_t port);
|
||||||
int sys_tcp_send(const void *data, size_t len);
|
int sys_tcp_send(const void *data, size_t len);
|
||||||
int sys_tcp_recv(void *buf, size_t max_len);
|
int sys_tcp_recv(void *buf, size_t max_len);
|
||||||
|
int sys_tcp_recv_nb(void *buf, size_t max_len);
|
||||||
int sys_tcp_close(void);
|
int sys_tcp_close(void);
|
||||||
int sys_dns_lookup(const char *name, net_ipv4_address_t *out_ip);
|
int sys_dns_lookup(const char *name, net_ipv4_address_t *out_ip);
|
||||||
int sys_set_dns_server(const net_ipv4_address_t *ip);
|
int sys_set_dns_server(const net_ipv4_address_t *ip);
|
||||||
void sys_network_force_unlock(void);
|
void sys_network_force_unlock(void);
|
||||||
|
void sys_yield(void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -363,7 +363,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
if (!connected) break;
|
if (!connected) break;
|
||||||
|
|
||||||
int len = sys_tcp_recv(recv_buf, sizeof(recv_buf) - 1);
|
int len = sys_tcp_recv_nb(recv_buf, sizeof(recv_buf) - 1);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
printf("\r\n[Connection error]\r\n");
|
printf("\r\n[Connection error]\r\n");
|
||||||
connected = 0;
|
connected = 0;
|
||||||
|
|
@ -377,8 +377,7 @@ int main(int argc, char **argv) {
|
||||||
connected = 0;
|
connected = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Brief spin
|
sys_yield();
|
||||||
for (volatile int d = 0; d < 100; d++);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue