greatbridf 2 anni fa
parent
commit
57bb3fc54e
6 ha cambiato i file con 72 aggiunte e 14 eliminazioni
  1. 1 1
      CMakeLists.txt
  2. 12 6
      include/kernel/tty.h
  3. 19 1
      src/kernel/syscall.cpp
  4. 9 3
      src/kernel/tty.cpp
  5. 4 1
      src/kernel/vfs.cpp
  6. 27 2
      src/kernel_main.c

+ 1 - 1
CMakeLists.txt

@@ -53,7 +53,7 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         src/kernel/errno.c
                         src/kernel/interrupt.cpp
                         src/kernel/process.cpp
-                        src/kernel/tty.c
+                        src/kernel/tty.cpp
                         src/kernel/stdio.c
                         src/kernel/syscall.cpp
                         src/kernel/mem.cpp

+ 12 - 6
include/kernel/tty.h

@@ -1,24 +1,30 @@
 #pragma once
 #include <asm/port_io.h>
+#include <types/stdint.h>
 
 #define STRUCT_TTY_NAME_LEN (32)
 
+#define SERIAL_TTY_BUFFER_SIZE (4096)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 struct tty;
 
-struct tty_operations
-{
+struct tty_operations {
     void (*put_char)(struct tty* p_tty, char c);
 };
 
-struct tty
-{
+struct tty {
     char name[STRUCT_TTY_NAME_LEN];
     struct tty_operations* ops;
-    char data[12];
+    union {
+        uint8_t u8[12];
+        uint16_t u16[6];
+        uint32_t u32[3];
+        void* p[12 / sizeof(void*)];
+    } data;
 };
 
 // in kernel_main.c
@@ -26,7 +32,7 @@ extern struct tty* console;
 
 void tty_print(struct tty* p_tty, const char* str);
 
-int make_serial_tty(struct tty* p_tty, int id);
+int make_serial_tty(struct tty* p_tty, int id, int buffered);
 int make_vga_tty(struct tty* p_tty);
 
 #ifdef __cplusplus

+ 19 - 1
src/kernel/syscall.cpp

@@ -91,6 +91,24 @@ void _syscall_write(interrupt_stack* data)
     SYSCALL_SET_RETURN_VAL(n_wrote, 0);
 }
 
+void _syscall_read(interrupt_stack* data)
+{
+    int fd = data->s_regs.edi;
+    char* buf = reinterpret_cast<char*>(data->s_regs.esi);
+    size_t n = data->s_regs.edx;
+
+    auto* file = current_process->files[fd];
+    if (file->type != fs::file::types::regular_file) {
+        SYSCALL_SET_RETURN_VAL(GB_FAILED, EINVAL);
+        return;
+    }
+
+    // TODO: copy to user function !IMPORTANT
+    int n_wrote = fs::vfs_read(file->impl.ind, buf, 0U - 1, file->cursor, n);
+    file->cursor += n_wrote;
+    SYSCALL_SET_RETURN_VAL(n_wrote, 0);
+}
+
 void _syscall_sleep(interrupt_stack* data)
 {
     current_thread->attr.ready = 0;
@@ -224,5 +242,5 @@ void init_syscall(void)
     syscall_handlers[4] = _syscall_exec;
     syscall_handlers[5] = _syscall_exit;
     syscall_handlers[6] = _syscall_wait;
-    syscall_handlers[7] = _syscall_not_impl;
+    syscall_handlers[7] = _syscall_read;
 }

+ 9 - 3
src/kernel/tty.c → src/kernel/tty.cpp

@@ -7,7 +7,7 @@
 
 static void serial_tty_put_char(struct tty* p_tty, char c)
 {
-    serial_send_data(*(port_id_t*)&p_tty->data, c);
+    serial_send_data(p_tty->data.u16[0], c);
 }
 
 static void vga_tty_put_char(struct tty* _unused, char c)
@@ -33,9 +33,15 @@ void tty_print(struct tty* p_tty, const char* str)
     }
 }
 
-int make_serial_tty(struct tty* p_tty, int id)
+int make_serial_tty(struct tty* p_tty, int id, int buffered)
 {
-    *(port_id_t*)&p_tty->data = id;
+    // 0-1: port id
+    // 2  : is_buffered
+    // 3  : unused
+    // 4-7: buffer pointer
+    p_tty->data.u16[0] = id;
+    p_tty->data.p[1] = buffered ? k_malloc(SERIAL_TTY_BUFFER_SIZE) : NULL;
+    p_tty->data.u8[2] = buffered;
     snprintf(p_tty->name, sizeof(p_tty->name), "ttyS%x", id);
     p_tty->ops = &serial_tty_ops;
     return GB_OK;

+ 4 - 1
src/kernel/vfs.cpp

@@ -473,6 +473,9 @@ size_t b_null_write(fs::special_node*, const char*, size_t, size_t n)
 {
     return n;
 }
+static size_t console_read(fs::special_node*, char* buf, size_t buf_size, size_t offset, size_t n)
+{
+}
 static size_t console_write(fs::special_node*, const char* buf, size_t, size_t n)
 {
     size_t orig_n = n;
@@ -489,7 +492,7 @@ void init_vfs(void)
     register_special_block(0, 0, b_null_read, b_null_write, 0, 0);
     // console (supports serial console only for now)
     // TODO: add interface to bind console device to other devices
-    register_special_block(1, 0, nullptr, console_write, 0, 0);
+    register_special_block(1, 0, console_read, console_write, 0, 0);
 
     fs_es = types::pnew<types::kernel_ident_allocator>(fs_es);
 

+ 27 - 2
src/kernel_main.c

@@ -123,7 +123,29 @@ void init_bss_section(void)
     memset(bss_addr, 0x00, bss_size);
 }
 
-static struct tty early_console;
+int init_console(const char* name)
+{
+    console = ki_malloc(sizeof(struct tty));
+    if (name[0] == 't' && name[1] == 't' && name[2] == 'y') {
+        if (name[3] == 'S' || name[3] == 's') {
+            if (name[4] == '0') {
+                make_serial_tty(console, PORT_SERIAL0, 1);
+                return GB_OK;
+            }
+            if (name[4] == '1') {
+                make_serial_tty(console, PORT_SERIAL1, 1);
+                return GB_OK;
+            }
+        }
+        if (name[3] == 'V' && name[3] == 'G' && name[3] == 'A') {
+            make_vga_tty(console);
+            return GB_OK;
+        }
+    }
+    ki_free(console);
+    console = NULL;
+    return GB_FAILED;
+}
 
 extern void init_vfs();
 extern void NORETURN init_scheduler();
@@ -142,8 +164,9 @@ void NORETURN kernel_main(void)
 
     char buf[KERNEL_MAIN_BUF_SIZE] = { 0 };
 
+    struct tty early_console;
     assert(init_serial_port(PORT_SERIAL0) == GB_OK);
-    assert(make_serial_tty(&early_console, PORT_SERIAL0) == GB_OK);
+    assert(make_serial_tty(&early_console, PORT_SERIAL0, 0) == GB_OK);
     console = &early_console;
 
     show_mem_info(buf);
@@ -174,6 +197,8 @@ void NORETURN kernel_main(void)
     tty_print(console, k_malloc_buf);
     k_free(k_malloc_buf);
 
+    assert(init_console("ttyS0") == GB_OK);
+
     init_vfs();
 
     printkf("switching execution to the scheduler...\n");