From 7a912d1b668ab86ffe088eca3ac7e6f78a04a0c5 Mon Sep 17 00:00:00 2001 From: Tyler Murphy <=> Date: Mon, 17 Jul 2023 19:34:52 -0400 Subject: refactoring --- kernel/Makefile | 8 +- kernel/arch/i686/linker.ld | 38 ++++ kernel/include/arch/i686/acpi.h | 106 ++++++++++ kernel/include/arch/i686/asm.h | 13 ++ kernel/include/arch/i686/drivers/ps2ctrl.h | 14 ++ kernel/include/arch/i686/drivers/rtc.h | 7 + kernel/include/arch/i686/idt.h | 6 + kernel/include/arch/i686/mboot.h | 34 ++++ kernel/include/arch/i686/memory.h | 22 ++ kernel/include/arch/i686/pic.h | 11 + kernel/include/drivers/ps2kb.h | 15 ++ kernel/include/drivers/ps2mouse.h | 18 ++ kernel/include/drivers/vga.h | 32 +++ kernel/include/memory.h | 6 + kernel/include/print.h | 14 -- kernel/include/sys.h | 10 + kernel/include/term.h | 26 +++ kernel/include/time.h | 23 ++- kernel/linker.ld | 40 ---- kernel/src/acpi/acpi.c | 141 ------------- kernel/src/acpi/acpi.h | 106 ---------- kernel/src/arch/i686/acpi.c | 106 ++++++++++ kernel/src/arch/i686/asm.c | 51 +++++ kernel/src/arch/i686/drivers/ps2ctrl.c | 91 +++++++++ kernel/src/arch/i686/drivers/ps2kb.c | 124 ++++++++++++ kernel/src/arch/i686/drivers/ps2mouse.c | 81 ++++++++ kernel/src/arch/i686/drivers/rtc.c | 152 ++++++++++++++ kernel/src/arch/i686/drivers/vga.c | 50 +++++ kernel/src/arch/i686/gdt.asm | 42 ++++ kernel/src/arch/i686/idt.asm | 99 +++++++++ kernel/src/arch/i686/idt.c | 140 +++++++++++++ kernel/src/arch/i686/mboot.c | 73 +++++++ kernel/src/arch/i686/memory.c | 197 ++++++++++++++++++ kernel/src/arch/i686/paging.asm | 62 ++++++ kernel/src/arch/i686/pic.c | 80 ++++++++ kernel/src/arch/i686/start.asm | 82 ++++++++ kernel/src/arch/i686/sys.c | 51 +++++ kernel/src/arch/i686/time.c | 17 ++ kernel/src/boot/tag.c | 75 ------- kernel/src/boot/tag.h | 35 ---- kernel/src/cpu/cpu.c | 18 -- kernel/src/cpu/cpu.h | 8 - kernel/src/cpu/fpu.asm | 19 -- kernel/src/cpu/sse.asm | 22 -- kernel/src/drivers/cmos.c | 138 ------------- kernel/src/drivers/ps2ctrl.c | 93 --------- kernel/src/drivers/ps2ctrl.h | 14 -- kernel/src/drivers/ps2kb.c | 126 ------------ kernel/src/drivers/ps2kb.h | 15 -- kernel/src/drivers/ps2mouse.c | 85 -------- kernel/src/drivers/ps2mouse.h | 18 -- kernel/src/interrupt/idt.asm | 99 --------- kernel/src/interrupt/idt.c | 118 ----------- kernel/src/interrupt/idt.h | 36 ---- kernel/src/interrupt/pic.c | 85 -------- kernel/src/interrupt/pic.h | 11 - kernel/src/main.c | 46 +---- kernel/src/memory.c | 310 ++++++++++++++++++++++++++++ kernel/src/memory/allocator.c | 314 ----------------------------- kernel/src/memory/memory.c | 202 ------------------- kernel/src/memory/memory.h | 22 -- kernel/src/panic.c | 25 +++ kernel/src/print.c | 83 ++++++++ kernel/src/print/panic.c | 27 --- kernel/src/print/print.c | 128 ------------ kernel/src/print/time.c | 146 -------------- kernel/src/start.asm | 135 ------------- kernel/src/term.c | 135 +++++++++++++ kernel/src/time.c | 144 +++++++++++++ kernel/src/tty/color.c | 67 ------ kernel/src/tty/color.h | 62 ------ kernel/src/tty/cursor.c | 30 --- kernel/src/tty/cursor.h | 9 - kernel/src/tty/term.c | 138 ------------- kernel/src/tty/term.h | 29 --- 75 files changed, 2588 insertions(+), 2667 deletions(-) create mode 100644 kernel/arch/i686/linker.ld create mode 100644 kernel/include/arch/i686/acpi.h create mode 100644 kernel/include/arch/i686/asm.h create mode 100644 kernel/include/arch/i686/drivers/ps2ctrl.h create mode 100644 kernel/include/arch/i686/drivers/rtc.h create mode 100644 kernel/include/arch/i686/idt.h create mode 100644 kernel/include/arch/i686/mboot.h create mode 100644 kernel/include/arch/i686/memory.h create mode 100644 kernel/include/arch/i686/pic.h create mode 100644 kernel/include/drivers/ps2kb.h create mode 100644 kernel/include/drivers/ps2mouse.h create mode 100644 kernel/include/drivers/vga.h create mode 100644 kernel/include/memory.h create mode 100644 kernel/include/sys.h create mode 100644 kernel/include/term.h delete mode 100644 kernel/linker.ld delete mode 100644 kernel/src/acpi/acpi.c delete mode 100644 kernel/src/acpi/acpi.h create mode 100644 kernel/src/arch/i686/acpi.c create mode 100644 kernel/src/arch/i686/asm.c create mode 100644 kernel/src/arch/i686/drivers/ps2ctrl.c create mode 100644 kernel/src/arch/i686/drivers/ps2kb.c create mode 100644 kernel/src/arch/i686/drivers/ps2mouse.c create mode 100644 kernel/src/arch/i686/drivers/rtc.c create mode 100644 kernel/src/arch/i686/drivers/vga.c create mode 100644 kernel/src/arch/i686/gdt.asm create mode 100644 kernel/src/arch/i686/idt.asm create mode 100644 kernel/src/arch/i686/idt.c create mode 100644 kernel/src/arch/i686/mboot.c create mode 100644 kernel/src/arch/i686/memory.c create mode 100644 kernel/src/arch/i686/paging.asm create mode 100644 kernel/src/arch/i686/pic.c create mode 100644 kernel/src/arch/i686/start.asm create mode 100644 kernel/src/arch/i686/sys.c create mode 100644 kernel/src/arch/i686/time.c delete mode 100644 kernel/src/boot/tag.c delete mode 100644 kernel/src/boot/tag.h delete mode 100644 kernel/src/cpu/cpu.c delete mode 100644 kernel/src/cpu/cpu.h delete mode 100644 kernel/src/cpu/fpu.asm delete mode 100644 kernel/src/cpu/sse.asm delete mode 100644 kernel/src/drivers/cmos.c delete mode 100644 kernel/src/drivers/ps2ctrl.c delete mode 100644 kernel/src/drivers/ps2ctrl.h delete mode 100644 kernel/src/drivers/ps2kb.c delete mode 100644 kernel/src/drivers/ps2kb.h delete mode 100644 kernel/src/drivers/ps2mouse.c delete mode 100644 kernel/src/drivers/ps2mouse.h delete mode 100644 kernel/src/interrupt/idt.asm delete mode 100644 kernel/src/interrupt/idt.c delete mode 100644 kernel/src/interrupt/idt.h delete mode 100644 kernel/src/interrupt/pic.c delete mode 100644 kernel/src/interrupt/pic.h create mode 100644 kernel/src/memory.c delete mode 100644 kernel/src/memory/allocator.c delete mode 100644 kernel/src/memory/memory.c delete mode 100644 kernel/src/memory/memory.h create mode 100644 kernel/src/panic.c create mode 100644 kernel/src/print.c delete mode 100644 kernel/src/print/panic.c delete mode 100644 kernel/src/print/print.c delete mode 100644 kernel/src/print/time.c delete mode 100644 kernel/src/start.asm create mode 100644 kernel/src/term.c create mode 100644 kernel/src/time.c delete mode 100644 kernel/src/tty/color.c delete mode 100644 kernel/src/tty/color.h delete mode 100644 kernel/src/tty/cursor.c delete mode 100644 kernel/src/tty/cursor.h delete mode 100644 kernel/src/tty/term.c delete mode 100644 kernel/src/tty/term.h (limited to 'kernel') diff --git a/kernel/Makefile b/kernel/Makefile index d4cbdf4..2e7954e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,9 +1,11 @@ include ../.env -C_SRC = $(shell find src -type f -name "*.c") +C_SRC = $(shell find src -type f -name "*.c" -not -path "src/arch/*") +C_SRC += $(shell find src/arch/$(ARCH) -type f -name "*.c") C_OBJ = $(patsubst %.c,bin/%.o, $(C_SRC)) -ASM_SRC = $(shell find src -type f -name "*.asm") +ASM_SRC = $(shell find src -type f -name "*.asm" -not -path "src/arch/*") +ASM_SRC += $(shell find src/arch/$(ARCH) -type f -name "*.asm") ASM_OBJ = $(patsubst %.asm,bin/%.asm.o, $(ASM_SRC)) CFLAGS += -Iinclude -Isrc -I../libk/include -std=gnu17 @@ -22,7 +24,7 @@ $(ASM_OBJ): bin/%.asm.o : %.asm bin/kernel.bin: $(C_OBJ) $(ASM_OBJ) @mkdir -p $(@D) - $(LD) -o bin/kernel.bin -T linker.ld $(C_OBJ) $(ASM_OBJ) ../libk/bin/libk.a $(LDFLAGS) + $(LD) -o bin/kernel.bin -T arch/$(ARCH)/linker.ld $(C_OBJ) $(ASM_OBJ) ../libk/bin/libk.a $(LDFLAGS) clean: rm -fr bin diff --git a/kernel/arch/i686/linker.ld b/kernel/arch/i686/linker.ld new file mode 100644 index 0000000..ae48afb --- /dev/null +++ b/kernel/arch/i686/linker.ld @@ -0,0 +1,38 @@ +ENTRY(start) + +SECTIONS { + + . = 0x00100000; + + kernel_start = .; + + .bootstrap : { + *(.bootstrap.data) + *(.bootstrap.stack) + *(.bootstrap.text) + } + + . += 0xC0000000; + + .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) + { + *(.text) + } + .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000) + { + *(.rodata) + } + .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000) + { + *(.data) + } + .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000) + { + *(COMMON) + *(.bss) + *(.stack) + } + + kernel_end = .; + +} diff --git a/kernel/include/arch/i686/acpi.h b/kernel/include/arch/i686/acpi.h new file mode 100644 index 0000000..bb35010 --- /dev/null +++ b/kernel/include/arch/i686/acpi.h @@ -0,0 +1,106 @@ +#pragma once + +#include + +struct RootSystemDescriptionPointer { + char signature[8]; + uint8_t checksum; + char oemid[6]; + uint8_t revision; + uint32_t rsdt_address; +}; + +struct SystemDescriptionTableHeader { + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table_id[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +}; + +struct RootSystemDescriptionTable { + struct SystemDescriptionTableHeader header; + uint32_t sdt_table[]; +}; + +struct GenericAddressStructure { + uint8_t address_space; + uint8_t bit_width; + uint8_t bit_offset; + uint8_t access_size; + uint64_t address; +}; + +struct FixedACPIDescriptionTable { + struct SystemDescriptionTableHeader header; + uint32_t firmware_ctrl; + uint32_t dsdt; + + // field used in ACPI 1.0; no longer in use, for compatibility only + uint8_t reserved; + + uint8_t preferred_power_management_profile; + uint16_t sci_interrupt; + uint32_t smi_command_port; + uint8_t acpi_enable; + uint8_t acpi_disable; + uint8_t s4bios_req; + uint8_t pstate_control; + uint32_t pm1_a_event_block; + uint32_t pm1_b_event_block; + uint32_t pm1_a_control_block; + uint32_t pm1_b_control_block; + uint32_t pm2_control_block; + uint32_t pm_timer_block; + uint32_t gpe0_block; + uint32_t gpe1_block; + uint8_t pm1_event_length; + uint8_t pm1_control_length; + uint8_t pm2_control_length; + uint8_t pm_timer_length; + uint8_t gpe0_length; + uint8_t gpe1_length; + uint8_t gpe1_base; + uint8_t cstate_control; + uint16_t worst_c2_latency; + uint16_t worst_c3_latency; + uint16_t flush_size; + uint16_t flush_stride; + uint8_t duty_offset; + uint8_t duty_width; + uint8_t day_alarm; + uint8_t month_alarm; + uint8_t century; + + // reserved in ACPI 1.0; used since ACPI 2.0+ + uint16_t boot_architecture_flags; + + uint8_t reserved_2; + uint32_t flags; + + // 12 byte structure; see below for details + struct GenericAddressStructure reset_reg; + + uint8_t reset_value; + uint8_t reserved_3[3]; + + // 64bit pointers - Available on ACPI 2.0+ + uint64_t x_firmware_control; + uint64_t x_dsdt; + + struct GenericAddressStructure x_pm1_a_event_block; + struct GenericAddressStructure x_pm1_b_event_block; + struct GenericAddressStructure x_pm1_a_control_block; + struct GenericAddressStructure x_pm1_b_control_block; + struct GenericAddressStructure x_pm2_control_block; + struct GenericAddressStructure x_pm_timer_block; + struct GenericAddressStructure x_gpe0_block; + struct GenericAddressStructure x_gpe1_block; +}; + +void acpi_init(void *rsdp); +void acpi_poweroff(void); diff --git a/kernel/include/arch/i686/asm.h b/kernel/include/arch/i686/asm.h new file mode 100644 index 0000000..0e2d9db --- /dev/null +++ b/kernel/include/arch/i686/asm.h @@ -0,0 +1,13 @@ +#include + +extern uint8_t inb(uint16_t port); +extern void outb(uint16_t port, uint8_t val); +extern uint16_t inw(uint16_t port); +extern void outw(uint16_t port, uint16_t val); +extern uint32_t inl(uint16_t port); +extern void outl(uint16_t port, uint32_t val); +extern void io_wait(void); +extern void int_enable(void); +extern void int_disable(void); +extern void int_wait(void); +extern void halt(void); diff --git a/kernel/include/arch/i686/drivers/ps2ctrl.h b/kernel/include/arch/i686/drivers/ps2ctrl.h new file mode 100644 index 0000000..a674c57 --- /dev/null +++ b/kernel/include/arch/i686/drivers/ps2ctrl.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +uint8_t ps2ctrl_in(void); +uint8_t ps2ctrl_in_status(void); +void ps2ctrl_out_cmd(uint8_t cmd); +void ps2ctrl_out_data(uint8_t data); +void ps2ctrl_set_port2(void); + +void ps2ctrl_init(void); + +bool ps2ctrl_is_init(void); diff --git a/kernel/include/arch/i686/drivers/rtc.h b/kernel/include/arch/i686/drivers/rtc.h new file mode 100644 index 0000000..29dbf8f --- /dev/null +++ b/kernel/include/arch/i686/drivers/rtc.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +extern void rtc_update(void); +extern struct Time rtc_utctime(void); +extern struct Time rtc_localtime(enum Timezone tz); diff --git a/kernel/include/arch/i686/idt.h b/kernel/include/arch/i686/idt.h new file mode 100644 index 0000000..8dcee02 --- /dev/null +++ b/kernel/include/arch/i686/idt.h @@ -0,0 +1,6 @@ +#pragma once + +#define IDT_SIZE 256 +#define IDT_INTERRUPTS 256 + +void idt_init(void); diff --git a/kernel/include/arch/i686/mboot.h b/kernel/include/arch/i686/mboot.h new file mode 100644 index 0000000..394071f --- /dev/null +++ b/kernel/include/arch/i686/mboot.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include + +#define CMDLINE_MAX 32 + +struct BootTag { + uint8_t valid; + uint32_t type; + uint32_t size; + union { + char cmdline[CMDLINE_MAX]; + struct MemoryMap *memory_map; + struct RootSystemDescriptionPointer *rsdp; + } data; +}; + +struct BootInfo { + uint32_t total_size; + uint32_t reserved; + struct BootTag tags[21]; +}; + +enum BootTagID { + ID_CMDLINE = 0, + iD_MEMORYMAP = 6, + ID_RSDP = 14 +}; + +void load_boot_info(void* boot_info); +bool get_boot_tag(enum BootTagID id, struct BootTag **tag); diff --git a/kernel/include/arch/i686/memory.h b/kernel/include/arch/i686/memory.h new file mode 100644 index 0000000..5d99025 --- /dev/null +++ b/kernel/include/arch/i686/memory.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +struct MemorySegment { + uint64_t addr; + uint64_t len; + uint32_t type; + uint32_t reserved; +} __attribute__((packed)); + +struct MemoryMap { + uint32_t entry_size; + uint32_t entry_version; + struct MemorySegment entries[]; +} __attribute__((packed)); + +uint32_t memory_total(void); +uint32_t memory_free(void); +uint32_t memory_used(void); + +void memory_init(void); diff --git a/kernel/include/arch/i686/pic.h b/kernel/include/arch/i686/pic.h new file mode 100644 index 0000000..593a33a --- /dev/null +++ b/kernel/include/arch/i686/pic.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#define PIC_REMAP_OFFSET 0x20 + +void pic_remap(void); +void pic_mask(int irq); +void pic_unmask(int irq); +void pic_disable(void); +void pic_eoi(int irq); diff --git a/kernel/include/drivers/ps2kb.h b/kernel/include/drivers/ps2kb.h new file mode 100644 index 0000000..1aaefb2 --- /dev/null +++ b/kernel/include/drivers/ps2kb.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +struct Keycode { + uint8_t key; + uint8_t flags; +}; + +void ps2kb_init(void); + +void ps2kb_recv(void); +struct Keycode ps2kb_get(void); diff --git a/kernel/include/drivers/ps2mouse.h b/kernel/include/drivers/ps2mouse.h new file mode 100644 index 0000000..9cd4818 --- /dev/null +++ b/kernel/include/drivers/ps2mouse.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +struct MouseEvent { + bool updated; + bool lmb; + bool rmb; + bool mmb; + int relx; + int rely; +}; + +void ps2mouse_init(void); + +void ps2mouse_recv(void); +struct MouseEvent ps2mouse_get(void); diff --git a/kernel/include/drivers/vga.h b/kernel/include/drivers/vga.h new file mode 100644 index 0000000..68e8690 --- /dev/null +++ b/kernel/include/drivers/vga.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +enum vga_color { + VGA_BLACK = 0, + VGA_BLUE = 1, + VGA_GREEN = 2, + VGA_CYAN = 3, + VGA_RED = 4, + VGA_MAGENTA = 5, + VGA_BROWN = 6, + VGA_LIGHT_GREY = 7, + VGA_DARK_GREY = 8, + VGA_LIGHT_BLUE = 9, + VGA_LIGHT_GREEN = 10, + VGA_LIGHT_CYAN = 11, + VGA_LIGHT_RED = 12, + VGA_LIGHT_MAGENTA = 13, + VGA_LIGHT_BROWN = 14, + VGA_WHITE = 15, +}; + +#define VGA_TEXT_W 80 +#define VGA_TEXT_H 25 + +void vgatext_write_char(char c, enum vga_color color, uint8_t x, uint8_t y); +void vgatext_write_data(uint16_t data, uint16_t index); +void vgatext_write_buf(const uint16_t *buffer); +void vgatext_cur_mov(uint8_t x, uint8_t y); +void vgatext_cur_resize(uint8_t start, uint8_t end); +void vgatext_cur_visible(bool visible); diff --git a/kernel/include/memory.h b/kernel/include/memory.h new file mode 100644 index 0000000..07a55c0 --- /dev/null +++ b/kernel/include/memory.h @@ -0,0 +1,6 @@ +#pragma once + +extern int memory_lock(void); +extern int memory_unlock(void); +extern void *memory_alloc_page(int); +extern int memory_free_page(void* ,int); diff --git a/kernel/include/print.h b/kernel/include/print.h index dc7f862..7dbd298 100644 --- a/kernel/include/print.h +++ b/kernel/include/print.h @@ -7,17 +7,3 @@ extern void putchar(int c); extern void puts(const char* s); extern void printk(const char *restrict format, ...); extern void vprintk(const char *restrict format, va_list ap); - -#ifdef KERNEL_LOG -#define debugk(msg, ...) _debugk_impl(msg, ## __VA_ARGS__) -#define succek(msg, ...) _succek_impl(msg, ## __VA_ARGS__) -#define errork(msg, ...) _errork_impl(msg, ## __VA_ARGS__) -#else -#define debugk(msg, ...) -#define succek(msg, ...) -#define errork(msg, ...) -#endif - -extern void _debugk_impl(char* msg, ...); -extern void _succek_impl(char* msg, ...); -extern void _errork_impl(char* msg, ...); diff --git a/kernel/include/sys.h b/kernel/include/sys.h new file mode 100644 index 0000000..003f85c --- /dev/null +++ b/kernel/include/sys.h @@ -0,0 +1,10 @@ +#pragma once + +extern void arch_init(void *boot_info); +extern void arch_update(void); +extern void arch_halt(void); +extern void arch_wait_io(void); +extern void arch_wait_int(void); +extern void arch_disable_int(void); +extern void arch_enable_int(void); +extern void arch_poweroff(void); diff --git a/kernel/include/term.h b/kernel/include/term.h new file mode 100644 index 0000000..8a8f1ef --- /dev/null +++ b/kernel/include/term.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +#define TERM_W VGA_TEXT_W +#define TERM_H VGA_TEXT_H + +void term_init(void); +void term_reset(void); +void term_setfg(enum vga_color color); +void term_setbg(enum vga_color color); +void term_clear(void); +void term_scroll(int lines); +void term_setpos(uint8_t x, uint8_t y); + +uint32_t term_save(void); +void term_load(uint32_t state); + +uint16_t term_save_col(void); +void term_load_col(uint16_t color); + +bool term_newline(void); + +void term_flush(void); diff --git a/kernel/include/time.h b/kernel/include/time.h index 783d96f..2e86a69 100644 --- a/kernel/include/time.h +++ b/kernel/include/time.h @@ -16,10 +16,25 @@ struct Time { int leap; /// If year is a leap year (True == 1) }; -extern void rtc_update(void); -extern void rtc_set_timezone(int offset); -extern struct Time *rtc_utctime(void); -extern struct Time *rtc_localtime(void); +enum Timezone { + UTC = 0, + EST = -4 +}; + +/** + * Sets the current timezone + */ +extern void set_timezone(enum Timezone tz); + +/** + * Returns current time in UTC + */ +extern struct Time get_utctime(void); + +/** + * Returns current time from current Timezone + */ +extern struct Time get_localtime(void); /** * Converts the time into a string format diff --git a/kernel/linker.ld b/kernel/linker.ld deleted file mode 100644 index 541975e..0000000 --- a/kernel/linker.ld +++ /dev/null @@ -1,40 +0,0 @@ -ENTRY(start) - -SECTIONS { - - . = 0x00100000; - - kernel_start = .; - - .multiboot.data : { - *(.multiboot.data) - } - - .multiboot.text : { - *(.multiboot.text) - } - - . += 0xC0000000; - - .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) - { - *(.text) - } - .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000) - { - *(.rodata) - } - .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000) - { - *(.data) - } - .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000) - { - *(COMMON) - *(.bss) - *(.bootstrap_stack) - } - - kernel_end = .; - -} diff --git a/kernel/src/acpi/acpi.c b/kernel/src/acpi/acpi.c deleted file mode 100644 index ef1fb76..0000000 --- a/kernel/src/acpi/acpi.c +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "acpi.h" -#include "boot/tag.h" -#include "print.h" - -static struct RootSystemDescriptionTable *rsdt; -static struct FixedACPIDescriptionTable *fadt; - -static uint16_t SLP_TYPa; -static uint16_t SLP_TYPb; -static uint16_t SLP_EN; -static uint16_t SCI_EN; - -static bool is_init = false; - -bool checksum(uint8_t *data, size_t len) { - unsigned char sum = 0; - for (size_t i = 0; i < len; i++) - sum += data[i]; - return sum == 0; -} - -static void *find_fadt(void) { - int entries = (rsdt->header.length - sizeof(rsdt->header)) / 4; - - for (int i = 0; i < entries; i++) { - uintptr_t sdt_ptr = rsdt->sdt_table[i]; - struct SystemDescriptionTableHeader *h = (void*) sdt_ptr; - if (!strncmp(h->signature, "FACP", 4)) - return (void *) h; - } - - return NULL; -} - -static int read_s5_addr(void) { - uintptr_t ptr = fadt->dsdt; - char *s5_addr = (void*) (ptr + 36); - - int dsdt_len = *((int*) (ptr+1)) - 36; - while (0 < dsdt_len--) { - if ( memcmp(s5_addr, "_S5_", 4) == 0) - break; - s5_addr++; - } - - if (dsdt_len > 0) { - // check for valid AML structure - if ( ( *(s5_addr-1) == 0x08 || ( *(s5_addr-2) == 0x08 && *(s5_addr-1) == '\\') ) && *(s5_addr+4) == 0x12 ) { - s5_addr += 5; - s5_addr += ((*s5_addr &0xC0)>>6) +2; // calculate PkgLength size - - if (*s5_addr == 0x0A) - s5_addr++; // skip byteprefix - SLP_TYPa = *(s5_addr)<<10; - s5_addr++; - - if (*s5_addr == 0x0A) - s5_addr++; // skip byteprefix - SLP_TYPb = *(s5_addr)<<10; - - SLP_EN = 1<<13; - SCI_EN = 1; - - } else { - errork("\\_S5 parse error."); - return 1; - } - } else { - errork("\\_S5 not present."); - return 1; - } - return 0; -} - -void acpi_init(void) { - - is_init = false; - - debugk("Loading ACPI"); - - struct BootTag *tag; - if(!get_boot_tag(ID_RSDP, &tag)) { - errork("Could not find RSDP"); - return; - } - - debugk("Loading RSDT"); - - struct RootSystemDescriptionPointer *rsdp = tag->data.rsdp; - if (!checksum((uint8_t*) rsdp, sizeof(struct RootSystemDescriptionPointer))) { - errork("RSDP checksum failed to validate"); - return; - } - - uintptr_t rsdt_ptr = rsdp->rsdt_address; - rsdt = (void *) rsdt_ptr; - if (!checksum((uint8_t*) &rsdt->header, rsdt->header.length)) { - errork("RSDT checksum failed to validate"); - return; - } - - debugk("Loading FADT"); - - fadt = find_fadt(); - if (fadt == NULL) { - errork("Could not find FADT"); - return; - } - - if (!checksum((uint8_t*) &fadt->header, fadt->header.length)) { - errork("FADT checksum failed to validate"); - return; - } - - debugk("Reading \\_S5 Addr"); - - if (read_s5_addr()) { - return; - } - - outb(fadt->smi_command_port,fadt->acpi_enable); - - succek("ACPI has been loaded"); - is_init = true; -} - -void acpi_poweroff(void) { - if (is_init) { - outw((unsigned int) fadt->pm1_a_control_block, SLP_TYPb | SLP_EN); - panic("failed to shutdown"); - } else { - errork("Cannot shutdown, ACPI not loaded"); - } -} diff --git a/kernel/src/acpi/acpi.h b/kernel/src/acpi/acpi.h deleted file mode 100644 index 889497e..0000000 --- a/kernel/src/acpi/acpi.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include - -struct RootSystemDescriptionPointer { - char signature[8]; - uint8_t checksum; - char oemid[6]; - uint8_t revision; - uint32_t rsdt_address; -}; - -struct SystemDescriptionTableHeader { - char signature[4]; - uint32_t length; - uint8_t revision; - uint8_t checksum; - char oem_id[6]; - char oem_table_id[8]; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; -}; - -struct RootSystemDescriptionTable { - struct SystemDescriptionTableHeader header; - uint32_t sdt_table[]; -}; - -struct GenericAddressStructure { - uint8_t address_space; - uint8_t bit_width; - uint8_t bit_offset; - uint8_t access_size; - uint64_t address; -}; - -struct FixedACPIDescriptionTable { - struct SystemDescriptionTableHeader header; - uint32_t firmware_ctrl; - uint32_t dsdt; - - // field used in ACPI 1.0; no longer in use, for compatibility only - uint8_t reserved; - - uint8_t preferred_power_management_profile; - uint16_t sci_interrupt; - uint32_t smi_command_port; - uint8_t acpi_enable; - uint8_t acpi_disable; - uint8_t s4bios_req; - uint8_t pstate_control; - uint32_t pm1_a_event_block; - uint32_t pm1_b_event_block; - uint32_t pm1_a_control_block; - uint32_t pm1_b_control_block; - uint32_t pm2_control_block; - uint32_t pm_timer_block; - uint32_t gpe0_block; - uint32_t gpe1_block; - uint8_t pm1_event_length; - uint8_t pm1_control_length; - uint8_t pm2_control_length; - uint8_t pm_timer_length; - uint8_t gpe0_length; - uint8_t gpe1_length; - uint8_t gpe1_base; - uint8_t cstate_control; - uint16_t worst_c2_latency; - uint16_t worst_c3_latency; - uint16_t flush_size; - uint16_t flush_stride; - uint8_t duty_offset; - uint8_t duty_width; - uint8_t day_alarm; - uint8_t month_alarm; - uint8_t century; - - // reserved in ACPI 1.0; used since ACPI 2.0+ - uint16_t boot_architecture_flags; - - uint8_t reserved_2; - uint32_t flags; - - // 12 byte structure; see below for details - struct GenericAddressStructure reset_reg; - - uint8_t reset_value; - uint8_t reserved_3[3]; - - // 64bit pointers - Available on ACPI 2.0+ - uint64_t x_firmware_control; - uint64_t x_dsdt; - - struct GenericAddressStructure x_pm1_a_event_block; - struct GenericAddressStructure x_pm1_b_event_block; - struct GenericAddressStructure x_pm1_a_control_block; - struct GenericAddressStructure x_pm1_b_control_block; - struct GenericAddressStructure x_pm2_control_block; - struct GenericAddressStructure x_pm_timer_block; - struct GenericAddressStructure x_gpe0_block; - struct GenericAddressStructure x_gpe1_block; -}; - -void acpi_init(void); -void acpi_poweroff(void); diff --git a/kernel/src/arch/i686/acpi.c b/kernel/src/arch/i686/acpi.c new file mode 100644 index 0000000..7807558 --- /dev/null +++ b/kernel/src/arch/i686/acpi.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include +#include + +extern uintptr_t KERNEL_MAPPING; + +static struct RootSystemDescriptionTable *rsdt; +static struct FixedACPIDescriptionTable *fadt; + +static uint16_t SLP_TYPa; +static uint16_t SLP_TYPb; +static uint16_t SLP_EN; +static uint16_t SCI_EN; + +static bool checksum(uint8_t *data, size_t len) { + unsigned char sum = 0; + for (size_t i = 0; i < len; i++) + sum += data[i]; + return sum == 0; +} + +static void *find_fadt(void) { + int entries = (rsdt->header.length - sizeof(rsdt->header)) / 4; + + for (int i = 0; i < entries; i++) { + uintptr_t sdt_ptr = rsdt->sdt_table[i]; + struct SystemDescriptionTableHeader *h = (void*) sdt_ptr; + if (!strncmp(h->signature, "FACP", 4)) + return (void *) h; + } + + return NULL; +} + +static void read_s5_addr(void) { + uintptr_t ptr = fadt->dsdt; + char *s5_addr = (void*) (ptr + 36); + + int dsdt_len = *((int*) (ptr+1)) - 36; + while (0 < dsdt_len--) { + if ( memcmp(s5_addr, "_S5_", 4) == 0) + break; + s5_addr++; + } + + if (dsdt_len > 0) { + // check for valid AML structure + if ( ( *(s5_addr-1) == 0x08 || ( *(s5_addr-2) == 0x08 && *(s5_addr-1) == '\\') ) && *(s5_addr+4) == 0x12 ) { + s5_addr += 5; + s5_addr += ((*s5_addr &0xC0)>>6) +2; // calculate PkgLength size + + if (*s5_addr == 0x0A) + s5_addr++; // skip byteprefix + SLP_TYPa = *(s5_addr)<<10; + s5_addr++; + + if (*s5_addr == 0x0A) + s5_addr++; // skip byteprefix + SLP_TYPb = *(s5_addr)<<10; + + SLP_EN = 1<<13; + SCI_EN = 1; + + } else { + panic("\\_S5 parse error."); + } + } else { + panic("\\_S5 not present."); + } +} + +void acpi_init(void *ptr) { + + struct RootSystemDescriptionPointer *rsdp = ptr; + if (!checksum((uint8_t*) rsdp, sizeof(struct RootSystemDescriptionPointer))) { + panic("RSDP checksum failed to validate"); + } + + uintptr_t rsdt_ptr = rsdp->rsdt_address; + rsdt = (void *) rsdt_ptr; + if (!checksum((uint8_t*) &rsdt->header, rsdt->header.length)) { + panic("RSDT checksum failed to validate"); + } + + fadt = find_fadt(); + if (fadt == NULL) { + panic("Could not find FADT"); + } + + if (!checksum((uint8_t*) &fadt->header, fadt->header.length)) { + panic("FADT checksum failed to validate"); + } + + read_s5_addr(); + + outb(fadt->smi_command_port,fadt->acpi_enable); +} + +void acpi_poweroff(void) { + outw((unsigned int) fadt->pm1_a_control_block, SLP_TYPb | SLP_EN); + panic("failed to shutdown"); +} diff --git a/kernel/src/arch/i686/asm.c b/kernel/src/arch/i686/asm.c new file mode 100644 index 0000000..8ed00d0 --- /dev/null +++ b/kernel/src/arch/i686/asm.c @@ -0,0 +1,51 @@ +#include + +uint8_t inb(uint16_t port) { + uint8_t ret; + __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +void outb(uint16_t port, uint8_t val) { + __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +uint16_t inw(uint16_t port) { + uint16_t ret; + __asm__ volatile ("inw %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +void outw(uint16_t port, uint16_t val) { + __asm__ volatile ("outw %0, %1" : : "a"(val), "Nd"(port)); +} + +uint32_t inl(uint16_t port) { + uint32_t ret; + __asm__ volatile ("inl %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +void outl(uint16_t port, uint32_t val) { + __asm__ volatile ("outl %0, %1" : : "a"(val), "Nd"(port)); +} + +void io_wait(void) { + outb(0x80, 0); +} + +void int_enable(void) { + __asm__ volatile ("sti"); +} + +void int_disable(void) { + __asm__ volatile ("cli"); +} + +void int_wait(void) { + __asm__ volatile ("sti; hlt"); +} + +void halt(void) { + __asm__ volatile ("cli; hlt"); +} diff --git a/kernel/src/arch/i686/drivers/ps2ctrl.c b/kernel/src/arch/i686/drivers/ps2ctrl.c new file mode 100644 index 0000000..794aabd --- /dev/null +++ b/kernel/src/arch/i686/drivers/ps2ctrl.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include + +#define STATUS_OUT_BUF ((uint8_t)0x01) +#define STATUS_IN_BUF ((uint8_t)0x02) + +#define CONFIG_INT_0 ((uint8_t)0x01) +#define CONFIG_INT_1 ((uint8_t)0x02) +#define CONFIG_SYS ((uint8_t)0x04) +#define CONFIG_CLOCK_0 ((uint8_t)0x10) +#define CONFIG_CLOCK_1 ((uint8_t)0x20) +#define CONFIG_TRANS ((uint8_t)0x40) + +static bool is_init = false; + +uint8_t ps2ctrl_in(void) { + while((ps2ctrl_in_status() & STATUS_OUT_BUF) == 0) { + io_wait(); + } + return inb(0x60); +} + +uint8_t ps2ctrl_in_status(void) { + return inb(0x64); +} + +void ps2ctrl_out_cmd(uint8_t cmd) { + while((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) { + io_wait(); + } + outb(0x64, cmd); +} + +void ps2ctrl_out_data(uint8_t data) { + while((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) { + io_wait(); + } + outb(0x60, data); +} + +void ps2ctrl_set_port2(void) { + outb(0x64, 0xD4); +} + +void ps2ctrl_init(void) { + + is_init = false; + + pic_mask(1); // keyboard + pic_mask(12); // mouse + + inb(0x60); + + // self-test + ps2ctrl_out_cmd(0xAA); + uint8_t response = ps2ctrl_in(); + if(response != 0x55) { + panic("PS/2 controller failed to initialize"); + } + + // set config + ps2ctrl_out_cmd(0x20); + uint8_t config = ps2ctrl_in(); + config = (config | CONFIG_INT_0 | CONFIG_INT_1) & ~CONFIG_TRANS; + // config = 0xFF; + ps2ctrl_out_cmd(0x60); + ps2ctrl_out_data(config); + + // enable port 0 + ps2ctrl_out_cmd(0xAE); + + // enable port 2 + ps2ctrl_out_cmd(0xA9); + response = ps2ctrl_in(); + if (response == 0x01) { + panic("PS/2 port 2 not supported"); + } + + ps2ctrl_out_cmd(0xA8); + + is_init = true; + + pic_unmask(1); + pic_unmask(12); +} + +bool ps2ctrl_is_init(void) { + return is_init; +} diff --git a/kernel/src/arch/i686/drivers/ps2kb.c b/kernel/src/arch/i686/drivers/ps2kb.c new file mode 100644 index 0000000..50bdfb6 --- /dev/null +++ b/kernel/src/arch/i686/drivers/ps2kb.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include + +#define BUFFER_LEN 16 + +#define KEYCODE_ARRAY_LEN 0x84 + +static uint8_t scancodes[] = { +// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F +/*00*/ KEY_NONE, KEY_F9, KEY_NONE, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, +/*08*/ KEY_NONE, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK, KEY_NONE, +/*10*/ KEY_NONE, KEY_L_ALT, KEY_L_SHIFT, KEY_NONE, KEY_L_CTRL, KEY_Q, KEY_1, KEY_NONE, +/*18*/ KEY_NONE, KEY_NONE, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_NONE, +/*20*/ KEY_NONE, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_NONE, +/*28*/ KEY_NONE, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_NONE, +/*30*/ KEY_NONE, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_NONE, +/*38*/ KEY_NONE, KEY_NONE, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_NONE, +/*40*/ KEY_NONE, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_NONE, +/*48*/ KEY_NONE, KEY_PERIOD, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_NONE, +/*50*/ KEY_NONE, KEY_NONE, KEY_QUOTE, KEY_NONE, KEY_L_BRACE, KEY_EQUAL, KEY_NONE, KEY_NONE, +/*58*/ KEY_CAPS_LOCK, KEY_R_SHIFT, KEY_ENTER, KEY_R_BRACE, KEY_NONE, KEY_BACKSLASH, KEY_NONE, KEY_NONE, +/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_BACKSPACE, KEY_NONE, +/*68*/ KEY_NONE, KEY_NP_1, KEY_NONE, KEY_NP_4, KEY_NP_7, KEY_NONE, KEY_NONE, KEY_NONE, +/*70*/ KEY_NP_0, KEY_NP_PERIOD, KEY_NP_2, KEY_NP_5, KEY_NP_6, KEY_NP_8, KEY_ESCAPE, KEY_NUM_LOCK, +/*78*/ KEY_F11, KEY_NP_PLUS, KEY_NP_3, KEY_NP_MINUS, KEY_NP_ASTERISK, KEY_NP_9, KEY_SCROLL_LOCK, KEY_NONE, +/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_F7, +}; +static uint8_t scancodes_ext[] = { +// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F +/*00*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*08*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*10*/ KEY_UNKNOWN, KEY_R_ALT, KEY_PRINT_SCREEN, KEY_NONE, KEY_R_CTRL, KEY_UNKNOWN, KEY_NONE, KEY_NONE, +/*18*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_L_META, +/*20*/ KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_R_META, +/*28*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_MENU, +/*30*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, +/*38*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, +/*40*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*48*/ KEY_UNKNOWN, KEY_NONE, KEY_NP_SLASH, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, +/*50*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*58*/ KEY_NONE, KEY_NONE, KEY_NP_ENTER, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, +/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +/*68*/ KEY_NONE, KEY_END, KEY_NONE, KEY_LEFT, KEY_HOME, KEY_NONE, KEY_NONE, KEY_NONE, +/*70*/ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_NONE, KEY_RIGHT, KEY_UP, KEY_NONE, KEY_NONE, +/*78*/ KEY_NONE, KEY_NONE, KEY_PAGE_DOWN, KEY_NONE, KEY_NONE, KEY_PAGE_UP, KEY_NONE, KEY_NONE, +/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, +}; + +static struct Keycode last_keycode; + +static bool is_init = false; +static bool state_keyup = false; +static bool state_ext = false; + +void ps2kb_init(void) { + + is_init = false; + pic_mask(1); + + uint8_t result; + + ps2ctrl_out_data(0xFF); + result = ps2ctrl_in(); + if(result != 0xFA) { + panic("Failed to reset PS/2 keyboard: expected 0xFA, got 0x%X\n", result); + return; + } + result = ps2ctrl_in(); + if(result != 0xAA) { + panic("Failed to reset PS/2 keyboard: expected 0xAA, got 0x%X\n", result); + return; + } + + ps2ctrl_out_data(0xF4); + result = ps2ctrl_in(); + if(result != 0xFA) { + panic("Failed to enable PS/2 keyboard: expected 0xFA, got 0x%X\n", result); + return; + } + + pic_unmask(1); + is_init = true; +} + +void ps2kb_recv(void) { + if(!ps2ctrl_is_init() || !is_init) { + inb(0x60); + return; + } + uint8_t code = ps2ctrl_in(); + if (code == 0x00 || code == 0x0F) { + last_keycode.key = KEY_NONE; + last_keycode.flags = KC_FLAG_ERROR; + } else if(code == 0xF0) { + state_keyup = true; + } else if(code == 0xE0) { + state_ext = true; + } else if(code <= KEYCODE_ARRAY_LEN) { + uint8_t *scancode_table = state_ext ? scancodes_ext : scancodes; + uint8_t keycode = scancode_table[code]; + if(keycode != KEY_NONE) { + last_keycode.key = keycode; + last_keycode.flags = state_keyup ? KC_FLAG_KEY_UP : KC_FLAG_KEY_DOWN; + } + state_keyup = false; + state_ext = false; + } +} + +struct Keycode ps2kb_get(void) { + struct Keycode code; + if(is_init) { + code = last_keycode; + } else { + code.key = KEY_NONE; + code.flags = KC_FLAG_ERROR; + } + last_keycode.key = KEY_NONE; + last_keycode.flags = 0; + return code; +} diff --git a/kernel/src/arch/i686/drivers/ps2mouse.c b/kernel/src/arch/i686/drivers/ps2mouse.c new file mode 100644 index 0000000..d1082a1 --- /dev/null +++ b/kernel/src/arch/i686/drivers/ps2mouse.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +static bool is_init = false; + +static struct MouseEvent last_event; +static uint8_t first_b, second_b, third_b; + +void ps2mouse_init(void) { + + is_init = false; + pic_mask(12); + + uint8_t result; + + ps2ctrl_set_port2(); + ps2ctrl_out_data(0xFF); + result = ps2ctrl_in(); + if (result != 0xFA) { + panic("Failed to reset PS/2 mouse: expected 0xFA, got 0x%X", result); + return; + } + result = ps2ctrl_in(); + if (result != 0xAA) { + panic("Failed to reset PS/2 mouse: expected 0xAA, got 0x%X", result); + return; + } + + ps2ctrl_set_port2(); + ps2ctrl_out_data(0xF4); + + pic_unmask(12); + is_init = true; +} + +static uint8_t packet_num = 0; +void ps2mouse_recv(void) { + if (!ps2ctrl_is_init() || !is_init) { + inb(0x60); + return; + } + + uint8_t packet = ps2ctrl_in(); + switch (packet_num) { + case 0: + first_b = packet; + break; + case 1: + second_b = packet; + break; + case 2: { + third_b = packet; + + int state, d; + state = first_b; + d = second_b; + last_event.relx = d - ((state << 4) & 0x100); + d = third_b; + last_event.rely = d - ((state << 3) & 0x100); + + last_event.lmb = first_b & 0x01; + last_event.rmb = first_b & 0x02; + last_event.mmb = first_b & 0x04; + last_event.updated = true; + break; + } + } + + packet_num += 1; + packet_num %= 3; + +} + +struct MouseEvent ps2mouse_get(void) { + struct MouseEvent event = last_event; + last_event.updated = false; + return event; +} diff --git a/kernel/src/arch/i686/drivers/rtc.c b/kernel/src/arch/i686/drivers/rtc.c new file mode 100644 index 0000000..ba69d15 --- /dev/null +++ b/kernel/src/arch/i686/drivers/rtc.c @@ -0,0 +1,152 @@ +#include "time.h" +#include +#include +#include +#include + +#define CMOS_WRITE_PORT 0x70 +#define CMOS_READ_PORT 0x71 + +#define CMOS_REG_SEC 0x00 +#define CMOS_REG_MIN 0x02 +#define CMOS_REG_HOUR 0x04 +#define CMOS_REG_WDAY 0x06 +#define CMOS_REG_MDAY 0x07 +#define CMOS_REG_MON 0x08 +#define CMOS_REG_YEAR 0x09 +#define CMOS_REG_CEN 0x32 + +// Live buffers to work on data +static struct Time time; +static struct Time localtime; + +// Front buffers so interupts dont request data that is half done +static struct Time cur_time; +static struct Time cur_localtime; + +// Current set Time Zone +static enum Timezone last_timezone = UTC; + +static uint8_t cmos_read(uint8_t reg) { + uint8_t hex, ret; + + outb(CMOS_WRITE_PORT, reg); + hex = inb(CMOS_READ_PORT); + + ret = hex & 0x0F; + ret += (hex & 0xF0) / 16 * 10; + + return ret; +} + +static int mday_offset[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +static int month_days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +static void update_localtime(void) { + + int change, max; + + // set localtime + localtime = time; + + // if tz is UTC, we dont need to do anythin + if (last_timezone == UTC) { + cur_localtime = localtime; + return; + } + + // check if day rolled over + change = localtime.hour < 0 ? -1 : localtime.hour >= 24 ? 1 : 0; + if (!change) return; + + // roll over day + localtime.hour = (localtime.hour + 24) % 24; + localtime.wday = (localtime.wday + change + 7) % 7; + localtime.mday += change; + localtime.yday += change; + + // check if month rolled over + max = month_days[localtime.mon]; + if (localtime.leap && localtime.mon == 1) max++; + change = localtime.mday < 0 ? -1 : localtime.mday >= max ? 1 : 0; + if (!change) return; + + // roll over month + localtime.mon = (localtime.mon + change + 12) % 12; + + // check if year rolled over + max = localtime.leap ? 366 : 365; + change = localtime.yday < 0 ? -1 : localtime.yday >= max ? 1 : 0; + if (!change) return; + + // roll over year + localtime.yn += change; + + // check if cen rolled over + change = localtime.yn < 0 ? -1 : localtime.yn >= 100 ? 1 : 0; + if (!change) goto year; + + // roll over cen + localtime.cen += change; + + +year: + + localtime.year = localtime.yn + localtime.cen * 100; + localtime.leap = localtime.year % 4 == 0 && localtime.year % 100 != 0; + + if (localtime.leap && localtime.yday == -1) + localtime.yday = 365; + else if (localtime.yday == -1) + localtime.yday = 364; + else + localtime.yday = 0; + + localtime.year -= 1900; + + cur_localtime = localtime; + +} + +void rtc_update(void) { + time.sec = cmos_read(CMOS_REG_SEC); + time.min = cmos_read(CMOS_REG_MIN); + time.hour = cmos_read(CMOS_REG_HOUR); + time.wday = cmos_read(CMOS_REG_WDAY) - 1; + time.mday = cmos_read(CMOS_REG_MDAY); + time.mon = cmos_read(CMOS_REG_MON) - 1; + time.yn = cmos_read(CMOS_REG_YEAR); + time.cen = 20; + + time.year = time.yn + time.cen * 100; + + time.leap = time.year % 4 == 0 && time.year % 100 != 0; + + time.yday = mday_offset[time.mon] + time.mday; + + if (time.leap && time.mon > 2) + time.yday++; + + time.year -= 1900; + + update_localtime(); + + cur_time = time; +} + +struct Time rtc_utctime(void) { + return cur_time; +} + +struct Time rtc_localtime(enum Timezone tz) { + if (tz != last_timezone) { + last_timezone = tz; + update_localtime(); + } + return cur_localtime; +} diff --git a/kernel/src/arch/i686/drivers/vga.c b/kernel/src/arch/i686/drivers/vga.c new file mode 100644 index 0000000..a41ce54 --- /dev/null +++ b/kernel/src/arch/i686/drivers/vga.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +static uint16_t *buffer = (uint16_t*) 0xC03FF000; +static uint8_t start, end; + +void vgatext_write(char c, enum vga_color color, uint8_t x, uint8_t y) { + const size_t index = y * VGA_TEXT_W + x; + buffer[index] = c | (uint16_t) color << 8; +} + +void vgatext_write_data(uint16_t data, uint16_t index) { + buffer[index] = data; +} + +void vgatext_write_buf(const uint16_t *src) { + memcpy(buffer, src, VGA_TEXT_W * VGA_TEXT_H * sizeof(uint16_t)); +} + +void vgatext_cur_mov(uint8_t x, uint8_t y) { +; const uint16_t pos = y * VGA_TEXT_W + x; + + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); +} + +void vgatext_cur_resize(uint8_t s, uint8_t e) { + start = s; + end = e; + + outb(0x3D4, 0x0A); + outb(0x3D5, (inb(0x3D5) & 0xC0) | start); + + outb(0x3D4, 0x0B); + outb(0x3D5, (inb(0x3D5) & 0xE0) | end); +} + +void vgatext_cur_visible(bool visible) { + if (visible) { + vgatext_cur_resize(start, end); + } else { + outb(0x3D4, 0x0A); + outb(0x3D5, 0x20); + } +} diff --git a/kernel/src/arch/i686/gdt.asm b/kernel/src/arch/i686/gdt.asm new file mode 100644 index 0000000..ea8a86b --- /dev/null +++ b/kernel/src/arch/i686/gdt.asm @@ -0,0 +1,42 @@ +global load_gdt + +%macro gdt_entry 4 + db %2 & 0xff + db (%2 >> 8) & 0xff + db %1 & 0xff + db (%1 >> 8) & 0xff + db (%1 >> 16) & 0xff + db %3 + db ((%2 >> 16) & 0x0f) | (%4 << 4) + db (%1 >> 24) & 0xff +%endmacro + +section .rodata +align 16 +gdt_start: +gdt_entry 0, 0, 0, 0 +gdt_entry 0, 0xFFFFF, 0x9A, 0xC +gdt_entry 0, 0xFFFFF, 0x92, 0xC +gdt_end: +gdt_descriptor: + dw gdt_end - gdt_start - 1 + dd gdt_start + + +section .text +align 8 +load_gdt: + cli + lgdt [gdt_descriptor] + mov eax, cr0 + or al, 1 + mov cr0, eax + mov ax, 0x10 + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + jmp 0x08:after_gdt +after_gdt: + ret diff --git a/kernel/src/arch/i686/idt.asm b/kernel/src/arch/i686/idt.asm new file mode 100644 index 0000000..6cccdc6 --- /dev/null +++ b/kernel/src/arch/i686/idt.asm @@ -0,0 +1,99 @@ +extern idt_exception_handler +extern idt_pic_timer +extern idt_pic_keyboard +extern idt_pic_mouse +extern idt_pic_eoi +global isr_stub_table + +%macro ISRErrorStub 1 +isr_stub_%+%1: + push dword %1 + call idt_exception_handler + pop eax + iret +%endmacro + +%macro PICGeneric 1 +isr_stub_%+%1: + push dword %1 + call idt_pic_eoi + pop eax + iret +%endmacro + +%macro PICTimer 1 +isr_stub_%+%1: + call idt_pic_timer + push dword %1 + call idt_pic_eoi + pop eax + iret +%endmacro + +%macro PICKeyboard 1 +isr_stub_%+%1: + call idt_pic_keyboard + push dword %1 + call idt_pic_eoi + pop eax + iret +%endmacro + +%macro PICMouse 1 +isr_stub_%+%1: + call idt_pic_mouse + push dword %1 + call idt_pic_eoi + pop eax + iret +%endmacro + +%macro ISRSyscall 1 +isr_stub_%+%1: + push eax + push ebx + push ecx + push edx + call idt_syscall + add esp, 16 + pop eax + iret +%endmacro + +section .text +align 8 +%assign i 0 +%rep 32 + ISRErrorStub i +%assign i i+1 +%endrep +PICTimer 32 ; 0 +PICKeyboard 33 ; 1 +PICGeneric 34 ; 2 +PICGeneric 35 ; 3 +PICGeneric 36 ; 4 +PICGeneric 37 ; 5 +PICGeneric 38 ; 6 +PICGeneric 39 ; 7 +PICGeneric 40 ; 8 +PICGeneric 41 ; 9 +PICGeneric 42 ; 10 +PICGeneric 43 ; 11 +PICMouse 44 ; 12 +PICGeneric 45 ; 13 +PICGeneric 46 ; 14 +PICGeneric 47 ; 15 +%assign i 48 +%rep 256 - 48 + ISRErrorStub i +%assign i i+1 +%endrep + +section .rodata +align 8 +isr_stub_table: +%assign i 0x00 +%rep 256 + dd isr_stub_%+i +%assign i i+0x01 +%endrep diff --git a/kernel/src/arch/i686/idt.c b/kernel/src/arch/i686/idt.c new file mode 100644 index 0000000..04fd5f8 --- /dev/null +++ b/kernel/src/arch/i686/idt.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tty/term.h" + +struct IdtEntry { + uint16_t isr_low; + uint16_t kernel_cs; + uint8_t _reserved; + uint8_t attributes; + uint16_t isr_high; +} __attribute__((packed)); + +struct Idtr { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + +enum IDTFlags { + IDT_FLAG_GATE_TASK = 0x5, + IDT_FLAG_GATE_16BIT_INT = 0x6, + IDT_FLAG_GATE_16BIT_TRAP = 0x7, + IDT_FLAG_GATE_32BIT_INT = 0xE, + IDT_FLAG_GATE_32BIT_TRAP = 0xF, + + IDT_FLAG_RING0 = (0 << 5), + IDT_FLAG_RING1 = (1 << 5), + IDT_FLAG_RING2 = (2 << 5), + IDT_FLAG_RING3 = (3 << 5), + + IDT_FLAG_PRESENT = 0x80, +}; + +#define WIDTH 30 +static char buf[WIDTH]; +static int timer = -1; + +void idt_pic_eoi(uint8_t exception) { + pic_eoi(exception - PIC_REMAP_OFFSET); +} + +void idt_pic_timer(void) { + + timer += 1; + if (timer % 20 != 0) return; + + uint32_t state = term_save(); + + term_setfg(VGA_LIGHT_GREEN); + term_setpos(TERM_W - WIDTH - 1, 0); + for (size_t i = 0; i < WIDTH; i++) putchar(' '); + term_setpos(TERM_W - WIDTH - 1, 0); + + struct Time t = get_localtime(); + timetostr(&t, "%a %b %d %Y %H:%M:%S", buf, WIDTH); + printk("%s", buf); + + term_load(state); +} + +void idt_pic_keyboard(void) { + ps2kb_recv(); +} + +void idt_pic_mouse(void) { + ps2mouse_recv(); +} + +void idt_exception_handler(uint8_t exception) { + char* msg; + switch(exception) { + case 0x00: + msg = "Division by zero"; + break; + case 0x02: + msg = "NMI"; + break; + case 0x04: + msg = "Overflow"; + break; + case 0x06: + msg = "invalid opcode"; + break; + case 0x08: + msg = "double fault"; + break; + case 0x0A: + msg = "invalid task state segment"; + break; + case 0x0C: + msg = "stack segment fault"; + break; + case 0x0D: + msg = "general protection fault"; + break; + case 0x0E: + msg = "page fault"; + break; + default: + msg = "unknown exception"; + break; + } + panic("E%u: %s", exception, msg); +} + +__attribute__((aligned(0x10))) +static struct IdtEntry idt[256]; +static struct Idtr idtr; +extern void* isr_stub_table[]; + +static void set_descriptor(uint8_t vector, void* isr, uint8_t flags) { + struct IdtEntry* entry = &idt[vector]; + entry->isr_low = (size_t)isr & 0xffff; + entry->kernel_cs = 0x08; + entry->attributes = flags; + entry->isr_high = (size_t)isr >> 16; + entry->_reserved = 0; +} + +void idt_init(void) { + idtr.base = (uintptr_t)&idt[0]; + idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_SIZE - 1; + + for(int i = 0; i < IDT_INTERRUPTS; i++) { + set_descriptor(i, isr_stub_table[i], 0x8e); + } + + __asm__ volatile ("lidt %0" : : "m"(idtr)); +} + diff --git a/kernel/src/arch/i686/mboot.c b/kernel/src/arch/i686/mboot.c new file mode 100644 index 0000000..108812f --- /dev/null +++ b/kernel/src/arch/i686/mboot.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +static struct BootInfo info; + +static void read_cmdline(struct BootTag *tag, char *data, uint8_t len) { + if (len >= CMDLINE_MAX) + panic("multiboot2 cmd line to long\nmax is %d but was provided %d\n", + CMDLINE_MAX, len); + memcpy(tag->data.cmdline, data, len); + info.tags[ID_CMDLINE] = *tag; +} + +static void read_memorymap(struct BootTag *tag, uint32_t *data) { + tag->data.memory_map = (struct MemoryMap *) data; + info.tags[iD_MEMORYMAP] = *tag; +} + +static void read_rsdp(struct BootTag *tag, char *data) { + tag->data.rsdp = (struct RootSystemDescriptionPointer *) data; + info.tags[ID_RSDP] = *tag; +} + +static uint32_t *read_tag(uint32_t *data) { + struct BootTag tag; + tag.type = ((uint16_t*)data)[0]; + tag.size = data[1]; + tag.valid = 1; + + uint8_t data_len = tag.size - 2 * sizeof(uint32_t); + + switch (tag.type) { + case ID_CMDLINE: + read_cmdline(&tag, (char *)(data + 2), data_len); + break; + case iD_MEMORYMAP: + read_memorymap(&tag, data + 2); + break; + case ID_RSDP: + read_rsdp(&tag, (char *) (data + 2)); + break; + default: + break; + } + + if(tag.size % 8 != 0) { + tag.size += 8 - (tag.size % 8); + } + + return data + tag.size / sizeof(uint32_t); +} + +void load_boot_info(void* boot_info) { + + memset(&info, 0, sizeof(boot_info)); + + uint32_t* data = (uint32_t*) boot_info; + info.total_size = *data++; + info.reserved = *data++; + + while((uint8_t*) data < (uint8_t*) boot_info + info.total_size) { + data = read_tag(data); + } + +} + +bool get_boot_tag(enum BootTagID id, struct BootTag **tag) { + *tag = &info.tags[id]; + return (*tag)->valid; +} diff --git a/kernel/src/arch/i686/memory.c b/kernel/src/arch/i686/memory.c new file mode 100644 index 0000000..29f1f56 --- /dev/null +++ b/kernel/src/arch/i686/memory.c @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include + +struct MemoryArea { + uint32_t len; + struct MemoryArea *prev; + struct MemoryArea *next; +}; + +typedef unsigned char page[4096]; + +extern unsigned char kernel_start, kernel_end; +static uintptr_t kernel_start_addr, kernel_end_addr; +static uint32_t *bitmap; +static uint32_t total_memory; +static uint32_t free_memory; +static uint32_t page_count; +static uint32_t page_free_start; +static struct MemoryArea *page_start; + +int memory_lock(void) { + // int_disable(); + return 0; +} + +int memory_unlock(void) { + // int_enable(); + return 0; +} + +static int n_pages(const struct MemoryArea *m) { + return (m->len - sizeof(*m)) / sizeof(page); +} + +static void *page_at(int i) { + int cur_page = 0; + for (struct MemoryArea *m = page_start; m != NULL; m = m->next) { + int pages = n_pages(m); + if (i - cur_page < pages) { + page *page_array = (page *) (m + 1); + return page_array[i - cur_page]; + } + cur_page += pages; + } + return NULL; +} + +static int page_idx(page p) { + uintptr_t addr = (uintptr_t) p; + int cur_page = 0; + for (struct MemoryArea *m = page_start; m != NULL; m = m->next) { + if ((uintptr_t) m + m->len > addr) { + return cur_page + (addr - (uintptr_t) m) / sizeof(page); + } + cur_page += n_pages(m); + } + return -1; +} + +static inline bool bitmap_get(int i) { + return (bitmap[i / 32] >> i % 32) & 1; +} + +static inline void bitmap_set(int i, bool v) { + int idx = i / 32; + bitmap[idx] &= ~(1 << i % 32); + bitmap[idx] |= (v << i % 32); +} + +void *memory_alloc_page(int pages) { + if (pages < 1) return NULL; + + int n_contiguous = 0; + int free_region_start = 0; + bool first = true; + for (uint32_t i = page_free_start; i < page_count; i++) { + bool free = !bitmap_get(i); + + if (first) { + first = false; + page_free_start = i; + } + + if (free) { + if (n_contiguous == 0) free_region_start = i; + n_contiguous++; + if (n_contiguous == pages) { + for (int j = 0; j < pages; j++) + bitmap_set(free_region_start + j, true); + return page_at(free_region_start); + } + } else n_contiguous = 0; + } + + return NULL; +} + +int memory_free_page(void *ptr, int pages) { + int idx = page_idx(ptr); + if (idx == -1) return 1; + + if ((unsigned) idx < page_free_start) page_free_start = idx; + + for (int i = 0; i < pages; i++) + bitmap_set(idx + pages, false); + return 0; +} + +void memory_init(void) { + + memory_lock(); + + bitmap = NULL; + total_memory = 0; + free_memory = 0; + page_count = 0; + page_free_start = 0; + page_start = NULL; + + kernel_start_addr = (uintptr_t) &kernel_start; + kernel_end_addr = (uintptr_t) &kernel_end; + + struct BootTag *tag; + if (!get_boot_tag(iD_MEMORYMAP, &tag)) { + panic("No multiboot memory map found"); + } + + uintptr_t end = (uintptr_t) tag->data.memory_map; + end += tag->size; + + struct MemoryArea *prev = NULL; + struct MemorySegment *segment = &tag->data.memory_map->entries[0]; + for(; (uintptr_t) segment < end; segment++) { + + if (segment->type != 1) continue; + if (segment->addr >= UINT32_MAX) continue; + if (segment->addr < kernel_start_addr) continue; + + uint32_t length; + if (segment->addr + segment->len > UINT32_MAX) { + length = UINT32_MAX - segment->addr; + } else { + length = segment->len; + } + + uintptr_t addr; + if (segment->addr < kernel_end_addr) { + addr = kernel_end_addr; + length -= addr - segment->addr; + } else { + addr = segment->addr; + } + + struct MemoryArea *current = (struct MemoryArea *) addr; + current->prev = prev; + current->next = NULL; + current->len = length; + + if (prev != NULL) { + prev->next = current; + } else { + page_start = current; + } + + page_count += n_pages(current); + total_memory += length; + + prev = current; + + } + + int bitmap_pages = page_count / 32 / sizeof(page) + 1; + bitmap = (uint32_t *) page_at(page_count - bitmap_pages); + page_count -= bitmap_pages; + memset(bitmap, 0, bitmap_pages * sizeof(page)); + free_memory = page_count * sizeof(page); + + memory_unlock(); + +} + +uint32_t memory_total(void) { + return total_memory; +} + +uint32_t memory_free(void) { + return free_memory; +} + +uint32_t memory_used(void) { + return total_memory - free_memory; +} diff --git a/kernel/src/arch/i686/paging.asm b/kernel/src/arch/i686/paging.asm new file mode 100644 index 0000000..f74cc55 --- /dev/null +++ b/kernel/src/arch/i686/paging.asm @@ -0,0 +1,62 @@ +global page_directory +global paging_init +global paging_finish +global KERNEL_MAPPING + +KERNEL_MAPPING equ 0xC0000000 +VGABUF equ 0x000B8000 + +section .bss +align 4096 +page_directory: +resb 4096 +page_table1: +resb 4096 + +section .bootstrap.text +align 8 +paging_init: + extern kernel_start + extern kernel_end + +paging_load: + mov edi, page_table1 - KERNEL_MAPPING + mov esi, 0 + mov ecx, 1023 + +paging_cmp: + cmp esi, kernel_start + jl paging_add + cmp esi, kernel_end - KERNEL_MAPPING + jge paging_map + + mov edx, esi + or edx, 0x003 + mov [edi], edx + +paging_add: + add esi, 4096 + add edi, 4 + loop paging_cmp + +paging_map: + mov dword [page_table1 - KERNEL_MAPPING + 1023 * 4], VGABUF | 0x003 + mov dword [page_directory - KERNEL_MAPPING + 0], page_table1 - KERNEL_MAPPING + 0x003 + mov dword [page_directory - KERNEL_MAPPING + 768 * 4], page_table1 - KERNEL_MAPPING + 0x003 + + mov ecx, page_directory - KERNEL_MAPPING + mov cr3, ecx + + mov ecx, cr0 + or ecx, 0x80010000 + mov cr0, ecx + + ret + +section .text +align 8 +paging_finish: + mov dword [page_directory], 0 + mov ecx, cr3 + mov cr3, ecx + ret diff --git a/kernel/src/arch/i686/pic.c b/kernel/src/arch/i686/pic.c new file mode 100644 index 0000000..f5d0f94 --- /dev/null +++ b/kernel/src/arch/i686/pic.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +#define PIC1_COMMAND_PORT 0x20 +#define PIC1_DATA_PORT 0x21 +#define PIC2_COMMAND_PORT 0xA0 +#define PIC2_DATA_PORT 0xA1 + +void pic_remap(void) { + char a1 = inb(PIC1_DATA_PORT); + char a2 = inb(PIC2_DATA_PORT); + // control word 1 + // 0x11: initialize, enable ICW4 + outb(PIC1_COMMAND_PORT, 0x11); + io_wait(); + outb(PIC2_COMMAND_PORT, 0x11); + io_wait(); + // control word 2 + // interrupt offset + outb(PIC1_DATA_PORT, PIC_REMAP_OFFSET); + io_wait(); + outb(PIC2_DATA_PORT, PIC_REMAP_OFFSET + 8); + io_wait(); + // control word 3 + // primary pic: set which pin secondary is connected to + // (pin 2) + outb(PIC1_DATA_PORT, 0x04); + io_wait(); + outb(PIC2_DATA_PORT, 2); + io_wait(); + // control word 3 + // 0x01: enable 8086 mode + outb(PIC1_DATA_PORT, 0x01); + io_wait(); + outb(PIC2_DATA_PORT, 0x01); + io_wait(); + // clear data registers + outb(PIC1_DATA_PORT, a1); + outb(PIC2_DATA_PORT, a2); +} + +void pic_mask(int irq) { + uint8_t port; + if(irq < 8) { + port = PIC1_DATA_PORT; + } else { + irq -= 8; + port = PIC2_DATA_PORT; + } + uint8_t mask = inb(port); + outb(port, mask | (1 << irq)); +} + +void pic_unmask(int irq) { + uint8_t port; + if(irq < 8) { + port = PIC1_DATA_PORT; + } else { + irq -= 8; + port = PIC2_DATA_PORT; + } + uint8_t mask = inb(port); + outb(port, mask & ~(1 << irq)); +} + +void pic_disable(void) { + outb(PIC1_DATA_PORT, 0xff); + io_wait(); + outb(PIC2_DATA_PORT, 0xff); + io_wait(); +} + +void pic_eoi(int irq) { + if(irq >= 8) { + outb(PIC2_COMMAND_PORT, 0x20); + } + outb(PIC1_COMMAND_PORT, 0x20); +} diff --git a/kernel/src/arch/i686/start.asm b/kernel/src/arch/i686/start.asm new file mode 100644 index 0000000..2151b51 --- /dev/null +++ b/kernel/src/arch/i686/start.asm @@ -0,0 +1,82 @@ +global start +bits 32 + + +; create the multiboot header +section .bootstrap.data +align 8 +mb_start: +dd 0xe85250d6 +dd 0 +dd mb_end - mb_start +dd -(0xe85250d6 + (mb_end - mb_start)) +dw 0 +dw 0 +dd 8 +mb_end: + + +; create the stack for bootstrapping +section .bootstrap.stack +align 16 +bootstrap_stack_start: +resb 1024 ; 1 KiB +bootstrap_stack_end: + + +; create the stack for the kernel +section .stack +align 16 +stack_start: +resb 16384 ; 16 KiB +stack_end: + + +; load the kernel into the higher half +section .bootstrap.text +align 8 +start: + ; init bootstrap stack + mov esp, bootstrap_stack_end + mov ebp, bootstrap_stack_end + + ; load kernel into higher half and init paging + extern paging_init + call paging_init + + jmp near load_kernel + +; initalize kernel after it has been loaded in higher half +section .text +align 8 +load_kernel: + ; init stack + mov esp, stack_end + mov ebp, stack_end + + ; load global descripter table + extern load_gdt + call load_gdt + + ; unmap kernel at page 0 + extern paging_finish + call paging_finish + + ; initalize the FPU + finit + + ; push multiboot header + extern KERNEL_MAPPING + add ebx, KERNEL_MAPPING + push ebx + + ; start kernel + sti + call kernel_main + extern kernel_main + + ; hlt forever if kernel quits (it should never) + cli +halt: + hlt + jmp halt diff --git a/kernel/src/arch/i686/sys.c b/kernel/src/arch/i686/sys.c new file mode 100644 index 0000000..209fea4 --- /dev/null +++ b/kernel/src/arch/i686/sys.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void arch_init(void *boot_info) { + rtc_update(); + + idt_init(); + pic_remap(); + + load_boot_info(boot_info); + + /* havent refactored to work with paging yet */ + // acpi_init(); + // memory_init(); + + ps2ctrl_init(); +} + +extern void arch_update(void) { + rtc_update(); +} + +void arch_halt(void) { + halt(); +} + +void arch_wait_io(void) { + io_wait(); +} + +void arch_disable_int(void) { + int_disable(); +} + +void arch_enable_int(void) { + int_enable(); +} + +extern void arch_wait_int(void) { + int_wait(); +} + +void arch_poweroff(void) { + acpi_poweroff(); +} diff --git a/kernel/src/arch/i686/time.c b/kernel/src/arch/i686/time.c new file mode 100644 index 0000000..66fabc1 --- /dev/null +++ b/kernel/src/arch/i686/time.c @@ -0,0 +1,17 @@ +#include +#include + +static enum Timezone cur_tz = UTC; + +struct Time get_utctime(void) { + return rtc_utctime(); +} + +struct Time get_localtime(void) { + return rtc_localtime(cur_tz); +} + +void set_timezone(enum Timezone tz) { + cur_tz = tz; +} + diff --git a/kernel/src/boot/tag.c b/kernel/src/boot/tag.c deleted file mode 100644 index a344d72..0000000 --- a/kernel/src/boot/tag.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "print.h" -#include "tag.h" -#include "acpi/acpi.h" -#include "memory/memory.h" - -static struct BootInfo info; - -static void read_cmdline(struct BootTag *tag, char *data, uint8_t len) { - if (len >= CMDLINE_MAX) - panic("multiboot2 cmd line to long\nmax is %d but was provided %d\n", - CMDLINE_MAX, len); - memcpy(tag->data.cmdline, data, len); - info.tags[ID_CMDLINE] = *tag; -} - -static void read_memorymap(struct BootTag *tag, uint32_t *data) { - tag->data.memory_map = (struct MemoryMap *) data; - info.tags[iD_MEMORYMAP] = *tag; -} - -static void read_rsdp(struct BootTag *tag, char *data) { - tag->data.rsdp = (struct RootSystemDescriptionPointer *) data; - info.tags[ID_RSDP] = *tag; -} - -static uint32_t *read_tag(uint32_t *data) { - struct BootTag tag; - tag.type = ((uint16_t*)data)[0]; - tag.size = data[1]; - tag.valid = 1; - - uint8_t data_len = tag.size - 2 * sizeof(uint32_t); - - switch (tag.type) { - case ID_CMDLINE: - read_cmdline(&tag, (char *)(data + 2), data_len); - break; - case iD_MEMORYMAP: - read_memorymap(&tag, data + 2); - break; - case ID_RSDP: - read_rsdp(&tag, (char *) (data + 2)); - break; - default: - break; - } - - if(tag.size % 8 != 0) { - tag.size += 8 - (tag.size % 8); - } - - return data + tag.size / sizeof(uint32_t); -} - -void load_boot_info(void* boot_info) { - - memset(&info, 0, sizeof(boot_info)); - - uint32_t* data = (uint32_t*) boot_info; - info.total_size = *data++; - info.reserved = *data++; - - while((uint8_t*) data < (uint8_t*) boot_info + info.total_size) { - data = read_tag(data); - } - -} - -bool get_boot_tag(enum BootTagID id, struct BootTag **tag) { - *tag = &info.tags[id]; - return (*tag)->valid; -} diff --git a/kernel/src/boot/tag.h b/kernel/src/boot/tag.h deleted file mode 100644 index a81e443..0000000 --- a/kernel/src/boot/tag.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include - -#include "acpi/acpi.h" -#include "memory/memory.h" - -#define CMDLINE_MAX 32 - -struct BootTag { - uint8_t valid; - uint32_t type; - uint32_t size; - union { - char cmdline[CMDLINE_MAX]; - struct MemoryMap *memory_map; - struct RootSystemDescriptionPointer *rsdp; - } data; -}; - -struct BootInfo { - uint32_t total_size; - uint32_t reserved; - struct BootTag tags[21]; -}; - -enum BootTagID { - ID_CMDLINE = 0, - iD_MEMORYMAP = 6, - ID_RSDP = 14 -}; - -void load_boot_info(void* boot_info); -bool get_boot_tag(enum BootTagID id, struct BootTag **tag); diff --git a/kernel/src/cpu/cpu.c b/kernel/src/cpu/cpu.c deleted file mode 100644 index 416a1ad..0000000 --- a/kernel/src/cpu/cpu.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "cpu.h" - -#include "print.h" - -extern uint8_t sse_init (void); -extern uint8_t fpu_init (void); - -uint8_t init_registers (uint8_t reg) { - uint8_t res = 0; - - if (reg & SSE_REG) - res |= ~sse_init() & SSE_REG; - - if (reg & FPU_REG) - res |= ~fpu_init() & FPU_REG; - - return res; -} diff --git a/kernel/src/cpu/cpu.h b/kernel/src/cpu/cpu.h deleted file mode 100644 index b6221aa..0000000 --- a/kernel/src/cpu/cpu.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -#define SSE_REG 0x01 -#define FPU_REG 0x02 - -uint8_t init_registers (uint8_t reg); diff --git a/kernel/src/cpu/fpu.asm b/kernel/src/cpu/fpu.asm deleted file mode 100644 index d03feba..0000000 --- a/kernel/src/cpu/fpu.asm +++ /dev/null @@ -1,19 +0,0 @@ -global fpu_init - -fpu_init: - mov edx, cr0 - and edx, (-1) - ((1 << 3) + (1 << 4)) - mov cr0, edx - fninit - fnstsw [test] - cmp word [test], 0 - jne no_fpu - - mov eax, 0 - ret - -no_fpu: - mov eax, 1 - ret - -test: dw 0x55AA diff --git a/kernel/src/cpu/sse.asm b/kernel/src/cpu/sse.asm deleted file mode 100644 index e7b5a99..0000000 --- a/kernel/src/cpu/sse.asm +++ /dev/null @@ -1,22 +0,0 @@ -global sse_init - -sse_init: - mov eax, 0x1 - cpuid - test edx, 1<<25 - jmp no_sse - - mov eax, cr0 - and ax, 0xFFFB - or ax, 0x2 - mov cr0, eax - mov eax, cr4 - or ax, 3 << 9 - mov cr4, eax - - mov eax, 0 - ret - -no_sse: - mov eax, 1 - ret diff --git a/kernel/src/drivers/cmos.c b/kernel/src/drivers/cmos.c deleted file mode 100644 index 5ac12c3..0000000 --- a/kernel/src/drivers/cmos.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "print.h" -#include -#include -#include - -#define CMOS_WRITE_PORT 0x70 -#define CMOS_READ_PORT 0x71 - -#define CMOS_REG_SEC 0x00 -#define CMOS_REG_MIN 0x02 -#define CMOS_REG_HOUR 0x04 -#define CMOS_REG_WDAY 0x06 -#define CMOS_REG_MDAY 0x07 -#define CMOS_REG_MON 0x08 -#define CMOS_REG_YEAR 0x09 -#define CMOS_REG_CEN 0x32 - -static struct Time time; -static struct Time localtime; -static int cur_offset = 0; - -static uint8_t cmos_read(uint8_t reg) { - uint8_t hex, ret; - - outb(CMOS_WRITE_PORT, reg); - hex = inb(CMOS_READ_PORT); - - ret = hex & 0x0F; - ret += (hex & 0xF0) / 16 * 10; - - return ret; -} - -static int mday_offset[12] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -}; - -static int month_days[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -static void update_localtime(void) { - - int change, max; - - // set localtime - localtime = time; - - // do we acutally need to do anything - if (cur_offset == 0) return; - localtime.hour += cur_offset; - - // check if day rolled over - change = localtime.hour < 0 ? -1 : localtime.hour >= 24 ? 1 : 0; - if (!change) return; - - // roll over day - localtime.hour = (localtime.hour + 24) % 24; - localtime.wday = (localtime.wday + change + 7) % 7; - localtime.mday += change; - localtime.yday += change; - - // check if month rolled over - max = month_days[localtime.mon]; - if (localtime.leap && localtime.mon == 1) max++; - change = localtime.mday < 0 ? -1 : localtime.mday >= max ? 1 : 0; - if (!change) return; - - // roll over month - localtime.mon = (localtime.mon + change + 12) % 12; - - // check if year rolled over - max = localtime.leap ? 366 : 365; - change = localtime.yday < 0 ? -1 : localtime.yday >= max ? 1 : 0; - if (!change) return; - - // roll over year - localtime.yn += change; - - // check if cen rolled over - change = localtime.yn < 0 ? -1 : localtime.yn >= 100 ? 1 : 0; - if (!change) goto year; - - // roll over cen - localtime.cen += change; - - -year: - - localtime.year = localtime.yn + localtime.cen * 100; - localtime.leap = localtime.year % 4 == 0 && localtime.year % 100 != 0; - - if (localtime.leap && localtime.yday == -1) - localtime.yday = 365; - else if (localtime.yday == -1) - localtime.yday = 364; - else - localtime.yday = 0; - - localtime.year -= 1900; - -} - -void rtc_set_timezone(int offset) { - cur_offset = offset; -} - -void rtc_update(void) { - time.sec = cmos_read(CMOS_REG_SEC); - time.min = cmos_read(CMOS_REG_MIN); - time.hour = cmos_read(CMOS_REG_HOUR); - time.wday = cmos_read(CMOS_REG_WDAY) - 1; - time.mday = cmos_read(CMOS_REG_MDAY); - time.mon = cmos_read(CMOS_REG_MON) - 1; - time.yn = cmos_read(CMOS_REG_YEAR); - time.cen = 20; - - time.year = time.yn + time.cen * 100; - - time.leap = time.year % 4 == 0 && time.year % 100 != 0; - - time.yday = mday_offset[time.mon] + time.mday; - - if (time.leap && time.mon > 2) - time.yday++; - - time.year -= 1900; - - update_localtime(); -} - -struct Time *rtc_utctime(void) { - return &time; -} - -struct Time *rtc_localtime(void) { - return &localtime; -} diff --git a/kernel/src/drivers/ps2ctrl.c b/kernel/src/drivers/ps2ctrl.c deleted file mode 100644 index 05ef25d..0000000 --- a/kernel/src/drivers/ps2ctrl.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "print.h" -#include "ps2ctrl.h" -#include "interrupt/pic.h" - -#define STATUS_OUT_BUF ((uint8_t)0x01) -#define STATUS_IN_BUF ((uint8_t)0x02) - -#define CONFIG_INT_0 ((uint8_t)0x01) -#define CONFIG_INT_1 ((uint8_t)0x02) -#define CONFIG_SYS ((uint8_t)0x04) -#define CONFIG_CLOCK_0 ((uint8_t)0x10) -#define CONFIG_CLOCK_1 ((uint8_t)0x20) -#define CONFIG_TRANS ((uint8_t)0x40) - -static bool is_init = false; - -uint8_t ps2ctrl_in(void) { - while((ps2ctrl_in_status() & STATUS_OUT_BUF) == 0) { - io_wait(); - } - return inb(0x60); -} - -uint8_t ps2ctrl_in_status(void) { - return inb(0x64); -} - -void ps2ctrl_out_cmd(uint8_t cmd) { - while((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) { - io_wait(); - } - outb(0x64, cmd); -} - -void ps2ctrl_out_data(uint8_t data) { - while((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) { - io_wait(); - } - outb(0x60, data); -} - -void ps2ctrl_set_port2(void) { - outb(0x64, 0xD4); -} - -void ps2ctrl_init(void) { - - is_init = false; - - pic_mask(1); // keyboard - pic_mask(12); // mouse - - inb(0x60); - - // self-test - ps2ctrl_out_cmd(0xAA); - uint8_t response = ps2ctrl_in(); - if(response != 0x55) { - panic("PS/2 controller failed to initialize"); - } - - // set config - ps2ctrl_out_cmd(0x20); - uint8_t config = ps2ctrl_in(); - config = (config | CONFIG_INT_0 | CONFIG_INT_1) & ~CONFIG_TRANS; - // config = 0xFF; - ps2ctrl_out_cmd(0x60); - ps2ctrl_out_data(config); - - // enable port 0 - ps2ctrl_out_cmd(0xAE); - - // enable port 2 - ps2ctrl_out_cmd(0xA9); - response = ps2ctrl_in(); - if (response == 0x01) { - panic("PS/2 port 2 not supported"); - } - - ps2ctrl_out_cmd(0xA8); - - is_init = true; - - pic_unmask(1); - pic_unmask(12); -} - -bool ps2ctrl_is_init(void) { - return is_init; -} diff --git a/kernel/src/drivers/ps2ctrl.h b/kernel/src/drivers/ps2ctrl.h deleted file mode 100644 index a674c57..0000000 --- a/kernel/src/drivers/ps2ctrl.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include - -uint8_t ps2ctrl_in(void); -uint8_t ps2ctrl_in_status(void); -void ps2ctrl_out_cmd(uint8_t cmd); -void ps2ctrl_out_data(uint8_t data); -void ps2ctrl_set_port2(void); - -void ps2ctrl_init(void); - -bool ps2ctrl_is_init(void); diff --git a/kernel/src/drivers/ps2kb.c b/kernel/src/drivers/ps2kb.c deleted file mode 100644 index f6fc514..0000000 --- a/kernel/src/drivers/ps2kb.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include - -#include "print.h" -#include "ps2kb.h" -#include "ps2ctrl.h" -#include "interrupt/pic.h" - -#define BUFFER_LEN 16 - -#define KEYCODE_ARRAY_LEN 0x84 - -static uint8_t scancodes[] = { -// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F -/*00*/ KEY_NONE, KEY_F9, KEY_NONE, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, -/*08*/ KEY_NONE, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK, KEY_NONE, -/*10*/ KEY_NONE, KEY_L_ALT, KEY_L_SHIFT, KEY_NONE, KEY_L_CTRL, KEY_Q, KEY_1, KEY_NONE, -/*18*/ KEY_NONE, KEY_NONE, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_NONE, -/*20*/ KEY_NONE, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_NONE, -/*28*/ KEY_NONE, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_NONE, -/*30*/ KEY_NONE, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_NONE, -/*38*/ KEY_NONE, KEY_NONE, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_NONE, -/*40*/ KEY_NONE, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_NONE, -/*48*/ KEY_NONE, KEY_PERIOD, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_NONE, -/*50*/ KEY_NONE, KEY_NONE, KEY_QUOTE, KEY_NONE, KEY_L_BRACE, KEY_EQUAL, KEY_NONE, KEY_NONE, -/*58*/ KEY_CAPS_LOCK, KEY_R_SHIFT, KEY_ENTER, KEY_R_BRACE, KEY_NONE, KEY_BACKSLASH, KEY_NONE, KEY_NONE, -/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_BACKSPACE, KEY_NONE, -/*68*/ KEY_NONE, KEY_NP_1, KEY_NONE, KEY_NP_4, KEY_NP_7, KEY_NONE, KEY_NONE, KEY_NONE, -/*70*/ KEY_NP_0, KEY_NP_PERIOD, KEY_NP_2, KEY_NP_5, KEY_NP_6, KEY_NP_8, KEY_ESCAPE, KEY_NUM_LOCK, -/*78*/ KEY_F11, KEY_NP_PLUS, KEY_NP_3, KEY_NP_MINUS, KEY_NP_ASTERISK, KEY_NP_9, KEY_SCROLL_LOCK, KEY_NONE, -/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_F7, -}; -static uint8_t scancodes_ext[] = { -// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F -/*00*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, -/*08*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, -/*10*/ KEY_UNKNOWN, KEY_R_ALT, KEY_PRINT_SCREEN, KEY_NONE, KEY_R_CTRL, KEY_UNKNOWN, KEY_NONE, KEY_NONE, -/*18*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_L_META, -/*20*/ KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_R_META, -/*28*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_MENU, -/*30*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, -/*38*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, -/*40*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, -/*48*/ KEY_UNKNOWN, KEY_NONE, KEY_NP_SLASH, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, -/*50*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, -/*58*/ KEY_NONE, KEY_NONE, KEY_NP_ENTER, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, -/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, -/*68*/ KEY_NONE, KEY_END, KEY_NONE, KEY_LEFT, KEY_HOME, KEY_NONE, KEY_NONE, KEY_NONE, -/*70*/ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_NONE, KEY_RIGHT, KEY_UP, KEY_NONE, KEY_NONE, -/*78*/ KEY_NONE, KEY_NONE, KEY_PAGE_DOWN, KEY_NONE, KEY_NONE, KEY_PAGE_UP, KEY_NONE, KEY_NONE, -/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, -}; - -static struct Keycode last_keycode; - -static bool is_init = false; -static bool state_keyup = false; -static bool state_ext = false; - -void ps2kb_init(void) { - - is_init = false; - pic_mask(1); - - uint8_t result; - - ps2ctrl_out_data(0xFF); - result = ps2ctrl_in(); - if(result != 0xFA) { - panic("Failed to reset PS/2 keyboard: expected 0xFA, got 0x%X\n", result); - return; - } - result = ps2ctrl_in(); - if(result != 0xAA) { - panic("Failed to reset PS/2 keyboard: expected 0xAA, got 0x%X\n", result); - return; - } - - ps2ctrl_out_data(0xF4); - result = ps2ctrl_in(); - if(result != 0xFA) { - panic("Failed to enable PS/2 keyboard: expected 0xFA, got 0x%X\n", result); - return; - } - - pic_unmask(1); - is_init = true; -} - -void ps2kb_recv(void) { - if(!ps2ctrl_is_init() || !is_init) { - inb(0x60); - return; - } - uint8_t code = ps2ctrl_in(); - if (code == 0x00 || code == 0x0F) { - last_keycode.key = KEY_NONE; - last_keycode.flags = KC_FLAG_ERROR; - } else if(code == 0xF0) { - state_keyup = true; - } else if(code == 0xE0) { - state_ext = true; - } else if(code <= KEYCODE_ARRAY_LEN) { - uint8_t *scancode_table = state_ext ? scancodes_ext : scancodes; - uint8_t keycode = scancode_table[code]; - if(keycode != KEY_NONE) { - last_keycode.key = keycode; - last_keycode.flags = state_keyup ? KC_FLAG_KEY_UP : KC_FLAG_KEY_DOWN; - } - state_keyup = false; - state_ext = false; - } -} - -struct Keycode ps2kb_get(void) { - struct Keycode code; - if(is_init) { - code = last_keycode; - } else { - code.key = KEY_NONE; - code.flags = KC_FLAG_ERROR; - } - last_keycode.key = KEY_NONE; - last_keycode.flags = 0; - return code; -} diff --git a/kernel/src/drivers/ps2kb.h b/kernel/src/drivers/ps2kb.h deleted file mode 100644 index 1aaefb2..0000000 --- a/kernel/src/drivers/ps2kb.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include -#include - -struct Keycode { - uint8_t key; - uint8_t flags; -}; - -void ps2kb_init(void); - -void ps2kb_recv(void); -struct Keycode ps2kb_get(void); diff --git a/kernel/src/drivers/ps2mouse.c b/kernel/src/drivers/ps2mouse.c deleted file mode 100644 index 1616cd6..0000000 --- a/kernel/src/drivers/ps2mouse.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include - -#include "print.h" -#include "ps2mouse.h" -#include "drivers/ps2ctrl.h" -#include "interrupt/pic.h" - -static bool is_init = false; - -static struct MouseEvent last_event; -static uint8_t first_b, second_b, third_b; - -void ps2mouse_init(void) { - - is_init = false; - pic_mask(12); - - uint8_t result; - - ps2ctrl_set_port2(); - ps2ctrl_out_data(0xFF); - result = ps2ctrl_in(); - if (result != 0xFA) { - panic("Failed to reset PS/2 mouse: expected 0xFA, got 0x%X", result); - return; - } - result = ps2ctrl_in(); - if (result != 0xAA) { - panic("Failed to reset PS/2 mouse: expected 0xAA, got 0x%X", result); - return; - } - - ps2ctrl_set_port2(); - ps2ctrl_out_data(0xF4); - - pic_unmask(12); - is_init = true; -} - -static uint8_t packet_num = 0; -void ps2mouse_recv(void) { - if (!ps2ctrl_is_init() || !is_init) { - inb(0x60); - return; - } - - uint8_t packet = ps2ctrl_in(); - switch (packet_num) { - case 0: - first_b = packet; - break; - case 1: - second_b = packet; - break; - case 2: { - third_b = packet; - - int state, d; - state = first_b; - d = second_b; - last_event.relx = d - ((state << 4) & 0x100); - d = third_b; - last_event.rely = d - ((state << 3) & 0x100); - - last_event.lmb = first_b & 0x01; - last_event.rmb = first_b & 0x02; - last_event.mmb = first_b & 0x04; - last_event.updated = true; - break; - } - } - - packet_num += 1; - packet_num %= 3; - -} - -struct MouseEvent ps2mouse_get(void) { - struct MouseEvent event = last_event; - last_event.updated = false; - return event; -} diff --git a/kernel/src/drivers/ps2mouse.h b/kernel/src/drivers/ps2mouse.h deleted file mode 100644 index 9cd4818..0000000 --- a/kernel/src/drivers/ps2mouse.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include - -struct MouseEvent { - bool updated; - bool lmb; - bool rmb; - bool mmb; - int relx; - int rely; -}; - -void ps2mouse_init(void); - -void ps2mouse_recv(void); -struct MouseEvent ps2mouse_get(void); diff --git a/kernel/src/interrupt/idt.asm b/kernel/src/interrupt/idt.asm deleted file mode 100644 index 6cccdc6..0000000 --- a/kernel/src/interrupt/idt.asm +++ /dev/null @@ -1,99 +0,0 @@ -extern idt_exception_handler -extern idt_pic_timer -extern idt_pic_keyboard -extern idt_pic_mouse -extern idt_pic_eoi -global isr_stub_table - -%macro ISRErrorStub 1 -isr_stub_%+%1: - push dword %1 - call idt_exception_handler - pop eax - iret -%endmacro - -%macro PICGeneric 1 -isr_stub_%+%1: - push dword %1 - call idt_pic_eoi - pop eax - iret -%endmacro - -%macro PICTimer 1 -isr_stub_%+%1: - call idt_pic_timer - push dword %1 - call idt_pic_eoi - pop eax - iret -%endmacro - -%macro PICKeyboard 1 -isr_stub_%+%1: - call idt_pic_keyboard - push dword %1 - call idt_pic_eoi - pop eax - iret -%endmacro - -%macro PICMouse 1 -isr_stub_%+%1: - call idt_pic_mouse - push dword %1 - call idt_pic_eoi - pop eax - iret -%endmacro - -%macro ISRSyscall 1 -isr_stub_%+%1: - push eax - push ebx - push ecx - push edx - call idt_syscall - add esp, 16 - pop eax - iret -%endmacro - -section .text -align 8 -%assign i 0 -%rep 32 - ISRErrorStub i -%assign i i+1 -%endrep -PICTimer 32 ; 0 -PICKeyboard 33 ; 1 -PICGeneric 34 ; 2 -PICGeneric 35 ; 3 -PICGeneric 36 ; 4 -PICGeneric 37 ; 5 -PICGeneric 38 ; 6 -PICGeneric 39 ; 7 -PICGeneric 40 ; 8 -PICGeneric 41 ; 9 -PICGeneric 42 ; 10 -PICGeneric 43 ; 11 -PICMouse 44 ; 12 -PICGeneric 45 ; 13 -PICGeneric 46 ; 14 -PICGeneric 47 ; 15 -%assign i 48 -%rep 256 - 48 - ISRErrorStub i -%assign i i+1 -%endrep - -section .rodata -align 8 -isr_stub_table: -%assign i 0x00 -%rep 256 - dd isr_stub_%+i -%assign i i+0x01 -%endrep diff --git a/kernel/src/interrupt/idt.c b/kernel/src/interrupt/idt.c deleted file mode 100644 index aaa7034..0000000 --- a/kernel/src/interrupt/idt.c +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "acpi/acpi.h" -#include "drivers/ps2kb.h" -#include "drivers/ps2mouse.h" -#include "time.h" -#include "tty/color.h" -#include "idt.h" -#include "pic.h" -#include "tty/term.h" - -#define WIDTH 30 -static char buf[WIDTH]; -static int timer = -1; - -void idt_pic_eoi(uint8_t exception) { - pic_eoi(exception - PIC_REMAP_OFFSET); -} - -void idt_pic_timer(void) { - - timer += 1; - if (timer % 20 != 0) return; - - uint32_t state = term_save(); - - term_setfg(VGA_LIGHT_GREEN); - term_setpos(TERM_W - WIDTH - 1, 0); - for (size_t i = 0; i < WIDTH; i++) putchar(' '); - term_setpos(TERM_W - WIDTH - 1, 0); - - timetostr(rtc_localtime(), "%a %b %d %Y %H:%M:%S", buf, WIDTH); - printk("%s", buf); - - term_load(state); -} - -void idt_pic_keyboard(void) { - ps2kb_recv(); -} - -void idt_pic_mouse(void) { - ps2mouse_recv(); -} - -void idt_exception_handler(uint8_t exception) { - char* msg; - switch(exception) { - case 0x00: - msg = "Division by zero"; - break; - case 0x02: - msg = "NMI"; - break; - case 0x04: - msg = "Overflow"; - break; - case 0x06: - msg = "invalid opcode"; - break; - case 0x08: - msg = "double fault"; - break; - case 0x0A: - msg = "invalid task state segment"; - break; - case 0x0C: - msg = "stack segment fault"; - break; - case 0x0D: - msg = "general protection fault"; - break; - case 0x0E: - msg = "page fault"; - break; - default: - msg = "unknown exception"; - break; - } - panic("E%u: %s", exception, msg); -} - -__attribute__((aligned(0x10))) -static struct IdtEntry idt[256]; -static struct Idtr idtr; -extern void* isr_stub_table[]; - -static void set_descriptor(uint8_t vector, void* isr, uint8_t flags) { - struct IdtEntry* entry = &idt[vector]; - entry->isr_low = (size_t)isr & 0xffff; - entry->kernel_cs = 0x08; - entry->attributes = flags; - entry->isr_high = (size_t)isr >> 16; - entry->_reserved = 0; -} - -void idt_init(void) { - - debugk("Loading IDT"); - - idtr.base = (uintptr_t)&idt[0]; - idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_SIZE - 1; - - for(int i = 0; i < IDT_INTERRUPTS; i++) { - set_descriptor(i, isr_stub_table[i], 0x8e); - } - - __asm__ volatile ("lidt %0" : : "m"(idtr)); - - succek("IDT has been loaded"); -} - diff --git a/kernel/src/interrupt/idt.h b/kernel/src/interrupt/idt.h deleted file mode 100644 index 86a685f..0000000 --- a/kernel/src/interrupt/idt.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include - -#define IDT_SIZE 256 -#define IDT_INTERRUPTS 256 - -struct IdtEntry { - uint16_t isr_low; - uint16_t kernel_cs; - uint8_t _reserved; - uint8_t attributes; - uint16_t isr_high; -} __attribute__((packed)); - -struct Idtr { - uint16_t limit; - uint32_t base; -} __attribute__((packed)); - -enum IDTFlags { - IDT_FLAG_GATE_TASK = 0x5, - IDT_FLAG_GATE_16BIT_INT = 0x6, - IDT_FLAG_GATE_16BIT_TRAP = 0x7, - IDT_FLAG_GATE_32BIT_INT = 0xE, - IDT_FLAG_GATE_32BIT_TRAP = 0xF, - - IDT_FLAG_RING0 = (0 << 5), - IDT_FLAG_RING1 = (1 << 5), - IDT_FLAG_RING2 = (2 << 5), - IDT_FLAG_RING3 = (3 << 5), - - IDT_FLAG_PRESENT = 0x80, -}; - -void idt_init(void); diff --git a/kernel/src/interrupt/pic.c b/kernel/src/interrupt/pic.c deleted file mode 100644 index 86056a1..0000000 --- a/kernel/src/interrupt/pic.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include - -#include "pic.h" - -#define PIC1_COMMAND_PORT 0x20 -#define PIC1_DATA_PORT 0x21 -#define PIC2_COMMAND_PORT 0xA0 -#define PIC2_DATA_PORT 0xA1 - -void pic_remap(uint8_t offset) { - - debugk("Remapping PIC"); - - char a1 = inb(PIC1_DATA_PORT); - char a2 = inb(PIC2_DATA_PORT); - // control word 1 - // 0x11: initialize, enable ICW4 - outb(PIC1_COMMAND_PORT, 0x11); - io_wait(); - outb(PIC2_COMMAND_PORT, 0x11); - io_wait(); - // control word 2 - // interrupt offset - outb(PIC1_DATA_PORT, offset); - io_wait(); - outb(PIC2_DATA_PORT, offset + 8); - io_wait(); - // control word 3 - // primary pic: set which pin secondary is connected to - // (pin 2) - outb(PIC1_DATA_PORT, 0x04); - io_wait(); - outb(PIC2_DATA_PORT, 2); - io_wait(); - // control word 3 - // 0x01: enable 8086 mode - outb(PIC1_DATA_PORT, 0x01); - io_wait(); - outb(PIC2_DATA_PORT, 0x01); - io_wait(); - // clear data registers - outb(PIC1_DATA_PORT, a1); - outb(PIC2_DATA_PORT, a2); - - succek("PIC has been remapped to offset 0x%X", offset); -} - -void pic_mask(int irq) { - uint8_t port; - if(irq < 8) { - port = PIC1_DATA_PORT; - } else { - irq -= 8; - port = PIC2_DATA_PORT; - } - uint8_t mask = inb(port); - outb(port, mask | (1 << irq)); -} - -void pic_unmask(int irq) { - uint8_t port; - if(irq < 8) { - port = PIC1_DATA_PORT; - } else { - irq -= 8; - port = PIC2_DATA_PORT; - } - uint8_t mask = inb(port); - outb(port, mask & ~(1 << irq)); -} - -void pic_disable(void) { - outb(PIC1_DATA_PORT, 0xff); - io_wait(); - outb(PIC2_DATA_PORT, 0xff); - io_wait(); -} - -void pic_eoi(int irq) { - if(irq >= 8) { - outb(PIC2_COMMAND_PORT, 0x20); - } - outb(PIC1_COMMAND_PORT, 0x20); -} diff --git a/kernel/src/interrupt/pic.h b/kernel/src/interrupt/pic.h deleted file mode 100644 index a87420d..0000000 --- a/kernel/src/interrupt/pic.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define PIC_REMAP_OFFSET 0x20 - -void pic_remap(uint8_t offset); -void pic_mask(int irq); -void pic_unmask(int irq); -void pic_disable(void); -void pic_eoi(int irq); diff --git a/kernel/src/main.c b/kernel/src/main.c index da5879a..33e4cea 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -1,52 +1,29 @@ -#include "acpi/acpi.h" -#include "boot/tag.h" -#include "cpu/cpu.h" -#include "drivers/ps2ctrl.h" -#include "drivers/ps2kb.h" -#include "drivers/ps2mouse.h" -#include "interrupt/idt.h" -#include "interrupt/pic.h" #include "time.h" -#include "tty/cursor.h" -#include "tty/term.h" - +#include +#include +#include #include +#include #include #include #include -#include +#include static double x = 0, y = 0; -void kernel_boot(void *boot_info) { - (void)boot_info; -} - - -void kernel_main(void) { +void kernel_main(void *boot_info) { term_init(); - cursor_enable(); - - rtc_set_timezone(-4); - rtc_update(); - - idt_init(); - pic_remap(PIC_REMAP_OFFSET); - - // load_boot_info(boot_info); - // acpi_init(); - - // memory_init(); - ps2ctrl_init(); + arch_init(boot_info); ps2kb_init(); ps2mouse_init(); - init_registers(FPU_REG | SSE_REG); + set_timezone(EST); while(1) { - int_wait(); + arch_wait_int(); + arch_update(); struct Keycode code = ps2kb_get(); if(code.key != KEY_NONE) { @@ -60,7 +37,7 @@ void kernel_main(void) { } if (code.key == KEY_ESCAPE) { - acpi_poweroff(); + arch_poweroff(); } struct MouseEvent event = ps2mouse_get(); @@ -76,6 +53,5 @@ void kernel_main(void) { } term_flush(); - rtc_update(); } } diff --git a/kernel/src/memory.c b/kernel/src/memory.c new file mode 100644 index 0000000..e8d864b --- /dev/null +++ b/kernel/src/memory.c @@ -0,0 +1,310 @@ +#include +#include +#include +#include + +struct boundary_tag { + unsigned int magic; + unsigned int size; + unsigned int real_size; + int index; + + struct boundary_tag *split_left; + struct boundary_tag *split_right; + + struct boundary_tag *next; + struct boundary_tag *prev; +}; + +#define ALLOC_MAGIC 0xc001c0de +#define MAXCOMPLETE 5 +#define MAXEXP 32 +#define MINEXP 8 + +#define MODE_BEST 0 +#define MODE_INSTANT 1 + +#define MODE MODE_BEST + +struct boundary_tag* l_freePages[MAXEXP]; +int l_completePages[MAXEXP]; + +static int l_initialized = 0; +static int l_pageSize = 4096; +static int l_pageCount = 16; + +static inline int getexp(unsigned int size) { + if (size < (1< size) break; + shift += 1; + } + + return shift - 1; +} + +static inline void insert_tag(struct boundary_tag *tag, int index) { + int realIndex; + + if (index < 0) { + realIndex = getexp(tag->real_size - sizeof(struct boundary_tag)); + if (realIndex < MINEXP) realIndex = MINEXP; + } else { + realIndex = index; + } + + tag->index = realIndex; + + if (l_freePages[ realIndex ] != NULL) { + l_freePages[ realIndex ]->prev = tag; + tag->next = l_freePages[ realIndex ]; + } + + l_freePages[ realIndex ] = tag; +} + +static inline void remove_tag(struct boundary_tag *tag) { + if (l_freePages[ tag->index ] == tag) l_freePages[ tag->index ] = tag->next; + + if (tag->prev != NULL) tag->prev->next = tag->next; + if (tag->next != NULL) tag->next->prev = tag->prev; + + tag->next = NULL; + tag->prev = NULL; + tag->index = -1; +} + +static inline struct boundary_tag* melt_left(struct boundary_tag *tag) { + struct boundary_tag *left = tag->split_left; + + left->real_size += tag->real_size; + left->split_right = tag->split_right; + + if (tag->split_right != NULL) tag->split_right->split_left = left; + + return left; +} + + +static inline struct boundary_tag* absorb_right(struct boundary_tag *tag) { + struct boundary_tag *right = tag->split_right; + + remove_tag(right); + + tag->real_size += right->real_size; + + tag->split_right = right->split_right; + if (right->split_right != NULL) + right->split_right->split_left = tag; + + return tag; +} + +static inline struct boundary_tag* split_tag(struct boundary_tag* tag) { + unsigned int remainder = tag->real_size - sizeof(struct boundary_tag) - tag->size; + + struct boundary_tag *new_tag = + (struct boundary_tag*)((uintptr_t)(void *)tag + sizeof(struct boundary_tag) + tag->size); + + new_tag->magic = ALLOC_MAGIC; + new_tag->real_size = remainder; + + new_tag->next = NULL; + new_tag->prev = NULL; + + new_tag->split_left = tag; + new_tag->split_right = tag->split_right; + + if (new_tag->split_right != NULL) new_tag->split_right->split_left = new_tag; + tag->split_right = new_tag; + + tag->real_size -= new_tag->real_size; + + insert_tag(new_tag, -1); + + return new_tag; +} + +static struct boundary_tag* allocate_new_tag(unsigned int size) { + unsigned int pages; + unsigned int usage; + struct boundary_tag *tag; + + usage = size + sizeof(struct boundary_tag); + + pages = usage / l_pageSize; + if ((usage % l_pageSize) != 0) pages += 1; + + if (pages < (unsigned) l_pageCount) pages = l_pageCount; + + tag = (struct boundary_tag*)memory_alloc_page(pages); + + if (tag == NULL) return NULL; + + tag->magic = ALLOC_MAGIC; + tag->size = size; + tag->real_size = pages * l_pageSize; + tag->index = -1; + + tag->next = NULL; + tag->prev = NULL; + tag->split_left = NULL; + tag->split_right = NULL; + + return tag; +} + + + +void *malloc(size_t size) { + int index; + void *ptr; + struct boundary_tag *tag = NULL; + + memory_lock(); + + if (l_initialized == 0) { + for (index = 0; index < MAXEXP; index++) { + l_freePages[index] = NULL; + l_completePages[index] = 0; + } + l_initialized = 1; + } + + index = getexp(size) + MODE; + if (index < MINEXP) index = MINEXP; + + tag = l_freePages[index]; + while (tag != NULL) { + if ( + (tag->real_size - sizeof(struct boundary_tag)) + >= (size + sizeof(struct boundary_tag)) + ) { + break; + } + tag = tag->next; + } + + if (tag == NULL) { + if ((tag = allocate_new_tag(size)) == NULL) { + memory_unlock(); + return NULL; + } + index = getexp(tag->real_size - sizeof(struct boundary_tag)); + } else { + remove_tag(tag); + + if ((tag->split_left == NULL) && (tag->split_right == NULL)) + l_completePages[ index ] -= 1; + } + + tag->size = size; + + unsigned int remainder = tag->real_size - size - sizeof(struct boundary_tag) * 2; + + if (((int)(remainder) > 0)) { + int childIndex = getexp(remainder); + + if (childIndex >= 0) { + struct boundary_tag *new_tag = split_tag(tag); + tag = new_tag; + } + } + + ptr = (void*)((uintptr_t)(void *)tag + sizeof(struct boundary_tag)); + memory_unlock(); + return ptr; +} + +void free(void *ptr) { + int index; + struct boundary_tag *tag; + + if (ptr == NULL) return; + + memory_lock(); + + tag = (struct boundary_tag*)((uintptr_t)(void *)ptr - sizeof(struct boundary_tag)); + + if (tag->magic != ALLOC_MAGIC) { + memory_unlock(); + return; + } + + while ((tag->split_left != NULL) && (tag->split_left->index >= 0)) { + tag = melt_left(tag); + remove_tag(tag); + } + + while ((tag->split_right != NULL) && (tag->split_right->index >= 0)) { + tag = absorb_right(tag); + } + + index = getexp(tag->real_size - sizeof(struct boundary_tag)); + if (index < MINEXP) index = MINEXP; + + if ((tag->split_left == NULL) && (tag->split_right == NULL)) { + if (l_completePages[index] == MAXCOMPLETE) { + unsigned int pages = tag->real_size / l_pageSize; + + if ((tag->real_size % l_pageSize) != 0) pages += 1; + if (pages < (unsigned) l_pageCount) pages = l_pageCount; + + memory_free_page(tag, pages); + memory_unlock(); + return; + } + + l_completePages[ index ] += 1; + } + + insert_tag(tag, index); + + memory_unlock(); +} + +void* calloc(size_t nobj, size_t size) { + int real_size; + void *p; + + real_size = nobj * size; + + p = malloc(real_size); + + memset(p, 0, real_size); + + return p; +} + +void* realloc(void *p, size_t size) { + void *ptr; + struct boundary_tag *tag; + size_t real_size; + + if (size == 0) { + free(p); + return NULL; + } + + if (p == NULL) { + return malloc(size); + } + + memory_lock(); + tag = (struct boundary_tag*)((uintptr_t)(void *)p - sizeof(struct boundary_tag)); + real_size = tag->size; + memory_unlock(); + + if (real_size > size) real_size = size; + + ptr = malloc(size); + memcpy(ptr, p, real_size); + free(p); + + return ptr; +} diff --git a/kernel/src/memory/allocator.c b/kernel/src/memory/allocator.c deleted file mode 100644 index 6217ad4..0000000 --- a/kernel/src/memory/allocator.c +++ /dev/null @@ -1,314 +0,0 @@ -#include -#include -#include - -struct boundary_tag { - unsigned int magic; - unsigned int size; - unsigned int real_size; - int index; - - struct boundary_tag *split_left; - struct boundary_tag *split_right; - - struct boundary_tag *next; - struct boundary_tag *prev; -}; - -extern int memory_lock(void); -extern int memory_unlock(void); -extern void *memory_alloc_page(int); -extern int memory_free_page(void* ,int); - -#define ALLOC_MAGIC 0xc001c0de -#define MAXCOMPLETE 5 -#define MAXEXP 32 -#define MINEXP 8 - -#define MODE_BEST 0 -#define MODE_INSTANT 1 - -#define MODE MODE_BEST - -struct boundary_tag* l_freePages[MAXEXP]; -int l_completePages[MAXEXP]; - -static int l_initialized = 0; -static int l_pageSize = 4096; -static int l_pageCount = 16; - -static inline int getexp(unsigned int size) { - if (size < (1< size) break; - shift += 1; - } - - return shift - 1; -} - -static inline void insert_tag(struct boundary_tag *tag, int index) { - int realIndex; - - if (index < 0) { - realIndex = getexp(tag->real_size - sizeof(struct boundary_tag)); - if (realIndex < MINEXP) realIndex = MINEXP; - } else { - realIndex = index; - } - - tag->index = realIndex; - - if (l_freePages[ realIndex ] != NULL) { - l_freePages[ realIndex ]->prev = tag; - tag->next = l_freePages[ realIndex ]; - } - - l_freePages[ realIndex ] = tag; -} - -static inline void remove_tag(struct boundary_tag *tag) { - if (l_freePages[ tag->index ] == tag) l_freePages[ tag->index ] = tag->next; - - if (tag->prev != NULL) tag->prev->next = tag->next; - if (tag->next != NULL) tag->next->prev = tag->prev; - - tag->next = NULL; - tag->prev = NULL; - tag->index = -1; -} - -static inline struct boundary_tag* melt_left(struct boundary_tag *tag) { - struct boundary_tag *left = tag->split_left; - - left->real_size += tag->real_size; - left->split_right = tag->split_right; - - if (tag->split_right != NULL) tag->split_right->split_left = left; - - return left; -} - - -static inline struct boundary_tag* absorb_right(struct boundary_tag *tag) { - struct boundary_tag *right = tag->split_right; - - remove_tag(right); - - tag->real_size += right->real_size; - - tag->split_right = right->split_right; - if (right->split_right != NULL) - right->split_right->split_left = tag; - - return tag; -} - -static inline struct boundary_tag* split_tag(struct boundary_tag* tag) { - unsigned int remainder = tag->real_size - sizeof(struct boundary_tag) - tag->size; - - struct boundary_tag *new_tag = - (struct boundary_tag*)((uintptr_t)(void *)tag + sizeof(struct boundary_tag) + tag->size); - - new_tag->magic = ALLOC_MAGIC; - new_tag->real_size = remainder; - - new_tag->next = NULL; - new_tag->prev = NULL; - - new_tag->split_left = tag; - new_tag->split_right = tag->split_right; - - if (new_tag->split_right != NULL) new_tag->split_right->split_left = new_tag; - tag->split_right = new_tag; - - tag->real_size -= new_tag->real_size; - - insert_tag(new_tag, -1); - - return new_tag; -} - -static struct boundary_tag* allocate_new_tag(unsigned int size) { - unsigned int pages; - unsigned int usage; - struct boundary_tag *tag; - - usage = size + sizeof(struct boundary_tag); - - pages = usage / l_pageSize; - if ((usage % l_pageSize) != 0) pages += 1; - - if (pages < (unsigned) l_pageCount) pages = l_pageCount; - - tag = (struct boundary_tag*)memory_alloc_page(pages); - - if (tag == NULL) return NULL; - - tag->magic = ALLOC_MAGIC; - tag->size = size; - tag->real_size = pages * l_pageSize; - tag->index = -1; - - tag->next = NULL; - tag->prev = NULL; - tag->split_left = NULL; - tag->split_right = NULL; - - return tag; -} - - - -void *malloc(size_t size) { - int index; - void *ptr; - struct boundary_tag *tag = NULL; - - memory_lock(); - - if (l_initialized == 0) { - for (index = 0; index < MAXEXP; index++) { - l_freePages[index] = NULL; - l_completePages[index] = 0; - } - l_initialized = 1; - } - - index = getexp(size) + MODE; - if (index < MINEXP) index = MINEXP; - - tag = l_freePages[index]; - while (tag != NULL) { - if ( - (tag->real_size - sizeof(struct boundary_tag)) - >= (size + sizeof(struct boundary_tag)) - ) { - break; - } - tag = tag->next; - } - - if (tag == NULL) { - if ((tag = allocate_new_tag(size)) == NULL) { - memory_unlock(); - return NULL; - } - index = getexp(tag->real_size - sizeof(struct boundary_tag)); - } else { - remove_tag(tag); - - if ((tag->split_left == NULL) && (tag->split_right == NULL)) - l_completePages[ index ] -= 1; - } - - tag->size = size; - - unsigned int remainder = tag->real_size - size - sizeof(struct boundary_tag) * 2; - - if (((int)(remainder) > 0)) { - int childIndex = getexp(remainder); - - if (childIndex >= 0) { - struct boundary_tag *new_tag = split_tag(tag); - tag = new_tag; - } - } - - ptr = (void*)((uintptr_t)(void *)tag + sizeof(struct boundary_tag)); - memory_unlock(); - return ptr; -} - -void free(void *ptr) { - int index; - struct boundary_tag *tag; - - if (ptr == NULL) return; - - memory_lock(); - - tag = (struct boundary_tag*)((uintptr_t)(void *)ptr - sizeof(struct boundary_tag)); - - if (tag->magic != ALLOC_MAGIC) { - memory_unlock(); - return; - } - - while ((tag->split_left != NULL) && (tag->split_left->index >= 0)) { - tag = melt_left(tag); - remove_tag(tag); - } - - while ((tag->split_right != NULL) && (tag->split_right->index >= 0)) { - tag = absorb_right(tag); - } - - index = getexp(tag->real_size - sizeof(struct boundary_tag)); - if (index < MINEXP) index = MINEXP; - - if ((tag->split_left == NULL) && (tag->split_right == NULL)) { - if (l_completePages[index] == MAXCOMPLETE) { - unsigned int pages = tag->real_size / l_pageSize; - - if ((tag->real_size % l_pageSize) != 0) pages += 1; - if (pages < (unsigned) l_pageCount) pages = l_pageCount; - - memory_free_page(tag, pages); - memory_unlock(); - return; - } - - l_completePages[ index ] += 1; - } - - insert_tag(tag, index); - - memory_unlock(); -} - -void* calloc(size_t nobj, size_t size) { - int real_size; - void *p; - - real_size = nobj * size; - - p = malloc(real_size); - - memset(p, 0, real_size); - - return p; -} - -void* realloc(void *p, size_t size) { - void *ptr; - struct boundary_tag *tag; - size_t real_size; - - if (size == 0) { - free(p); - return NULL; - } - - if (p == NULL) { - return malloc(size); - } - - memory_lock(); - tag = (struct boundary_tag*)((uintptr_t)(void *)p - sizeof(struct boundary_tag)); - real_size = tag->size; - memory_unlock(); - - if (real_size > size) real_size = size; - - ptr = malloc(size); - memcpy(ptr, p, real_size); - free(p); - - return ptr; -} diff --git a/kernel/src/memory/memory.c b/kernel/src/memory/memory.c deleted file mode 100644 index 30da0fc..0000000 --- a/kernel/src/memory/memory.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include -#include - -#include "memory.h" -#include "boot/tag.h" -#include "print.h" - -struct MemoryArea { - uint32_t len; - struct MemoryArea *prev; - struct MemoryArea *next; -}; - -typedef unsigned char page[4096]; - -extern unsigned char kernel_start, kernel_end; -static uintptr_t kernel_start_addr, kernel_end_addr; -static uint32_t *bitmap; -static uint32_t total_memory; -static uint32_t free_memory; -static uint32_t page_count; -static uint32_t page_free_start; -static struct MemoryArea *page_start; - -int memory_lock(void) { - int_disable(); - return 0; -} - -int memory_unlock(void) { - int_enable(); - return 0; -} - -static int n_pages(const struct MemoryArea *m) { - return (m->len - sizeof(*m)) / sizeof(page); -} - -static void *page_at(int i) { - int cur_page = 0; - for (struct MemoryArea *m = page_start; m != NULL; m = m->next) { - int pages = n_pages(m); - if (i - cur_page < pages) { - page *page_array = (page *) (m + 1); - return page_array[i - cur_page]; - } - cur_page += pages; - } - return NULL; -} - -static int page_idx(page p) { - uintptr_t addr = (uintptr_t) p; - int cur_page = 0; - for (struct MemoryArea *m = page_start; m != NULL; m = m->next) { - if ((uintptr_t) m + m->len > addr) { - return cur_page + (addr - (uintptr_t) m) / sizeof(page); - } - cur_page += n_pages(m); - } - return -1; -} - -static inline bool bitmap_get(int i) { - return (bitmap[i / 32] >> i % 32) & 1; -} - -static inline void bitmap_set(int i, bool v) { - int idx = i / 32; - bitmap[idx] &= ~(1 << i % 32); - bitmap[idx] |= (v << i % 32); -} - -void *memory_alloc_page(int pages) { - if (pages < 1) return NULL; - - int n_contiguous = 0; - int free_region_start = 0; - bool first = true; - for (uint32_t i = page_free_start; i < page_count; i++) { - bool free = !bitmap_get(i); - - if (first) { - first = false; - page_free_start = i; - } - - if (free) { - if (n_contiguous == 0) free_region_start = i; - n_contiguous++; - if (n_contiguous == pages) { - for (int j = 0; j < pages; j++) - bitmap_set(free_region_start + j, true); - return page_at(free_region_start); - } - } else n_contiguous = 0; - } - - return NULL; -} - -int memory_free_page(void *ptr, int pages) { - int idx = page_idx(ptr); - if (idx == -1) return 1; - - if ((unsigned) idx < page_free_start) page_free_start = idx; - - for (int i = 0; i < pages; i++) - bitmap_set(idx + pages, false); - return 0; -} - -void memory_init(void) { - - debugk("Loading memory pages"); - - memory_lock(); - - bitmap = NULL; - total_memory = 0; - free_memory = 0; - page_count = 0; - page_free_start = 0; - page_start = NULL; - - kernel_start_addr = (uintptr_t) &kernel_start; - kernel_end_addr = (uintptr_t) &kernel_end; - - struct BootTag *tag; - if (!get_boot_tag(iD_MEMORYMAP, &tag)) { - panic("No multiboot memory map found"); - } - - uintptr_t end = (uintptr_t) tag->data.memory_map; - end += tag->size; - - struct MemoryArea *prev = NULL; - struct MemorySegment *segment = &tag->data.memory_map->entries[0]; - for(; (uintptr_t) segment < end; segment++) { - - if (segment->type != 1) continue; - if (segment->addr >= UINT32_MAX) continue; - if (segment->addr < kernel_start_addr) continue; - - uint32_t length; - if (segment->addr + segment->len > UINT32_MAX) { - length = UINT32_MAX - segment->addr; - } else { - length = segment->len; - } - - uintptr_t addr; - if (segment->addr < kernel_end_addr) { - addr = kernel_end_addr; - length -= addr - segment->addr; - } else { - addr = segment->addr; - } - - struct MemoryArea *current = (struct MemoryArea *) addr; - current->prev = prev; - current->next = NULL; - current->len = length; - - if (prev != NULL) { - prev->next = current; - } else { - page_start = current; - } - - page_count += n_pages(current); - total_memory += length; - - prev = current; - - } - - int bitmap_pages = page_count / 32 / sizeof(page) + 1; - bitmap = (uint32_t *) page_at(page_count - bitmap_pages); - page_count -= bitmap_pages; - memset(bitmap, 0, bitmap_pages * sizeof(page)); - free_memory = page_count * sizeof(page); - - memory_unlock(); - - succek("Memory loaded. %k total %k free", total_memory, free_memory); - -} - -uint32_t memory_total(void) { - return total_memory; -} - -uint32_t memory_free(void) { - return free_memory; -} - -uint32_t memory_used(void) { - return total_memory - free_memory; -} diff --git a/kernel/src/memory/memory.h b/kernel/src/memory/memory.h deleted file mode 100644 index 5d99025..0000000 --- a/kernel/src/memory/memory.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -struct MemorySegment { - uint64_t addr; - uint64_t len; - uint32_t type; - uint32_t reserved; -} __attribute__((packed)); - -struct MemoryMap { - uint32_t entry_size; - uint32_t entry_version; - struct MemorySegment entries[]; -} __attribute__((packed)); - -uint32_t memory_total(void); -uint32_t memory_free(void); -uint32_t memory_used(void); - -void memory_init(void); diff --git a/kernel/src/panic.c b/kernel/src/panic.c new file mode 100644 index 0000000..96ad3b9 --- /dev/null +++ b/kernel/src/panic.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include + +__attribute__((noreturn)) +void _panic_impl(char* msg, int line, char* file, ...) { + arch_disable_int(); + va_list args; + va_start(args, file); + term_clear(); + term_setpos(0, 0); + term_setfg(VGA_LIGHT_RED); + puts("!!!PANIC!!!\n"); + term_setfg(VGA_WHITE); + vprintk(msg, args); + if (!term_newline()) putchar('\n'); + printk("\nin %s at line %d\n", file, line); + term_flush(); + while(1) { + arch_halt(); + } +} diff --git a/kernel/src/print.c b/kernel/src/print.c new file mode 100644 index 0000000..12f45de --- /dev/null +++ b/kernel/src/print.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include + +void printk(const char *restrict format, ...) { + va_list args; + va_start(args, format); + vprintk(format, args); + va_end(args); +} + +void vprintk(const char *restrict format, va_list args) { + char buf[80]; + for (; *format; format++) { + if (*format == '%') { + bool l = false; + char c = *++format; + if (c == 'l') { + l = true; + c = *++format; + } + switch(c) { + case '%': + putchar('%'); + break; + case 's': + puts(va_arg(args, char*)); + break; + case 'c': + putchar(va_arg(args, int)); + break; + case 'd': + if (l) ltoa(va_arg(args, long long), buf, 10); + else itoa(va_arg(args, int), buf, 10); + puts(buf); + break; + case 'u': + if (l) ultoa(va_arg(args, unsigned long long), buf, 10); + else utoa(va_arg(args, unsigned int), buf, 10); + puts(buf); + break; + case 'f': + case 'F': + ftoa(va_arg(args, double), buf); + puts(buf); + break; + case 'x': + case 'X': + utoa(va_arg(args, unsigned int), buf, 16); + puts(buf); + break; + case 'b': + va_arg(args, int) ? puts("true") : puts("false"); + break; + case 'k': { + static char disp[] = {'B', 'K', 'M', 'G'}; + uint32_t size = va_arg(args, unsigned int); + size_t i = 0; + while (size / 1024 > 0) { + size /= 1024; + i++; + } + utoa(size, buf, 10); + puts(buf); + putchar(disp[i]); + if (i > 0) putchar('B'); + break; + } + default: + break; + } + } else { + putchar(*format); + } + } +} + +void puts(const char *s) { + for(; *s; s++) putchar(*s); +} diff --git a/kernel/src/print/panic.c b/kernel/src/print/panic.c deleted file mode 100644 index 58ffe40..0000000 --- a/kernel/src/print/panic.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include -#include -#include - -#include "tty/color.h" -#include "tty/term.h" - -__attribute__((noreturn)) -void _panic_impl(char* msg, int line, char* file, ...) { - int_disable(); - va_list args; - va_start(args, file); - term_clear(); - term_setpos(0, 0); - term_setfg(VGA_LIGHT_RED); - puts("!!!PANIC!!!\n"); - term_setfg(VGA_WHITE); - vprintk(msg, args); - if (!term_newline()) putchar('\n'); - printk("\nin %s at line %d\n", file, line); - term_flush(); - while(1) { - halt(); - } -} diff --git a/kernel/src/print/print.c b/kernel/src/print/print.c deleted file mode 100644 index 46ec047..0000000 --- a/kernel/src/print/print.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "tty/color.h" -#include "tty/term.h" -#include -#include -#include -#include -#include - -void printk(const char *restrict format, ...) { - va_list args; - va_start(args, format); - vprintk(format, args); - va_end(args); -} - -void vprintk(const char *restrict format, va_list args) { - char buf[80]; - for (; *format; format++) { - if (*format == '%') { - bool l = false; - char c = *++format; - if (c == 'l') { - l = true; - c = *++format; - } - switch(c) { - case '%': - putchar('%'); - break; - case 's': - puts(va_arg(args, char*)); - break; - case 'c': - putchar(va_arg(args, int)); - break; - case 'd': - if (l) ltoa(va_arg(args, long long), buf, 10); - else itoa(va_arg(args, int), buf, 10); - puts(buf); - break; - case 'u': - if (l) ultoa(va_arg(args, unsigned long long), buf, 10); - else utoa(va_arg(args, unsigned int), buf, 10); - puts(buf); - break; - case 'f': - case 'F': - ftoa(va_arg(args, double), buf); - puts(buf); - break; - case 'x': - case 'X': - utoa(va_arg(args, unsigned int), buf, 16); - puts(buf); - break; - case 'b': - va_arg(args, int) ? puts("true") : puts("false"); - break; - case 'k': { - static char disp[] = {'B', 'K', 'M', 'G'}; - uint32_t size = va_arg(args, unsigned int); - size_t i = 0; - while (size / 1024 > 0) { - size /= 1024; - i++; - } - utoa(size, buf, 10); - puts(buf); - putchar(disp[i]); - if (i > 0) putchar('B'); - break; - } - default: - break; - } - } else { - putchar(*format); - } - } -} - -void puts(const char *s) { - for(; *s; s++) putchar(*s); -} - -void printl(enum VGAColor color, const char* msg) { - term_setbg(VGA_BLACK); - term_setfg(VGA_WHITE); - putchar('['); - term_setfg(color); - printk("%s", msg); - term_setfg(VGA_WHITE); - putchar(']'); - putchar(' '); -} - -void _debugk_impl(char *format, ...) { - uint16_t color = term_save_col(); - printl(VGA_LIGHT_CYAN, "LOG"); - va_list args; - va_start(args, format); - vprintk(format, args); - va_end(args); - if (!term_newline()) putchar('\n'); - term_load_col(color); -} - -void _succek_impl(char *format, ...) { - uint16_t color = term_save_col(); - printl(VGA_LIGHT_GREEN, "OK"); - va_list args; - va_start(args, format); - vprintk(format, args); - va_end(args); - if (!term_newline()) putchar('\n'); - term_load_col(color); -} - -void _errork_impl(char *format, ...) { - uint16_t color = term_save_col(); - printl(VGA_LIGHT_RED, "ERR"); - va_list args; - va_start(args, format); - vprintk(format, args); - va_end(args); - if (!term_newline()) putchar('\n'); - term_load_col(color); -} diff --git a/kernel/src/print/time.c b/kernel/src/print/time.c deleted file mode 100644 index 7f52a98..0000000 --- a/kernel/src/print/time.c +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include - -static char* ABB_WEEKDAY[7] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -static char* FULL_WEEKDAY[7] = { - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturady" -}; - -static char* ABB_MONTH[12] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static char* FULL_MONTH[12] = { - "January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" -}; - -static char *write_num(unsigned int num, unsigned int pad, char *buf, size_t n) { - size_t digits = 1; - unsigned int x = num; - - while (x /= 10, x > 0) digits++; - if (pad == 0) pad = digits; - - for (size_t i = 0; i < pad; i++) { - - size_t digit; - if (i >= digits) { - digit = 0; - } else { - digit = num % 10; - num /= 10; - } - - if (pad - i - 1 >= n) continue; - buf[pad - i - 1] = '0' + digit; - - } - - if (pad > n) pad = n; - - return buf + pad; -} - -void timetostr(struct Time *time, char *format, char *buf, size_t n) { - char *index = buf; - char c; - int space; - - while ( - c = *format++, - space = (buf + n) - index, - c != '\0' && space > 0 - ) { - if (c != '%') { - *index++ = c; - continue; - } else { - c = *format++; - } - - switch (c) { - case '%': - *index++ = '%'; - break; - case 'a': - index = strncpy(index, ABB_WEEKDAY[time->wday], space); - break; - case 'A': - index = strncpy(index, FULL_WEEKDAY[time->wday], space); - break; - case 'b': - case 'h': - index = strncpy(index, ABB_MONTH[time->mon], space); - break; - case 'B': - index = strncpy(index, FULL_MONTH[time->mon], space); - break; - case 'C': - index = write_num(time->cen, 0, index, space); - break; - case 'd': - index = write_num(time->mday, 2, index, space); - break; - case 'H': - index = write_num(time->hour, 2, index, space); - break; - case 'I': - index = write_num((time->hour + 12) % 12 + 1, 2, index, space); - break; - case 'j': - index = write_num(time->yday, 3, index, space); - break; - case 'm': - index = write_num(time->mon + 1, 2, index, space); - break; - case 'M': - index = write_num(time->min, 2, index, space); - break; - case 'n': - *index++ = '\n'; - break; - case 'p': - index = strncpy(index, time->hour > 11 ? "PM" : "AM", space); - break; - case 'P': - index = strncpy(index, time->hour > 11 ? "pm" : "am", space); - break; - case 'q': - index = write_num((time->mon + 3) / 3, 0, index, space); - break; - case 'S': - index = write_num(time->sec, 2, index, space); - break; - case 't': - *index++ = '\t'; - break; - case 'u': - index = write_num(((time->wday + 1 )% 7) + 1, 0, index, space); - break; - case 'w': - index = write_num(time->wday, 0, index, space); - break; - case 'y': - index = write_num(time->yn, 2, index, space); - break; - case 'Y': - index = write_num(time->year + 1900, 0, index, space); - break; - default: { - char b[3] = {'%', c, '\0'}; - index = strncpy(index, b, space); - break; - } - } - } - - if (space < 1) - buf[n - 1] = '\0'; - else - *index = '\0'; -} diff --git a/kernel/src/start.asm b/kernel/src/start.asm deleted file mode 100644 index c01cbaa..0000000 --- a/kernel/src/start.asm +++ /dev/null @@ -1,135 +0,0 @@ -global start -extern kernel_boot -extern kernel_main -extern kernel_start -extern kernel_end -bits 32 - -; base, limit, access, flags -%macro gdt_entry 4 - db %2 & 0xff - db (%2 >> 8) & 0xff - db %1 & 0xff - db (%1 >> 8) & 0xff - db (%1 >> 16) & 0xff - db %3 - db ((%2 >> 16) & 0x0f) | (%4 << 4) - db (%1 >> 24) & 0xff -%endmacro - -MAGIC equ 0xe85250d6 -FLAGS equ 0 -LENGTH equ mb_end - mb_start -CHECKSUM equ -(MAGIC + LENGTH) - -VGABUF equ 0x000B8000 -KRNMAP equ 0xC0000000 - -section .multiboot.data -align 8 -mb_start: -dd MAGIC -dd FLAGS -dd LENGTH -dd CHECKSUM -dw 0 -dw 0 -dd 8 -mb_end: - -section .rodata -align 16 -gdt_start: -gdt_entry 0, 0, 0, 0 -gdt_entry 0, 0xFFFFF, 0x9A, 0xC -gdt_entry 0, 0xFFFFF, 0x92, 0xC -gdt_end: -gdt_descriptor: - dw gdt_end - gdt_start - 1 - dd gdt_start - -section .bootstrap_stack -align 16 -stack_start: -resb 16384 ; 16 KiB -stack_end: - -section .bss -align 4096 -page_directory: -resb 4096 -page_table1: -resb 4096 - -section .multiboot.text -align 8 -start: - - ; push ebx - ; call kernel_boot - ; pop eax - - mov edi, page_table1 - KRNMAP - mov esi, 0 - mov ecx, 1023 - -paging_cmp: - cmp esi, kernel_start - jl paging_add - cmp esi, kernel_end - KRNMAP - jge paging_map - - mov edx, esi - or edx, 0x003 - mov [edi], edx - -paging_add: - add esi, 4096 - add edi, 4 - loop paging_cmp - -paging_map: - mov dword [page_table1 - KRNMAP + 1023 * 4], VGABUF | 0x003 - mov dword [page_directory - KRNMAP + 0], page_table1 - KRNMAP + 0x003 - mov dword [page_directory - KRNMAP + 768 * 4], page_table1 - KRNMAP + 0x003 - - mov ecx, page_directory - KRNMAP - mov cr3, ecx - - mov ecx, cr0 - or ecx, 0x80010000 - mov cr0, ecx - - lea ecx, load_gdt - jmp near ecx - -section .text -align 8 -load_gdt: - cli - lgdt [gdt_descriptor] - mov eax, cr0 - or al, 1 - mov cr0, eax - jmp 0x08:load_kernel - -load_kernel: - - mov dword [page_directory], 0 - mov ecx, cr3 - mov cr3, ecx - - mov ax, 0x10 - mov ds, ax - mov ss, ax - mov es, ax - mov fs, ax - mov gs, ax - mov esp, stack_end - mov ebp, stack_end - sti - call kernel_main - cli -halt: - hlt - jmp halt diff --git a/kernel/src/term.c b/kernel/src/term.c new file mode 100644 index 0000000..4b42a6a --- /dev/null +++ b/kernel/src/term.c @@ -0,0 +1,135 @@ + +#include +#include +#include +#include +#include + +#include "drivers/vga.h" +#include "term.h" + +uint16_t buffer[TERM_W * TERM_H * sizeof(uint16_t)]; +uint8_t x, y; +uint8_t color; + +const uint16_t blank = (uint16_t) 0 | VGA_BLACK << 12 | VGA_WHITE << 8; + +static void term_clear_line(int y) { + if (y < 0 || y >= TERM_H) + return; + for (uint8_t x = 0; x < TERM_W; x++) { + const size_t index = y * TERM_W + x; + buffer[index] = blank; + } +} + +void term_init (void) { + x = 0; + y = 0; + term_setfg(VGA_WHITE); + term_setbg(VGA_BLACK); + term_clear(); +} + +void term_setpos(uint8_t xp, uint8_t yp) { + x = xp; + y = yp; + vgatext_cur_mov(x, y); +} + +void term_scroll (int lines) { + arch_disable_int(); + y -= lines; + if (!lines) return; + if(lines >= TERM_H || lines <= -TERM_H) { + term_clear(); + } else if(lines > 0) { + memmove(buffer, buffer + lines * TERM_W, 2 * (TERM_H - lines) * TERM_W); + term_clear_line(TERM_H - lines); + } else { + memmove(buffer + lines * TERM_W, buffer + lines, (TERM_H + lines) * TERM_W); + } + arch_enable_int(); +} + +void term_setfg(enum vga_color c) { + color = (color & 0xF0) | c; +} + +void term_setbg(enum vga_color c) { + color = (color & 0x0F) | c << 4; +} + +void term_clear (void) { + for (uint8_t y = 0; y < TERM_H; y++) + term_clear_line(y); +} + +uint32_t term_save(void) { + uint32_t state = 0; + state |= (uint32_t) x << 16; + state |= (uint32_t) y << 8; + state |= (uint32_t) color << 0; + return state; +} + +void term_load(uint32_t state) { + x = (uint8_t) (state >> 16); + y = (uint8_t) (state >> 8); + color = (uint8_t) (state >> 0); + vgatext_cur_mov(x, y); +} + +uint16_t term_save_col(void) { + return color; +} + +void term_load_col(uint16_t c) { + color = c; +} + +void putchar(int c) { + switch (c) { + case '\n': + x = 0; + y++; + break; + case '\t': + x += 4; + break; + case '\v': + case '\f': + y++; + break; + case '\r': + x = 0; + break; + default: { + const size_t index = y * TERM_W + x; + buffer[index] = c | (uint16_t) color << 8; + x++; + } + } + + if (x >= TERM_W) { + x = 0; + y++; + } + + if (y >= TERM_H) { + term_scroll(y - (TERM_H - 1)); + y = TERM_H - 1; + } + + vgatext_cur_mov(x, y); +} + +bool term_newline(void) { + return x == 0; +} + +void term_flush(void) { + arch_disable_int(); + vgatext_write_buf(buffer); + arch_enable_int(); +} diff --git a/kernel/src/time.c b/kernel/src/time.c new file mode 100644 index 0000000..e949882 --- /dev/null +++ b/kernel/src/time.c @@ -0,0 +1,144 @@ +#include +#include + +static char* ABB_WEEKDAY[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static char* FULL_WEEKDAY[7] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturady" +}; + +static char* ABB_MONTH[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static char* FULL_MONTH[12] = { + "January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" +}; + +static char *write_num(unsigned int num, unsigned int pad, char *buf, size_t n) { + size_t digits = 1; + unsigned int x = num; + + while (x /= 10, x > 0) digits++; + if (pad == 0) pad = digits; + + for (size_t i = 0; i < pad; i++) { + + size_t digit; + if (i >= digits) { + digit = 0; + } else { + digit = num % 10; + num /= 10; + } + + if (pad - i - 1 >= n) continue; + buf[pad - i - 1] = '0' + digit; + + } + + if (pad > n) pad = n; + + return buf + pad; +} + +void timetostr(struct Time *time, char *format, char *buf, size_t n) { + char *index = buf; + char c; + int space; + + while ( + c = *format++, + space = (buf + n) - index, + c != '\0' && space > 0 + ) { + if (c != '%') { + *index++ = c; + continue; + } else { + c = *format++; + } + + switch (c) { + case '%': + *index++ = '%'; + break; + case 'a': + index = strncpy(index, ABB_WEEKDAY[time->wday], space); + break; + case 'A': + index = strncpy(index, FULL_WEEKDAY[time->wday], space); + break; + case 'b': + case 'h': + index = strncpy(index, ABB_MONTH[time->mon], space); + break; + case 'B': + index = strncpy(index, FULL_MONTH[time->mon], space); + break; + case 'C': + index = write_num(time->cen, 0, index, space); + break; + case 'd': + index = write_num(time->mday, 2, index, space); + break; + case 'H': + index = write_num(time->hour, 2, index, space); + break; + case 'I': + index = write_num((time->hour + 12) % 12 + 1, 2, index, space); + break; + case 'j': + index = write_num(time->yday, 3, index, space); + break; + case 'm': + index = write_num(time->mon + 1, 2, index, space); + break; + case 'M': + index = write_num(time->min, 2, index, space); + break; + case 'n': + *index++ = '\n'; + break; + case 'p': + index = strncpy(index, time->hour > 11 ? "PM" : "AM", space); + break; + case 'P': + index = strncpy(index, time->hour > 11 ? "pm" : "am", space); + break; + case 'q': + index = write_num((time->mon + 3) / 3, 0, index, space); + break; + case 'S': + index = write_num(time->sec, 2, index, space); + break; + case 't': + *index++ = '\t'; + break; + case 'u': + index = write_num(((time->wday + 1 )% 7) + 1, 0, index, space); + break; + case 'w': + index = write_num(time->wday, 0, index, space); + break; + case 'y': + index = write_num(time->yn, 2, index, space); + break; + case 'Y': + index = write_num(time->year + 1900, 0, index, space); + break; + default: { + char b[3] = {'%', c, '\0'}; + index = strncpy(index, b, space); + break; + } + } + } + + if (space < 1) + buf[n - 1] = '\0'; + else + *index = '\0'; +} diff --git a/kernel/src/tty/color.c b/kernel/src/tty/color.c deleted file mode 100644 index c7258d9..0000000 --- a/kernel/src/tty/color.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "color.h" -#include "panic.h" - -bool itoac(int i, enum AnsiiColor *color) { - if (i < 0 || i > 15) return false; - *color = i; - return true; -} - -bool itovc(int i, enum VGAColor *color) { - if ( - (i >= 30 && i <= 37) || - (i >= 40 && i <= 47) || - (i >= 90 && i <= 97) || - (i >= 100 && i <= 107) - ) { - *color = i; - return true; - } - return false; -} - -enum VGAColor atovc(enum AnsiiColor color) { - switch(color) { - case ANSII_FRONT_BLACK: - case ANSII_FRONT_BLACK_EMPH: - case ANSII_BACK_BLACK: - case ANSII_BACK_BLACK_EMPH: - return VGA_BLACK; - case ANSII_FRONT_RED: - case ANSII_FRONT_RED_EMPH: - case ANSII_BACK_RED: - case ANSII_BACK_RED_EMPH: - return VGA_LIGHT_RED; - case ANSII_FRONT_GREEN: - case ANSII_FRONT_GREEN_EMPH: - case ANSII_BACK_GREEN: - case ANSII_BACK_GREEN_EMPH: - return VGA_LIGHT_GREEN; - case ANSII_FRONT_YELLOW: - case ANSII_FRONT_YELLOW_EMPH: - case ANSII_BACK_YELLOW: - case ANSII_BACK_YELLOW_EMPH: - return VGA_LIGHT_BROWN; - case ANSII_FRONT_BLUE: - case ANSII_FRONT_BLUE_EMPH: - case ANSII_BACK_BLUE: - case ANSII_BACK_BLUE_EMPH: - return VGA_LIGHT_BLUE; - case ANSII_FRONT_PURPLE: - case ANSII_FRONT_PURPLE_EMPH: - case ANSII_BACK_PURPLE: - case ANSII_BACK_PURPLE_EMPH: - return VGA_LIGHT_MAGENTA; - case ANSII_FRONT_CYAN: - case ANSII_FRONT_CYAN_EMPH: - case ANSII_BACK_CYAN: - case ANSII_BACK_CYAN_EMPH: - return VGA_LIGHT_CYAN; - case ANSII_FRONT_WHITE: - case ANSII_FRONT_WHITE_EMPH: - case ANSII_BACK_WHITE: - case ANSII_BACK_WHITE_EMPH: - return VGA_WHITE; - } - panic("this should not be reached (make gcc quiet)"); -} diff --git a/kernel/src/tty/color.h b/kernel/src/tty/color.h deleted file mode 100644 index 0751353..0000000 --- a/kernel/src/tty/color.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include -#include - -enum VGAColor { - VGA_BLACK = 0, - VGA_BLUE = 1, - VGA_GREEN = 2, - VGA_CYAN = 3, - VGA_RED = 4, - VGA_MAGENTA = 5, - VGA_BROWN = 6, - VGA_LIGHT_GREY = 7, - VGA_DARK_GREY = 8, - VGA_LIGHT_BLUE = 9, - VGA_LIGHT_GREEN = 10, - VGA_LIGHT_CYAN = 11, - VGA_LIGHT_RED = 12, - VGA_LIGHT_MAGENTA = 13, - VGA_LIGHT_BROWN = 14, - VGA_WHITE = 15, -}; - -enum AnsiiColor { - ANSII_FRONT_BLACK = 30, - ANSII_FRONT_RED = 31, - ANSII_FRONT_GREEN = 32, - ANSII_FRONT_YELLOW = 33, - ANSII_FRONT_BLUE = 34, - ANSII_FRONT_PURPLE = 35, - ANSII_FRONT_CYAN = 36, - ANSII_FRONT_WHITE = 37, - ANSII_FRONT_BLACK_EMPH = 90, - ANSII_FRONT_RED_EMPH = 91, - ANSII_FRONT_GREEN_EMPH = 92, - ANSII_FRONT_YELLOW_EMPH = 93, - ANSII_FRONT_BLUE_EMPH = 94, - ANSII_FRONT_PURPLE_EMPH = 95, - ANSII_FRONT_CYAN_EMPH = 96, - ANSII_FRONT_WHITE_EMPH = 97, - ANSII_BACK_BLACK = 40, - ANSII_BACK_RED = 41, - ANSII_BACK_GREEN = 42, - ANSII_BACK_YELLOW = 43, - ANSII_BACK_BLUE = 44, - ANSII_BACK_PURPLE = 45, - ANSII_BACK_CYAN = 46, - ANSII_BACK_WHITE = 47, - ANSII_BACK_BLACK_EMPH = 100, - ANSII_BACK_RED_EMPH = 101, - ANSII_BACK_GREEN_EMPH = 102, - ANSII_BACK_YELLOW_EMPH = 103, - ANSII_BACK_BLUE_EMPH = 104, - ANSII_BACK_PURPLE_EMPH = 105, - ANSII_BACK_CYAN_EMPH = 106, - ANSII_BACK_WHITE_EMPH = 107, -}; - -bool itoac(int i, enum AnsiiColor *color); -bool itovc(int i, enum VGAColor *color); -enum VGAColor atovc(enum AnsiiColor color); diff --git a/kernel/src/tty/cursor.c b/kernel/src/tty/cursor.c deleted file mode 100644 index 3a3888b..0000000 --- a/kernel/src/tty/cursor.c +++ /dev/null @@ -1,30 +0,0 @@ -#include - -#include "cursor.h" -#include "term.h" - -void cursor_enable(void) { - cursor_setsize(13, 16); -} - -void cursor_disable(void) { - outb(0x3D4, 0x0A); - outb(0x3D5, 0x20); -} - -void cursor_setsize(uint8_t start, uint8_t end) { - outb(0x3D4, 0x0A); - outb(0x3D5, (inb(0x3D5) & 0xC0) | start); - - outb(0x3D4, 0x0B); - outb(0x3D5, (inb(0x3D5) & 0xE0) | end); -} - -void cursor_setpos(uint8_t x, uint8_t y) { -; uint16_t pos = y * TERM_W + x; - - outb(0x3D4, 0x0F); - outb(0x3D5, (uint8_t) (pos & 0xFF)); - outb(0x3D4, 0x0E); - outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); -} diff --git a/kernel/src/tty/cursor.h b/kernel/src/tty/cursor.h deleted file mode 100644 index 602d9cd..0000000 --- a/kernel/src/tty/cursor.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -void cursor_enable(void); -void cursor_disable(void); -void cursor_setsize(uint8_t start, uint8_t end); -void cursor_setpos(uint8_t x, uint8_t y); - diff --git a/kernel/src/tty/term.c b/kernel/src/tty/term.c deleted file mode 100644 index a7451d2..0000000 --- a/kernel/src/tty/term.c +++ /dev/null @@ -1,138 +0,0 @@ - -#include -#include -#include -#include -#include - -#include "term.h" -#include "color.h" -#include "cursor.h" - -uint16_t buffer[TERM_W * TERM_H * sizeof(uint16_t)]; -uint16_t *front; -uint8_t x, y; -uint8_t color; - -const uint16_t blank = (uint16_t) 0 | VGA_BLACK << 12 | VGA_WHITE << 8; - -static void term_clear_line(int y) { - if (y < 0 || y >= TERM_H) - return; - for (uint8_t x = 0; x < TERM_W; x++) { - const size_t index = y * TERM_W + x; - buffer[index] = blank; - } -} - -void term_init (void) { - x = 0; - y = 0; - front = (uint16_t*) 0xC03FF000; - term_setfg(VGA_WHITE); - term_setbg(VGA_BLACK); - term_clear(); -} - -void term_setpos(uint8_t xp, uint8_t yp) { - x = xp; - y = yp; - cursor_setpos(x, y); -} - -void term_scroll (int lines) { - int_disable(); - y -= lines; - if (!lines) return; - if(lines >= TERM_H || lines <= -TERM_H) { - term_clear(); - } else if(lines > 0) { - memmove(buffer, buffer + lines * TERM_W, 2 * (TERM_H - lines) * TERM_W); - term_clear_line(TERM_H - lines); - } else { - memmove(buffer + lines * TERM_W, buffer + lines, (TERM_H + lines) * TERM_W); - } - int_enable(); -} - -void term_setfg(enum VGAColor c) { - color = (color & 0xF0) | c; -} - -void term_setbg(enum VGAColor c) { - color = (color & 0x0F) | c << 4; -} - -void term_clear (void) { - for (uint8_t y = 0; y < TERM_H; y++) - term_clear_line(y); -} - -uint32_t term_save(void) { - uint32_t state = 0; - state |= (uint32_t) x << 16; - state |= (uint32_t) y << 8; - state |= (uint32_t) color << 0; - return state; -} - -void term_load(uint32_t state) { - x = (uint8_t) (state >> 16); - y = (uint8_t) (state >> 8); - color = (uint8_t) (state >> 0); - cursor_setpos(x, y); -} - -uint16_t term_save_col(void) { - return color; -} - -void term_load_col(uint16_t c) { - color = c; -} - -void putchar(int c) { - switch (c) { - case '\n': - x = 0; - y++; - break; - case '\t': - x += 4; - break; - case '\v': - case '\f': - y++; - break; - case '\r': - x = 0; - break; - default: { - const size_t index = y * TERM_W + x; - buffer[index] = c | (uint16_t) color << 8; - x++; - } - } - - if (x >= TERM_W) { - x = 0; - y++; - } - - if (y >= TERM_H) { - term_scroll(y - (TERM_H - 1)); - y = TERM_H - 1; - } - - cursor_setpos(x, y); -} - -bool term_newline(void) { - return x == 0; -} - -void term_flush(void) { - int_disable(); - memcpy(front, buffer, TERM_W * TERM_H * sizeof(uint16_t)); - int_enable(); -} diff --git a/kernel/src/tty/term.h b/kernel/src/tty/term.h deleted file mode 100644 index ceda255..0000000 --- a/kernel/src/tty/term.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -#include "color.h" - -#define TERM_W 80 -#define TERM_H 25 - -void term_init(void); - -void term_reset(void); -void term_setfg(enum VGAColor color); -void term_setbg(enum VGAColor color); - -void term_clear(void); -void term_scroll(int lines); -void term_setpos(uint8_t x, uint8_t y); - -uint32_t term_save(void); -void term_load(uint32_t state); - -uint16_t term_save_col(void); -void term_load_col(uint16_t color); - -bool term_newline(void); - -void term_flush(void); -- cgit v1.2.3-freya