瀏覽代碼

feat: tty, memcpy and strlen

greatbridf 2 年之前
父節點
當前提交
7cb2030b14

+ 3 - 0
CMakeLists.txt

@@ -42,6 +42,7 @@ include_directories(${PROJECT_SOURCE_DIR}/include)
 set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         src/kernel/errno.c
                         src/kernel/interrupt.c
+                        src/kernel/tty.c
                         src/kernel/stdio.c
                         src/kernel/mem.c
                         src/kernel/vga.c
@@ -55,6 +56,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/asm/sys.h
                         include/kernel/event/event.h
                         include/kernel/errno.h
+                        include/kernel/tty.h
                         include/kernel/interrupt.h
                         include/kernel/stdio.h
                         include/kernel/mem.h
@@ -67,6 +69,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/types/buffer.h
                         include/types/types.h
                         include/types/size.h
+                        include/types/status.h
                         include/types/stdint.h
                         include/types/list.hpp
                         include/kernel_main.h

+ 1 - 1
include/kernel/mem.h

@@ -33,7 +33,7 @@ struct mem_blk {
     uint8_t data[4];
 };
 
-void init_heap(void);
+int init_heap(void);
 
 void* k_malloc(size_t size);
 

+ 4 - 0
include/kernel/stdio.h

@@ -14,6 +14,10 @@
 extern "C" {
 #endif
 
+void* memcpy(void* dst, const void* src, size_t n);
+size_t strlen(const char* str);
+char* strncpy(char* dst, const char* src, size_t max_n);
+
 ssize_t
 snprint_decimal(
     char* buf,

+ 23 - 0
include/kernel/tty.h

@@ -0,0 +1,23 @@
+#pragma once
+#include <asm/port_io.h>
+
+#define STRUCT_TTY_NAME_LEN (32)
+
+struct tty;
+
+struct tty_operations
+{
+    void (*put_char)(struct tty* p_tty, char c);
+};
+
+struct tty
+{
+    char name[STRUCT_TTY_NAME_LEN];
+    struct tty_operations* ops;
+    char data[12];
+};
+
+void tty_print(struct tty* p_tty, const char* str);
+
+int make_serial_tty(struct tty* p_tty, int id);
+int make_vga_tty(struct tty* p_tty);

+ 3 - 1
include/kernel/vga.h

@@ -8,6 +8,8 @@
 extern "C" {
 #endif
 
+#define VGA_CHAR_COLOR_WHITE (0x0fU)
+
 struct vga_char {
     int8_t c;
     uint8_t color;
@@ -18,7 +20,7 @@ struct vga_char {
 #define VGA_SCREEN_HEIGHT_IN_CHARS (25U)
 
 void vga_put_char(struct vga_char* c);
-void vga_printk(const char* str, uint8_t color);
+void vga_print(const char* str, uint8_t color);
 
 #ifdef __cplusplus
 }

+ 4 - 0
include/types/status.h

@@ -0,0 +1,4 @@
+#pragma once
+
+#define GB_OK (0)
+#define GB_FAILED (1)

+ 2 - 0
include/types/stdint.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#define NULL ((void*)0)
+
 typedef __INT8_TYPE__ int8_t;
 typedef __INT16_TYPE__ int16_t;
 typedef __INT32_TYPE__ int32_t;

+ 1 - 0
include/types/types.h

@@ -2,4 +2,5 @@
 
 #include "buffer.h"
 #include "size.h"
+#include "status.h"
 #include "stdint.h"

+ 2 - 1
src/kernel/event/event.cpp

@@ -28,7 +28,8 @@ void dispatch_event(void)
         for (auto iter = input_event_queue.begin(); iter != input_event_queue.end(); ++iter) {
             const auto& item = *iter;
             snprintf(buf, 1024, "\rinput event: type%x, data%x, code%x\r", item.type, item.data, item.code);
-            vga_printk(buf, 0x0fu);
+            // TODO: change to tty
+            vga_print(buf, 0x0fu);
             input_event_queue.erase(iter);
         }
     }

+ 18 - 9
src/kernel/interrupt.c

@@ -67,7 +67,8 @@ void int6_handler(
 {
     char buf[512];
 
-    vga_printk("---- INVALID OPCODE ----\n", 0x0fu);
+    // TODO: change to tty
+    vga_print("---- INVALID OPCODE ----\n", 0x0fu);
 
     snprintf(
         buf, 512,
@@ -78,9 +79,11 @@ void int6_handler(
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
         cs, error_code);
-    vga_printk(buf, 0x0fu);
+    // TODO: change to tty
+    vga_print(buf, 0x0fu);
 
-    vga_printk("----   HALTING SYSTEM   ----", 0x0fu);
+    // TODO: change to tty
+    vga_print("----   HALTING SYSTEM   ----", 0x0fu);
 
     asm_cli();
     asm_hlt();
@@ -96,7 +99,8 @@ void int13_handler(
 {
     char buf[512];
 
-    vga_printk("---- SEGMENTATION FAULT ----\n", 0x0fu);
+    // TODO: change to tty
+    vga_print("---- SEGMENTATION FAULT ----\n", 0x0fu);
 
     snprintf(
         buf, 512,
@@ -108,9 +112,11 @@ void int13_handler(
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
         cs, error_code, eflags);
-    vga_printk(buf, 0x0fu);
+    // TODO: change to tty
+    vga_print(buf, 0x0fu);
 
-    vga_printk("----   HALTING SYSTEM   ----", 0x0fu);
+    // TODO: change to tty
+    vga_print("----   HALTING SYSTEM   ----", 0x0fu);
 
     asm_cli();
     asm_hlt();
@@ -127,7 +133,8 @@ void int14_handler(
 {
     char buf[512];
 
-    vga_printk("---- PAGE FAULT ----\n", 0x0fu);
+    // TODO: change to tty
+    vga_print("---- PAGE FAULT ----\n", 0x0fu);
 
     snprintf(
         buf, 512,
@@ -139,9 +146,11 @@ void int14_handler(
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
         cs, error_code, eflags, addr);
-    vga_printk(buf, 0x0fu);
+    // TODO: change to tty
+    vga_print(buf, 0x0fu);
 
-    vga_printk("----   HALTING SYSTEM   ----", 0x0fu);
+    // TODO: change to tty
+    vga_print("----   HALTING SYSTEM   ----", 0x0fu);
 
     asm_cli();
     asm_hlt();

+ 3 - 5
src/kernel/mem.c

@@ -38,7 +38,7 @@ static void* sbrk(size_t increment)
     }
 }
 
-void init_heap(void)
+int init_heap(void)
 {
     // start of the available address space
     // TODO: adjust heap start address
@@ -46,15 +46,13 @@ void init_heap(void)
     set_heap_start(HEAP_START);
 
     if (brk(HEAP_START) != 0) {
-        vga_printk("Failed to initialize heap, halting...", 0x0fu);
-        MAKE_BREAK_POINT();
-        asm_cli();
-        asm_hlt();
+        return GB_FAILED;
     }
     struct mem_blk* p_blk = sbrk(0);
     p_blk->size = 4;
     p_blk->flags.has_next = 0;
     p_blk->flags.is_free = 1;
+    return GB_OK;
 }
 
 // @param start_pos position where to start finding

+ 21 - 0
src/kernel/stdio.c

@@ -411,3 +411,24 @@ snprintf(
 
     return n_write;
 }
+
+#define BYTES_PER_MAX_COPY_UNIT (sizeof(uint32_t)/sizeof(uint8_t))
+void* memcpy(void* dst, const void* src, size_t n)
+{
+    void* orig_dst = dst;
+    for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
+        *((uint32_t*)dst++) = *((uint32_t*)src++);
+    }
+    for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
+        *((char*)dst++) = *((char*)src++);
+    }
+    return orig_dst;
+}
+
+size_t strlen(const char* str)
+{
+    size_t n = 0;
+    while (*(str++) != '\0')
+        ++n;
+    return n;
+}

+ 49 - 0
src/kernel/tty.c

@@ -0,0 +1,49 @@
+#include <asm/port_io.h>
+#include <kernel/stdio.h>
+#include <kernel/tty.h>
+#include <kernel/mem.h>
+#include <kernel/vga.h>
+#include <kernel/hw/serial.h>
+
+static void serial_tty_put_char(struct tty* p_tty, char c)
+{
+    serial_send_data(*(port_id_t*)&p_tty->data, c);
+}
+
+static void vga_tty_put_char(struct tty* _unused, char c)
+{
+    static struct vga_char vc = { .c = '\0', .color = VGA_CHAR_COLOR_WHITE };
+    vc.c = c;
+    vga_put_char(&vc);
+}
+
+static struct tty_operations serial_tty_ops = {
+    .put_char = serial_tty_put_char,
+};
+
+static struct tty_operations vga_tty_ops = {
+    .put_char = vga_tty_put_char,
+};
+
+void tty_print(struct tty* p_tty, const char* str)
+{
+    while (*str != '\0') {
+        p_tty->ops->put_char(p_tty, *str);
+        ++str;
+    }
+}
+
+int make_serial_tty(struct tty* p_tty, int id)
+{
+    *(port_id_t*)&p_tty->data = id;
+    snprintf(p_tty->name, sizeof(p_tty->name), "ttyS%d", id);
+    p_tty->ops = &serial_tty_ops;
+    return GB_OK;
+}
+
+int make_vga_tty(struct tty* p_tty)
+{
+    snprintf(p_tty->name, sizeof(p_tty->name), "ttyVGA");
+    p_tty->ops = &vga_tty_ops;
+    return GB_OK;
+}

+ 28 - 23
src/kernel/vga.c

@@ -6,22 +6,13 @@
 
 static struct vga_char* p_vga_head = VGA_MEM;
 
-void vga_put_char(struct vga_char* c)
-{
-    *p_vga_head = *c;
-    ++p_vga_head;
-    if ((p_vga_head - VGA_MEM) == 80 * 25) {
-        p_vga_head = VGA_MEM;
-    }
-}
-
-void vga_return()
+static inline void vga_return()
 {
     const int32_t offset = p_vga_head - VGA_MEM;
     p_vga_head -= (offset % VGA_SCREEN_WIDTH_IN_CHARS);
 }
 
-void vga_new_line()
+static inline void vga_new_line()
 {
     int32_t offset = p_vga_head - VGA_MEM;
     offset %= VGA_SCREEN_WIDTH_IN_CHARS;
@@ -31,21 +22,35 @@ void vga_new_line()
     }
 }
 
-void vga_printk(const char* str, uint8_t color)
+static inline void real_vga_put_char(struct vga_char* c)
+{
+    *p_vga_head = *c;
+    ++p_vga_head;
+    if ((p_vga_head - VGA_MEM) == 80 * 25) {
+        p_vga_head = VGA_MEM;
+    }
+}
+
+void vga_put_char(struct vga_char* c)
+{
+    switch (c->c) {
+    case CR:
+        vga_return();
+        break;
+    case LF:
+        vga_new_line();
+        break;
+    default:
+        real_vga_put_char(c);
+        break;
+    }
+}
+
+void vga_print(const char* str, uint8_t color)
 {
     struct vga_char s_c;
     s_c.color = color;
     while ((s_c.c = *(str++)) != 0x00) {
-        switch (s_c.c) {
-        case CR:
-            vga_return();
-            break;
-        case LF:
-            vga_new_line();
-            break;
-        default:
-            vga_put_char(&s_c);
-            break;
-        }
+        vga_put_char(&s_c);
     }
 }

+ 28 - 6
src/kernel_main.c

@@ -7,6 +7,7 @@
 #include <kernel/hw/serial.h>
 #include <kernel/hw/timer.h>
 #include <kernel/interrupt.h>
+#include <kernel/tty.h>
 #include <kernel/mem.h>
 #include <kernel/stdio.h>
 #include <kernel/vga.h>
@@ -23,9 +24,11 @@ void call_constructors_for_cpp(void)
 
 #define KERNEL_MAIN_BUF_SIZE (128)
 
+
+static struct tty* console = NULL;
 #define printkf(x...)                       \
     snprintf(buf, KERNEL_MAIN_BUF_SIZE, x); \
-    vga_printk(buf, 0x0fu);
+    tty_print(console, buf)
 
 static inline void show_mem_info(char* buf)
 {
@@ -73,18 +76,32 @@ static inline void check_a20_status(void)
     result = check_a20_on();
 
     if (result) {
-        vga_printk("A20 is ON\n", 0x0fU);
+        // TODO: change to tty
     } else {
-        vga_printk("A20 is NOT ON\n", 0x0fU);
+        // TODO: change to tty
     }
 }
 
+static inline void halt_on_init_error(void)
+{
+    MAKE_BREAK_POINT();
+    asm_cli();
+    while (1)
+        asm_hlt();
+}
+
 void kernel_main(void)
 {
     MAKE_BREAK_POINT();
 
     char buf[KERNEL_MAIN_BUF_SIZE];
 
+    struct tty early_console;
+    if (make_serial_tty(&early_console, PORT_SERIAL0) != GB_OK) {
+        halt_on_init_error();
+    }
+    console = &early_console;
+
     show_mem_info(buf);
 
     init_paging();
@@ -102,8 +119,12 @@ void kernel_main(void)
     init_pit();
     printkf("IDT initialized\n");
 
-    init_heap();
-    printkf("Heap space initialized\n");
+    printkf("initializing heap space... ");
+    if (init_heap() != GB_OK) {
+        printkf("failed\n");
+        halt_on_init_error();
+    }
+    printkf("ok\n");
 
     call_constructors_for_cpp();
     printkf("C++ global objects constructed\n");
@@ -111,7 +132,8 @@ void kernel_main(void)
     printkf("Testing k_malloc...\n");
     char* k_malloc_buf = (char*)k_malloc(sizeof(char) * 128);
     snprintf(k_malloc_buf, 128, "This text is printed on the heap!\n");
-    vga_printk(k_malloc_buf, 0x0fu);
+    // TODO: change to tty
+    // vga_printk(k_malloc_buf, 0x0fu);
     k_free(k_malloc_buf);
 
     printkf("initializing serial ports... ");