From fb4216543db951c2b3ad7bbf392cf921f7b98934 Mon Sep 17 00:00:00 2001 From: Erdem Ersoy Date: Wed, 17 Jan 2024 07:40:21 +0300 Subject: [PATCH] New initial commit with new repository --- .gitignore | 5 + LICENSE | 7 + README.md | 41 ++ src/Makefile | 36 ++ src/cpu/idt.c | 23 ++ src/cpu/idt.h | 47 +++ src/cpu/interrupts.asm | 382 ++++++++++++++++++ src/cpu/isr.c | 149 +++++++ src/cpu/isr.h | 97 +++++ src/cpu/ports.c | 33 ++ src/cpu/ports.h | 19 + src/cpu/registers.h | 19 + src/cpu/timer.c | 51 +++ src/cpu/timer.h | 23 ++ src/cpu/types.h | 15 + src/drivers/keyboard.c | 45 +++ src/drivers/keyboard.h | 47 +++ src/drivers/screen.c | 194 +++++++++ src/drivers/screen.h | 39 ++ src/drivers/screen_colors.h | 294 ++++++++++++++ src/drivers/speaker.c | 33 ++ src/drivers/speaker.h | 18 + src/kernel/kernel.c | 92 +++++ src/kernel/kernel.h | 21 + src/libc/function.h | 12 + src/libc/memory.c | 44 ++ src/libc/memory.h | 20 + src/libc/string.c | 117 ++++++ src/libc/string.h | 22 + src/loader/kernel_entry.asm | 10 + src/loader/loader.asm | 58 +++ src/loader/loader_disk.asm | 44 ++ src/loader/loader_gdt.asm | 33 ++ src/loader/loader_print.asm | 29 ++ src/loader/loader_print_hex.asm | 37 ++ src/loader/loader_print_protected_mode.asm | 30 ++ .../loader_switch_to_protected_mode.asm | 32 ++ 37 files changed, 2218 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/Makefile create mode 100644 src/cpu/idt.c create mode 100644 src/cpu/idt.h create mode 100644 src/cpu/interrupts.asm create mode 100644 src/cpu/isr.c create mode 100644 src/cpu/isr.h create mode 100644 src/cpu/ports.c create mode 100644 src/cpu/ports.h create mode 100644 src/cpu/registers.h create mode 100644 src/cpu/timer.c create mode 100644 src/cpu/timer.h create mode 100644 src/cpu/types.h create mode 100644 src/drivers/keyboard.c create mode 100644 src/drivers/keyboard.h create mode 100644 src/drivers/screen.c create mode 100644 src/drivers/screen.h create mode 100644 src/drivers/screen_colors.h create mode 100644 src/drivers/speaker.c create mode 100644 src/drivers/speaker.h create mode 100644 src/kernel/kernel.c create mode 100644 src/kernel/kernel.h create mode 100644 src/libc/function.h create mode 100644 src/libc/memory.c create mode 100644 src/libc/memory.h create mode 100644 src/libc/string.c create mode 100644 src/libc/string.h create mode 100644 src/loader/kernel_entry.asm create mode 100644 src/loader/loader.asm create mode 100644 src/loader/loader_disk.asm create mode 100644 src/loader/loader_gdt.asm create mode 100644 src/loader/loader_print.asm create mode 100644 src/loader/loader_print_hex.asm create mode 100644 src/loader/loader_print_protected_mode.asm create mode 100644 src/loader/loader_switch_to_protected_mode.asm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..243960b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.bin +*.img +src/output/* +.vscode/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..822a707 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2022-2024 Erdem Ersoy (eersoy93) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..519a2d2 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# E93 + +Erdem Ersoy's (eersoy93's) monolithic operating system for PCs. + +## Building and Running + +In [Pardus 23](https://www.pardus.org.tr/), clone this repository. After that, install GCC x86 cross compiler, NASM and QEMU: + +`sudo apt install nasm qemu-system-x86 gcc-i686-linux-gnu` + +After that, move to the src directory: + +`cd src` + +After that, build the OS: + +`make` + +After building, you can run: + +`make run` + +## TODO + +- [X] Finish studying [os-tutorial](https://github.com/cfenollosa/os-tutorial). + +## References + +- [https://github.com/cfenollosa/os-tutorial](https://github.com/cfenollosa/os-tutorial) +- [https://wiki.osdev.org/PC_Speaker](https://wiki.osdev.org/PC_Speaker) +- [https://www.felixcloutier.com/x86/index.html](https://www.felixcloutier.com/x86/index.html) +- [https://www.fountainware.com/EXPL/vga_color_palettes.htm](https://www.fountainware.com/EXPL/vga_color_palettes.htm) +- [https://en.wikipedia.org/wiki/VGA_text_mode](https://en.wikipedia.org/wiki/VGA_text_mode) +- [https://www.rapidtables.com/code/text/ascii-table.html](https://www.rapidtables.com/code/text/ascii-table.html) +- [Pardus's Calculator :)](https://apps.pardus.org.tr/app/gnome-calculator) + +## Copyright and License + +Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + +Licensed with MIT License. See LICENSE file for details. diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..27d0520 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,36 @@ +# DESCRIPTION: E93 Makefile +# AUTHOR: Erdem Ersoy (eersoy93) +# COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +# LICENSE: Licensed with MIT License. See LICENSE file for details. + +C_SOURCES = $(wildcard kernel/*.c drivers/*.c cpu/*.c libc/*.c) +C_HEADERS = $(wildcard kernel/*.h drivers/*.h cpu/*.h libc/*.h) + +OBJ = ${C_SOURCES:.c=.o cpu/interrupts.o} + +CC = /usr/bin/i686-linux-gnu-gcc +CFLAGS = -g -m32 -ffreestanding -fno-PIC -fno-stack-protector -nostartfiles -nodefaultlibs \ + -Wall -Wextra -Werror + +e93-os.img: loader/loader.bin kernel.bin + cat $^ > e93-os.bin + dd if=/dev/zero bs=512 count=2880 >> $@ + dd if=e93-os.bin of=$@ conv=notrunc + +kernel.bin: loader/kernel_entry.o ${OBJ} + i686-linux-gnu-ld -no-pie -o $@ -Ttext 0x1000 $^ --oformat binary --allow-multiple-definition + +run: e93-os.img + qemu-system-i386 -fda $< -audiodev alsa,id=default -machine pcspk-audiodev=default + +%.o: %.c ${C_HEADERS} + ${CC} ${CFLAGS} -ffreestanding -c $< -o $@ + +%.o: %.asm + nasm $< -f elf -o $@ + +%.bin: %.asm + nasm $< -f bin -o $@ + +clean: + rm -f *.bin *.img *.o loader/*.bin kernel/*.o loader/*.o drivers/*.o cpu/*.o libc/*.o diff --git a/src/cpu/idt.c b/src/cpu/idt.c new file mode 100644 index 0000000..ed0d1c9 --- /dev/null +++ b/src/cpu/idt.c @@ -0,0 +1,23 @@ +/* DESCRIPTION: E93 Interrupt Descriptor Table Code File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "idt.h" + +void set_idt_gate(int n, uint32_t handler) +{ + idt[n].offset_handler_function_address_low = low16(handler); + idt[n].kernel_segment_selector = KERNEL_CS; + idt[n].always_zero = (uint8_t) 0; + idt[n].flags = 0x8E; // 1000 1110 + idt[n].offset_handler_function_address_high = high16(handler); +} + +void set_idt(void) +{ + idt_register.base = (uint32_t) &idt; + idt_register.limit = sizeof(idt_gate_type) * IDT_ENTRIES_COUNT - 1; + asm volatile("lidtl (%0)" : : "r" (&idt_register)); +} diff --git a/src/cpu/idt.h b/src/cpu/idt.h new file mode 100644 index 0000000..12b627e --- /dev/null +++ b/src/cpu/idt.h @@ -0,0 +1,47 @@ +/* DESCRIPTION: E93 Interrupt Descriptor Table Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef IDT_H +#define IDT_H + +#include "../cpu/types.h" + +#include + +// Segment selectors +#define KERNEL_CS (uint16_t)0x08 + +// Interrupt gate handler struct +typedef struct +{ + uint16_t offset_handler_function_address_low; + uint16_t kernel_segment_selector; + uint8_t always_zero; + + /* 7: Interrupt is present + * 6-5: CPU privilege level of the caller + * 4: Zero for interrupt gates + * 3-0: 32-bit interrupt gate */ + uint8_t flags; + uint16_t offset_handler_function_address_high; +} __attribute__((packed)) idt_gate_type; + +// Interrupt handlers array pointer +typedef struct +{ + uint16_t limit; + uint32_t base; +} __attribute__((packed)) idt_register_type; + +#define IDT_ENTRIES_COUNT 256 +idt_gate_type idt[IDT_ENTRIES_COUNT]; +idt_register_type idt_register; + +// IDT Functions +void set_idt_gate(int n, uint32_t handler); +void set_idt(void); + +#endif diff --git a/src/cpu/interrupts.asm b/src/cpu/interrupts.asm new file mode 100644 index 0000000..16d4f7f --- /dev/null +++ b/src/cpu/interrupts.asm @@ -0,0 +1,382 @@ +; DESCRIPTION: E93 Interrupts Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +[extern isr_handler] +[extern irq_handler] + +; Common ISR code +isr_common_stub: + ; Save CPU state + pusha + mov ax, ds + push eax + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + push esp + cld + + ; Call C ISR handler + call isr_handler + + ; Restore CPU state + pop eax + pop eax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + popa + add esp, 8 + iret + +; Common IRQ code +irq_common_stub: + ; Save CPU state + pusha + mov ax, ds + push eax + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + push esp + cld + + ; Call C IRQ Handler + call irq_handler + + ; Restore CPU state + pop ebx + pop ebx + mov ds, bx + mov es, bx + mov fs, bx + mov gs, bx + popa + add esp, 8 + iret + +; Make ISRs global +global isr0 +global isr1 +global isr2 +global isr3 +global isr4 +global isr5 +global isr6 +global isr7 +global isr8 +global isr9 +global isr10 +global isr11 +global isr12 +global isr13 +global isr14 +global isr15 +global isr16 +global isr17 +global isr18 +global isr19 +global isr20 +global isr21 +global isr22 +global isr23 +global isr24 +global isr25 +global isr26 +global isr27 +global isr28 +global isr29 +global isr30 +global isr31 + +; Make IRQs global +global irq0 +global irq1 +global irq2 +global irq3 +global irq4 +global irq5 +global irq6 +global irq7 +global irq8 +global irq9 +global irq10 +global irq11 +global irq12 +global irq13 +global irq14 +global irq15 + +; Division By Zero Exception +isr0: + push byte 0 + push byte 0 + jmp isr_common_stub + +; Debug Exception +isr1: + push byte 0 + push byte 1 + jmp isr_common_stub + +; Non Maskable Interrupt Exception +isr2: + push byte 0 + push byte 2 + jmp isr_common_stub + +; Breakpoint Exception +isr3: + push byte 0 + push byte 3 + jmp isr_common_stub + +; Overflow Exception +isr4: + push byte 0 + push byte 4 + jmp isr_common_stub + +; Out of Bounds Exception +isr5: + push byte 0 + push byte 5 + jmp isr_common_stub + +; Invalid Opcode Exception +isr6: + push byte 0 + push byte 6 + jmp isr_common_stub + +; Coprocessor Not Available Exception +isr7: + push byte 0 + push byte 7 + jmp isr_common_stub + +; Double Fault Exception (with error code) +isr8: + push byte 8 + jmp isr_common_stub + +; Coprocessor Segment Overrun Exception +isr9: + push byte 0 + push byte 9 + jmp isr_common_stub + +; Invalid Task State Segment Exception (with error code) +isr10: + push byte 10 + jmp isr_common_stub + +; Segment Not Present Exception (with error code) +isr11: + push byte 11 + jmp isr_common_stub + +; Stack Segment Fault Exception (with error code) +isr12: + push byte 12 + jmp isr_common_stub + +; General Protection Fault Exception (with error code) +isr13: + push byte 13 + jmp isr_common_stub + +; Page Fault Exception (with error code) +isr14: + push byte 14 + jmp isr_common_stub + +; Reserved Exception +isr15: + push byte 0 + push byte 15 + jmp isr_common_stub + +; x87 Floating Point Fault Exception +isr16: + push byte 0 + push byte 16 + jmp isr_common_stub + +; Alignment Check Exception +isr17: + push byte 0 + push byte 17 + jmp isr_common_stub + +; Machine Check Exception +isr18: + push byte 0 + push byte 18 + jmp isr_common_stub + +; Reserved Exception +isr19: + push byte 0 + push byte 19 + jmp isr_common_stub + +; Reserved Exception +isr20: + push byte 0 + push byte 20 + jmp isr_common_stub + +; Reserved Exception +isr21: + push byte 0 + push byte 21 + jmp isr_common_stub + +; Reserved Exception +isr22: + push byte 0 + push byte 22 + jmp isr_common_stub + +; Reserved Exception +isr23: + push byte 0 + push byte 23 + jmp isr_common_stub + +; Reserved Exception +isr24: + push byte 0 + push byte 24 + jmp isr_common_stub + +; Reserved Exception +isr25: + push byte 0 + push byte 25 + jmp isr_common_stub + +; Reserved Exception +isr26: + push byte 0 + push byte 26 + jmp isr_common_stub + +; Reserved Exception +isr27: + push byte 0 + push byte 27 + jmp isr_common_stub + +; Reserved Exception +isr28: + push byte 0 + push byte 28 + jmp isr_common_stub + +; Reserved Exception +isr29: + push byte 0 + push byte 29 + jmp isr_common_stub + +; Reserved Exception +isr30: + push byte 0 + push byte 30 + jmp isr_common_stub + +; Reserved Exception +isr31: + push byte 0 + push byte 31 + jmp isr_common_stub + +; IRQ handlers +irq0: + push byte 0 + push byte 32 + jmp irq_common_stub + +irq1: + push byte 1 + push byte 33 + jmp irq_common_stub + +irq2: + push byte 2 + push byte 34 + jmp irq_common_stub + +irq3: + push byte 3 + push byte 35 + jmp irq_common_stub + +irq4: + push byte 4 + push byte 36 + jmp irq_common_stub + +irq5: + push byte 5 + push byte 37 + jmp irq_common_stub + +irq6: + push byte 6 + push byte 38 + jmp irq_common_stub + +irq7: + push byte 7 + push byte 39 + jmp irq_common_stub + +irq8: + push byte 8 + push byte 40 + jmp irq_common_stub + +irq9: + push byte 9 + push byte 41 + jmp irq_common_stub + +irq10: + push byte 10 + push byte 42 + jmp irq_common_stub + +irq11: + push byte 11 + push byte 43 + jmp irq_common_stub + +irq12: + push byte 12 + push byte 44 + jmp irq_common_stub + +irq13: + push byte 13 + push byte 45 + jmp irq_common_stub + +irq14: + push byte 14 + push byte 46 + jmp irq_common_stub + +irq15: + push byte 15 + push byte 47 + jmp irq_common_stub diff --git a/src/cpu/isr.c b/src/cpu/isr.c new file mode 100644 index 0000000..4d796bb --- /dev/null +++ b/src/cpu/isr.c @@ -0,0 +1,149 @@ +/* DESCRIPTION: E93 Interrupt Service Routine Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "isr.h" + +isr_t interrupt_handlers[256]; + +void isr_install() +{ + set_idt_gate(0, (uint32_t) isr0); + set_idt_gate(1, (uint32_t) isr1); + set_idt_gate(2, (uint32_t) isr2); + set_idt_gate(3, (uint32_t) isr3); + set_idt_gate(4, (uint32_t) isr4); + set_idt_gate(5, (uint32_t) isr5); + set_idt_gate(6, (uint32_t) isr6); + set_idt_gate(7, (uint32_t) isr7); + set_idt_gate(8, (uint32_t) isr8); + set_idt_gate(9, (uint32_t) isr9); + set_idt_gate(10, (uint32_t) isr10); + set_idt_gate(11, (uint32_t) isr11); + set_idt_gate(12, (uint32_t) isr12); + set_idt_gate(13, (uint32_t) isr13); + set_idt_gate(14, (uint32_t) isr14); + set_idt_gate(15, (uint32_t) isr15); + set_idt_gate(16, (uint32_t) isr16); + set_idt_gate(17, (uint32_t) isr17); + set_idt_gate(18, (uint32_t) isr18); + set_idt_gate(19, (uint32_t) isr19); + set_idt_gate(20, (uint32_t) isr20); + set_idt_gate(21, (uint32_t) isr21); + set_idt_gate(22, (uint32_t) isr22); + set_idt_gate(23, (uint32_t) isr23); + set_idt_gate(24, (uint32_t) isr24); + set_idt_gate(25, (uint32_t) isr25); + set_idt_gate(26, (uint32_t) isr26); + set_idt_gate(27, (uint32_t) isr27); + set_idt_gate(28, (uint32_t) isr28); + set_idt_gate(29, (uint32_t) isr29); + set_idt_gate(30, (uint32_t) isr30); + set_idt_gate(31, (uint32_t) isr31); + + // Remap the PIC + port_byte_out(0x20, 0x11); + port_byte_out(0xA0, 0x11); + port_byte_out(0x21, 0x20); + port_byte_out(0xA1, 0x28); + port_byte_out(0x21, 0x04); + port_byte_out(0xA1, 0x02); + port_byte_out(0x21, 0x01); + port_byte_out(0xA1, 0x01); + port_byte_out(0x21, 0x0); + port_byte_out(0xA1, 0x0); + + // Install the IRQs + set_idt_gate(32, (uint32_t) irq0); + set_idt_gate(33, (uint32_t) irq1); + set_idt_gate(34, (uint32_t) irq2); + set_idt_gate(35, (uint32_t) irq3); + set_idt_gate(36, (uint32_t) irq4); + set_idt_gate(37, (uint32_t) irq5); + set_idt_gate(38, (uint32_t) irq6); + set_idt_gate(39, (uint32_t) irq7); + set_idt_gate(40, (uint32_t) irq8); + set_idt_gate(41, (uint32_t) irq9); + set_idt_gate(42, (uint32_t) irq10); + set_idt_gate(43, (uint32_t) irq11); + set_idt_gate(44, (uint32_t) irq12); + set_idt_gate(45, (uint32_t) irq13); + set_idt_gate(46, (uint32_t) irq14); + set_idt_gate(47, (uint32_t) irq15); + + set_idt(); +} + +char * isr_exception_messages[] = +{ + "Division By Zero", + "Debug", + "Non Maskable Interrupt", + "Breakpoint", + "Overflow", + "Out of Bounds", + "Invalid Opcode", + "Coprocessor Not Available", + "Double Fault", + "Coprocessor Segment Overrun", + "Invalid Task State Segment", + "Segment Not Present", + "Stack Segment Fault", + "General Protection Fault", + "Page Fault", + "Reserved", + "x87 Floating Point Fault", + "Alignment Check", + "Machine Check", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved" +}; + +void isr_handler(registers_struct_type * registers) +{ + printk_color("Received interrupt: ", OUTPUT_COLOR); + char interrupt_no_str[3]; + int_to_ascii(registers->interrupt_no, interrupt_no_str); + printk_color(interrupt_no_str, OUTPUT_COLOR); + printk_color("\n", OUTPUT_COLOR); + + printk_color(isr_exception_messages[registers->interrupt_no], OUTPUT_COLOR); + printk_color("\n", OUTPUT_COLOR); +} + +void register_interrupt_handler(uint8_t n, isr_t handler) +{ + interrupt_handlers[n] = handler; +} + +void irq_handler(registers_struct_type * registers) +{ + if (registers->interrupt_no >= 40) port_byte_out(0xA0, 0x20); + port_byte_out(0x20, 0x20); + + if (interrupt_handlers[registers->interrupt_no] != 0) + { + isr_t handler = interrupt_handlers[registers->interrupt_no]; + handler(registers); + } +} + +void irq_install(void) +{ + asm volatile("sti"); + init_timer(50); + init_keyboard(); +} diff --git a/src/cpu/isr.h b/src/cpu/isr.h new file mode 100644 index 0000000..0c1f648 --- /dev/null +++ b/src/cpu/isr.h @@ -0,0 +1,97 @@ +/* DESCRIPTION: E93 Interrupt Service Routine Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef ISR_H +#define ISR_H + +#include "idt.h" +#include "ports.h" +#include "../drivers/screen.h" +#include "../drivers/keyboard.h" +#include "../libc/string.h" +#include "registers.h" +#include "timer.h" + +#include + +// Reserved ISRs +extern void isr0(void); +extern void isr1(void); +extern void isr2(void); +extern void isr3(void); +extern void isr4(void); +extern void isr5(void); +extern void isr6(void); +extern void isr7(void); +extern void isr8(void); +extern void isr9(void); +extern void isr10(void); +extern void isr11(void); +extern void isr12(void); +extern void isr13(void); +extern void isr14(void); +extern void isr15(void); +extern void isr16(void); +extern void isr17(void); +extern void isr18(void); +extern void isr19(void); +extern void isr20(void); +extern void isr21(void); +extern void isr22(void); +extern void isr23(void); +extern void isr24(void); +extern void isr25(void); +extern void isr26(void); +extern void isr27(void); +extern void isr28(void); +extern void isr29(void); +extern void isr30(void); +extern void isr31(void); + +// IRQ definitions +extern void irq0(void); +extern void irq1(void); +extern void irq2(void); +extern void irq3(void); +extern void irq4(void); +extern void irq5(void); +extern void irq6(void); +extern void irq7(void); +extern void irq8(void); +extern void irq9(void); +extern void irq10(void); +extern void irq11(void); +extern void irq12(void); +extern void irq13(void); +extern void irq14(void); +extern void irq15(void); + +#define IRQ0 32 +#define IRQ1 33 +#define IRQ2 34 +#define IRQ3 35 +#define IRQ4 36 +#define IRQ5 37 +#define IRQ6 38 +#define IRQ7 39 +#define IRQ8 40 +#define IRQ9 41 +#define IRQ10 42 +#define IRQ11 43 +#define IRQ12 44 +#define IRQ13 45 +#define IRQ14 46 +#define IRQ15 47 + +// ISR Functions +void isr_install(); +void isr_handler(registers_struct_type * registers); +void irq_install(); + +typedef void (*isr_t)(registers_struct_type *); +void register_interrupt_handler(uint8_t n, isr_t handler); + +#endif diff --git a/src/cpu/ports.c b/src/cpu/ports.c new file mode 100644 index 0000000..81fc731 --- /dev/null +++ b/src/cpu/ports.c @@ -0,0 +1,33 @@ +/* DESCRIPTION: E93 Port Driver Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +// Read byte from port +unsigned char port_byte_in(unsigned short port) +{ + unsigned char result; + asm("in %%dx, %%al": "=a" (result) : "d" (port)); + return result; +} + +// Write byte to port +void port_byte_out(unsigned short port, unsigned char data) +{ + asm("out %%al, %%dx": : "a" (data), "d" (port)); +} + +// Read word from port +unsigned char port_word_in(unsigned short port) +{ + unsigned char result; + asm("in %%dx, %%ax": "=a" (result) : "d" (port)); + return result; +} + +// Write word to port +void port_word_out(unsigned short port, unsigned short data) +{ + asm("out %%ax, %%dx": : "a" (data), "d" (port)); +} diff --git a/src/cpu/ports.h b/src/cpu/ports.h new file mode 100644 index 0000000..57998b0 --- /dev/null +++ b/src/cpu/ports.h @@ -0,0 +1,19 @@ +/* DESCRIPTION: E93 Port Driver Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef PORTS_H +#define PORTS_H + + +// Port Driver Declarations + +unsigned char port_byte_in(unsigned short port); +void port_byte_out(unsigned short port, unsigned char data); + +unsigned short port_word_in(unsigned short port); +void port_word_out(unsigned short port, unsigned short data); + +#endif diff --git a/src/cpu/registers.h b/src/cpu/registers.h new file mode 100644 index 0000000..7cfdc37 --- /dev/null +++ b/src/cpu/registers.h @@ -0,0 +1,19 @@ +/* DESCRIPTION: E93 CPU Registers Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef REGISTERS_H +#define REGISTERS_H + +// Registers struct +typedef struct +{ + uint32_t ds; + uint32_t edi, esi, ebp, useless, ebx, edx, ecx, eax; + uint32_t interrupt_no, error_code; + uint32_t eip, cs, eflags, esp, ss; +} registers_struct_type; + +#endif \ No newline at end of file diff --git a/src/cpu/timer.c b/src/cpu/timer.c new file mode 100644 index 0000000..f919d84 --- /dev/null +++ b/src/cpu/timer.c @@ -0,0 +1,51 @@ +/* DESCRIPTION: E93 CPU Timer Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "timer.h" + +volatile uint32_t tick = 0; + +static void timer_callback(registers_struct_type * registers) +{ + tick++; + UNUSED(registers); +} + +void set_PIT_2(uint32_t frequency) +{ + uint32_t divisor = 1193180 / frequency; // Hardware clock frequency is 1193180 Hz. + uint8_t low = (uint8_t)(divisor & 0xFF); + uint8_t high = (uint8_t)((divisor >> 8) & 0xFF); + + port_byte_out(0x43, 0xB6); + port_byte_out(0x42, low); + port_byte_out(0x42, high); +} + +void init_timer(uint32_t frequency) +{ + printk_color("Initializing the CPU timer...\n", OUTPUT_COLOR); + + uint32_t divisor = 1193180 / frequency; // Hardware clock frequency is 1193180 Hz. + uint8_t low = (uint8_t)(divisor & 0xFF); + uint8_t high = (uint8_t)((divisor >> 8) & 0xFF); + + port_byte_out(0x43, 0x36); + port_byte_out(0x40, low); + port_byte_out(0x40, high); + + register_interrupt_handler(IRQ0, timer_callback); +} + +void wait_timer(uint32_t ticks) +{ + uint32_t ticks_end = tick + ticks; + + while (tick < ticks_end) + { + asm volatile("nop"); + } +} diff --git a/src/cpu/timer.h b/src/cpu/timer.h new file mode 100644 index 0000000..ae7a637 --- /dev/null +++ b/src/cpu/timer.h @@ -0,0 +1,23 @@ +/* DESCRIPTION: E93 CPU Timer Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef TIMER_H +#define TIMER_H + +#include "ports.h" +#include "isr.h" +#include "../drivers/screen.h" +#include "../libc/function.h" +#include "../libc/string.h" +#include "registers.h" + +#include + +void set_PIT_2(uint32_t frequency); +void init_timer(uint32_t frequency); +void wait_timer(uint32_t ticks); + +#endif diff --git a/src/cpu/types.h b/src/cpu/types.h new file mode 100644 index 0000000..ff44526 --- /dev/null +++ b/src/cpu/types.h @@ -0,0 +1,15 @@ +/* DESCRIPTION: E93 Machine-Dependent (x86-32) Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef TYPES_H +#define TYPES_H + +#include + +#define low16(address) (uint16_t)((address) & 0xFFFF) +#define high16(address) (uint16_t)(((address) >> 16) & 0xFFFF) + +#endif diff --git a/src/drivers/keyboard.c b/src/drivers/keyboard.c new file mode 100644 index 0000000..2487e10 --- /dev/null +++ b/src/drivers/keyboard.c @@ -0,0 +1,45 @@ +/* DESCRIPTION: E93 Keyboard Driver Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "keyboard.h" + +static char key_buffer[256]; + +static void keyboard_callback(registers_struct_type * registers) +{ + uint8_t scancode = port_byte_in(0x60); + + if (scancode > SCANCODE_MAX) + { + return; + } + else if (scancode == BACKSPACE) + { + backspace(key_buffer); + printk_backspace(); + } + else if (scancode == ENTER) + { + printk("\n"); + user_input(key_buffer); + key_buffer[0] = '\0'; + } + else + { + char letter = scancode_ascii[(int)scancode]; + char str[2] = {letter, '\0'}; + append(key_buffer, letter); + printk_color(str, COMMAND_COLOR); + } + + UNUSED(registers); +} + +void init_keyboard(void) +{ + printk_color("Initializing the keyboard...\n", OUTPUT_COLOR); + register_interrupt_handler(IRQ1, keyboard_callback); +} diff --git a/src/drivers/keyboard.h b/src/drivers/keyboard.h new file mode 100644 index 0000000..e22c0a0 --- /dev/null +++ b/src/drivers/keyboard.h @@ -0,0 +1,47 @@ +/* DESCRIPTION: E93 Keyboard Driver Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef KEYBOARD_H +#define KEYBOARD_H + +#include "../cpu/ports.h" +#include "../cpu/isr.h" +#include "screen.h" +#include "../libc/string.h" +#include "../libc/function.h" +#include "../kernel/kernel.h" + +#include + +#define BACKSPACE 0x0E +#define ENTER 0x1C + +#define SCANCODE_MAX 57 + +const char * scancode_name[] = {"ERROR", "Esc", "1", "2", "3", "4", "5", "6", + "7", "8", "9", "0", "-", "=", "Backspace", + "Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", + "O", "P", "[", "]", "Enter", "Left Ctrl", + "A", "S", "D", "F", "G", "H", "J", "K", "L", + ";", "'", "`", "Left Shift", "\\", "Z", "X", + "C", "V", "B", "N", "M", ",", ".", "/", + "Right Shift", "Keypad *", "Left Alt", + "Spacebar"}; + +const char scancode_ascii[] = {'?', '?', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '?', + '?', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '[', ']', '?', '?', + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', + ';', '\'', '`', '?', '\\', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', ',', '.', '/', + '?', '?', '?', + ' '}; + +void init_keyboard(void); + +#endif + diff --git a/src/drivers/screen.c b/src/drivers/screen.c new file mode 100644 index 0000000..630831d --- /dev/null +++ b/src/drivers/screen.c @@ -0,0 +1,194 @@ +/* DESCRIPTION: E93 Screen Driver Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "screen.h" + +// Private Kernel API Declarations + +int get_cursor_offset(void); +int get_offset(int col, int row); +int get_offset_col(int offset); +int get_offset_row(int offset); +int printk_char(char character, int col, int row, char attribute); +void set_cursor_offset(int offset); + + +// Public Kernel API Definitions + +// Clear entire screen with black +void clear_screen(void) +{ + int screen_size = COLS_MAX * ROWS_MAX; + int i = 0; + char * screen = VIDEO_ADDRESS; + + for (i = 0; i < screen_size; i++) + { + screen[i * 2] = ' '; + screen[i * 2 + 1] = CLRSCR_COLOR; + } + + set_cursor_offset(get_offset(0, 0)); +} + +// Print message at cursor location +void printk(char * message) +{ + printk_color(message, DEFAULT_COLOR); +} + +// Print message at specific location +void printk_at(char * message, int col, int row) +{ + printk_at_color(message, col, row, DEFAULT_COLOR); +} + +// Print message at cursor location with specfific color +void printk_color(char * message, char color) +{ + printk_at_color(message, -1, -1, color); +} + +// Print message at specific location with specfific color +void printk_at_color(char * message, int col, int row, char color) +{ + int offset = 0; + + if (col >= 0 && row >= 0) + { + offset = get_offset(col, row); + } + else + { + offset = get_cursor_offset(); + row = get_offset_row(offset); + col = get_offset_col(offset); + } + + int i = 0; + + while (message[i] != 0) + { + offset = printk_char(message[i++], col, row, color); + row = get_offset_row(offset); + col = get_offset_col(offset); + } +} + +// Revert printing via backspace +void printk_backspace(void) +{ + int offset = get_cursor_offset() - 2; + int row = get_offset_row(offset); + int col = get_offset_col(offset); + if (col != 0) + { + printk_char(0x20, col, row, COMMAND_COLOR); + set_cursor_offset(offset); + } +} + + +// Private Kernel API Definitions + +// Get cursor video memory offset +int get_cursor_offset() +{ + port_byte_out(PORT_SCREEN_CTRL, 14); + int offset = port_byte_in(PORT_SCREEN_DATA) << 8; + port_byte_out(PORT_SCREEN_CTRL, 15); + offset += port_byte_in(PORT_SCREEN_DATA); + + return offset * 2; +} + +// Get specific location video memory offset +int get_offset(int col, int row) +{ + return 2 * (row * COLS_MAX + col); +} + +// Get specific column of video memory offset +int get_offset_col(int offset) +{ + return (offset - (get_offset_row(offset) * 2 * COLS_MAX)) / 2; +} + +// Get specific row of video memory offset +int get_offset_row(int offset) +{ + return offset / (2 * COLS_MAX); +} + +// Print specific character with specific attribute at specific loaction +int printk_char(char character, int col, int row, char attribute) +{ + unsigned char * video_memory = (unsigned char *) VIDEO_ADDRESS; + if (!attribute) + { + attribute = DEFAULT_COLOR; + } + + if (col >= COLS_MAX || row >= ROWS_MAX) + { + video_memory[2 * COLS_MAX * ROWS_MAX - 2] = 'E'; + video_memory[2 * COLS_MAX * ROWS_MAX - 1] = ERROR_COLOR_2; + return get_offset(col, row); + } + + int offset = 0; + if (col >= 0 && row >= 0) + { + offset = get_offset(col, row); + } + else { + offset = get_cursor_offset(); + } + + if (character == '\n') + { + row = get_offset_row(offset); + offset = get_offset(0, row + 1) ; + } + else + { + video_memory[offset] = character; + video_memory[offset + 1] = attribute; + offset += 2; + } + + if (offset >= ROWS_MAX * COLS_MAX * 2) + { + int i = 0; + for (i = 1; i < ROWS_MAX; i++) + { + memory_copy((uint8_t *)(get_offset(0, i) + VIDEO_ADDRESS), + (uint8_t *)(get_offset(0, i - 1) + VIDEO_ADDRESS), + COLS_MAX * 2); + } + + char * lastline = get_offset(0, ROWS_MAX - 1) + VIDEO_ADDRESS; + for (i = 0; i < COLS_MAX * 2; i++) + { + lastline[i] = 0; + } + + offset -= COLS_MAX * 2; + } + + set_cursor_offset(offset); + return offset; +} + +// Set cursor video memory offset +void set_cursor_offset(int offset) +{ + offset /= 2; + port_byte_out(PORT_SCREEN_CTRL, 14); + port_byte_out(PORT_SCREEN_DATA, (unsigned char) (offset >> 8)); + port_byte_out(PORT_SCREEN_CTRL, 15); + port_byte_out(PORT_SCREEN_DATA, (unsigned char) (offset & 0xff)); +} diff --git a/src/drivers/screen.h b/src/drivers/screen.h new file mode 100644 index 0000000..9e82180 --- /dev/null +++ b/src/drivers/screen.h @@ -0,0 +1,39 @@ +/* DESCRIPTION: E93 Screen Driver Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef SCREEN_H +#define SCREEN_H + +#include "../cpu/ports.h" +#include "../libc/memory.h" +#include "screen_colors.h" + +#include + +// Video Constants Definitions + +#define VIDEO_ADDRESS (char *) 0xb8000 +#define ROWS_MAX 25 +#define COLS_MAX 80 + +// Screen I/O Ports Definitions + +#define PORT_SCREEN_CTRL 0x3d4 +#define PORT_SCREEN_DATA 0x3d5 + +// Public Kernel API Declarations + +void clear_screen(void); + +void printk(char * message); +void printk_at(char * message, int col, int row); + +void printk_color(char * message, char color); +void printk_at_color(char * message, int col, int row, char color); + +void printk_backspace(void); + +#endif diff --git a/src/drivers/screen_colors.h b/src/drivers/screen_colors.h new file mode 100644 index 0000000..108bb57 --- /dev/null +++ b/src/drivers/screen_colors.h @@ -0,0 +1,294 @@ +/* DESCRIPTION: E93 Screen Color Constants Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2023-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef SCREEN_COLORS_H +#define SCREEN_COLORS_H + +// Video Constants Definitions (Color) + +#define BLACK_ON_BLACK 0x00 +#define BLUE_ON_BLACK 0x01 +#define GREEN_ON_BLACK 0x02 +#define CYAN_ON_BLACK 0x03 +#define RED_ON_BLACK 0x04 +#define MAGENTA_ON_BLACK 0x05 +#define BROWN_ON_BLACK 0x06 +#define WHITE_ON_BLACK 0x07 +#define GRAY_ON_BLACK 0x08 +#define LIGHTBLUE_ON_BLACK 0x09 +#define LIGHTGREEN_ON_BLACK 0x0a +#define LIGHTCYAN_ON_BLACK 0x0b +#define LIGHTRED_ON_BLACK 0x0c +#define LIGHTMAGENTA_ON_BLACK 0x0d +#define YELLOW_ON_BLACK 0x0e +#define BRIGHTWHITE_ON_BLACK 0x0f + +#define BLACK_ON_BLUE 0x10 +#define BLUE_ON_BLUE 0x11 +#define GREEN_ON_BLUE 0x12 +#define CYAN_ON_BLUE 0x13 +#define RED_ON_BLUE 0x14 +#define MAGENTA_ON_BLUE 0x15 +#define BROWN_ON_BLUE 0x16 +#define WHITE_ON_BLUE 0x17 +#define GRAY_ON_BLUE 0x18 +#define LIGHTBLUE_ON_BLUE 0x19 +#define LIGHTGREEN_ON_BLUE 0x1a +#define LIGHTCYAN_ON_BLUE 0x1b +#define LIGHTRED_ON_BLUE 0x1c +#define LIGHTMAGENTA_ON_BLUE 0x1d +#define YELLOW_ON_BLUE 0x1e +#define BRIGHTWHITE_ON_BLUE 0x1f + +#define BLACK_ON_GREEN 0x20 +#define BLUE_ON_GREEN 0x21 +#define GREEN_ON_GREEN 0x22 +#define CYAN_ON_GREEN 0x23 +#define RED_ON_GREEN 0x24 +#define MAGENTA_ON_GREEN 0x25 +#define BROWN_ON_GREEN 0x26 +#define WHITE_ON_GREEN 0x27 +#define GRAY_ON_GREEN 0x28 +#define LIGHTBLUE_ON_GREEN 0x29 +#define LIGHTGREEN_ON_GREEN 0x2a +#define LIGHTCYAN_ON_GREEN 0x2b +#define LIGHTRED_ON_GREEN 0x2c +#define LIGHTMAGENTA_ON_GREEN 0x2d +#define YELLOW_ON_GREEN 0x2e +#define BRIGHTWHITE_ON_GREEN 0x2f + +#define BLACK_ON_CYAN 0x30 +#define BLUE_ON_CYAN 0x31 +#define GREEN_ON_CYAN 0x32 +#define CYAN_ON_CYAN 0x33 +#define RED_ON_CYAN 0x34 +#define MAGENTA_ON_CYAN 0x35 +#define BROWN_ON_CYAN 0x36 +#define WHITE_ON_CYAN 0x37 +#define GRAY_ON_CYAN 0x38 +#define LIGHTBLUE_ON_CYAN 0x39 +#define LIGHTGREEN_ON_CYAN 0x3a +#define LIGHTCYAN_ON_CYAN 0x3b +#define LIGHTRED_ON_CYAN 0x3c +#define LIGHTMAGENTA_ON_CYAN 0x3d +#define YELLOW_ON_CYAN 0x3e +#define BRIGHTWHITE_ON_CYAN 0x3f + +#define BLACK_ON_RED 0x40 +#define BLUE_ON_RED 0x41 +#define GREEN_ON_RED 0x42 +#define CYAN_ON_RED 0x43 +#define RED_ON_RED 0x44 +#define MAGENTA_ON_RED 0x45 +#define BROWN_ON_RED 0x46 +#define WHITE_ON_RED 0x47 +#define GRAY_ON_RED 0x48 +#define LIGHTBLUE_ON_RED 0x49 +#define LIGHTGREEN_ON_RED 0x4a +#define LIGHTCYAN_ON_RED 0x4b +#define LIGHTRED_ON_RED 0x4c +#define LIGHTMAGENTA_ON_RED 0x4d +#define YELLOW_ON_RED 0x4e +#define BRIGHTWHITE_ON_RED 0x4f + +#define BLACK_ON_MAGENTA 0x50 +#define BLUE_ON_MAGENTA 0x51 +#define GREEN_ON_MAGENTA 0x52 +#define CYAN_ON_MAGENTA 0x53 +#define RED_ON_MAGENTA 0x54 +#define MAGENTA_ON_MAGENTA 0x55 +#define BROWN_ON_MAGENTA 0x56 +#define WHITE_ON_MAGENTA 0x57 +#define GRAY_ON_MAGENTA 0x58 +#define LIGHTBLUE_ON_MAGENTA 0x59 +#define LIGHTGREEN_ON_MAGENTA 0x5a +#define LIGHTCYAN_ON_MAGENTA 0x5b +#define LIGHTRED_ON_MAGENTA 0x5c +#define LIGHTMAGENTA_ON_MAGENTA 0x5d +#define YELLOW_ON_MAGENTA 0x5e +#define BRIGHTWHITE_ON_MAGENTA 0x5f + +#define BLACK_ON_BROWN 0x60 +#define BLUE_ON_BROWN 0x61 +#define GREEN_ON_BROWN 0x62 +#define CYAN_ON_BROWN 0x63 +#define RED_ON_BROWN 0x64 +#define MAGENTA_ON_BROWN 0x65 +#define BROWN_ON_BROWN 0x66 +#define WHITE_ON_BROWN 0x67 +#define GRAY_ON_BROWN 0x68 +#define LIGHTBLUE_ON_BROWN 0x69 +#define LIGHTGREEN_ON_BROWN 0x6a +#define LIGHTCYAN_ON_BROWN 0x6b +#define LIGHTRED_ON_BROWN 0x6c +#define LIGHTMAGENTA_ON_BROWN 0x6d +#define YELLOW_ON_BROWN 0x6e +#define BRIGHTWHITE_ON_BROWN 0x6f + +#define BLACK_ON_WHITE 0x70 +#define BLUE_ON_WHITE 0x71 +#define GREEN_ON_WHITE 0x72 +#define CYAN_ON_WHITE 0x73 +#define RED_ON_WHITE 0x74 +#define MAGENTA_ON_WHITE 0x75 +#define BROWN_ON_WHITE 0x76 +#define WHITE_ON_WHITE 0x77 +#define GRAY_ON_WHITE 0x78 +#define LIGHTBLUE_ON_WHITE 0x79 +#define LIGHTGREEN_ON_WHITE 0x7a +#define LIGHTCYAN_ON_WHITE 0x7b +#define LIGHTRED_ON_WHITE 0x7c +#define LIGHTMAGENTA_ON_WHITE 0x7d +#define YELLOW_ON_WHITE 0x7e +#define BRIGHTWHITE_ON_WHITE 0x7f + +#define BLACK_ON_GRAY 0x80 +#define BLUE_ON_GRAY 0x81 +#define GREEN_ON_GRAY 0x82 +#define CYAN_ON_GRAY 0x83 +#define RED_ON_GRAY 0x84 +#define MAGENTA_ON_GRAY 0x85 +#define BROWN_ON_GRAY 0x86 +#define WHITE_ON_GRAY 0x87 +#define GRAY_ON_GRAY 0x88 +#define LIGHTBLUE_ON_GRAY 0x89 +#define LIGHTGREEN_ON_GRAY 0x8a +#define LIGHTCYAN_ON_GRAY 0x8b +#define LIGHTRED_ON_GRAY 0x8c +#define LIGHTMAGENTA_ON_GRAY 0x8d +#define YELLOW_ON_GRAY 0x8e +#define BRIGHTWHITE_ON_GRAY 0x8f + +#define BLACK_ON_LIGHTBLUE 0x90 +#define BLUE_ON_LIGHTBLUE 0x91 +#define GREEN_ON_LIGHTBLUE 0x92 +#define CYAN_ON_LIGHTBLUE 0x93 +#define RED_ON_LIGHTBLUE 0x94 +#define MAGENTA_ON_LIGHTBLUE 0x95 +#define BROWN_ON_LIGHTBLUE 0x96 +#define WHITE_ON_LIGHTBLUE 0x97 +#define GRAY_ON_LIGHTBLUE 0x98 +#define LIGHTBLUE_ON_LIGHTBLUE 0x99 +#define LIGHTGREEN_ON_LIGHTBLUE 0x9a +#define LIGHTCYAN_ON_LIGHTBLUE 0x9b +#define LIGHTRED_ON_LIGHTBLUE 0x9c +#define LIGHTMAGENTA_ON_LIGHTBLUE 0x9d +#define YELLOW_ON_LIGHTBLUE 0x9e +#define BRIGHTWHITE_ON_LIGHTBLUE 0x9f + +#define BLACK_ON_LIGHTGREEN 0xa0 +#define BLUE_ON_LIGHTGREEN 0xa1 +#define GREEN_ON_LIGHTGREEN 0xa2 +#define CYAN_ON_LIGHTGREEN 0xa3 +#define RED_ON_LIGHTGREEN 0xa4 +#define MAGENTA_ON_LIGHTGREEN 0xa5 +#define BROWN_ON_LIGHTGREEN 0xa6 +#define WHITE_ON_LIGHTGREEN 0xa7 +#define GRAY_ON_LIGHTGREEN 0xa8 +#define LIGHTBLUE_ON_LIGHTGREEN 0xa9 +#define LIGHTGREEN_ON_LIGHTGREEN 0xaa +#define LIGHTCYAN_ON_LIGHTGREEN 0xab +#define LIGHTRED_ON_LIGHTGREEN 0xac +#define LIGHTMAGENTA_ON_LIGHTGREEN 0xad +#define YELLOW_ON_LIGHTGREEN 0xae +#define BRIGHTWHITE_ON_LIGHTGREEN 0xaf + +#define BLACK_ON_LIGHTCYAN 0xb0 +#define BLUE_ON_LIGHTCYAN 0xb1 +#define GREEN_ON_LIGHTCYAN 0xb2 +#define CYAN_ON_LIGHTCYAN 0xb3 +#define RED_ON_LIGHTCYAN 0xb4 +#define MAGENTA_ON_LIGHTCYAN 0xb5 +#define BROWN_ON_LIGHTCYAN 0xb6 +#define WHITE_ON_LIGHTCYAN 0xb7 +#define GRAY_ON_LIGHTCYAN 0xb8 +#define LIGHTBLUE_ON_LIGHTCYAN 0xb9 +#define LIGHTGREEN_ON_LIGHTCYAN 0xba +#define LIGHTCYAN_ON_LIGHTCYAN 0xbb +#define LIGHTRED_ON_LIGHTCYAN 0xbc +#define LIGHTMAGENTA_ON_LIGHTCYAN 0xbd +#define YELLOW_ON_LIGHTCYAN 0xbe +#define BRIGHTWHITE_ON_LIGHTCYAN 0xbf + +#define BLACK_ON_LIGHTRED 0xc0 +#define BLUE_ON_LIGHTRED 0xc1 +#define GREEN_ON_LIGHTRED 0xc2 +#define CYAN_ON_LIGHTRED 0xc3 +#define RED_ON_LIGHTRED 0xc4 +#define MAGENTA_ON_LIGHTRED 0xc5 +#define BROWN_ON_LIGHTRED 0xc6 +#define WHITE_ON_LIGHTRED 0xc7 +#define GRAY_ON_LIGHTRED 0xc8 +#define LIGHTBLUE_ON_LIGHTRED 0xc9 +#define LIGHTGREEN_ON_LIGHTRED 0xca +#define LIGHTCYAN_ON_LIGHTRED 0xcb +#define LIGHTRED_ON_LIGHTRED 0xcc +#define LIGHTMAGENTA_ON_LIGHTRED 0xcd +#define YELLOW_ON_LIGHTRED 0xce +#define BRIGHTWHITE_ON_LIGHTRED 0xcf + +#define BLACK_ON_LIGHTMAGENTA 0xd0 +#define BLUE_ON_LIGHTMAGENTA 0xd1 +#define GREEN_ON_LIGHTMAGENTA 0xd2 +#define CYAN_ON_LIGHTMAGENTA 0xd3 +#define RED_ON_LIGHTMAGENTA 0xd4 +#define MAGENTA_ON_LIGHTMAGENTA 0xd5 +#define BROWN_ON_LIGHTMAGENTA 0xd6 +#define WHITE_ON_LIGHTMAGENTA 0xd7 +#define GRAY_ON_LIGHTMAGENTA 0xd8 +#define LIGHTBLUE_ON_LIGHTMAGENTA 0xd9 +#define LIGHTGREEN_ON_LIGHTMAGENTA 0xda +#define LIGHTCYAN_ON_LIGHTMAGENTA 0xdb +#define LIGHTRED_ON_LIGHTMAGENTA 0xdc +#define LIGHTMAGENTA_ON_LIGHTMAGENTA 0xdd +#define YELLOW_ON_LIGHTMAGENTA 0xde +#define BRIGHTWHITE_ON_LIGHTMAGENTA 0xdf + +#define BLACK_ON_YELLOW 0xe0 +#define BLUE_ON_YELLOW 0xe1 +#define GREEN_ON_YELLOW 0xe2 +#define CYAN_ON_YELLOW 0xe3 +#define RED_ON_YELLOW 0xe4 +#define MAGENTA_ON_YELLOW 0xe5 +#define BROWN_ON_YELLOW 0xe6 +#define WHITE_ON_YELLOW 0xe7 +#define GRAY_ON_YELLOW 0xe8 +#define LIGHTBLUE_ON_YELLOW 0xe9 +#define LIGHTGREEN_ON_YELLOW 0xea +#define LIGHTCYAN_ON_YELLOW 0xeb +#define LIGHTRED_ON_YELLOW 0xec +#define LIGHTMAGENTA_ON_YELLOW 0xed +#define YELLOW_ON_YELLOW 0xee +#define BRIGHTWHITE_ON_YELLOW 0xef + +#define BLACK_ON_BRIGHTWHITE 0xf0 +#define BLUE_ON_BRIGHTWHITE 0xf1 +#define GREEN_ON_BRIGHTWHITE 0xf2 +#define CYAN_ON_BRIGHTWHITE 0xf3 +#define RED_ON_BRIGHTWHITE 0xf4 +#define MAGENTA_ON_BRIGHTWHITE 0xf5 +#define BROWN_ON_BRIGHTWHITE 0xf6 +#define WHITE_ON_BRIGHTWHITE 0xf7 +#define GRAY_ON_BRIGHTWHITE 0xf8 +#define LIGHTBLUE_ON_BRIGHTWHITE 0xf9 +#define LIGHTGREEN_ON_BRIGHTWHITE 0xfa +#define LIGHTCYAN_ON_BRIGHTWHITE 0xfb +#define LIGHTRED_ON_BRIGHTWHITE 0xfc +#define LIGHTMAGENTA_ON_BRIGHTWHITE 0xfd +#define YELLOW_ON_BRIGHTWHITE 0xfe +#define BRIGHTWHITE_ON_BRIGHTWHITE 0xff + +#define COMMAND_COLOR GREEN_ON_BLACK +#define CLRSCR_COLOR WHITE_ON_BLACK +#define DEFAULT_COLOR WHITE_ON_BLACK +#define ERROR_COLOR LIGHTRED_ON_BLACK +#define ERROR_COLOR_2 RED_ON_BRIGHTWHITE +#define HALT_COLOR LIGHTRED_ON_BLACK +#define OUTPUT_COLOR CYAN_ON_BLACK +#define PROMPT_COLOR MAGENTA_ON_BLACK +#define VARIABLE_COLOR GREEN_ON_BLACK + +#endif diff --git a/src/drivers/speaker.c b/src/drivers/speaker.c new file mode 100644 index 0000000..b74f5fc --- /dev/null +++ b/src/drivers/speaker.c @@ -0,0 +1,33 @@ +/* DESCRIPTION: E93 PC Speaker Driver Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "speaker.h" + +static void play_sound(uint32_t frequency) +{ + set_PIT_2(frequency); + + uint8_t tmp = port_byte_in(0x61); + if (tmp != (tmp | 3)) + { + port_byte_out(0x61, tmp | 3); + } +} + +static void nosound(void) +{ + uint8_t tmp = port_byte_in(0x61) & 0xFC; + port_byte_out(0x61, tmp); +} + +void beep(void) +{ + asm volatile("sti"); + play_sound(1000); + wait_timer(10); + nosound(); + set_PIT_2(50); +} diff --git a/src/drivers/speaker.h b/src/drivers/speaker.h new file mode 100644 index 0000000..b98fbe4 --- /dev/null +++ b/src/drivers/speaker.h @@ -0,0 +1,18 @@ +/* DESCRIPTION: E93 PC Speaker Driver Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef SPEAKER_H +#define SPEAKER_H + +#include "../cpu/ports.h" +#include "../cpu/timer.h" +#include "../cpu/types.h" + +#include + +void beep(void); + +#endif diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c new file mode 100644 index 0000000..4c74d19 --- /dev/null +++ b/src/kernel/kernel.c @@ -0,0 +1,92 @@ +/* DESCRIPTION: E93 Kernel Main Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + + +#include "kernel.h" + +void kernel_main(void) +{ + clear_screen(); + printk_color("Executing the kernel...\n", OUTPUT_COLOR); + + printk_color("Initializing the ISR...\n", OUTPUT_COLOR); + isr_install(); + + printk_color("Initializing the IRQ...\n", OUTPUT_COLOR); + irq_install(); + + printk_color("\nWelcome to E93!\n", OUTPUT_COLOR); + printk_color("Type HELP for help.\n", OUTPUT_COLOR); + show_prompt(); +} + +void printk_help(void) +{ + printk_color("Type BEEP to beep.\n", OUTPUT_COLOR); + printk_color("Type CLS to clear the screen.\n", OUTPUT_COLOR); + printk_color("Type END to halt the CPU.\n", OUTPUT_COLOR); + printk_color("Type HELP for HELP.\n", OUTPUT_COLOR); + printk_color("Type PAGE to request a kernel allocation.\n", OUTPUT_COLOR); +} + +void show_prompt(void) +{ + printk_color(">", PROMPT_COLOR); +} + +void user_input(char * input) +{ + if (strcmp(input, "BEEP") == 0) + { + beep(); + show_prompt(); + } + else if (strcmp(input, "CLS") == 0) + { + clear_screen(); + show_prompt(); + } + else if (strcmp(input, "END") == 0) + { + printk_color("Halting the CPU...\n", HALT_COLOR); + asm volatile("hlt"); + } + else if (strcmp(input, "HELP") == 0) + { + printk_help(); + show_prompt(); + } + else if (strcmp(input, "PAGE") == 0) + { + uint32_t physical_address = 0; + uint32_t page = kmalloc(1000, 1, &physical_address); + + char page_str[16] = ""; + hex_to_ascii(page, page_str); + + char physical_address_str[16] = ""; + hex_to_ascii(physical_address, physical_address_str); + + printk_color("Memory has been allocated. ", OUTPUT_COLOR); + printk_color("Page: ", OUTPUT_COLOR); + printk_color(page_str, VARIABLE_COLOR); + printk_color("\nPhysical Address: ", OUTPUT_COLOR); + printk_color(physical_address_str, VARIABLE_COLOR); + printk_color("\n", OUTPUT_COLOR); + show_prompt(); + } + else if (strcmp(input, "") == 0) + { + show_prompt(); + } + else + { + printk_color("Unrecognized command: ", ERROR_COLOR); + printk_color(input, COMMAND_COLOR); + printk_color("\n", OUTPUT_COLOR); + show_prompt(); + } +} diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h new file mode 100644 index 0000000..446874e --- /dev/null +++ b/src/kernel/kernel.h @@ -0,0 +1,21 @@ +/* DESCRIPTION: E93 Kernel Main Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef KERNEL_H +#define KERNEL_H + +#include "../cpu/isr.h" +#include "../cpu/timer.h" +#include "../drivers/screen.h" +#include "../drivers/speaker.h" +#include "../libc/memory.h" +#include "../libc/string.h" + +void printk_help(void); +void show_prompt(void); +void user_input(char * input); + +#endif diff --git a/src/libc/function.h b/src/libc/function.h new file mode 100644 index 0000000..6666caa --- /dev/null +++ b/src/libc/function.h @@ -0,0 +1,12 @@ +/* DESCRIPTION: E93 C Library Unused Parameters Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef FUNCTION_H +#define FUNCTION_H + +#define UNUSED(x) (void)(x) + +#endif diff --git a/src/libc/memory.c b/src/libc/memory.c new file mode 100644 index 0000000..a71cf6e --- /dev/null +++ b/src/libc/memory.c @@ -0,0 +1,44 @@ +/* DESCRIPTION: E93 C Library Memory Functions Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "memory.h" + +void memory_copy(uint8_t * source, uint8_t * destination, int n_bytes) +{ + int i = 0; + for (i = 0; i < n_bytes; i++) + { + *(destination + i) = *(source + i); + } +} + +void memory_set(uint8_t * destination, uint8_t value, uint32_t length) +{ + uint8_t * tmp = (uint8_t *) destination; + for( ; length != 0; length--) + { + *tmp = value; + tmp++; + } +} + +uint32_t kmalloc(size_t size, int align, uint32_t * physical_address) +{ + if (align == 1 && (free_memory_address & 0xFFFFF000)) + { + free_memory_address &= 0xFFFFF000; + free_memory_address += 0x1000; + } + + if (physical_address) + { + *physical_address = free_memory_address; + } + + uint32_t temp = free_memory_address; + free_memory_address += size; + return temp; +} diff --git a/src/libc/memory.h b/src/libc/memory.h new file mode 100644 index 0000000..a2dfe8c --- /dev/null +++ b/src/libc/memory.h @@ -0,0 +1,20 @@ +/* DESCRIPTION: E93 C Library Memory Functions Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef MEM_H +#define MEM_H + +#include +#include + +void memory_copy(uint8_t * source, uint8_t * destination, int n_bytes); +void memory_set(uint8_t * destination, uint8_t value, uint32_t length); + +uint32_t free_memory_address = 0x10000; + +uint32_t kmalloc(size_t size, int align, uint32_t * physical_address); + +#endif diff --git a/src/libc/string.c b/src/libc/string.c new file mode 100644 index 0000000..b241d4c --- /dev/null +++ b/src/libc/string.c @@ -0,0 +1,117 @@ +/* DESCRIPTION: E93 C Library String Functions Source File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#include "string.h" + +void int_to_ascii(int n, char str[]) +{ + int i = 0; + int sign = n; + + if (sign < 0) + { + n = -n; + } + + do + { + str[i++] = n % 10 + '0'; + } while((n /= 10) > 0); + + if (sign < 0) + { + str[i++] = '-'; + } + + str[i] = '\0'; + + reverse(str); +} + +void hex_to_ascii(int n, char str[]) +{ + append(str, '0'); + append(str, 'x'); + + char zeroes = 0; + int32_t temp = 0; + for(int i = 28; i > 0; i -= 4) + { + temp = (n >> i) & 0xF; + + if (temp == 0 && zeroes == 0) + { + continue; + } + zeroes = 1; + + if (temp >= 0xA) + { + append(str, temp - 0xA + 'A'); + } + else + { + append(str, temp + '0'); + } + } + + temp = n & 0xF; + if (temp >= 0xA) + { + append(str, temp - 0xA + 'A'); + } + else + { + append(str, temp + '0'); + } +} + +void reverse(char s[]) +{ + int c, i, j; + for (i = 0, j = strlen(s) - 1; i < j; i++, j--) + { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } +} + +int strlen(char s[]) +{ + int i = 0; + while (s[i] != '\0') + { + ++i; + } + return i; +} + +void append(char str[], char n) +{ + int len = strlen(str); + str[len] = n; + str[len + 1] = '\0'; +} + +void backspace(char str[]) +{ + int len = strlen(str); + str[len - 1] = '\0'; +} + +int strcmp(char str_1[], char str_2[]) +{ + int i = 0; + for (i = 0; str_1[i] == str_2[i]; i++) + { + if (str_1[i] == '\0') + { + return 0; + } + } + return str_1[i] - str_2[i]; +} diff --git a/src/libc/string.h b/src/libc/string.h new file mode 100644 index 0000000..a23c22d --- /dev/null +++ b/src/libc/string.h @@ -0,0 +1,22 @@ +/* DESCRIPTION: E93 C Library String Functions Header File + * AUTHOR: Erdem Ersoy (eersoy93) + * COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). + * LICENSE: Licensed with MIT License. See LICENSE file for details. + */ + +#ifndef STRING_H +#define STRING_H + +#include + +void int_to_ascii(int n, char str[]); +void hex_to_ascii(int n, char str[]); + +void reverse(char str[]); +int strlen(char str[]); + +void backspace(char str[]); +void append(char str[], char n); +int strcmp(char str_1[], char str_2[]); + +#endif diff --git a/src/loader/kernel_entry.asm b/src/loader/kernel_entry.asm new file mode 100644 index 0000000..8ff953b --- /dev/null +++ b/src/loader/kernel_entry.asm @@ -0,0 +1,10 @@ +; DESCRIPTION: E93 Kernel Entry Point Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +[bits 32] + +[extern kernel_main] +call kernel_main +jmp $ diff --git a/src/loader/loader.asm b/src/loader/loader.asm new file mode 100644 index 0000000..1bb2f46 --- /dev/null +++ b/src/loader/loader.asm @@ -0,0 +1,58 @@ +; DESCRIPTION: E93 Loader Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +[org 0x7c00] + +KERNEL_OFFSET equ 0x1000 + +mov [BOOT_DRIVE], dl +mov bp, 0x9000 +mov sp, bp + +mov bx, MSG_WELCOME +call print + +mov bx, MSG_ENTER_REALMODE +call print + +call load_kernel +call switch_to_protected_mode +jmp $ + +%include "loader/loader_print.asm" ; E93 Loader Printing Module +%include "loader/loader_print_hex.asm" ; E93 Loader Printing Hex Values Module +%include "loader/loader_disk.asm" ; E93 Loader Disk Module +%include "loader/loader_gdt.asm" ; E93 Loader Global Descriptor Table Module +%include "loader/loader_switch_to_protected_mode.asm" ; E93 Loader Switch to Protected Mode Module +%include "loader/loader_print_protected_mode.asm" ; E93 Loader Printing Module (for Protected Mode) + +[bits 16] + +load_kernel: + mov bx, MSG_LOADING_KERNEL + call print + + mov bx, KERNEL_OFFSET + mov dh, 31 + mov dl, [BOOT_DRIVE] + call disk_load + ret + +[bits 32] + +begin_protected_mode: + mov ebx, MSG_ENTER_PROTECTEDMODE + call print_protected_mode + call KERNEL_OFFSET + jmp $ + +BOOT_DRIVE db 0 +MSG_WELCOME db "Welcome to E93 Loader!", 0 +MSG_ENTER_REALMODE db "Started in 16-bit real mode!", 0 +MSG_LOADING_KERNEL db "Loading the kernel...", 0 +MSG_ENTER_PROTECTEDMODE db "Started in 32-bit protected mode!", 0 + +times 510-($-$$) db 0 +dw 0xaa55 diff --git a/src/loader/loader_disk.asm b/src/loader/loader_disk.asm new file mode 100644 index 0000000..54c1847 --- /dev/null +++ b/src/loader/loader_disk.asm @@ -0,0 +1,44 @@ +; DESCRIPTION: E93 Loader Disk Module Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +disk_load: + pusha + + push dx + + mov ah, 0x02 + mov al, dh + mov cl, 0x02 + + mov ch, 0x00 + mov dh, 0x00 + + int 0x13 + jc disk_error + + pop dx + cmp al, dh + jne sectors_error + + popa + ret + +disk_error: + mov bx, MSG_DISK_ERROR + call print + + mov dh, ah + call print_hex ; For error codes, see INT 13 reference + jmp disk_loop + +sectors_error: + mov bx, MSG_SECTORS_ERROR + call print + +disk_loop: + jmp $ + +MSG_DISK_ERROR db "ERROR: Disk read error! Error code:", 0 +MSG_SECTORS_ERROR db "ERROR: Incorrect number of sectors read!", 0 diff --git a/src/loader/loader_gdt.asm b/src/loader/loader_gdt.asm new file mode 100644 index 0000000..a45995d --- /dev/null +++ b/src/loader/loader_gdt.asm @@ -0,0 +1,33 @@ +; DESCRIPTION: E93 Loader Global Descriptor Table Module Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +gdt_start: + dd 0x0 + dd 0x0 + +gdt_code: + dw 0xffff + dw 0x0 + db 0x0 + db 10011010b + db 11001111b + db 0x0 + +gdt_data: + dw 0xffff + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 + dd gdt_start + +CODE_SEGMENT equ gdt_code - gdt_start +DATA_SEGMENT equ gdt_data - gdt_start diff --git a/src/loader/loader_print.asm b/src/loader/loader_print.asm new file mode 100644 index 0000000..e2da9b3 --- /dev/null +++ b/src/loader/loader_print.asm @@ -0,0 +1,29 @@ +; DESCRIPTION: E93 Loader Printing Module Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +print: + pusha + +print_loop: + mov al, [bx] + cmp al, 0 + je print_done + + ; Print shift out character for printing + mov ah, 0x0e + int 0x10 + + add bx, 1 + jmp print_loop + +print_done: + ; Print newline characters (CR + LF) + mov al, 0x0d + int 0x10 + mov al, 0x0a + int 0x10 + + popa + ret diff --git a/src/loader/loader_print_hex.asm b/src/loader/loader_print_hex.asm new file mode 100644 index 0000000..d8c4dce --- /dev/null +++ b/src/loader/loader_print_hex.asm @@ -0,0 +1,37 @@ +; DESCRIPTION: E93 Loader Printing Hex Values Module Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +print_hex: + pusha + mov cx, 0 + +print_hex_loop: + cmp cx, 4 + je print_hex_end + + mov ax, dx + and ax, 0x000f + add al, 0x30 + cmp al, 0x39 + jle print_hex_step2 + add al, 7 + +print_hex_step2: + mov bx, HEX_OUTPUT + 5 + sub bx, cx + mov [bx], al + ror dx, 4 + + add cx, 1 + jmp print_hex_loop + +print_hex_end: + mov bx, HEX_OUTPUT + call print + + popa + ret + +HEX_OUTPUT db "0x0000", 0 diff --git a/src/loader/loader_print_protected_mode.asm b/src/loader/loader_print_protected_mode.asm new file mode 100644 index 0000000..7afbcc5 --- /dev/null +++ b/src/loader/loader_print_protected_mode.asm @@ -0,0 +1,30 @@ +; DESCRIPTION: E93 Loader Printing (Protected Module) Module Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +[bits 32] + +VIDEO_MEMORY equ 0xb8000 +WHITE_ON_BLACK equ 0x0f + +print_protected_mode: + pusha + mov edx, VIDEO_MEMORY + +print_protected_mode_loop: + mov al, [ebx] + mov ah, WHITE_ON_BLACK + + cmp al, 0 + je print_protected_mode_done + + mov [edx], ax + add ebx, 1 + add edx, 2 + + jmp print_protected_mode_loop + +print_protected_mode_done: + popa + ret diff --git a/src/loader/loader_switch_to_protected_mode.asm b/src/loader/loader_switch_to_protected_mode.asm new file mode 100644 index 0000000..e76f2f5 --- /dev/null +++ b/src/loader/loader_switch_to_protected_mode.asm @@ -0,0 +1,32 @@ +; DESCRIPTION: E93 Loader Switch to Protected Mode Module Assembly File +; AUTHOR: Erdem Ersoy (eersoy93) +; COPYRIGHT: Copyright (c) 2022-2024 Erdem Ersoy (eersoy93). +; LICENSE: Licensed with MIT License. See LICENSE file for details. + +[bits 16] + +switch_to_protected_mode: + cli + + lgdt [gdt_descriptor] + + mov eax, cr0 + or eax, 0x1 + mov cr0, eax + + jmp CODE_SEGMENT:init_protected_mode + +[bits 32] + +init_protected_mode: + mov ax, DATA_SEGMENT + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov ebp, 0x90000 + mov esp, ebp + + call begin_protected_mode