diff --git a/.gitignore b/.gitignore index d25af32d..cb75e7f2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ dump .cache/* compile_commands.json .clangd +*.d diff --git a/Makefile b/Makefile index 282b54e6..3255c719 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,4 @@ -ARCH ?= aarch64-none-elf -CC := $(ARCH)-gcc -LD := $(ARCH)-ld -AR := $(ARCH)-ar -OBJCOPY := $(ARCH)-objcopy - -CFLAGS_BASE ?= -g -O0 -nostdlib -ffreestanding \ - -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables \ - -Wall -Wextra -Wno-unused-parameter -Wno-address-of-packed-member -mcpu=cortex-a72 -CONLY_FLAGS_BASE ?= -std=c17 -LDFLAGS_BASE ?= - -LOAD_ADDR ?= 0x41000000 -XHCI_CTX_SIZE ?= 32 -QEMU ?= true -MODE ?= virt - -export ARCH CC LD AR OBJCOPY CFLAGS_BASE CONLY_FLAGS_BASE LDFLAGS_BASE LOAD_ADDR XHCI_CTX_SIZE QEMU +include common.mk OS := $(shell uname) FS_DIRS := fs/redos/user @@ -42,13 +25,13 @@ kernel: $(MAKE) -C kernel LOAD_ADDR=$(LOAD_ADDR) XHCI_CTX_SIZE=$(XHCI_CTX_SIZE) QEMU=$(QEMU) clean: - $(MAKE) -C shared clean - $(MAKE) -C user clean - $(MAKE) -C kernel clean + $(MAKE) -C shared $@ + $(MAKE) -C user $@ + $(MAKE) -C kernel $@ @echo "removing fs dirs" - rm -rf $(FS_DIRS) + $(RM) -r $(FS_DIRS) @echo "removing images" - rm -f kernel.img kernel.elf disk.img dump + $(RM) kernel.img kernel.elf disk.img dump raspi: $(MAKE) LOAD_ADDR=0x80000 XHCI_CTX_SIZE=64 QEMU=true all @@ -63,11 +46,11 @@ run: debug: $(MAKE) $(MODE) ./rundebug MODE=$(MODE) $(ARGS) - + dump: $(OBJCOPY) -O binary kernel.elf kernel.img - aarch64-none-elf-objdump -D kernel.elf > dump - + $(ARCH)-objdump -D kernel.elf > dump + install: $(MAKE) clean $(MAKE) LOAD_ADDR=0x80000 XHCI_CTX_SIZE=64 QEMU=false all @@ -89,4 +72,6 @@ help: make debug build and run with debugger\n\ make dump disassemble kernel.elf\n\ make install create raspi kernel and mount it on a bootable partition\n\ - make prepare-fs create directories for the filesystem\n\n" + make prepare-fs create directories for the filesystem\n\n"\ + \n\ + Use 'make V=1' for verbose build output. diff --git a/common.mk b/common.mk new file mode 100644 index 00000000..676b839e --- /dev/null +++ b/common.mk @@ -0,0 +1,34 @@ +ARCH ?= aarch64-none-elf +CC := $(ARCH)-gcc +CXX := $(ARCH)-g++ +LD := $(ARCH)-ld +AR := $(ARCH)-ar +OBJCOPY := $(ARCH)-objcopy + +COMMON_FLAGS ?= -ffreestanding -nostdlib -fno-exceptions -fno-unwind-tables \ + -fno-asynchronous-unwind-tables -g -O0 -Wall -Wextra \ + -Wno-unused-parameter -Wno-address-of-packed-member \ + -mcpu=cortex-a72 + +CFLAGS_BASE ?= $(COMMON_FLAGS) -std=c17 +CXXFLAGS_BASE ?= $(COMMON_FLAGS) -fno-rtti +LDFLAGS_BASE ?= + +LOAD_ADDR ?= 0x41000000 +XHCI_CTX_SIZE ?= 32 +QEMU ?= true +MODE ?= virt + +ifeq ($(V), 1) + VAR = $(AR) + VAS = $(CC) + VCC = $(CC) + VCXX = $(CXX) + VLD = $(LD) +else + VAR = @echo " [AR] $@" && $(AR) + VAS = @echo " [AS] $@" && $(CC) + VCC = @echo " [CC] $@" && $(CC) + VCXX = @echo " [CXX] $@" && $(CXX) + VLD = @echo " [LD] $@" && $(LD) +endif diff --git a/kernel/Makefile b/kernel/Makefile index b50e98e6..db1c553c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,19 +1,26 @@ #kernel # toolchain (inherited from top-level) -CFLAGS := $(CFLAGS_BASE) -I. -I../shared -I../user -DXHCI_CTX_SIZE=$(XHCI_CTX_SIZE) +include ../common.mk + +CPPFLAGS := -I. -I../shared -I../user -DXHCI_CTX_SIZE=$(XHCI_CTX_SIZE) + ifeq ($(QEMU),true) - CFLAGS += -DQEMU + CPPFLAGS += -DQEMU endif -LDFLAGS := $(LDFLAGS_BASE) -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) +CFLAGS := $(CFLAGS_BASE) $(CPPFLAGS) +CXXFLAGS := $(CXXFLAGS_BASE) $(CPPFLAGS) +LDFLAGS := $(LDFLAGS_BASE) -T $(shell ls *.ld) --defsym=LOAD_ADDR=$(LOAD_ADDR) CLEAN_OBJS := $(shell find . -name '*.o') +CLEAN_DEPS := $(shell find . -name '*.d') C_SRC := $(shell find . -name '*.c') ASM_SRC := $(shell find . -name '*.S') CPP_SRC := $(shell find . -name '*.cpp') OBJ := $(C_SRC:.c=.o) $(ASM_SRC:.S=.o) $(CPP_SRC:.cpp=.o) OBJL := $(filter-out ./boot.o,$(OBJ)) +DEP := $(C_SRC:.c=.d) $(ASM_SRC:.S=.d) $(CPP_SRC:.cpp=.d) ELF := ../kernel.elf TARGET := ../kernel.img @@ -21,15 +28,19 @@ TARGET := ../kernel.img all: $(TARGET) $(TARGET): ../shared/libshared.a $(OBJ) - $(LD) $(LDFLAGS) -o $(ELF) $(OBJL) ../shared/libshared.a + $(VLD) $(LDFLAGS) -o $(ELF) $(OBJL) ../shared/libshared.a $(OBJCOPY) -O binary $(ELF) $@ %.o: %.S - $(CC) $(CFLAGS) -c $< -o $@ + $(VAS) $(CFLAGS) -c $< -o $@ + %.o: %.c - $(CC) $(CFLAGS) $(CONLY_FLAGS_BASE) -c $< -o $@ + $(VCC) $(CFLAGS) -c -MMD -MP $< -o $@ + %.o: %.cpp - $(CC) $(CFLAGS) -fno-rtti -c $< -o $@ + $(VCXX) $(CXXFLAGS) -c -MMD -MP $< -o $@ clean: - rm -f $(CLEAN_OBJS) $(ELF) $(TARGET) + $(RM) $(CLEAN_OBJS) $(CLEAN_DEPS) $(ELF) $(TARGET) + +-include $(DEP) diff --git a/kernel/audio/virtio_audio_pci.cpp b/kernel/audio/virtio_audio_pci.cpp index 7f77991c..8e7791ac 100644 --- a/kernel/audio/virtio_audio_pci.cpp +++ b/kernel/audio/virtio_audio_pci.cpp @@ -195,11 +195,12 @@ bool VirtioAudioDriver::config_streams(uint32_t streams){ kprintf("[VIRTIO_AUDIO error] Failed to configure stream %i",stream); } +#if false if (stream_info[stream].direction == VIRTIO_SND_D_OUTPUT){ kprintf("Playing from stream %i",stream); select_queue(&audio_dev, TRANSMIT_QUEUE); - for (uint16_t i = 0; i < 100; i++){ + for (uint16_t i = 0; i < 10; i++){ size_t total_size = sizeof(virtio_snd_pcm_status) + sizeof(virtio_snd_pcm_xfer) + TOTAL_BUF_SIZE; uintptr_t full_buffer = (uintptr_t)kalloc(audio_dev.memory_page, total_size, ALIGN_4KB, true, true); virtio_snd_pcm_xfer *header = (virtio_snd_pcm_xfer*)full_buffer; @@ -218,8 +219,8 @@ bool VirtioAudioDriver::config_streams(uint32_t streams){ select_queue(&audio_dev, CONTROL_QUEUE); } +#endif } - return true; } diff --git a/kernel/bin/bin_mod.c b/kernel/bin/bin_mod.c new file mode 100644 index 00000000..98cf49e8 --- /dev/null +++ b/kernel/bin/bin_mod.c @@ -0,0 +1,52 @@ +#include "bin_mod.h" +#include "cat.h" +#include "kernel_processes/kprocess_loader.h" + +#define N_ARR(arr) (sizeof(arr)/sizeof((arr)[0])) + +bool init_bin(){ + return true; +} + +typedef struct open_bin_ref { + char *name; + int (*func)(int argc, char* argv[]); +} open_bin_ref; + +open_bin_ref available_cmds[] = { + { "cat", run_cat } +}; + +process_t* exec(const char* prog_name, int argc, const char* argv[]){ + for (uint32_t i = 0; i < N_ARR(available_cmds); i++){ + if (strcmp(available_cmds[i].name, prog_name, false) == 0){ + return create_kernel_process(available_cmds[i].name, available_cmds[i].func, argc, argv); + } + } + return 0; +} + +FS_RESULT open_bin(){ + return FS_RESULT_DRIVER_ERROR; +} + +size_t read_bin(){ + return 0; +} + +sizedptr list_bin(const char *path){ + return (sizedptr){0,0}; +} + +driver_module bin_module = (driver_module){ + .name = "bin", + .mount = "/bin", + .version = VERSION_NUM(0, 1, 0, 1), + .init = init_bin, + .fini = 0, + .open = 0, + .read = read_bin, + .write = 0, + .seek = 0, + .readdir = list_bin, +}; \ No newline at end of file diff --git a/kernel/bin/bin_mod.h b/kernel/bin/bin_mod.h new file mode 100644 index 00000000..9edc457b --- /dev/null +++ b/kernel/bin/bin_mod.h @@ -0,0 +1,16 @@ +#pragma once + +#include "dev/driver_base.h" +#include "process/process.h" + +#ifdef __cplusplus +extern "C" { +#endif + +process_t* exec(const char* prog_name, int argc, const char* argv[]); + +#ifdef __cplusplus +} +#endif + +extern driver_module bin_module; \ No newline at end of file diff --git a/kernel/bin/cat.c b/kernel/bin/cat.c new file mode 100644 index 00000000..050f7515 --- /dev/null +++ b/kernel/bin/cat.c @@ -0,0 +1,36 @@ +#include "cat.h" +#include "kernel_processes/kprocess_loader.h" +#include "filesystem/filesystem.h" +#include "process/scheduler.h" +#include "syscalls/syscalls.h" +#include "console/kio.h" + +int run_cat(int argc, char* argv[]){ + uint16_t pid = get_current_proc_pid(); + string s = string_format("/proc/%i/out",pid); + file fd2; + open_file(s.data, &fd2); + if (argc != 2){ + string err_msg = string_l("Usage cat "); + write_file(&fd2, err_msg.data, err_msg.length); + free(err_msg.data, err_msg.mem_length); + return 2; + } + const char* path = argv[0]; + size_t size = parse_int_u64(argv[1], UINT32_MAX); + file fd; + open_file(path, &fd); + if (fd.size == 0){ + string err_msg = string_format("Couldn't find file %s", argv[0]); + write_file(&fd2, err_msg.data, err_msg.length); + free(err_msg.data, err_msg.mem_length); + return 1; + } + if (size == 0) size = fd.size; + char* buf = (char*)malloc(size); + read_file(&fd, buf, size); + + write_file(&fd2, buf, size); + free(s.data, s.mem_length); + return 0; +} \ No newline at end of file diff --git a/kernel/bin/cat.h b/kernel/bin/cat.h new file mode 100644 index 00000000..9a517a31 --- /dev/null +++ b/kernel/bin/cat.h @@ -0,0 +1,13 @@ +#pragma once + +#include "process/process.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int run_cat(int argc, char* argv[]); + +#ifdef __cplusplus +} +#endif diff --git a/kernel/boot.S b/kernel/boot.S index 489f2c5b..62c3b5f1 100644 --- a/kernel/boot.S +++ b/kernel/boot.S @@ -102,7 +102,7 @@ el2_entry: eret stack_setup: - ldr x1, =stack_top + ldr x1, =ksp mov sp, x1 mov x29, xzr diff --git a/kernel/console/kconsole/console.cpp b/kernel/console/kconsole/console.cpp index a013e2e5..95dc721d 100644 --- a/kernel/console/kconsole/console.cpp +++ b/kernel/console/kconsole/console.cpp @@ -1,6 +1,9 @@ #include "kconsole.hpp" #include "kconsole.h" #include "graph/graphics.h" +#include "input/input_dispatch.h" +#include "kernel_processes/windows/windows.h" +#include "terminal.hpp" KernelConsole kconsole; @@ -15,4 +18,37 @@ extern "C" void kconsole_puts(const char *s) { extern "C" void kconsole_clear() { kconsole.clear(); +} + +extern "C" int toggle_visual(int argc, char* argv[]){ + keypress kp = { + .modifier = KEY_MOD_LALT, + .rsvd = 0, + .keys = {0x13}, + }; + uint16_t shortcut = sys_subscribe_shortcut_current(kp); + bool active = false; + Terminal *terminal = new Terminal(); + terminal->initialize(); + while (1){ + if (sys_shortcut_triggered_current(shortcut)){ + active = !active; + if (active){ + pause_window_draw(); + sys_focus_current(); + terminal->refresh(); + } else { + resume_window_draw(); + terminal->clear(); + } + } + if (active){ + terminal->update(); + } + } + return 1; +} + +process_t* start_terminal(){ + return create_kernel_process("terminal",toggle_visual, 0, 0); } \ No newline at end of file diff --git a/kernel/console/kconsole/kconsole.cpp b/kernel/console/kconsole/kconsole.cpp index 6cd1ff38..13a64031 100644 --- a/kernel/console/kconsole/kconsole.cpp +++ b/kernel/console/kconsole/kconsole.cpp @@ -1,19 +1,27 @@ #include "kconsole.hpp" #include "console/serial/uart.h" #include "memory/page_allocator.h" +#include "filesystem/filesystem.h" +#include "theme/theme.h" +#include "std/memfunctions.h" KernelConsole::KernelConsole() : cursor_x(0), cursor_y(0), is_initialized(false){ + initialize(); +} + +void KernelConsole::initialize(){ + is_initialized = true; + mem_page = palloc(PAGE_SIZE, true, true, false); resize(); clear(); + default_text_color = COLOR_WHITE; + text_color = default_text_color; } bool KernelConsole::check_ready(){ if (!gpu_ready()) return false; if (!is_initialized){ - is_initialized= true; - mem_page = palloc(PAGE_SIZE, true, true, false); - resize(); - clear(); + initialize(); } return true; } @@ -21,55 +29,88 @@ bool KernelConsole::check_ready(){ void KernelConsole::resize(){ gpu_size screen_size = gpu_get_screen_size(); columns = screen_size.width / char_width; - rows = screen_size.height / char_height; + rows = screen_size.height / line_height; if (row_data) kfree(row_data, buffer_data_size); buffer_data_size = rows * columns; - uart_puts("Data Size "); - uart_puthex(buffer_data_size); row_data = (char*)kalloc(mem_page, buffer_data_size, ALIGN_16B, true, true); if (!row_data){ rows = columns = 0; - row_ring.clear(); return; } - row_ring.clear(); - for (uint32_t i = 0; i < rows; i++) row_ring.push(i); + scroll_row_offset = 0; } void KernelConsole::put_char(char c){ if (!check_ready()) return; if (c == '\n'){ newline(); + gpu_flush(); return; } if (cursor_x >= columns) newline(); - uint32_t row_index = row_ring.peek(); + uint32_t row_index = (scroll_row_offset + cursor_y) % rows; char* line = row_data + row_index * columns; line[cursor_x] = c; - gpu_draw_char({cursor_x * char_width, cursor_y * char_height}, c, 1, 0xFFFFFFFF); + gpu_draw_char({cursor_x * char_width, (cursor_y * line_height)+(line_height/2)}, c, 1, text_color); cursor_x++; } +//TODO: generalize this function to handle movement in general +void KernelConsole::delete_last_char(){ + if (cursor_x > 0){ + cursor_x--; + } else if (cursor_y > 0){ + cursor_y--; + cursor_x = 0; + char* line = row_data + cursor_y * columns; + while (*line){ + line++; + cursor_x++; + } + draw_cursor(); + gpu_flush(); + return; + } else return; + + char* line = row_data + cursor_y * columns; + line[cursor_x] = 0; + gpu_fill_rect({{cursor_x*char_width, cursor_y * line_height}, {char_width, line_height}}, COLOR_BLACK); + draw_cursor(); + gpu_flush(); +} + +void KernelConsole::draw_cursor(){ + if (last_drawn_cursor_x >= 0 && last_drawn_cursor_y >= 0){ + gpu_fill_rect({{last_drawn_cursor_x*char_width, last_drawn_cursor_y * line_height}, {char_width, line_height}}, COLOR_BLACK); + char *line = row_data + (last_drawn_cursor_y * columns); + gpu_draw_char({last_drawn_cursor_x * char_width, (last_drawn_cursor_y * line_height)+(line_height/2)}, line[last_drawn_cursor_x], 1, text_color); + } + gpu_fill_rect({{cursor_x*char_width, cursor_y * line_height}, {char_width, line_height}}, COLOR_WHITE); + last_drawn_cursor_x = cursor_x; + last_drawn_cursor_y = cursor_y; +} + void KernelConsole::put_string(const char* str){ if (!check_ready()) return; - for (uint32_t i = 0; str[i]; i++) put_char(str[i]); + for (uint32_t i = 0; str[i]; i++){ + char c = str[i]; + put_char(c); + } + draw_cursor(); gpu_flush(); } void KernelConsole::newline(){ if (!check_ready()) return; - uint32_t row_index; - if (row_ring.pop(row_index)){ - char* line = row_data + row_index * columns; - for (uint32_t x = cursor_x; x < columns; x++) line[x] = 0; - row_ring.push(row_index); - } + uint32_t row_index = (scroll_row_offset + cursor_y) % rows; + char* line = row_data + row_index * columns; + for (uint32_t x = cursor_x; x < columns; x++) line[x] = 0; cursor_x = 0; cursor_y++; - if (cursor_y >= rows){ + if (cursor_y >= rows - 1){ scroll(); cursor_y = rows - 1; } @@ -77,42 +118,49 @@ void KernelConsole::newline(){ void KernelConsole::scroll(){ if (!check_ready()) return; - uint32_t row_index; - if (row_ring.pop(row_index)){ - char* line = row_data + row_index * columns; - for (uint32_t x = 0; x < columns; x++) line[x] = 0; - row_ring.push(row_index); - } + scroll_row_offset = (scroll_row_offset + 1) % rows; + uint32_t row_index = (scroll_row_offset + cursor_y) % rows; + char* line = row_data + row_index * columns; + for (uint32_t x = 0; x < columns; x++) line[x] = 0; redraw(); } +void KernelConsole::refresh(){ + resize(); + clear(); + redraw(); + gpu_flush(); +} + void KernelConsole::redraw(){ screen_clear(); for (uint32_t y = 0; y < rows; y++){ - uint32_t row_index; - if (row_ring.pop(row_index)){ - row_ring.push(row_index); - char* line = row_data + row_index * columns; - for (uint32_t x = 0; x < columns; x++){ - gpu_draw_char({x * char_width, y * char_height}, line[x], 1, 0xFFFFFFFF); - } + uint32_t row_index = (scroll_row_offset + y) % rows; + char* line = row_data + row_index * columns; + for (uint32_t x = 0; x < columns; x++){ + gpu_draw_char({x * char_width, (y * line_height)+(line_height/2)}, line[x], 1, text_color); } } + draw_cursor(); } void KernelConsole::screen_clear(){ - gpu_clear(0x0); + gpu_clear(COLOR_BLACK); + last_drawn_cursor_x = -1; + last_drawn_cursor_y = -1; } void KernelConsole::clear(){ screen_clear(); - for (uint32_t i = 0; i < rows; i++){ - uint32_t row_index; - if (row_ring.pop(row_index)){ - char* line = row_data + row_index * columns; - for (uint32_t x = 0; x < columns; x++) line[x] = 0; - row_ring.push(row_index); - } - } + memset(row_data, 0, buffer_data_size); cursor_x = cursor_y = 0; } + +const char* KernelConsole::get_current_line(){ + uint32_t row_index = (scroll_row_offset + cursor_y) % rows; + return row_data + row_index * columns; +} + +void KernelConsole::set_text_color(uint32_t hex){ + text_color = hex | 0xFF000000; +} \ No newline at end of file diff --git a/kernel/console/kconsole/kconsole.h b/kernel/console/kconsole/kconsole.h index c9a2e807..893de9a2 100644 --- a/kernel/console/kconsole/kconsole.h +++ b/kernel/console/kconsole/kconsole.h @@ -1,5 +1,8 @@ #pragma once +#include "process/process.h" +#include "kernel_processes/kprocess_loader.h" + #ifdef __cplusplus extern "C" { #endif @@ -7,6 +10,7 @@ extern "C" { void kconsole_putc(char c); void kconsole_puts(const char *s); void kconsole_clear(); +process_t* start_terminal(); #ifdef __cplusplus } diff --git a/kernel/console/kconsole/kconsole.hpp b/kernel/console/kconsole/kconsole.hpp index 4cedb623..42cb5b9b 100644 --- a/kernel/console/kconsole/kconsole.hpp +++ b/kernel/console/kconsole/kconsole.hpp @@ -3,12 +3,15 @@ #include "types.h" #include "data_struct/ring_buffer.hpp" #include "graph/graphics.h" +#include "ui/draw/draw.h" #include "memory/talloc.h" class KernelConsole{ public: KernelConsole(); + void initialize(); + void put_char(char c); void put_string(const char* str); @@ -17,24 +20,39 @@ class KernelConsole{ void clear(); void resize(); -private: + void refresh(); + + void set_active(bool active); + void delete_last_char(); + +protected: bool check_ready(); void screen_clear(); void redraw(); + void draw_cursor(); + const char* get_current_line(); + + void set_text_color(uint32_t color); uint32_t cursor_x, cursor_y; + int32_t last_drawn_cursor_x, last_drawn_cursor_y; uint32_t columns, rows; bool is_initialized; - static constexpr uint32_t char_width=8; - static constexpr uint32_t char_height=16; + static constexpr uint32_t char_width=CHAR_SIZE; + static constexpr uint32_t line_height=CHAR_SIZE*2; static constexpr uint32_t max_rows=128; - RingBuffer row_ring; + uint32_t default_text_color = 0xFFFFFFFF; + uint32_t text_color = default_text_color; + + int32_t scroll_row_offset = 0; char* row_data; + uint32_t gap_start, gap_end; uint32_t buffer_data_size; void *mem_page; + bool active = true; }; extern KernelConsole kconsole; diff --git a/kernel/console/kconsole/terminal.cpp b/kernel/console/kconsole/terminal.cpp new file mode 100644 index 00000000..7a7c9774 --- /dev/null +++ b/kernel/console/kconsole/terminal.cpp @@ -0,0 +1,135 @@ +#include "terminal.hpp" +#include "input/input_dispatch.h" +#include "../kio.h" +#include "../serial/uart.h" +#include "std/std.hpp" +#include "filesystem/filesystem.h" +#include "bin/bin_mod.h" + +void Terminal::update(){ + if (!command_running) handle_input(); + else { + end_command(); + } +} + +void Terminal::end_command(){ + command_running = false; + put_char('\r'); + put_char('\n'); + draw_cursor(); + gpu_flush(); + set_text_color(default_text_color); +} + +bool Terminal::exec_cmd(const char *cmd, int argc, const char *argv[]){ + process_t *proc = exec(cmd, argc, argv); + if (!proc) return false; + string s = string_format("/proc/%i/out",proc->id); + file fd; + open_file(s.data, &fd); + free(s.data, s.mem_length); + while (proc->state != process_t::STOPPED){ + size_t amount = 0x100; + char *buf = (char*)malloc(amount); + read_file(&fd, buf, amount); + put_string(buf); + free(buf, amount); + } + string exit_msg = string_format("Process %i ended with exit code %i.",proc->id, proc->exit_code); + put_string(exit_msg.data); + free(exit_msg.data, exit_msg.mem_length); + return true; +} + +const char** Terminal::parse_arguments(char *args, int *count){ + *count = 0; + const char* prev = args; + char* next_args; + const char **argv = (const char**)malloc(16 * sizeof(uintptr_t)); + do { + next_args = (char*)seek_to(args, ' '); + argv[*count] = prev; + (*count)++; + prev = next_args; + *(next_args - 1) = 0; + kprintf("Found an argument %s",prev); + } while(prev != next_args); + if (*next_args){ + argv[*count] = prev; + (*count)++; + kprintf("Ended at %s",next_args); + } + return argv; +} + +void Terminal::run_command(){ + const char* fullcmd = get_current_line(); + const char* args = seek_to(fullcmd, ' '); + + string cmd; + int argc = 0; + const char** argv; + string args_copy; + + if (fullcmd == args){ + cmd = string_l(fullcmd); + } else { + cmd = string_ca_max(fullcmd, args - fullcmd - 1); + args_copy = string_l(args); + argv = parse_arguments(args_copy.data, &argc); + } + + put_char('\r'); + put_char('\n'); + + if (!exec_cmd(cmd.data, argc, argv)){ + if (strcmp(cmd.data, "test", true) == 0){ + TMP_test(argc, argv); + } else { + string s = string_format("Unknown command %s with args %s", cmd.data, args); + put_string(s.data); + free(s.data, s.mem_length); + } + } + + free(cmd.data, cmd.mem_length); + if (args_copy.mem_length) free(args_copy.data, args_copy.mem_length); + + draw_cursor(); + gpu_flush(); + command_running = true; +} + +//TODO: implement the full state machine explained at https://vt100.net/emu/dec_ansi_parser & https://en.wikipedia.org/wiki/ANSI_escape_code#Colors +//The current implementation is not standard compliant and uses hex colors as [FF0000; +void Terminal::TMP_test(int argc, const char* args[]){ + // const char *term = seek_to(args, '\033'); + // if (*term == 0) return; + const char *term = seek_to(*args, '['); + if (*term == 0) return; + const char *next = seek_to(term, ';'); + uint64_t color = parse_hex_u64(term, next - term); + set_text_color(color & UINT32_MAX); + put_string(next); +} + +void Terminal::handle_input(){ + keypress kp; + if (sys_read_input_current(&kp)){ + for (int i = 0; i < 6; i++){ + char key = kp.keys[i]; + char readable = hid_to_char((uint8_t)key); + if (key == KEY_ENTER || key == KEY_KPENTER){ + run_command(); + } else if (readable){ + put_char(readable); + draw_cursor(); + gpu_flush(); + } else if (key == KEY_BACKSPACE){ + delete_last_char(); + } + } + } +} + diff --git a/kernel/console/kconsole/terminal.hpp b/kernel/console/kconsole/terminal.hpp new file mode 100644 index 00000000..972c2188 --- /dev/null +++ b/kernel/console/kconsole/terminal.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "kconsole.hpp" + +class Terminal: public KernelConsole { +public: + void update(); +protected: + void handle_input(); + void end_command(); + void run_command(); + const char** parse_arguments(char *args, int *count); + + //TODO: proper commands + bool exec_cmd(const char *cmd, int argc, const char *args[]); + void TMP_test(int argc, const char *args[]); + + bool command_running; +}; \ No newline at end of file diff --git a/kernel/console/kio.c b/kernel/console/kio.c index 17b3bc26..9510b3b8 100644 --- a/kernel/console/kio.c +++ b/kernel/console/kio.c @@ -3,9 +3,25 @@ #include "kconsole/kconsole.h" #include "std/string.h" #include "memory/page_allocator.h" +#include "std/memfunctions.h" +#include "math/math.h" static bool use_visual = true; -void* print_buf; +char* print_buf; +uintptr_t cursor; + +#define CONSOLE_BUF_SIZE 0x3000 + +void reset_buffer(){ + cursor = (uintptr_t)print_buf; + memset(print_buf, 0, CONSOLE_BUF_SIZE); +} + + +void init_print_buf(){ + print_buf = palloc(CONSOLE_BUF_SIZE,true, false, true); + reset_buffer(); +} bool console_init(){ enable_uart(); @@ -18,18 +34,23 @@ bool console_fini(){ } FS_RESULT console_open(const char *path, file *out_fd){ + out_fd->id = reserve_fd_id(); + out_fd->size = CONSOLE_BUF_SIZE; return FS_RESULT_SUCCESS; } size_t console_read(file *fd, char *out_buf, size_t size, file_offset offset){ - return 0; + size = min(size,CONSOLE_BUF_SIZE); + memcpy(out_buf, print_buf+offset, size); + return size; } size_t console_write(file *fd, const char *buf, size_t size, file_offset offset){ + //TODO: kinda allowing arbitrary buffers here kprintf(buf); + return size; } - file_offset console_seek(file *fd, file_offset offset){ return 0; } @@ -63,43 +84,58 @@ void putc(const char c){ kconsole_putc(c); } -void init_print_buf(){ - print_buf = palloc(0x1000,true, false, false); -} - +//TODO: __attribute__((format)) void kprintf(const char *fmt, ...){ if (!print_buf) init_print_buf(); - va_list args; + __attribute__((aligned(16))) va_list args; va_start(args, fmt); - char* buf = kalloc(print_buf, 256, ALIGN_64B, true, false); - size_t len = string_format_va_buf(fmt, buf, args); + + if (cursor >= ((uintptr_t)print_buf) + 0x2F00){ + reset_buffer(); + } + + //TODO: string_format_va_buf should be given a maximum size + size_t len = string_format_va_buf(fmt, (char*)cursor, args); va_end(args); - puts(buf); + puts((char*)cursor); putc('\r'); putc('\n'); - //TODO: these buffers should be freed sometime, maybe after writing them to disk, and even those should be wiped eventually - // kfree((void*)buf, 256); + cursor += len; + *(char*)(cursor++) = '\r'; + *(char*)(cursor++) = '\n'; } void kprint(const char *fmt){ puts(fmt); putc('\r'); putc('\n'); + + while (*fmt != '\0') { + *(char*)(cursor++) = *fmt; + fmt++; + } + *(char*)(cursor++) = '\r'; + *(char*)(cursor++) = '\n'; } void kputf(const char *fmt, ...){ if (!print_buf) init_print_buf(); - va_list args; + __attribute__((aligned(16))) va_list args; va_start(args, fmt); - char* buf = kalloc(print_buf, 256, ALIGN_64B, true, false); - size_t len = string_format_va_buf(fmt, buf, args); + + if (cursor >= ((uintptr_t)print_buf) + CONSOLE_BUF_SIZE - 0x100){ + reset_buffer(); + } + + size_t len = string_format_va_buf(fmt, (char*)cursor, args); va_end(args); - puts(buf); - // kfree((void*)buf, 256); + puts((char*)cursor); + cursor += len-1; } void disable_visual(){ use_visual = false; + kconsole_clear(); } void enable_visual(){ diff --git a/kernel/console/kio.h b/kernel/console/kio.h index 63764e66..0773bfd5 100644 --- a/kernel/console/kio.h +++ b/kernel/console/kio.h @@ -2,6 +2,7 @@ #include "types.h" #include "dev/driver_base.h" +#include "kernel_processes/kprocess_loader.h" #ifdef __cplusplus extern "C" { @@ -17,6 +18,8 @@ void putc(const char c); void disable_visual(); void enable_visual(); +process_t* start_terminal(); + extern driver_module console_module; #ifdef __cplusplus diff --git a/kernel/dev/driver_base.c b/kernel/dev/driver_base.c new file mode 100644 index 00000000..6aba402c --- /dev/null +++ b/kernel/dev/driver_base.c @@ -0,0 +1,7 @@ +#include "driver_base.h" + +uint64_t fd_id = 0; + +uint64_t reserve_fd_id(){ + return ++fd_id; +} \ No newline at end of file diff --git a/kernel/dev/driver_base.h b/kernel/dev/driver_base.h index 0caffff4..7332ccb8 100644 --- a/kernel/dev/driver_base.h +++ b/kernel/dev/driver_base.h @@ -6,6 +6,7 @@ typedef struct file { uint64_t id; size_t size; + uint64_t cursor; } file; typedef uint64_t file_offset; @@ -18,6 +19,14 @@ typedef enum FS_RESULT { #define VERSION_NUM(major,minor,patch,build) (uint64_t)((((uint64_t)major) << 48) | (((uint64_t)minor) << 32) | (((uint64_t)patch) << 16) | ((uint64_t)build)) +#ifdef __cplusplus +extern "C" { +#endif +uint64_t reserve_fd_id(); +#ifdef __cplusplus +} +#endif + typedef struct driver_module { const char* name; const char* mount; diff --git a/kernel/dev/module_loader.c b/kernel/dev/module_loader.c index 74a99881..fd3b5bcf 100644 --- a/kernel/dev/module_loader.c +++ b/kernel/dev/module_loader.c @@ -17,7 +17,6 @@ bool unload_module(driver_module *module){ int fs_search(void *node, void *key){ driver_module* module = (driver_module*)node; const char** path = (const char**)key; - kprintf("Comparing %s to %s",(uintptr_t)*path,(uintptr_t)module->mount); int index = strstart(*path, module->mount, false); if (index == (int)strlen(module->mount,0)){ *path += index; @@ -27,7 +26,6 @@ int fs_search(void *node, void *key){ } driver_module* get_module(const char **full_path){ - kprintf("Seeking module %s",(uintptr_t)*full_path); clinkedlist_node_t *node = clinkedlist_find(modules, (void*)full_path, fs_search); - return ((driver_module*)node->data); + return node ? ((driver_module*)node->data) : 0; } \ No newline at end of file diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index feb08cfe..c5d14697 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -14,6 +14,7 @@ }\ }) +//TODO: use seek_to const char* FAT32FS::advance_path(const char *path){ while (*path != '/' && *path != '\0') path++; @@ -34,11 +35,6 @@ bool FAT32FS::init(uint32_t partition_sector){ if (mbs->boot_signature != 0xAA55){ kprintf("[fat32] Wrong boot signature %x",mbs->boot_signature); - uint8_t *bytes = ((uint8_t*)mbs); - for (int i = 0; i < 512; i++){ - kputf("%x",bytes[i]); - } - kprintf("Failed to read"); return false; } if (mbs->signature != 0x29 && mbs->signature != 0x28){ @@ -264,15 +260,16 @@ FS_RESULT FAT32FS::open_file(const char* path, file* descriptor){ sizedptr buf_ptr = walk_directory(count, mbs->first_cluster_of_root_directory, path, read_entry_handler); void *buf = (void*)buf_ptr.ptr; if (!buf) return FS_RESULT_NOTFOUND; - descriptor->id = open_files.size(); + descriptor->id = reserve_fd_id(); descriptor->size = buf_ptr.size; - open_files.add(descriptor->id, buf); + open_files.add(reserve_fd_id(), buf); //TODO: go back to using a linked list, and a static id for the file, ideally global for system return FS_RESULT_SUCCESS; } size_t FAT32FS::read_file(file *descriptor, void* buf, size_t size){ void* file = open_files[descriptor->id]; + //TODO: keep track of file size and limit copy to only that or less memcpy(buf, file, size); return size; } diff --git a/kernel/filesystem/filesystem.cpp b/kernel/filesystem/filesystem.cpp index 81314d1f..cd5903cc 100644 --- a/kernel/filesystem/filesystem.cpp +++ b/kernel/filesystem/filesystem.cpp @@ -4,18 +4,19 @@ #include "fsdriver.hpp" #include "std/std.hpp" #include "console/kio.h" +#include "dev/module_loader.h" #include "memory/page_allocator.h" #include "math/math.h" -#include "dev/module_loader.h" FAT32FS *fs_driver; typedef struct { uint64_t file_id; + size_t file_size; driver_module* mod; -} file_mod_kvp; +} open_file_descriptors; -LinkedList *open_files; +LinkedList *open_files; bool boot_partition_init(){ uint32_t f32_partition = mbr_find_partition(0xC); @@ -75,34 +76,46 @@ bool init_boot_filesystem(){ FS_RESULT open_file(const char* path, file* descriptor){ const char *search_path = path; - kprintf("Getting module for path %s",(uintptr_t)search_path); driver_module *mod = get_module(&search_path); - kprintf("Got module %x for path %s",(uintptr_t)mod,(uintptr_t)search_path); if (!mod) return FS_RESULT_NOTFOUND; FS_RESULT result = mod->open(search_path, descriptor); if (!open_files) - open_files = new LinkedList(); + open_files = new LinkedList(); open_files->push_front({ .file_id = descriptor->id, + .file_size = descriptor->size, .mod = mod }); return result; } size_t read_file(file *descriptor, char* buf, size_t size){ + if (!open_files){ + kprintf("[FS] No open files"); + return 0; + } + open_file_descriptors file = open_files->find([descriptor](open_file_descriptors kvp){ + return descriptor->id == kvp.file_id; + })->data; + if (!file.mod) return 0; + size_t adj_size = min(size,file.file_size); + size_t amount_read = file.mod->read(descriptor, buf, adj_size, 0); + descriptor->cursor += amount_read; + return amount_read; +} + +size_t write_file(file *descriptor, const char* buf, size_t size){ if (!open_files) return 0; - driver_module *mod = open_files->find([descriptor](file_mod_kvp kvp){ + open_file_descriptors file = open_files->find([descriptor](open_file_descriptors kvp){ return descriptor->id == kvp.file_id; - })->data.mod; - size_t adj_size = min(size,descriptor->size);//TODO: still possible to modify the fd's size - return mod->read(descriptor, buf, adj_size, 0); + })->data; + if (!file.mod) return 0; + return file.mod->write(descriptor, buf, size, 0); } sizedptr list_directory_contents(const char *path){ const char *search_path = path; - kprintf("Getting module for path %s",(uintptr_t)search_path); driver_module *mod = get_module(&search_path); - kprintf("Got module %x for path %s",(uintptr_t)mod,(uintptr_t)search_path); if (!mod) return {0,0}; return mod->readdir(search_path); } \ No newline at end of file diff --git a/kernel/filesystem/filesystem.h b/kernel/filesystem/filesystem.h index b3572f0f..44a4baf1 100644 --- a/kernel/filesystem/filesystem.h +++ b/kernel/filesystem/filesystem.h @@ -10,6 +10,7 @@ extern "C" { FS_RESULT open_file(const char* path, file* descriptor); size_t read_file(file *descriptor, char* buf, size_t size); +size_t write_file(file *descriptor, const char* buf, size_t size); sizedptr list_directory_contents(const char *path); bool init_boot_filesystem(); diff --git a/kernel/graph/drivers/ramfb_driver/ramfb.cpp b/kernel/graph/drivers/ramfb_driver/ramfb.cpp index c7deefff..2f4d6045 100644 --- a/kernel/graph/drivers/ramfb_driver/ramfb.cpp +++ b/kernel/graph/drivers/ramfb_driver/ramfb.cpp @@ -2,7 +2,6 @@ #include "fw/fw_cfg.h" #include "memory/talloc.h" #include "console/kio.h" -#include "graph/font8x8_bridge.h" #include "ui/draw/draw.h" #include "memory/memory_access.h" #include "std/std.hpp" diff --git a/kernel/graph/drivers/videocore/videocore.cpp b/kernel/graph/drivers/videocore/videocore.cpp index dc5b6a52..1fc865fd 100644 --- a/kernel/graph/drivers/videocore/videocore.cpp +++ b/kernel/graph/drivers/videocore/videocore.cpp @@ -2,7 +2,6 @@ #include "fw/fw_cfg.h" #include "memory/talloc.h" #include "console/kio.h" -#include "graph/font8x8_bridge.h" #include "ui/draw/draw.h" #include "memory/memory_access.h" #include "std/std.hpp" @@ -90,8 +89,7 @@ void VideoCoreGPUDriver::flush(){ uint32_t* src = (uint32_t*)&bfb[dest_y * (stride / 4) + r.point.x]; uint32_t copy_width = r.size.width; - if (r.point.x + copy_width > screen_size.width) - copy_width = screen_size.width - r.point.x; + if (r.point.x + copy_width > screen_size.width) copy_width = screen_size.width - r.point.x; memcpy(dst, src, copy_width * sizeof(uint32_t)); } diff --git a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp index 83cac55b..48acc833 100644 --- a/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp +++ b/kernel/graph/drivers/virtio_gpu_pci/virtio_gpu_pci.cpp @@ -2,7 +2,6 @@ #include "pci.h" #include "memory/talloc.h" #include "console/kio.h" -#include "graph/font8x8_bridge.h" #include "ui/draw/draw.h" #include "std/std.hpp" diff --git a/kernel/graph/font8x8_bridge.h b/kernel/graph/font8x8_bridge.h index 1a70f8e6..bbc9a286 100644 --- a/kernel/graph/font8x8_bridge.h +++ b/kernel/graph/font8x8_bridge.h @@ -3,6 +3,7 @@ extern "C" { #endif #include "types.h" +//TODO: remove this header, use just #ifdef and else const uint8_t* get_font8x8(uint8_t c); #ifdef __cplusplus diff --git a/kernel/graph/graphics.cpp b/kernel/graph/graphics.cpp index 73af56ad..77726e68 100644 --- a/kernel/graph/graphics.cpp +++ b/kernel/graph/graphics.cpp @@ -15,7 +15,7 @@ GPUDriver *gpu_driver; bool gpu_init(){ kprint("Initializing GPU"); - gpu_size preferred_screen_size = {1080,720}; + gpu_size preferred_screen_size = {1920,1080}; if (BOARD_TYPE == 1){ if (VirtioGPUDriver *vgd = VirtioGPUDriver::try_init(preferred_screen_size)){ gpu_driver = vgd; diff --git a/kernel/input/USBKeyboard.cpp b/kernel/input/USBKeyboard.cpp index 8ba43a40..58b113ce 100644 --- a/kernel/input/USBKeyboard.cpp +++ b/kernel/input/USBKeyboard.cpp @@ -33,8 +33,10 @@ void USBKeyboard::process_data(USBDriver *driver){ void USBKeyboard::process_keypress(keypress *rkp){ keypress kp; if (is_new_keypress(rkp, &last_keypress) || repeated_keypresses > 3){ - if (is_new_keypress(rkp, &last_keypress)) + if (is_new_keypress(rkp, &last_keypress)){ repeated_keypresses = 0; + remove_double_keypresses(rkp, &last_keypress); + } kp.modifier = rkp->modifier; // kprintf("Mod: %i", kp.modifier); for (int i = 0; i < 6; i++){ diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.cpp index 52db6ef2..3611a701 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.cpp @@ -89,6 +89,20 @@ bool is_new_keypress(keypress* current, keypress* previous) { return false; } +void remove_double_keypresses(keypress* current, keypress* previous){ + for (int i = 0; i < 6; i++) + if (keypress_contains(previous, current->keys[i], previous->modifier)) current->keys[i] = 0; +} + +bool keypress_contains(keypress *kp, char key, uint8_t modifier){ + if (kp->modifier != modifier) return false;//TODO: This is not entirely accurate, some modifiers do not change key + + for (int i = 0; i < 6; i++) + if (kp->keys[i] == key) + return true; + return false; +} + bool sys_read_input(int pid, keypress *out){ process_t *process = get_proc_by_pid(pid); if (process->input_buffer.read_index == process->input_buffer.write_index) return false; @@ -122,23 +136,25 @@ bool input_init(){ } } -void input_process_poll(){ +int input_process_poll(int argc, char* argv[]){ while (1){ input_driver->poll_inputs(); } + return 1; } -void input_process_fake_interrupts(){ +int input_process_fake_interrupts(int argc, char* argv[]){ while (1){ input_driver->handle_interrupt(); } + return 1; } void init_input_process(){ if (!input_driver->use_interrupts) - create_kernel_process("input_poll", &input_process_poll); + create_kernel_process("input_poll", &input_process_poll, 0, 0); if (input_driver->quirk_simulate_interrupts) - create_kernel_process("input_int_mock", &input_process_fake_interrupts); + create_kernel_process("input_int_mock", &input_process_fake_interrupts, 0, 0); } void handle_input_interrupt(){ diff --git a/kernel/input/input_dispatch.h b/kernel/input/input_dispatch.h index 617b4dc8..758c1f35 100644 --- a/kernel/input/input_dispatch.h +++ b/kernel/input/input_dispatch.h @@ -25,6 +25,8 @@ bool sys_shortcut_triggered_current(uint16_t sid); bool sys_shortcut_triggered(uint16_t pid, uint16_t sid); bool is_new_keypress(keypress* current, keypress* previous); +bool keypress_contains(keypress *kp, char key, uint8_t modifier); +void remove_double_keypresses(keypress* current, keypress* previous); void handle_input_interrupt(); diff --git a/kernel/kernel.c b/kernel/kernel.c index 5075b852..1edde65b 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -71,4 +71,4 @@ void kernel_main() { panic("Kernel did not activate any process"); -} \ No newline at end of file +} diff --git a/kernel/kernel_processes/boot/bootprocess.cpp b/kernel/kernel_processes/boot/bootprocess.cpp index b18528a6..faa46d63 100644 --- a/kernel/kernel_processes/boot/bootprocess.cpp +++ b/kernel/kernel_processes/boot/bootprocess.cpp @@ -5,14 +5,17 @@ BootSM *state_machine; -extern "C" __attribute__((section(".text.kcoreprocesses"))) void eval_bootscreen() { +//TODO: This is overengineered, just use C +extern "C" int eval_bootscreen(int argc, char* argv[]) { + kprintf(">>>> There are %i arguments"); while (1){ state_machine->eval_state(); } + return 1; } extern "C" void init_bootprocess() { state_machine = new BootSM(); - create_kernel_process("bootsm",eval_bootscreen); + create_kernel_process("bootsm",eval_bootscreen, 0, 0); state_machine->initialize(); } diff --git a/kernel/kernel_processes/boot/bootprocess_sm.cpp b/kernel/kernel_processes/boot/bootprocess_sm.cpp index 6a590036..03b5813b 100644 --- a/kernel/kernel_processes/boot/bootprocess_sm.cpp +++ b/kernel/kernel_processes/boot/bootprocess_sm.cpp @@ -9,6 +9,7 @@ BootSM::BootSM(){ } void BootSM::initialize(){ + start_terminal(); AdvanceToState(Bootscreen); } diff --git a/kernel/kernel_processes/boot/bootscreen.c b/kernel/kernel_processes/boot/bootscreen.c index 264102de..2c5cafe3 100644 --- a/kernel/kernel_processes/boot/bootscreen.c +++ b/kernel/kernel_processes/boot/bootscreen.c @@ -8,9 +8,19 @@ #include "process/scheduler.h" #include "math/math.h" #include "syscalls/syscalls.h" +#include "filesystem/filesystem.h" + +file boot_fd; -__attribute__((section(".text.kcoreprocesses"))) void boot_draw_name(gpu_point screen_middle,int xoffset, int yoffset){ + uint16_t pid = get_current_proc_pid(); + if (boot_fd.size == 0){ + string proc_out = string_format("/proc/%i/out",pid); + open_file(proc_out.data, &boot_fd); + free(proc_out.data, proc_out.mem_length); + } + write_file(&boot_fd, "hello buffer", 12); + const char* name = BOOTSCREEN_TEXT; string s = string_l(name); int scale = 2; @@ -23,10 +33,8 @@ void boot_draw_name(gpu_point screen_middle,int xoffset, int yoffset){ free(s.data,s.mem_length); } -__attribute__((section(".rodata.kcoreprocesses"))) const gpu_point offsets[BOOTSCREEN_NUM_SYMBOLS] = BOOTSCREEN_OFFSETS; -__attribute__((section(".text.kcoreprocesses"))) gpu_point boot_calc_point(gpu_point offset, gpu_size screen_size, gpu_point screen_middle){ int xoff = (screen_size.width/BOOTSCREEN_DIV) * offset.x; int yoff = (screen_size.height/BOOTSCREEN_DIV) * offset.y; @@ -80,14 +88,13 @@ void boot_draw_lines(gpu_point current_point, gpu_point next_point, gpu_size siz keypress kp; if (sys_read_input_current(&kp)) if (kp.keys[0] != 0){ - stop_current_process(); + stop_current_process(0); } gpu_flush(); } } -__attribute__((section(".text.kcoreprocesses"))) -void bootscreen(){ +int bootscreen(){ disable_visual(); gpu_clear(BG_COLOR); sys_focus_current(); @@ -107,8 +114,9 @@ void bootscreen(){ } sleep(1000); } + return 0; } process_t* start_bootscreen(){ - return create_kernel_process("bootscreen",bootscreen); + return create_kernel_process("bootscreen",bootscreen, 0, 0); } \ No newline at end of file diff --git a/kernel/kernel_processes/boot/login_screen.c b/kernel/kernel_processes/boot/login_screen.c index fcbe367c..8561078d 100644 --- a/kernel/kernel_processes/boot/login_screen.c +++ b/kernel/kernel_processes/boot/login_screen.c @@ -10,35 +10,7 @@ #include "std/string.h" #include "syscalls/syscalls.h" -//TODO: properly handle keypad -static const char hid_keycode_to_char[256] = { - [0x04] = 'a', [0x05] = 'b', [0x06] = 'c', [0x07] = 'd', - [0x08] = 'e', [0x09] = 'f', [0x0A] = 'g', [0x0B] = 'h', - [0x0C] = 'i', [0x0D] = 'j', [0x0E] = 'k', [0x0F] = 'l', - [0x10] = 'm', [0x11] = 'n', [0x12] = 'o', [0x13] = 'p', - [0x14] = 'q', [0x15] = 'r', [0x16] = 's', [0x17] = 't', - [0x18] = 'u', [0x19] = 'v', [0x1A] = 'w', [0x1B] = 'x', - [0x1C] = 'y', [0x1D] = 'z', - [0x1E] = '1', [0x1F] = '2', [0x20] = '3', [0x21] = '4', - [0x22] = '5', [0x23] = '6', [0x24] = '7', [0x25] = '8', - [0x26] = '9', [0x27] = '0', - [0x28] = '\n', [0x2C] = ' ', [0x2D] = '-', [0x2E] = '=', - [0x2F] = '[', [0x30] = ']', [0x31] = '\\', [0x33] = ';', - [0x34] = '\'', [0x35] = '`', [0x36] = ',', [0x37] = '.', - [0x38] = '/', [0x58] = '\n', -}; - -bool keypress_contains(keypress *kp, char key, uint8_t modifier){ - if (kp->modifier != modifier) return false;//TODO: This is not entirely accurate, some modifiers do not change key - - for (int i = 0; i < 6; i++) - if (kp->keys[i] == key) - return true; - return false; -} - -__attribute__((section(".text.kcoreprocesses"))) -void login_screen(){ +int login_screen(){ sys_focus_current(); sys_set_secure(true); char* buf = (char*)malloc(256); @@ -69,14 +41,14 @@ void login_screen(){ for (int i = 0; i < 6; i++){ char key = kp.keys[i]; if (hid_keycode_to_char[(uint8_t)key]){ - if (key == KEY_ENTER || key == KEY_KEYPAD_ENTER){ + if (key == KEY_ENTER || key == KEY_KPENTER){ if (strcmp(buf,default_pwd, false) == 0){ free(buf, 256); free(s.data,s.mem_length); free(title.data,title.mem_length); free(subtitle.data,subtitle.mem_length); sys_set_secure(false); - stop_current_process(); + stop_current_process(0); } else break; } @@ -97,8 +69,9 @@ void login_screen(){ gpu_flush(); free(s.data,s.mem_length); } + return 1; } process_t* present_login(){ - return create_kernel_process("login",login_screen); + return create_kernel_process("login",login_screen, 0, 0); } \ No newline at end of file diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index f5beb114..16ec8122 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -4,7 +4,7 @@ #include "memory/page_allocator.h" #include "exceptions/irq.h" -process_t *create_kernel_process(const char *name, void (*func)()){ +process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]){ disable_interrupt(); @@ -30,9 +30,13 @@ process_t *create_kernel_process(const char *name, void (*func)()){ proc->sp = proc->stack; proc->pc = (uintptr_t)func; - kprintf("Kernel process %s allocated with address at %x, stack at %x, heap at %x", (uintptr_t)name, proc->pc, proc->sp, proc->heap); + kprintf("Kernel process %s allocated with address at %x, stack at %x, heap at %x. %i argument(s)", (uintptr_t)name, proc->pc, proc->sp, proc->heap, argc); proc->spsr = 0x205; proc->state = READY; + proc->regs[14] = argc; + proc->regs[13] = (uintptr_t)argv; + + proc->output = (uintptr_t)palloc(0x1000, true, false, true); enable_interrupt(); diff --git a/kernel/kernel_processes/kprocess_loader.h b/kernel/kernel_processes/kprocess_loader.h index a5a973c2..62b05b4d 100644 --- a/kernel/kernel_processes/kprocess_loader.h +++ b/kernel/kernel_processes/kprocess_loader.h @@ -7,7 +7,7 @@ extern "C" { #include "types.h" #include "process/process.h" -process_t *create_kernel_process(const char *name, void (*func)()); +process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]); #ifdef __cplusplus } diff --git a/kernel/kernel_processes/monitor/monitor_processes.c b/kernel/kernel_processes/monitor/monitor_processes.c index bcdb151f..22506f31 100644 --- a/kernel/kernel_processes/monitor/monitor_processes.c +++ b/kernel/kernel_processes/monitor/monitor_processes.c @@ -12,7 +12,6 @@ #include "syscalls/syscalls.h" #include "memory/memory_types.h" -__attribute__((section(".text.kcoreprocesses"))) char* parse_proc_state(int state){ switch (state) { @@ -37,7 +36,6 @@ uint64_t calc_heap(uintptr_t ptr){ return size; } -__attribute__((section(".text.kcoreprocesses"))) void print_process_info(){ process_t *processes = get_all_processes(); for (int i = 0; i < MAX_PROCS; i++){ @@ -75,7 +73,6 @@ void draw_memory(char *name,int x, int y, int width, int full_height, int used, free(str.data,str.mem_length); } -__attribute__((section(".text.kcoreprocesses"))) void draw_process_view(){ gpu_clear(BG_COLOR+0x112211); process_t *processes = get_all_processes(); @@ -86,9 +83,9 @@ void draw_process_view(){ keypress kp; while (sys_read_input_current(&kp)){ - if (kp.keys[0] == KEY_ARROW_LEFT) + if (kp.keys[0] == KEY_LEFT) scroll_index = max(scroll_index - 1, 0); - if (kp.keys[0] == KEY_ARROW_RIGHT) + if (kp.keys[0] == KEY_RIGHT) scroll_index = min(scroll_index + 1,MAX_PROCS); } @@ -148,10 +145,9 @@ void draw_process_view(){ print_process_info(); } -__attribute__((section(".text.kcoreprocesses"))) -void monitor_procs(){ +int monitor_procs(){ keypress kp = { - .modifier = KEY_MOD_ALT, + .modifier = KEY_MOD_LALT, .keys[0] = 0x15//R }; uint16_t shortcut = sys_subscribe_shortcut_current(kp); @@ -167,13 +163,14 @@ void monitor_procs(){ if (active) draw_process_view(); } + return 1; } process_t* start_process_monitor(){ #if QEMU - return create_kernel_process("procmonitor",monitor_procs); + return create_kernel_process("procmonitor",monitor_procs, 0, 0); #else //TODO: disabled process monitor since shortcuts seem broken on rpi - return 0x0;//create_kernel_process("procmonitor",monitor_procs); + return 0x0;//create_kernel_process("procmonitor",monitor_procs, 0, 0); #endif } \ No newline at end of file diff --git a/kernel/kernel_processes/windows/desktop.cpp b/kernel/kernel_processes/windows/desktop.cpp index d7aa1bc5..dd64099c 100644 --- a/kernel/kernel_processes/windows/desktop.cpp +++ b/kernel/kernel_processes/windows/desktop.cpp @@ -62,20 +62,20 @@ void Desktop::draw_desktop(){ while (sys_read_input_current(&kp)){ for (int i = 0; i < 6; i++){ char key = kp.keys[i]; - if (key == KEY_ENTER || key == KEY_KEYPAD_ENTER){ + if (key == KEY_ENTER || key == KEY_KPENTER){ activate_current(); return; } - if (key == KEY_ARROW_RIGHT){ + if (key == KEY_RIGHT){ selected.x = (selected.x + 1) % MAX_COLS; } - if (key == KEY_ARROW_LEFT){ + if (key == KEY_LEFT){ selected.x = (selected.x - 1 + MAX_COLS) % MAX_COLS; } - if (key == KEY_ARROW_DOWN){ + if (key == KEY_DOWN){ selected.y = (selected.y + 1) % MAX_ROWS; } - if (key == KEY_ARROW_UP){ + if (key == KEY_UP){ selected.y = (selected.y - 1 + MAX_ROWS) % MAX_ROWS; } } diff --git a/kernel/kernel_processes/windows/windows.cpp b/kernel/kernel_processes/windows/windows.cpp index 0eea918c..47c99bff 100644 --- a/kernel/kernel_processes/windows/windows.cpp +++ b/kernel/kernel_processes/windows/windows.cpp @@ -9,7 +9,7 @@ WindowManager manager; bool screen_overlay; -extern "C" __attribute__((section(".text.kcoreprocesses"))) void manage_windows(){ +extern "C" int manage_windows(int argc, char* argv[]){ manager.initialize(); while (1) { @@ -17,16 +17,14 @@ extern "C" __attribute__((section(".text.kcoreprocesses"))) void manage_windows( } } -__attribute__((section(".text.kcoreprocesses"))) void pause_window_draw(){ manager.pause(); } -__attribute__((section(".text.kcoreprocesses"))) void resume_window_draw(){ manager.resume(); } extern "C" process_t* start_windows(){ - return create_kernel_process("winmanager",manage_windows); + return create_kernel_process("winmanager",manage_windows, 0, 0); } \ No newline at end of file diff --git a/kernel/linker.ld b/kernel/linker.ld index 543b8d78..8c7f977a 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -14,7 +14,7 @@ SECTIONS { bss = .; *(.bss) } - . = ALIGN(4096); /* align to page size */ + . = ALIGN(4096); __bss_end = .; __bss_size = __bss_end - __bss_start; .vectors : { KEEP(*(.vectors)) } @@ -22,6 +22,7 @@ SECTIONS { . = ALIGN(16); stack_bottom = .; .stack_fill : { FILL(0); . = . + 0x10000; } + ksp = .; stack_top = .; . = ALIGN(4096); @@ -29,20 +30,9 @@ SECTIONS { .heap_fill : { FILL(0); . = . + 0x2000000; } heap_limit = .; - .kcoreprocesses : ALIGN(8) { - kcoreprocesses_rodata_start = .; - KEEP(*(.rodata.kcoreprocesses)) - KEEP(*(.data.kcoreprocesses)) - kcoreprocesses_rodata_end = .; - kcoreprocesses_start = .; - KEEP(*(.text.kcoreprocesses)) - kcoreprocesses_end = .; - } . = ALIGN(0x200000); kcode_end = .; - . = . + 0x200000; - .shared : ALIGN(4096) { shared_start = .; KEEP(*(.shared)) diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index 726024b9..0d203190 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -36,6 +36,7 @@ void page_allocator_init() { } void pfree(void* ptr, uint64_t size) { + //TODO: review this, we're not using size uint64_t addr = (uint64_t)ptr; addr /= PAGE_SIZE; uint64_t table_index = addr/64; @@ -58,7 +59,9 @@ void* palloc(uint64_t size, bool kernel, bool device, bool full) { uint64_t bit = __builtin_ctzll(inv); do { bool found = true; + //TODO: check bounds for (uint64_t b = bit; b < bit + (page_count - 1); b++){ + //TODO: Review parentheses here if (!mem_bitmap[i] >> b & 1){ bit += page_count; found = false; diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index effa3743..ed8dcf95 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -17,8 +17,9 @@ void network_handle_upload_interrupt() { if (dispatch) dispatch->handle_upload_interrupt(); } -void network_net_task_entry() { - if (dispatch) dispatch->net_task(); +int network_net_task_entry(int argc, char* argv[]) { + if (dispatch) return dispatch->net_task(); + return 0; } int net_tx_frame(uintptr_t frame_ptr, uint32_t frame_len) { diff --git a/kernel/networking/network.h b/kernel/networking/network.h index d68f6000..1726d7f7 100644 --- a/kernel/networking/network.h +++ b/kernel/networking/network.h @@ -18,7 +18,7 @@ uint16_t network_net_get_pid(); bool network_init(); void network_handle_download_interrupt(); void network_handle_upload_interrupt(); -void network_net_task_entry(); +int network_net_task_entry(int argc, char* argv[]); int net_tx_frame(uintptr_t frame_ptr, uint32_t frame_len); int net_rx_frame(sizedptr *out_frame); diff --git a/kernel/networking/network_dispatch.cpp b/kernel/networking/network_dispatch.cpp index 901b23e6..c49b0c04 100644 --- a/kernel/networking/network_dispatch.cpp +++ b/kernel/networking/network_dispatch.cpp @@ -79,20 +79,18 @@ bool NetworkDispatch::enqueue_frame(const sizedptr &frame) return true; } -void NetworkDispatch::net_task() +int NetworkDispatch::net_task() { for (;;) { bool did_work = false; sizedptr pkt; - //rx if (!rx_queue.is_empty() && rx_queue.dequeue(pkt)) { did_work = true; eth_input(pkt.ptr, pkt.size); free_frame(pkt); } - //tx if (!tx_queue.is_empty() && tx_queue.dequeue(pkt)) { did_work = true; driver->send_packet(pkt); @@ -101,6 +99,7 @@ void NetworkDispatch::net_task() if (!did_work) sleep(10); } + return 0; } bool NetworkDispatch::dequeue_packet_for(uint16_t pid, sizedptr *out) diff --git a/kernel/networking/network_dispatch.hpp b/kernel/networking/network_dispatch.hpp index 4093389c..35bba52d 100644 --- a/kernel/networking/network_dispatch.hpp +++ b/kernel/networking/network_dispatch.hpp @@ -15,7 +15,7 @@ class NetworkDispatch { void handle_download_interrupt(); void handle_upload_interrupt(); bool enqueue_frame(const sizedptr&); - void net_task(); + int net_task(); bool dequeue_packet_for(uint16_t, sizedptr*); void set_net_pid(uint16_t pid); diff --git a/kernel/networking/processes/net_proc.c b/kernel/networking/processes/net_proc.c index 8ce94e60..61a92f29 100644 --- a/kernel/networking/processes/net_proc.c +++ b/kernel/networking/processes/net_proc.c @@ -115,20 +115,20 @@ void http_server_hello_entry() uint16_t pid = get_current_proc_pid(); http_server_handle_t srv = http_server_create(pid); if (!srv) { - stop_current_process(); + stop_current_process(1); return; } if (http_server_bind(srv, 80) < 0) { http_server_destroy(srv); - stop_current_process(); + stop_current_process(2); return; } if (http_server_listen(srv, 4) < 0) { http_server_close(srv); http_server_destroy(srv); - stop_current_process(); + stop_current_process(3); return; } @@ -277,41 +277,41 @@ void test_network() } } -void net_test_entry(){ +int net_test_entry(){ test_network(); - stop_current_process(); + return 0; } -void ip_waiter_entry() +int ip_waiter_entry() { for (;;) { const net_cfg_t *cfg = ipv4_get_cfg(); if (cfg && cfg->mode != NET_MODE_DISABLED && cfg->ip != 0) { - create_kernel_process("net_test", net_test_entry); + create_kernel_process("net_test", net_test_entry, 0, 0); break; } sleep(200); } - stop_current_process(); + return 0; } process_t* launch_net_process() { const net_cfg_t *cfg = ipv4_get_cfg(); - process_t* net = create_kernel_process("net_net", network_net_task_entry); + process_t* net = create_kernel_process("net_net", network_net_task_entry, 0, 0); network_net_set_pid(net ? net->id : 0xFFFF); - process_t* arp = create_kernel_process("arp_daemon", arp_daemon_entry); + process_t* arp = create_kernel_process("arp_daemon", arp_daemon_entry, 0, 0); arp_set_pid(arp ? arp->id : 0xFFFF); if (cfg && cfg->mode != NET_MODE_DISABLED && cfg->ip != 0) { - create_kernel_process("net_test", net_test_entry); + create_kernel_process("net_test", net_test_entry, 0, 0); return NULL; } - process_t* dhcp = create_kernel_process("dhcp_daemon", dhcp_daemon_entry); + process_t* dhcp = create_kernel_process("dhcp_daemon", dhcp_daemon_entry, 0, 0); dhcp_set_pid(dhcp ? dhcp->id : 0xFFFF); - create_kernel_process("ip_waiter", ip_waiter_entry); + create_kernel_process("ip_waiter", ip_waiter_entry, 0, 0); return dhcp; } diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index c21d5f61..71332b0d 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -284,6 +284,8 @@ process_t* create_process(const char *name, void *content, uint64_t content_size proc->spsr = 0; proc->state = READY; + proc->output = (uintptr_t)palloc(0x1000, false, false, true); + enable_interrupt(); return proc; diff --git a/kernel/process/process.h b/kernel/process/process.h index be636578..c834870a 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -7,6 +7,7 @@ extern "C" { #include "types.h" #include "keypress.h" #include "net/network_types.h" +#include "dev/driver_base.h" #define INPUT_BUFFER_CAPACITY 64 #define PACKET_BUFFER_CAPACITY 128 @@ -36,6 +37,9 @@ typedef struct { uintptr_t stack; uint64_t stack_size; uintptr_t heap; + uintptr_t output; + file out_fd; + uint64_t exit_code; bool focused; enum process_state { STOPPED, READY, RUNNING, BLOCKED } state; input_buffer_t input_buffer; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 3c5b18d4..b9366778 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -9,6 +9,10 @@ #include "exceptions/timer.h" #include "console/kconsole/kconsole.h" #include "syscalls/syscalls.h" +#include "std/string.h" +#include "data_struct/linked_list.h" +#include "std/memfunctions.h" +#include "math/math.h" extern void save_context(process_t* proc); extern void save_pc_interrupt(process_t* proc); @@ -31,7 +35,16 @@ typedef struct sleep_tracker { sleep_tracker sleeping[MAX_PROCS]; uint16_t sleep_count; -uint64_t ksp; +clinkedlist_t *proc_opened_files; + +typedef struct proc_open_file { + uint64_t fid; + size_t file_size; + uintptr_t buffer; + uint16_t pid; +} proc_open_file; + +void* proc_page; void save_context_registers(){ save_context(&processes[current_proc]); @@ -101,6 +114,7 @@ void reset_process(process_t *proc){ pfree((void*)proc->stack-proc->stack_size,proc->stack_size); proc->pc = 0; proc->spsr = 0; + proc->exit_code = 0; for (int j = 0; j < 31; j++) proc->regs[j] = 0; for (int k = 0; k < MAX_PROC_NAME_LENGTH; k++) @@ -121,6 +135,7 @@ void reset_process(process_t *proc){ } void init_main_process(){ + proc_page = palloc(0x1000, true, false, false); process_t* proc = &processes[0]; reset_process(proc); proc->id = next_proc_index++; @@ -128,8 +143,8 @@ void init_main_process(){ proc->heap = (uintptr_t)palloc(0x1000, true, false, false); proc->stack_size = 0x1000; proc->stack = (uintptr_t)palloc(proc->stack_size,true,false,true); - ksp = proc->stack + proc->stack_size; proc->sp = ksp; + proc->output = (uintptr_t)palloc(0x1000, true, false, true); name_process(proc, "kernel"); proc_count++; } @@ -165,11 +180,12 @@ void name_process(process_t *proc, const char *name){ proc->name[i] = name[i]; } -void stop_process(uint16_t pid){ +void stop_process(uint16_t pid, uint32_t exit_code){ disable_interrupt(); process_t *proc = get_proc_by_pid(pid); if (proc->state != READY) return; proc->state = STOPPED; + proc->exit_code = exit_code; if (proc->focused) sys_unset_focus(); //TODO: we don't wipe the process' data. If we do, we corrupt our sp, since we're still in the process' sp. @@ -178,9 +194,9 @@ void stop_process(uint16_t pid){ switch_proc(HALT); } -void stop_current_process(){ +void stop_current_process(uint32_t exit_code){ disable_interrupt(); - stop_process(processes[current_proc].id); + stop_process(processes[current_proc].id, exit_code); } uint16_t process_count(){ @@ -260,17 +276,68 @@ sizedptr list_processes(const char *path){ return (sizedptr){(uintptr_t)list_buffer,size}; } +#define PROC_OUT_BUF 0x1000 + FS_RESULT open_proc(const char *path, file *descriptor){ - kprintf("OPEN: %s",path); - return FS_RESULT_DRIVER_ERROR; + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + descriptor->id = reserve_fd_id(); + descriptor->size = PROC_OUT_BUF; + descriptor->cursor = 0; + if (!proc_opened_files) + proc_opened_files = kalloc(proc_page, sizeof(clinkedlist_t), ALIGN_64B, true, false); + proc_open_file *file = kalloc(proc_page, sizeof(proc_open_file), ALIGN_64B, true, false); + file->fid = descriptor->id; + file->buffer = proc->output; + file->pid = proc->id; + file->file_size = descriptor->size; + clinkedlist_push_front(proc_opened_files, (void*)file); + return FS_RESULT_SUCCESS; } -size_t read_proc(file* fd, char *buf, size_t size, file_offset offset){ +int find_open_proc_file(void *node, void* key){ + uint64_t *fid = (uint64_t*)key; + proc_open_file *file = (proc_open_file*)node; + if (file->fid == *fid) return 0; + return -1; } -size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ +size_t read_proc(file* fd, char *buf, size_t size, file_offset offset){ + if (!proc_opened_files){ + kprint("No files open"); + return 0; + } + clinkedlist_node_t *node = clinkedlist_find(proc_opened_files, (void*)&fd->id, find_open_proc_file); + if (!node->data) return 0; + proc_open_file *file = (proc_open_file*)node->data; + size = min(size, file->file_size); + memcpy(buf, (void*)(file->buffer + fd->cursor), size); + return size; +} +size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ + if (!proc_opened_files){ + kprint("No files open"); + return 0; + } + clinkedlist_node_t *node = clinkedlist_find(proc_opened_files, (void*)&fd->id, find_open_proc_file); + if (!node->data) return 0; + proc_open_file *file = (proc_open_file*)node->data; + if (size >= PROC_OUT_BUF){ + kprint("Output buffer too large"); + return 0; + } + if (fd->cursor + size >= PROC_OUT_BUF){ + fd->cursor = 0; + memset((void*)file->buffer, 0, file->file_size); + } + memcpy((void*)(file->buffer + fd->cursor), buf, size); + fd->cursor += size; + kprintf("Wrote %i bytes into process %i's output buffer", size, file->pid); + return size; } driver_module scheduler_module = (driver_module){ diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 455d7f61..daf139f5 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -21,8 +21,8 @@ process_t* init_process(); void save_syscall_return(uint64_t value); void process_restore(); -void stop_process(uint16_t pid); -void stop_current_process(); +void stop_process(uint16_t pid, uint32_t exit_code); +void stop_current_process(uint32_t exit_code); void name_process(process_t *proc, const char *name); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 8882644a..3e8d6eac 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -14,10 +14,15 @@ #include "exceptions/timer.h" #include "networking/network.h" #include "networking/port_manager.h" +#include "filesystem/filesystem.h" + +int syscall_depth = 0; void sync_el0_handler_c(){ save_context_registers(); save_return_address_interrupt(); + + syscall_depth++; if (ksp > 0) asm volatile ("mov sp, %0" :: "r"(ksp)); @@ -56,7 +61,7 @@ void sync_el0_handler_c(){ switch (iss) { case 0: - void* page_ptr = (void*)get_current_heap(); + void* page_ptr = syscall_depth > 1 ? (void*)get_proc_by_pid(1)->heap : (void*)get_current_heap(); if ((uintptr_t)page_ptr == 0x0){ handle_exception_with_info("Wrong process heap state", iss); } @@ -68,7 +73,6 @@ void sync_el0_handler_c(){ case 3: kprint((const char *)x0); break; - case 5: keypress *kp = (keypress*)x0; result = sys_read_input_current(kp); @@ -125,7 +129,7 @@ void sync_el0_handler_c(){ break; case 33: - stop_current_process(); + stop_current_process(x0); break; case 40: @@ -166,18 +170,27 @@ void sync_el0_handler_c(){ break; } } else { - //We could handle more exceptions now, such as x25 (unmasked x96) = data abort + switch (ec) { + case 0x21: + uint64_t far; + asm volatile ("mrs %0, far_el1" : "=r"(far)); + if (far == 0){ + kprintf("Process has exited %x",x0); + stop_current_process(x0); + } + } + //We could handle more exceptions now, such as x25 (unmasked x96) = data abort. 0x21 at end of 0x25 = alignment fault if (currentEL == 1) handle_exception_with_info("UNEXPECTED EXCEPTION",ec); else { uint64_t far; asm volatile ("mrs %0, far_el1" : "=r"(far)); kprintf("Process has crashed. ESR: %x. ELR: %x. FAR: %x", esr, elr, far); - stop_current_process(); + stop_current_process(ec); } } + syscall_depth--; if (result > 0) save_syscall_return(result); process_restore(); -} - +} \ No newline at end of file diff --git a/kernel/theme/RedactedOS.h b/kernel/theme/RedactedOS.h index 1da14ffb..b665c4a7 100644 --- a/kernel/theme/RedactedOS.h +++ b/kernel/theme/RedactedOS.h @@ -29,7 +29,9 @@ #define BOOTSCREEN_LOWER_Y_CONST 30 #define PANIC_TEXT "FATAL ERROR" +#define default_pwd "hi" #define BG_COLOR 0xFF222233 -#define default_pwd "hi" \ No newline at end of file +#define COLOR_WHITE 0xFFFFFFFF +#define COLOR_BLACK 0 \ No newline at end of file diff --git a/run_virt b/run_virt index 9055b39e..3df29834 100755 --- a/run_virt +++ b/run_virt @@ -18,7 +18,7 @@ fi OS_TYPE="$(uname)" DISPLAY_MODE="default" -SELECTED_GPU="virtio-gpu-pci" +SELECTED_GPU="virtio-gpu-pci,xres=1920,yres=1080" if [ "$OS_TYPE" = "Darwin" ]; then NETDEV="-netdev vmnet-bridged,id=net0,ifname=en0" @@ -27,6 +27,7 @@ if [ "$OS_TYPE" = "Darwin" ]; then elif [ "$OS_TYPE" = "Linux" ]; then NETDEV="-netdev user,id=net0" PRIVILEGE="" + DISPLAY_MODE="sdl" else echo "Unknown OS: $OS_TYPE" >&2 exit 1 diff --git a/rundebug b/rundebug index 965618f0..e9563519 100755 --- a/rundebug +++ b/rundebug @@ -10,9 +10,11 @@ for arg in "$@"; do esac done -osascript < +#define KEY_SLASH 0x38 // Keyboard / and ? +#define KEY_CAPSLOCK 0x39 // Keyboard Caps Lock + +#define KEY_F1 0x3a // Keyboard F1 +#define KEY_F2 0x3b // Keyboard F2 +#define KEY_F3 0x3c // Keyboard F3 +#define KEY_F4 0x3d // Keyboard F4 +#define KEY_F5 0x3e // Keyboard F5 +#define KEY_F6 0x3f // Keyboard F6 +#define KEY_F7 0x40 // Keyboard F7 +#define KEY_F8 0x41 // Keyboard F8 +#define KEY_F9 0x42 // Keyboard F9 +#define KEY_F10 0x43 // Keyboard F10 +#define KEY_F11 0x44 // Keyboard F11 +#define KEY_F12 0x45 // Keyboard F12 + +#define KEY_SYSRQ 0x46 // Keyboard Print Screen +#define KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock +#define KEY_PAUSE 0x48 // Keyboard Pause +#define KEY_INSERT 0x49 // Keyboard Insert +#define KEY_HOME 0x4a // Keyboard Home +#define KEY_PAGEUP 0x4b // Keyboard Page Up +#define KEY_DELETE 0x4c // Keyboard Delete Forward +#define KEY_END 0x4d // Keyboard End +#define KEY_PAGEDOWN 0x4e // Keyboard Page Down +#define KEY_RIGHT 0x4f // Keyboard Right Arrow +#define KEY_LEFT 0x50 // Keyboard Left Arrow +#define KEY_DOWN 0x51 // Keyboard Down Arrow +#define KEY_UP 0x52 // Keyboard Up Arrow + +#define KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear +#define KEY_KPSLASH 0x54 // Keypad / +#define KEY_KPASTERISK 0x55 // Keypad * +#define KEY_KPMINUS 0x56 // Keypad - +#define KEY_KPPLUS 0x57 // Keypad + +#define KEY_KPENTER 0x58 // Keypad ENTER +#define KEY_KP1 0x59 // Keypad 1 and End +#define KEY_KP2 0x5a // Keypad 2 and Down Arrow +#define KEY_KP3 0x5b // Keypad 3 and PageDn +#define KEY_KP4 0x5c // Keypad 4 and Left Arrow +#define KEY_KP5 0x5d // Keypad 5 +#define KEY_KP6 0x5e // Keypad 6 and Right Arrow +#define KEY_KP7 0x5f // Keypad 7 and Home +#define KEY_KP8 0x60 // Keypad 8 and Up Arrow +#define KEY_KP9 0x61 // Keypad 9 and Page Up +#define KEY_KP0 0x62 // Keypad 0 and Insert +#define KEY_KPDOT 0x63 // Keypad . and Delete + +#define KEY_102ND 0x64 // Keyboard Non-US \ and | +#define KEY_COMPOSE 0x65 // Keyboard Application +#define KEY_POWER 0x66 // Keyboard Power +#define KEY_KPEQUAL 0x67 // Keypad = + +#define KEY_F13 0x68 // Keyboard F13 +#define KEY_F14 0x69 // Keyboard F14 +#define KEY_F15 0x6a // Keyboard F15 +#define KEY_F16 0x6b // Keyboard F16 +#define KEY_F17 0x6c // Keyboard F17 +#define KEY_F18 0x6d // Keyboard F18 +#define KEY_F19 0x6e // Keyboard F19 +#define KEY_F20 0x6f // Keyboard F20 +#define KEY_F21 0x70 // Keyboard F21 +#define KEY_F22 0x71 // Keyboard F22 +#define KEY_F23 0x72 // Keyboard F23 +#define KEY_F24 0x73 // Keyboard F24 + +#define KEY_OPEN 0x74 // Keyboard Execute +#define KEY_HELP 0x75 // Keyboard Help +#define KEY_PROPS 0x76 // Keyboard Menu +#define KEY_FRONT 0x77 // Keyboard Select +#define KEY_STOP 0x78 // Keyboard Stop +#define KEY_AGAIN 0x79 // Keyboard Again +#define KEY_UNDO 0x7a // Keyboard Undo +#define KEY_CUT 0x7b // Keyboard Cut +#define KEY_COPY 0x7c // Keyboard Copy +#define KEY_PASTE 0x7d // Keyboard Paste +#define KEY_FIND 0x7e // Keyboard Find +#define KEY_MUTE 0x7f // Keyboard Mute +#define KEY_VOLUMEUP 0x80 // Keyboard Volume Up +#define KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down +// 0x82 Keyboard Locking Caps Lock +// 0x83 Keyboard Locking Num Lock +// 0x84 Keyboard Locking Scroll Lock +#define KEY_KPCOMMA 0x85 // Keypad Comma +// 0x86 Keypad Equal Sign +#define KEY_RO 0x87 // Keyboard International1 +#define KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2 +#define KEY_YEN 0x89 // Keyboard International3 +#define KEY_HENKAN 0x8a // Keyboard International4 +#define KEY_MUHENKAN 0x8b // Keyboard International5 +#define KEY_KPJPCOMMA 0x8c // Keyboard International6 +// 0x8d Keyboard International7 +// 0x8e Keyboard International8 +// 0x8f Keyboard International9 +#define KEY_HANGEUL 0x90 // Keyboard LANG1 +#define KEY_HANJA 0x91 // Keyboard LANG2 +#define KEY_KATAKANA 0x92 // Keyboard LANG3 +#define KEY_HIRAGANA 0x93 // Keyboard LANG4 +#define KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5 +// 0x95 Keyboard LANG6 +// 0x96 Keyboard LANG7 +// 0x97 Keyboard LANG8 +// 0x98 Keyboard LANG9 +// 0x99 Keyboard Alternate Erase +// 0x9a Keyboard SysReq/Attention +// 0x9b Keyboard Cancel +// 0x9c Keyboard Clear +// 0x9d Keyboard Prior +// 0x9e Keyboard Return +// 0x9f Keyboard Separator +// 0xa0 Keyboard Out +// 0xa1 Keyboard Oper +// 0xa2 Keyboard Clear/Again +// 0xa3 Keyboard CrSel/Props +// 0xa4 Keyboard ExSel + +// 0xb0 Keypad 00 +// 0xb1 Keypad 000 +// 0xb2 Thousands Separator +// 0xb3 Decimal Separator +// 0xb4 Currency Unit +// 0xb5 Currency Sub-unit +#define KEY_KPLEFTPAREN 0xb6 // Keypad ( +#define KEY_KPRIGHTPAREN 0xb7 // Keypad ) +// 0xb8 Keypad { +// 0xb9 Keypad } +// 0xba Keypad Tab +// 0xbb Keypad Backspace +// 0xbc Keypad A +// 0xbd Keypad B +// 0xbe Keypad C +// 0xbf Keypad D +// 0xc0 Keypad E +// 0xc1 Keypad F +// 0xc2 Keypad XOR +// 0xc3 Keypad ^ +// 0xc4 Keypad % +// 0xc5 Keypad < +// 0xc6 Keypad > +// 0xc7 Keypad & +// 0xc8 Keypad && +// 0xc9 Keypad | +// 0xca Keypad || +// 0xcb Keypad : +// 0xcc Keypad # +// 0xcd Keypad Space +// 0xce Keypad @ +// 0xcf Keypad ! +// 0xd0 Keypad Memory Store +// 0xd1 Keypad Memory Recall +// 0xd2 Keypad Memory Clear +// 0xd3 Keypad Memory Add +// 0xd4 Keypad Memory Subtract +// 0xd5 Keypad Memory Multiply +// 0xd6 Keypad Memory Divide +// 0xd7 Keypad +/- +// 0xd8 Keypad Clear +// 0xd9 Keypad Clear Entry +// 0xda Keypad Binary +// 0xdb Keypad Octal +// 0xdc Keypad Decimal +// 0xdd Keypad Hexadecimal + +#define KEY_LEFTCTRL 0xe0 // Keyboard Left Control +#define KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift +#define KEY_LEFTALT 0xe2 // Keyboard Left Alt +#define KEY_LEFTMETA 0xe3 // Keyboard Left GUI +#define KEY_RIGHTCTRL 0xe4 // Keyboard Right Control +#define KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift +#define KEY_RIGHTALT 0xe6 // Keyboard Right Alt +#define KEY_RIGHTMETA 0xe7 // Keyboard Right GUI + +#define KEY_MEDIA_PLAYPAUSE 0xe8 +#define KEY_MEDIA_STOPCD 0xe9 +#define KEY_MEDIA_PREVIOUSSONG 0xea +#define KEY_MEDIA_NEXTSONG 0xeb +#define KEY_MEDIA_EJECTCD 0xec +#define KEY_MEDIA_VOLUMEUP 0xed +#define KEY_MEDIA_VOLUMEDOWN 0xee +#define KEY_MEDIA_MUTE 0xef +#define KEY_MEDIA_WWW 0xf0 +#define KEY_MEDIA_BACK 0xf1 +#define KEY_MEDIA_FORWARD 0xf2 +#define KEY_MEDIA_STOP 0xf3 +#define KEY_MEDIA_FIND 0xf4 +#define KEY_MEDIA_SCROLLUP 0xf5 +#define KEY_MEDIA_SCROLLDOWN 0xf6 +#define KEY_MEDIA_EDIT 0xf7 +#define KEY_MEDIA_SLEEP 0xf8 +#define KEY_MEDIA_COFFEE 0xf9 +#define KEY_MEDIA_REFRESH 0xfa +#define KEY_MEDIA_CALC 0xfb + +#ifndef __cplusplus +//TODO: properly handle keypad +static const char hid_keycode_to_char[256] = { + [0x04] = 'a', [0x05] = 'b', [0x06] = 'c', [0x07] = 'd', + [0x08] = 'e', [0x09] = 'f', [0x0A] = 'g', [0x0B] = 'h', + [0x0C] = 'i', [0x0D] = 'j', [0x0E] = 'k', [0x0F] = 'l', + [0x10] = 'm', [0x11] = 'n', [0x12] = 'o', [0x13] = 'p', + [0x14] = 'q', [0x15] = 'r', [0x16] = 's', [0x17] = 't', + [0x18] = 'u', [0x19] = 'v', [0x1A] = 'w', [0x1B] = 'x', + [0x1C] = 'y', [0x1D] = 'z', + [0x1E] = '1', [0x1F] = '2', [0x20] = '3', [0x21] = '4', + [0x22] = '5', [0x23] = '6', [0x24] = '7', [0x25] = '8', + [0x26] = '9', [0x27] = '0', + [0x28] = '\n', [0x2C] = ' ', [0x2D] = '-', [0x2E] = '=', + [0x2F] = '[', [0x30] = ']', [0x31] = '\\', [0x33] = ';', + [0x34] = '\'', [0x35] = '`', [0x36] = ',', [0x37] = '.', + [0x38] = '/', [0x58] = '\n', +}; +#else extern "C" { -#endif -#define KEY_ARROW_UP 0x52 -#define KEY_ARROW_DOWN 0x51 -#define KEY_ARROW_LEFT 0x50 -#define KEY_ARROW_RIGHT 0x4F -#define KEY_BACKSPACE 0x2A -#define KEY_ENTER 0x28 -#define KEY_KEYPAD_ENTER 0x58 -#define KEY_ESC 0x29 - -#define KEY_MOD_CMD 0x8 -#define KEY_MOD_ALT 0x4 -#define KEY_MOD_CTRL 0x1 +#endif +char hid_to_char(unsigned char c); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif \ No newline at end of file diff --git a/shared/net/application_layer/dhcp_daemon.c b/shared/net/application_layer/dhcp_daemon.c index 9fcc99c4..ff093f52 100644 --- a/shared/net/application_layer/dhcp_daemon.c +++ b/shared/net/application_layer/dhcp_daemon.c @@ -247,13 +247,13 @@ static void dhcp_fsm_once() if (old != g_state) log_state_change(old, g_state); } -void dhcp_daemon_entry(){ +int dhcp_daemon_entry(){ KP("[DHCP] daemon start pid=%i", get_current_proc_pid()); g_pid_dhcpd = (uint16_t)get_current_proc_pid(); g_sock = udp_socket_create(SOCK_ROLE_SERVER, g_pid_dhcpd); if(socket_bind_udp(g_sock, 68) != 0){ KP("[DHCP] bind failed\n"); - return; + return 1; } for(;;){ diff --git a/shared/net/application_layer/dhcp_daemon.h b/shared/net/application_layer/dhcp_daemon.h index fcf501dc..0b530d84 100644 --- a/shared/net/application_layer/dhcp_daemon.h +++ b/shared/net/application_layer/dhcp_daemon.h @@ -5,7 +5,7 @@ extern "C" { #endif -void dhcp_daemon_entry(); +int dhcp_daemon_entry(); uint16_t get_dhcp_pid(); bool dhcp_is_running(); void dhcp_set_pid(uint16_t pid); diff --git a/shared/net/link_layer/arp.c b/shared/net/link_layer/arp.c index 18eac6db..0e950e4f 100644 --- a/shared/net/link_layer/arp.c +++ b/shared/net/link_layer/arp.c @@ -153,7 +153,7 @@ bool arp_can_reply() { return (cfg && cfg->ip != 0 && cfg->mode != NET_MODE_DISABLED); } -void arp_daemon_entry() { +int arp_daemon_entry() { while (1){ const net_cfg_t *cfg = ipv4_get_cfg(); if(cfg && cfg->ip != 0 && cfg->mode != NET_MODE_DISABLED) break; diff --git a/shared/net/link_layer/arp.h b/shared/net/link_layer/arp.h index 4e5454a3..0066a149 100644 --- a/shared/net/link_layer/arp.h +++ b/shared/net/link_layer/arp.h @@ -43,9 +43,8 @@ void arp_table_init_static_defaults(); void arp_send_request(uint32_t target_ip); -void arp_daemon_entry(); +int arp_daemon_entry(); bool arp_can_reply(); -void arp_daemon_entry(); void arp_set_pid(uint16_t pid); uint16_t arp_get_pid(); void arp_input(uintptr_t frame_ptr, uint32_t frame_len); diff --git a/shared/std/std.hpp b/shared/std/std.hpp index 2beffcfc..80a04a5a 100644 --- a/shared/std/std.hpp +++ b/shared/std/std.hpp @@ -1,4 +1,5 @@ #pragma once #include "allocator.hpp" -#include "data_struct/data_struct.hpp" \ No newline at end of file +#include "data_struct/data_struct.hpp" +#include "../syscalls/syscalls.h" \ No newline at end of file diff --git a/shared/std/string.c b/shared/std/string.c index f7f572f2..0966f311 100644 --- a/shared/std/string.c +++ b/shared/std/string.c @@ -124,10 +124,20 @@ bool string_equals(string a, string b){ return strcmp(a.data,b.data, false) == 0; } +string string_replace(const char *str, char orig, char repl){ + size_t str_size = strlen(str, 0); + char *buf = (char*)malloc(str_size+1); + for (size_t i = 0; i < str_size && str[i]; i++){ + buf[i] = str[i] == orig ? repl : str[i]; + } + buf[str_size] = 0; + return (string){ .data = buf, .length = str_size, .mem_length = str_size + 1}; +} + string string_format(const char *fmt, ...){ if (fmt == NULL) return (string){ .data = NULL, .length = 0, .mem_length = 0}; - va_list args; + __attribute__((aligned(16))) va_list args; va_start(args, fmt); string result = string_format_va(fmt, args); va_end(args); @@ -160,7 +170,7 @@ size_t string_format_va_buf(const char *fmt, char *buf, va_list args){ buf[len++] = (char)val; } else if (fmt[i] == 's') { - char *str = ( char *)va_arg(args, uintptr_t); + char *str = ( char *)va_arg(args, uintptr_t); for (uint32_t j = 0; str[j] && len < 255; j++) buf[len++] = str[j]; } else if (fmt[i] == 'i') { @@ -306,6 +316,15 @@ bool strcont(const char *a, const char *b){ return 0; } +int count_occurrences(const char* str, char c){ + int count = 0; + while (*str) { + if (*str == c) count++; + str++; + } + return count; +} + bool utf16tochar(uint16_t* str_in, char* out_str, size_t max_len){ size_t out_i = 0; for (size_t i = 0; i < max_len && str_in[i]; i++){ @@ -316,7 +335,7 @@ bool utf16tochar(uint16_t* str_in, char* out_str, size_t max_len){ return true; } -uint64_t parse_hex_u64(char* str, size_t size){ +uint64_t parse_hex_u64(const char* str, size_t size){ uint64_t result = 0; for (uint32_t i = 0; i < size; i++){ char c = str[i]; @@ -330,6 +349,17 @@ uint64_t parse_hex_u64(char* str, size_t size){ return result; } +uint64_t parse_int_u64(const char* str, size_t size){ + uint64_t result = 0; + for (uint32_t i = 0; i < size; i++){ + char c = str[i]; + uint8_t digit = 0; + if (c >= '0' && c <= '9') digit = c - '0'; + else break; + result = (result * 10) + digit; + } + return result; +} string string_from_const(const char *lit) { @@ -377,4 +407,11 @@ void string_append_bytes(string *dest, const void *buf, uint32_t len) if (!len) return; string tmp = { (char *)buf, len, len }; string_concat_inplace(dest, tmp); +} + +const char* seek_to(const char *string, char character){ + while (*string != character && *string != '\0') + string++; + string++; + return string; } \ No newline at end of file diff --git a/shared/std/string.h b/shared/std/string.h index 8da8b39e..76dec23c 100644 --- a/shared/std/string.h +++ b/shared/std/string.h @@ -24,6 +24,7 @@ string string_ca_max(const char *array, uint32_t max_length); string string_c(const char c); string string_from_hex(uint64_t value); bool string_equals(string a, string b); +string string_replace(const char *str, char orig, char repl); string string_format(const char *fmt, ...); string string_format_va(const char *fmt, va_list args); __attribute__((used)) @@ -37,8 +38,10 @@ bool strcont(const char *a, const char *b); int strstart(const char *a, const char *b, bool case_insensitive); int strend(const char *a, const char *b, bool case_insensitive); int strindex(const char *a, const char *b); +int count_occurrences(const char* str, char c); -uint64_t parse_hex_u64(char* str, size_t size); +uint64_t parse_hex_u64(const char* str, size_t size); +uint64_t parse_int_u64(const char* str, size_t size); bool utf16tochar( uint16_t* str_in, char* out_str, size_t max_len); @@ -46,6 +49,7 @@ string string_from_const(const char *literal); string string_concat(string a, string b); void string_concat_inplace(string *dest, string src); void string_append_bytes(string *dest, const void *buf, uint32_t len); +const char* seek_to(const char *string, char character); #ifdef __cplusplus } diff --git a/shared/syscalls/syscalls.c b/shared/syscalls/syscalls.c index 5811ee72..807858f2 100644 --- a/shared/syscalls/syscalls.c +++ b/shared/syscalls/syscalls.c @@ -2,7 +2,7 @@ #include "std/string.h" void printf(const char *fmt, ...){ - va_list args; + __attribute__((aligned(16))) va_list args; va_start(args, fmt); string str = string_format_va(fmt, args); va_end(args); diff --git a/shared/syscalls/syscalls.h b/shared/syscalls/syscalls.h index 673a8ea5..c31154ea 100644 --- a/shared/syscalls/syscalls.h +++ b/shared/syscalls/syscalls.h @@ -18,7 +18,7 @@ extern void free(void *ptr, size_t size); extern bool read_key(keypress *kp); extern void sleep(uint64_t time); -extern void halt(); +extern void halt(uint32_t exit_code); extern void clear_screen(color color); extern void gpu_flush_data(); diff --git a/shared/ui/draw/draw.c b/shared/ui/draw/draw.c index 5348c88f..0e1322fb 100644 --- a/shared/ui/draw/draw.c +++ b/shared/ui/draw/draw.c @@ -107,15 +107,15 @@ gpu_rect fb_draw_line(uint32_t* fb, uint32_t x0, uint32_t y0, uint32_t x1, uint3 void fb_draw_char(uint32_t* fb, uint32_t x, uint32_t y, char c, uint32_t scale, uint32_t color){ const uint8_t* glyph = get_font8x8((uint8_t)c); - for (uint32_t row = 0; row < (8 * scale); row++) { + for (uint32_t row = 0; row < (CHAR_SIZE * scale); row++) { uint8_t bits = glyph[row/scale]; - for (uint32_t col = 0; col < (8 * scale); col++) { + for (uint32_t col = 0; col < (CHAR_SIZE * scale); col++) { if (bits & (1 << (7 - (col / scale)))) { fb_draw_pixel(fb, x + col, y + row, color); } } } - mark_dirty(x,y,8*scale,8*scale); + mark_dirty(x,y,CHAR_SIZE*scale,CHAR_SIZE*scale); } gpu_size fb_draw_string(uint32_t* fb, string s, uint32_t x0, uint32_t y0, uint32_t scale, uint32_t color){ @@ -150,7 +150,7 @@ gpu_size fb_draw_string(uint32_t* fb, string s, uint32_t x0, uint32_t y0, uint32 } uint32_t fb_get_char_size(uint32_t scale){ - return 8 * scale; + return CHAR_SIZE * scale; } void fb_set_stride(uint32_t new_stride){ diff --git a/shared/ui/draw/draw.h b/shared/ui/draw/draw.h index 0b949c8a..e441468a 100644 --- a/shared/ui/draw/draw.h +++ b/shared/ui/draw/draw.h @@ -6,6 +6,8 @@ extern "C" { #include "ui/graphic_types.h" #include "std/string.h" +#define CHAR_SIZE 8 + int try_merge(gpu_rect* a, gpu_rect* b); void mark_dirty(uint32_t x, uint32_t y, uint32_t w, uint32_t h); diff --git a/user/Makefile b/user/Makefile index 9aa864f1..5e5cabf1 100644 --- a/user/Makefile +++ b/user/Makefile @@ -1,11 +1,18 @@ #user -CFLAGS := $(CFLAGS_BASE) -I. -I../shared -Wno-unused-parameter -LDFLAGS := -T $(shell ls *.ld) + +include ../common.mk + +CPPFLAGS := -I. -I../shared +CFLAGS := $(CFLAGS_BASE) $(CPPFLAGS) +CXXFLAGS := $(CXXFLAGS_BASE) $(CPPFLAGS) +LDFLAGS := -T $(shell ls *.ld) CLEAN_OBJS := $(shell find . -name '*.o') +CLEAN_DEPS := $(shell find . -name '*.d') C_SRC := $(shell find . -name '*.c') CPP_SRC := $(shell find . -name '*.cpp') OBJ := $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) +DEP := $(C_SRC:.c=.d) $(CPP_SRC:.cpp=.d) NAME := $(notdir $(CURDIR)) ELF := $(NAME).elf @@ -17,17 +24,19 @@ LOCATION := ../fs/redos/user/ all: $(LOCATION)$(TARGET) $(LOCATION)$(TARGET): $(OBJ) - $(LD) $(LDFLAGS) -o $(LOCATION)$(ELF) $(OBJ) ../shared/libshared.a + $(VLD) $(LDFLAGS) -o $(LOCATION)$(ELF) $(OBJ) ../shared/libshared.a $(OBJCOPY) -O binary $(LOCATION)$(ELF) $@ %.o: %.S - $(CC) $(CFLAGS) -c $< -o $@ + $(VAS) $(CFLAGS) -c $< -o $@ %.o: %.c - $(CC) $(CFLAGS) $(CONLY_FLAGS_BASE) -c $< -o $@ + $(VCC) $(CFLAGS) -c -MMD -MP $< -o $@ %.o: %.cpp - $(CC) $(CFLAGS) -fno-rtti -c $< -o $@ + $(VCXX) $(CXXFLAGS) -c -MMD -MP $< -o $@ clean: - rm -f $(CLEAN_OBJS) $(TARGET) + $(RM) $(CLEAN_OBJS) $(CLEAN_DEPS) $(TARGET) + +-include $(DEP) diff --git a/user/default_process.c b/user/default_process.c index c75b6dad..599660da 100644 --- a/user/default_process.c +++ b/user/default_process.c @@ -11,7 +11,7 @@ void proc_func() { printf("Print console test %f", (get_time()/1000.f)); while (read_key(&kp)){ if (kp.keys[0] == KEY_ESC) - halt(); + halt(0); } clear_screen(0xFFFFFFFF); draw_primitive_rect(&rect, 0xFF222233); @@ -20,4 +20,5 @@ void proc_func() { free(s.data,s.mem_length); gpu_flush_data(); } + halt(1); } \ No newline at end of file