diff --git a/.gitignore b/.gitignore index 2cfa49f..cbbd0b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -i386-elf-toolchain-aur -i386-elf-tools-aur-pkgs +bin/ +obj/ \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 9e6febf..88da4ee 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,7 +3,7 @@ { "name": "Linux", "includePath": [ - "${workspaceFolder}/**" + "${workspaceFolder}/include/**" ], "defines": [], "compilerPath": "/usr/bin/clang", diff --git a/.vscode/settings.json b/.vscode/settings.json index 3e427ab..288d5f0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { "files.associations": { - "idt.h": "c" + "types.h": "c" } } diff --git a/Makefile b/Makefile index c4564c7..fbf99ed 100644 --- a/Makefile +++ b/Makefile @@ -1,56 +1,67 @@ -# $@ = target file -# $< = first dependency -# $^ = all dependencies +ASM := nasm -GDB = gdb +CC := x86_64-elf-gcc +CCFLAGS := -C_FILES = $(shell find src/ -type f -name '*.c') -CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES)) -ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm') -AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES)) -ABIN_FILES = $(patsubst src/%.asm, bin/%.bin, $(ASM_FILES)) +LD := x86_64-elf-ld +LDFLAGS := -os-image.bin: bin/boot.bin bin/kernel.bin - cat $^ > $@ +INCLUDE := include/ -bin/boot.bin: src/boot/boot.asm bin/kernel.bin .FORCE - sed -i.orig "s@CH_REPLACE_BOOTSECTORCOUNT@$(shell ./getinblocks.py $(shell du -b "bin/kernel.bin" | cut -f 1))@g" src/boot/kernel.asm - nasm -Isrc/boot/ $< -f bin -o $@ - mv src/boot/kernel.asm.orig src/boot/kernel.asm +# Target: kernel, type: C ASM +kernel_c_source_files = $(shell find src/kernel/ -type f -name *.c) +kernel_c_object_files = $(patsubst src/%.c,obj/%.o,$(kernel_c_source_files)) +kernel_asm_source_files = $(shell find src/kernel/ -type f -name *.asm) +kernel_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(kernel_asm_source_files)) +kernel_source_files = $(kernel_c_source_files) $(kernel_asm_object_files) +kernel_object_files = $(kernel_c_object_files) $(kernel_asm_object_files) -.FORCE: +# Target: libc, type: C ASM +libc_c_source_files = $(shell find src/libc/ -type f -name *.c) +libc_c_object_files = $(patsubst src/%.c,obj/%.o,$(libc_c_source_files)) +libc_asm_source_files = $(shell find src/libc/ -type f -name *.asm) +libc_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(libc_c_object_files)) +libc_source_files = $(libc_c_source_files) $(libc_asm_source_files) +libc_object_files = $(libc_c_object_files) $(libc_asm_object_files) -bin/kernel.bin: obj/kernel/entry.o ${CO_FILES} ${AO_FILES} - i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary +# Target: sboot, type: ASM +# Override: 32-bit +sboot_asm_source_files = $(shell find src/boot/ -type f -name *.asm) +sboot_asm_object_files = $(patsubst src/%.asm,obj/%.o,$(sboot_asm_source_files)) +sboot_source_files = $(sboot_asm_source_files) +sboot_object_files = $(sboot_asm_object_files) -kernel.elf: obj/kernel/entry.o ${CO_FILES} ${AO_FILES} - i386-elf-ld -o $@ -Ttext 0x1000 $^ +shade_bin_ldfile = src/linker.ld -run: clean os-image.bin - qemu-system-x86_64 -hdd os-image.bin +default: run -debug: clean os-image.bin kernel.elf - qemu-system-x86_64 -s -S -hdd os-image.bin & - ${GDB} os-image.bin -ex "symbol-file kernel.elf" -ex "target remote localhost:1234" +bin/shade.iso: bin/shade.bin + cp bin/shade.bin src/iso/boot/shade.bin + grub-mkrescue src/iso/ -o $@ + rm src/iso/boot/shade.bin +bin/shade.bin: $(sboot_object_files) $(kernel_object_files) $(libc_object_files) + mkdir -p "$(@D)" + $(LD) $(LDFLAGS) -n -T $(shade_bin_ldfile) $^ -o $@ + grub-file --is-x86-multiboot2 $@ +# Generics +# Source file types: C ASM +# C obj/%.o: src/%.c mkdir -p "$(@D)" - i386-elf-gcc -g -ffreestanding -c $< -o $@ + $(CC) $(CCFLAGS) -I $(INCLUDE) -ffreestanding -c $< -o $@ +# ASM obj/%.o: src/%.asm mkdir -p "$(@D)" - nasm -f elf $< -o $@ + $(ASM) -felf64 $< -o $@ -bin/%.bin: src/%.asm - mkdir -p "$(@D)" - nasm -f bin $< -o $@ +# Other +run: clean bin/shade.iso + qemu-system-x86_64 -drive file=bin/shade.iso,index=0,media=disk,format=raw clean: - find obj -type f -name '*.o' -exec rm {} + - find obj -type f -name '*.bin' -exec rm {} + - find bin -type f -name '*.o' -exec rm {} + - find bin -type f -name '*.bin' -exec rm {} + - find . -type f -name '*.dis' -exec rm {} + - rm -f kernel.elf \ No newline at end of file + rm -rf bin/* + rm -rf obj/* \ No newline at end of file diff --git a/bin/boot.bin b/bin/boot.bin deleted file mode 100644 index 9a84534..0000000 Binary files a/bin/boot.bin and /dev/null differ diff --git a/bin/kernel.bin b/bin/kernel.bin deleted file mode 100755 index 746678e..0000000 Binary files a/bin/kernel.bin and /dev/null differ diff --git a/bochsrc.txt b/bochsrc.txt new file mode 100644 index 0000000..2ba3db3 --- /dev/null +++ b/bochsrc.txt @@ -0,0 +1,57 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false +config_interface: textconfig +display_library: x +memory: host=32, guest=32 +romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44 +# no floppyb +ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path="bin/shade.iso", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto +ata0-slave: type=none +ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=false +ata3: enabled=false +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none +vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin +cpu: count=1:1:1, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor" +cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true +cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, avx_f16c=false +cpuid: avx_fma=false, bmi=0, xop=false, fma4=false, tbm=false, x86_64=true, 1g_pages=false +cpuid: pcid=false, fsgsbase=false, smep=false, smap=false, mwait=true +print_timestamps: enabled=0 +debugger_log: - +magic_break: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +log: - +logprefix: %t%e%d +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none +mouse: type=ps2, enabled=false, toggle=ctrl+mbutton +speaker: enabled=true, mode=system +parport1: enabled=true, file=none +parport2: enabled=false +com1: enabled=true, mode=null +com2: enabled=false +com3: enabled=false +com4: enabled=false diff --git a/src/kernel/platform/drivers/ports.h b/include/shade/platform/ports.h similarity index 100% rename from src/kernel/platform/drivers/ports.h rename to include/shade/platform/ports.h diff --git a/src/kernel/print.h b/include/shade/print.h similarity index 100% rename from src/kernel/print.h rename to include/shade/print.h diff --git a/src/kernel/util.h b/include/shade/util.h similarity index 100% rename from src/kernel/util.h rename to include/shade/util.h diff --git a/src/kernel/strings.h b/include/strings.h similarity index 100% rename from src/kernel/strings.h rename to include/strings.h diff --git a/old_src/16bit/boot.asm b/learning/old_src/16bit/boot.asm similarity index 100% rename from old_src/16bit/boot.asm rename to learning/old_src/16bit/boot.asm diff --git a/old_src/16bit/disk.asm b/learning/old_src/16bit/disk.asm similarity index 100% rename from old_src/16bit/disk.asm rename to learning/old_src/16bit/disk.asm diff --git a/old_src/16bit/disk_boot.asm b/learning/old_src/16bit/disk_boot.asm similarity index 100% rename from old_src/16bit/disk_boot.asm rename to learning/old_src/16bit/disk_boot.asm diff --git a/old_src/16bit/segmentation.asm b/learning/old_src/16bit/segmentation.asm similarity index 100% rename from old_src/16bit/segmentation.asm rename to learning/old_src/16bit/segmentation.asm diff --git a/old_src/32bit_gdt.asm b/learning/old_src/32bit_gdt.asm similarity index 100% rename from old_src/32bit_gdt.asm rename to learning/old_src/32bit_gdt.asm diff --git a/old_src/32bit_jump.asm b/learning/old_src/32bit_jump.asm similarity index 100% rename from old_src/32bit_jump.asm rename to learning/old_src/32bit_jump.asm diff --git a/old_src/32bit_main.asm b/learning/old_src/32bit_main.asm similarity index 100% rename from old_src/32bit_main.asm rename to learning/old_src/32bit_main.asm diff --git a/old_src/32bit_print.asm b/learning/old_src/32bit_print.asm similarity index 100% rename from old_src/32bit_print.asm rename to learning/old_src/32bit_print.asm diff --git a/old_src/function.c b/learning/old_src/function.c similarity index 100% rename from old_src/function.c rename to learning/old_src/function.c diff --git a/old_src/functioncalls.c b/learning/old_src/functioncalls.c similarity index 100% rename from old_src/functioncalls.c rename to learning/old_src/functioncalls.c diff --git a/old_src/old-16b/basic_boot.asm b/learning/old_src/old-16b/basic_boot.asm similarity index 100% rename from old_src/old-16b/basic_boot.asm rename to learning/old_src/old-16b/basic_boot.asm diff --git a/old_src/old-16b/boot_hello.asm b/learning/old_src/old-16b/boot_hello.asm similarity index 100% rename from old_src/old-16b/boot_hello.asm rename to learning/old_src/old-16b/boot_hello.asm diff --git a/old_src/old-16b/boot_memory.asm b/learning/old_src/old-16b/boot_memory.asm similarity index 100% rename from old_src/old-16b/boot_memory.asm rename to learning/old_src/old-16b/boot_memory.asm diff --git a/old_src/old-16b/boot_org.asm b/learning/old_src/old-16b/boot_org.asm similarity index 100% rename from old_src/old-16b/boot_org.asm rename to learning/old_src/old-16b/boot_org.asm diff --git a/old_src/old-16b/boot_stack.asm b/learning/old_src/old-16b/boot_stack.asm similarity index 100% rename from old_src/old-16b/boot_stack.asm rename to learning/old_src/old-16b/boot_stack.asm diff --git a/old_src/old_bin/boot_hello.bin b/learning/old_src/old_bin/boot_hello.bin similarity index 100% rename from old_src/old_bin/boot_hello.bin rename to learning/old_src/old_bin/boot_hello.bin diff --git a/old_src/old_bin/boot_memory.bin b/learning/old_src/old_bin/boot_memory.bin similarity index 100% rename from old_src/old_bin/boot_memory.bin rename to learning/old_src/old_bin/boot_memory.bin diff --git a/old_src/old_bin/boot_simple.bin b/learning/old_src/old_bin/boot_simple.bin similarity index 100% rename from old_src/old_bin/boot_simple.bin rename to learning/old_src/old_bin/boot_simple.bin diff --git a/old_src/old_bin/boot_stack.bin b/learning/old_src/old_bin/boot_stack.bin similarity index 100% rename from old_src/old_bin/boot_stack.bin rename to learning/old_src/old_bin/boot_stack.bin diff --git a/old_src/print.asm b/learning/old_src/print.asm similarity index 100% rename from old_src/print.asm rename to learning/old_src/print.asm diff --git a/old_src/print_hex.asm b/learning/old_src/print_hex.asm similarity index 100% rename from old_src/print_hex.asm rename to learning/old_src/print_hex.asm diff --git a/obj/kernel/entry.o b/obj/kernel/entry.o deleted file mode 100644 index fa6bc54..0000000 Binary files a/obj/kernel/entry.o and /dev/null differ diff --git a/obj/kernel/kernel.o b/obj/kernel/kernel.o index 987d3fc..66bfda7 100644 Binary files a/obj/kernel/kernel.o and b/obj/kernel/kernel.o differ diff --git a/obj/kernel/platform/drivers/ports.o b/obj/kernel/platform/drivers/ports.o deleted file mode 100644 index 1b53202..0000000 Binary files a/obj/kernel/platform/drivers/ports.o and /dev/null differ diff --git a/obj/kernel/platform/interrupts/int.o b/obj/kernel/platform/interrupts/int.o deleted file mode 100644 index 14dbc95..0000000 Binary files a/obj/kernel/platform/interrupts/int.o and /dev/null differ diff --git a/obj/kernel/platform/interrupts/int_lowlevel.o b/obj/kernel/platform/interrupts/int_lowlevel.o deleted file mode 100644 index 98f9819..0000000 Binary files a/obj/kernel/platform/interrupts/int_lowlevel.o and /dev/null differ diff --git a/obj/kernel/print.o b/obj/kernel/print.o index 6a393f3..99394ea 100644 Binary files a/obj/kernel/print.o and b/obj/kernel/print.o differ diff --git a/obj/kernel/strings.o b/obj/kernel/strings.o deleted file mode 100644 index 107b607..0000000 Binary files a/obj/kernel/strings.o and /dev/null differ diff --git a/obj/kernel/util.o b/obj/kernel/util.o index 5e77ddb..7032cdd 100644 Binary files a/obj/kernel/util.o and b/obj/kernel/util.o differ diff --git a/old/Makefile b/old/Makefile new file mode 100644 index 0000000..825ff4d --- /dev/null +++ b/old/Makefile @@ -0,0 +1,56 @@ +# $@ = target file +# $< = first dependency +# $^ = all dependencies + +GDB = gdb + +C_FILES = $(shell find src/ -type f -name '*.c') +CO_FILES = $(patsubst src/%.c, obj/%.o, $(C_FILES)) +ASM_FILES = $(shell find src/kernel/ -type f -name '*.asm') +AO_FILES = $(patsubst src/kernel/%.asm, obj/kernel/%.o, $(ASM_FILES)) +ABIN_FILES = $(patsubst src/%.asm, bin/%.bin, $(ASM_FILES)) + +os-image.bin: bin/boot.bin bin/kernel.bin + cat $^ > $@ + +bin/boot.bin: src/boot/boot.asm bin/kernel.bin .FORCE + sed -i.orig "s@CH_REPLACE_BOOTSECTORCOUNT@$(shell ./getinblocks.py $(shell du -b "bin/kernel.bin" | cut -f 1))@g" src/boot/kernel.asm + nasm -Isrc/boot/ $< -f bin -o $@ + mv src/boot/kernel.asm.orig src/boot/kernel.asm + +.FORCE: + +bin/kernel.bin: obj/kernel/entry.o ${CO_FILES} ${AO_FILES} + i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary + +kernel.elf: obj/kernel/entry.o ${CO_FILES} ${AO_FILES} + i386-elf-ld -o $@ -Ttext 0x1000 $^ + +run: clean os-image.bin + qemu-system-x86_64 -hdd os-image.bin -d int + +debug: clean os-image.bin kernel.elf + qemu-system-x86_64 -s -S -hdd os-image.bin & + ${GDB} os-image.bin -ex "symbol-file kernel.elf" -ex "target remote localhost:1234" + + + +obj/%.o: src/%.c + mkdir -p "$(@D)" + i386-elf-gcc -g -ffreestanding -c $< -o $@ + +obj/%.o: src/%.asm + mkdir -p "$(@D)" + nasm -f elf $< -o $@ + +bin/%.bin: src/%.asm + mkdir -p "$(@D)" + nasm -f bin $< -o $@ + +clean: + find obj -type f -name '*.o' -exec rm {} + + find obj -type f -name '*.bin' -exec rm {} + + find bin -type f -name '*.o' -exec rm {} + + find bin -type f -name '*.bin' -exec rm {} + + find . -type f -name '*.dis' -exec rm {} + + rm -f kernel.elf \ No newline at end of file diff --git a/getinblocks.py b/old/getinblocks.py similarity index 100% rename from getinblocks.py rename to old/getinblocks.py diff --git a/old/os-image.bin b/old/os-image.bin new file mode 100644 index 0000000..4683e53 Binary files /dev/null and b/old/os-image.bin differ diff --git a/src/boot/boot.asm b/old/src/boot/boot.asm similarity index 100% rename from src/boot/boot.asm rename to old/src/boot/boot.asm diff --git a/src/boot/disk/disk.asm b/old/src/boot/disk/disk.asm similarity index 100% rename from src/boot/disk/disk.asm rename to old/src/boot/disk/disk.asm diff --git a/src/boot/kernel.asm b/old/src/boot/kernel.asm similarity index 100% rename from src/boot/kernel.asm rename to old/src/boot/kernel.asm diff --git a/src/boot/output/print.asm b/old/src/boot/output/print.asm similarity index 100% rename from src/boot/output/print.asm rename to old/src/boot/output/print.asm diff --git a/src/boot/output/print_hex.asm b/old/src/boot/output/print_hex.asm similarity index 100% rename from src/boot/output/print_hex.asm rename to old/src/boot/output/print_hex.asm diff --git a/src/boot/output/vga-print.asm b/old/src/boot/output/vga-print.asm similarity index 100% rename from src/boot/output/vga-print.asm rename to old/src/boot/output/vga-print.asm diff --git a/src/boot/protected/gdt.asm b/old/src/boot/protected/gdt.asm similarity index 72% rename from src/boot/protected/gdt.asm rename to old/src/boot/protected/gdt.asm index 2618221..df7bfe2 100644 --- a/src/boot/protected/gdt.asm +++ b/old/src/boot/protected/gdt.asm @@ -1,3 +1,4 @@ + gdt_start: ; use labels to compute sizes and jumps ; gdt starts with 8 byte null dd 0x0 @@ -14,12 +15,12 @@ gdt_code: ; GDT for data segment gdt_data: - dw 0xffff - dw 0x0 - db 0x0 - db 10010010b - db 11001111b - db 0x0 + dw 0xffff ; segment length + dw 0x0 ; segment base + db 0x0 ; segment base + db 10010010b ; flags + db 11001111b ; flags + segment length + db 0x0 ; segment base gdt_end: diff --git a/src/boot/protected/protected-switch.asm b/old/src/boot/protected/protected-switch.asm similarity index 100% rename from src/boot/protected/protected-switch.asm rename to old/src/boot/protected/protected-switch.asm diff --git a/src/kernel/entry.asm b/old/src/kernel/entry.asm similarity index 100% rename from src/kernel/entry.asm rename to old/src/kernel/entry.asm diff --git a/old/src/kernel/kernel.c b/old/src/kernel/kernel.c new file mode 100644 index 0000000..a3f295a --- /dev/null +++ b/old/src/kernel/kernel.c @@ -0,0 +1,54 @@ +#include "./platform/drivers/ports.h" +#include "print.h" +#include "./platform/types.h" +#include "./platform/interrupts/int.h" + +void dummy_test_entrypoint() {} + +void kernel_welcome() { + print_str("Welcome to "); + print_set_color(PRINT_COLOR_CYAN, PRINT_COLOR_BLACK); + print_str("Shade"); + print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); + print_str("!\n"); + + print_str("shadeOS kernel version "); + + print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK); + print_str("0.2.2"); + + print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); + print_newline(); + + print_str("Running on "); + + print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK); + print_str("shade-development"); + + print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); + + print_newline(); +} + +// kMain +void main() { + // Initialize screen buffer + struct Char* buffer = (struct Char*) 0xb8000; + + clear_all(); // Clear screen + set_cursor_pos(0, 0); // Set cursor position + print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set print color + + // welcome messages + kernel_msg_ok("Initialized display successfully\n"); + kernel_welcome(); + + print_str("Copyright (c) e3team 2022. All rights reserved.\n"); + print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n"); + print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n"); + + idt_init(); + kernel_msg_ok("Interrupts initialized"); + + __asm__ __volatile__("int $2"); +} \ No newline at end of file diff --git a/src/kernel/platform/drivers/ports.c b/old/src/kernel/platform/drivers/ports.c similarity index 100% rename from src/kernel/platform/drivers/ports.c rename to old/src/kernel/platform/drivers/ports.c diff --git a/old/src/kernel/platform/drivers/ports.h b/old/src/kernel/platform/drivers/ports.h new file mode 100644 index 0000000..d616f0e --- /dev/null +++ b/old/src/kernel/platform/drivers/ports.h @@ -0,0 +1,4 @@ +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); \ No newline at end of file diff --git a/old/src/kernel/platform/gdt.h b/old/src/kernel/platform/gdt.h new file mode 100644 index 0000000..5545747 --- /dev/null +++ b/old/src/kernel/platform/gdt.h @@ -0,0 +1,28 @@ +#ifndef GDT_H +#define GDT_H + +#include + +// the GDT descriptor format makes literally no sense, who came up with this +typedef struct { + uint16_t limit_low16; // Low 16 bits of limit + uint16_t base_low16; // Low 16 bits of base + uint8_t base_mid8; // Middle 8 bits of base + uint8_t access; // 7: present, 6-5: priv level, 4: type, 3: executable, 2: dc, 1: rw, 0: accessed (zero) + uint8_t limit_flags; // High 4 bits of limit AND flags (?? why). flags: 3: granularity, 2: size, 1: long, 0: reserved + uint8_t base_high8; // High 8 bits of base +} __attribute__((packed)) gdt_entry_t; + +typedef struct { + uint16_t size; // GDT size (bytes) - 1 + uint32_t offset; // Address of element 0 of the GDT +} __attribute__((packed)) gdt_ptr_t; + +static gdt_entry_t gdt[8192]; +static gdt_ptr_t gdtr; + +void init_gdt(); +void gdt_set_segment(int limit, int base, int access); +void load_gdt(); + +#endif \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int.c b/old/src/kernel/platform/interrupts/int.c similarity index 85% rename from src/kernel/platform/interrupts/int.c rename to old/src/kernel/platform/interrupts/int.c index 3e63985..4b77162 100644 --- a/src/kernel/platform/interrupts/int.c +++ b/old/src/kernel/platform/interrupts/int.c @@ -1,8 +1,14 @@ #include "int.h" #include "../../print.h" -void exception_handler() { +int count = 0; + +void exception_handler(registers_t r) { print_str("I"); + count++; + if (count > 4) { + __asm__ __volatile__("cli; hlt"); + } } void idt_set_descriptor(u8 vector, void* isr, u8 flags) { diff --git a/src/kernel/platform/interrupts/int.h b/old/src/kernel/platform/interrupts/int.h similarity index 69% rename from src/kernel/platform/interrupts/int.h rename to old/src/kernel/platform/interrupts/int.h index a58b890..3f36fc9 100644 --- a/src/kernel/platform/interrupts/int.h +++ b/old/src/kernel/platform/interrupts/int.h @@ -21,8 +21,15 @@ typedef struct { static idtr_t idtr; +typedef struct { + u32 ds; /* Data segment selector */ + u32 edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */ + u32 int_no, err_code; /* Interrupt number and error code (if applicable) */ + u32 eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */ +} registers_t; + __attribute__((noreturn)) -void exception_handler(void); +void exception_handler(registers_t r); void idt_set_descriptor(u8 vector, void* isr, u8 flags); diff --git a/old/src/kernel/platform/interrupts/int_lowlevel.asm b/old/src/kernel/platform/interrupts/int_lowlevel.asm new file mode 100644 index 0000000..0d2f397 --- /dev/null +++ b/old/src/kernel/platform/interrupts/int_lowlevel.asm @@ -0,0 +1,102 @@ +%macro isr_err_stub 1 +isr_stub_%+%1: + push byte %1 ; Push interrupt no to stack + + ; 1. Save CPU state + pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + mov ax, ds ; Lower 16-bits of eax = ds. + push eax ; save the data segment descriptor + mov ax, 0x10 ; kernel data segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; 2. Call C handler + call exception_handler + + ; 3. Restore state + pop eax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + popa + add esp, 8 ; Cleans up the pushed error code and pushed ISR number + sti + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP +%endmacro +; if writing for 64-bit, use iretq instead +%macro isr_no_err_stub 1 +isr_stub_%+%1: + push byte 0 ; No error occured + push byte %1 ; Push interrupt no to stack + + ; 1. Save CPU state + pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + mov ax, ds ; Lower 16-bits of eax = ds. + push eax ; save the data segment descriptor + mov ax, 0x10 ; kernel data segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; 2. Call C handler + call exception_handler + + ; 3. Restore state + pop eax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + popa + add esp, 8 ; Cleans up the pushed error code and pushed ISR number + sti + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP +%endmacro + +extern exception_handler + +isr_no_err_stub 0 +isr_no_err_stub 1 +isr_no_err_stub 2 +isr_no_err_stub 3 +isr_no_err_stub 4 +isr_no_err_stub 5 +isr_no_err_stub 6 +isr_no_err_stub 7 +isr_err_stub 8 +isr_no_err_stub 9 +isr_err_stub 10 +isr_err_stub 11 +isr_err_stub 12 +isr_err_stub 13 +isr_err_stub 14 +isr_no_err_stub 15 +isr_no_err_stub 16 +isr_err_stub 17 +isr_no_err_stub 18 +isr_no_err_stub 19 +isr_no_err_stub 20 +isr_no_err_stub 21 +isr_no_err_stub 22 +isr_no_err_stub 23 +isr_no_err_stub 24 +isr_no_err_stub 25 +isr_no_err_stub 26 +isr_no_err_stub 27 +isr_no_err_stub 28 +isr_no_err_stub 29 +isr_err_stub 30 +isr_no_err_stub 31 + +global isr_stub_table +isr_stub_table: +%assign i 0 +%rep 32 + dd isr_stub_%+i ; use DQ instead if targeting 64-bit +%assign i i+1 +%endrep + diff --git a/src/kernel/platform/types.h b/old/src/kernel/platform/types.h similarity index 100% rename from src/kernel/platform/types.h rename to old/src/kernel/platform/types.h diff --git a/old/src/kernel/print.c b/old/src/kernel/print.c new file mode 100644 index 0000000..014de03 --- /dev/null +++ b/old/src/kernel/print.c @@ -0,0 +1,110 @@ +#include "print.h" +#include "./platform/drivers/ports.h" + +int row = 0; +int col = 0; +char color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4; + +void clear_row(int row) { + struct Char* buffer = (struct Char*) 0xb8000; + + struct Char empty = (struct Char) { + character: ' ', + color: color, + }; + + for (int x = 0; x < NUM_COLS; x++) { + buffer[x + NUM_COLS * row] = empty; + } + set_cursor_pos(col, row); +} + +void clear_all() { + for (int i = 0; i < NUM_ROWS; i++) { + clear_row(i); + } + set_cursor_pos(col, row); +} + +void print_newline() { + struct Char* buffer = (struct Char*) 0xb8000; + + col = 0; + + if (row < NUM_ROWS - 1) { + row++; + return; + } + + for (int row = 1; row < NUM_ROWS; row++) { + for (int col = 0; col < NUM_COLS; col++) { + struct Char character = buffer[col + NUM_COLS * row]; + buffer[col + NUM_COLS * (row - 1)] = character; + } + } + + clear_row(NUM_COLS - 1); + set_cursor_pos(col, row); +} + +void print_char(char character) { + struct Char* buffer = (struct Char*) 0xb8000; + + if (character == '\n') { + print_newline(); + return; + } + + if (col > NUM_COLS) { + print_newline(); + } + + struct Char cr = (struct Char) { + character: character, + color: color, + }; + buffer[col + NUM_COLS * row] = cr; + + col++; + set_cursor_pos(col, row); +} + +void print_str(char* str) { + for (int i = 0; 1; i++) { + char character = (char) str[i]; + + if (character == '\0') { + return; + } + + print_char(character); + } +} + +void print_set_color(char foreground, char background) { + color = foreground + (background << 4); +} + +void set_cursor_pos(int col, int row) { + int offset = col + NUM_COLS * row; + port_byte_out(REG_SCREEN_CTRL, 14); + port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8)); + port_byte_out(REG_SCREEN_CTRL, 15); + port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff)); +} + +void kernel_msg_ok(char* msg) { + char ok_p1[] = "[ "; + char ok_p2[] = "OK "; + char ok_p3[] = "] "; + + print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); + print_str(ok_p1); + + print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK); + print_str(ok_p2); + + print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); + print_str(ok_p3); + print_str(msg); +} \ No newline at end of file diff --git a/old/src/kernel/print.h b/old/src/kernel/print.h new file mode 100644 index 0000000..edd8a9e --- /dev/null +++ b/old/src/kernel/print.h @@ -0,0 +1,44 @@ +#ifndef PRINT_H +#define PRINT_H +#define REG_SCREEN_CTRL 0x3d4 +#define REG_SCREEN_DATA 0x3d5 + +enum { + PRINT_COLOR_BLACK = 0, + PRINT_COLOR_BLUE = 1, + PRINT_COLOR_GREEN = 2, + PRINT_COLOR_CYAN = 3, + PRINT_COLOR_RED = 4, + PRINT_COLOR_MAGENTA = 5, + PRINT_COLOR_BROWN = 6, + PRINT_COLOR_LIGHT_GRAY = 7, + PRINT_COLOR_DARK_GRAY = 8, + PRINT_COLOR_LIGHT_BLUE = 9, + PRINT_COLOR_LIGHT_GREEN = 10, + PRINT_COLOR_LIGHT_CYAN = 11, + PRINT_COLOR_LIGHT_RED = 12, + PRINT_COLOR_PINK = 13, + PRINT_COLOR_YELLOW = 14, + PRINT_COLOR_WHITE = 15, +}; + +const static int NUM_COLS = 80; +const static int NUM_ROWS = 25; + +struct Char { + char character; + char color; +}; + +void clear_row(int row); +void clear_all(); + +void print_newline(); +void print_char(char character); +void print_set_color(char foreground, char background); +void print_str(char* str); + +void set_cursor_pos(int col, int row); + +void kernel_msg_ok(char* msg); +#endif \ No newline at end of file diff --git a/src/kernel/strings.c b/old/src/kernel/strings.c similarity index 100% rename from src/kernel/strings.c rename to old/src/kernel/strings.c diff --git a/old/src/kernel/strings.h b/old/src/kernel/strings.h new file mode 100644 index 0000000..ee4402a --- /dev/null +++ b/old/src/kernel/strings.h @@ -0,0 +1,10 @@ +#ifndef STRINGS_H +#define STRINGS_H + +void itoa(int n, char str[]); +void strrev(char s[]); +int strlen(char s[]); +char* strcpy(char* strDest, const char* strSrc); +char* strcnc(char* str1, char* str2); + +#endif \ No newline at end of file diff --git a/old/src/kernel/util.c b/old/src/kernel/util.c new file mode 100644 index 0000000..e945d94 --- /dev/null +++ b/old/src/kernel/util.c @@ -0,0 +1,25 @@ +#include "util.h" + +void memcpy(char *source, char *dest, int nbytes) { + int i; + for (i = 0; i < nbytes; i++) { + *(dest + i) = *(source + i); + } +} + +void memset(char *dest, char val, int len) { + char *temp = (char *)dest; + for(; len !=0; len--) *temp++ = val; +} + +void int_to_ascii(int n, char str[]) { + int i, sign; + if ((sign = n) < 0) n = -n; + i = 0; + do { + str[i++] = n % 10 + '0'; + } while ((n /= 10) > 0); + + if (sign < 0) str[i++] = '-'; + str[i] = '\0'; +} \ No newline at end of file diff --git a/old/src/kernel/util.h b/old/src/kernel/util.h new file mode 100644 index 0000000..889ccb0 --- /dev/null +++ b/old/src/kernel/util.h @@ -0,0 +1,8 @@ +#ifndef UTIL_H +#define UTIL_H + +void memcpy(char *source, char *dest, int nbytes); +void memset(char *dest, char val, int len); +void int_to_ascii(int n, char str[]); + +#endif \ No newline at end of file diff --git a/os-image.bin b/os-image.bin deleted file mode 100644 index 5d875f0..0000000 Binary files a/os-image.bin and /dev/null differ diff --git a/src/boot/entry.asm b/src/boot/entry.asm new file mode 100644 index 0000000..fe7a356 --- /dev/null +++ b/src/boot/entry.asm @@ -0,0 +1,141 @@ + + +global entry_x86 +extern entry_x64 + +section .text +bits 32 +entry_x86: + mov esp, stack_top + + call check_mb2_boot + call check_cpuid + call check_x64_supported + + call setup_page_tables + call enable_paging + + lgdt [gdt64.pointer] + jmp gdt64.code_segment:entry_x64 ; Jump into 64 bit entry + + hlt + +check_mb2_boot: + cmp eax, 0x36d76289 ; compare eax to mb2 magic number + jne .mb2_not_booted + ret +.mb2_not_booted: + mov al, "B" ; err code B - boot error + jmp error + +check_cpuid: + pushfd ; Put flags on stack so we can mess with them + pop eax ; then put the stack into EAX so we can easily modify it + mov ecx, eax ; Make a copy of eax in ecx for comparison + xor eax, 1 << 21 ; Attempt to flip the CPUID bit which is bit 21 + push eax ; Put eax back onto stack + popfd ; Write flags back + pushfd ; Copy flags onto stack so we can check if the bit did flip + pop eax ; Put stack into EAX for comparison + push ecx ; Put original flags into stack so we can make sure they remain unchanged + popfd; Push original flags back onto the flags register + cmp eax, ecx ; Compare the modifided? flags to the original flags + je .cpuid_unsupported ; Flags were not changed, cpuid not supported + ret + +.cpuid_unsupported: + mov al, "C" ; err code C - cpuid unsupported + jmp error + +check_x64_supported: + mov eax, 0x80000000 ; Magic code that i dont understand + cpuid ; Magic code that i dont understand + cmp eax, 0x80000001 ; Magic code that i dont undetstand + jb .x64_unsupported ; Something went wrong so x64 isnt supported + + mov eax, 0x80000001 ; Set magic value 0x80000001 into EAX for cpuid + cpuid ; Get "extended features list" from CPU info + test edx, 1 << 29 ; Check if x64 is supported by checking bit 29 + jz .x64_unsupported ; If zero, x64 unsupported so jump to no x64 + + ret +.x64_unsupported: + mov al, "L" ; err code L, long mode/x64 unsupported + jmp error + +; Magic paging code that I don't understand +setup_page_tables: + mov eax, page_table_l3 + or eax, 0b11 ; present, writable + mov [page_table_l4], eax + + mov eax, page_table_l2 + or eax, 0b11 ; present, writable + mov [page_table_l3], eax + + mov ecx, 0 ; counter +.loop: + + mov eax, 0x200000 ; 2MiB + mul ecx + or eax, 0b10000011 ; present, writable, huge page + mov [page_table_l2 + ecx * 8], eax + + inc ecx ; increment counter + cmp ecx, 512 ; checks if the whole table is mapped + jne .loop ; if not, continue + + ret + +enable_paging: + ; pass page table location to cpu + mov eax, page_table_l4 + mov cr3, eax + + ; enable PAE + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + ; enable long mode + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + + ; enable paging + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret + +error: + ; print "ERR: X" where X is the error code + mov dword [0xb8000], 0x4f524f45 + mov dword [0xb8004], 0x4f3a4f52 + mov dword [0xb8008], 0x4f204f20 + mov byte [0xb800a], al + hlt + +section .bss +align 4096 +page_table_l4: + resb 4096 +page_table_l3: + resb 4096 +page_table_l2: + resb 4096 +stack_bottom: + resb 4096 * 4 +stack_top: + +section .rodata +gdt64: + dd 0 ; zero entry + dd 0 +.code_segment: equ $ - gdt64 + dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment +.pointer: + dw $ - gdt64 - 1 ; length + dq gdt64 ; address \ No newline at end of file diff --git a/src/boot/entry64.asm b/src/boot/entry64.asm new file mode 100644 index 0000000..2d10b51 --- /dev/null +++ b/src/boot/entry64.asm @@ -0,0 +1,17 @@ +global entry_x64 +extern kmain + +section .text +bits 64 +entry_x64: + ; Nullify all data registers + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + call kmain ; Jump into C kernel entry + + hlt \ No newline at end of file diff --git a/src/boot/mb2_header.asm b/src/boot/mb2_header.asm new file mode 100644 index 0000000..5eabae1 --- /dev/null +++ b/src/boot/mb2_header.asm @@ -0,0 +1,16 @@ +section .mb2_header +header_start: + ; https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html for more information, section 3.1.1 + dd 0xe85250d6 ; multiboot2 magic number + + dd 0 ; i386 protected 32 bit mode + + dd header_end - header_start ; Header length + + dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) ; Checksum, total is 0 + + ; Ending tag + dw 0 + dw 0 + dd 8 +header_end: \ No newline at end of file diff --git a/src/iso/boot/grub/grub.cfg b/src/iso/boot/grub/grub.cfg new file mode 100644 index 0000000..9c6aeb4 --- /dev/null +++ b/src/iso/boot/grub/grub.cfg @@ -0,0 +1,7 @@ +set timeout=5 +set default=0 + +menuentry "shadeOS Development Build" { + multiboot2 /boot/shade.bin + boot +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index a3f295a..84b5789 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,9 +1,5 @@ -#include "./platform/drivers/ports.h" -#include "print.h" -#include "./platform/types.h" -#include "./platform/interrupts/int.h" - -void dummy_test_entrypoint() {} +#include +#include void kernel_welcome() { print_str("Welcome to "); @@ -31,7 +27,7 @@ void kernel_welcome() { } // kMain -void main() { +void kmain() { // Initialize screen buffer struct Char* buffer = (struct Char*) 0xb8000; @@ -47,8 +43,4 @@ void main() { print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n"); print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n"); - idt_init(); - kernel_msg_ok("Interrupts initialized"); - - __asm__ __volatile__("int $2"); } \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int_lowlevel.asm b/src/kernel/platform/interrupts/int_lowlevel.asm deleted file mode 100644 index a38fd41..0000000 --- a/src/kernel/platform/interrupts/int_lowlevel.asm +++ /dev/null @@ -1,54 +0,0 @@ -%macro isr_err_stub 1 -isr_stub_%+%1: - call exception_handler - iret -%endmacro -; if writing for 64-bit, use iretq instead -%macro isr_no_err_stub 1 -isr_stub_%+%1: - call exception_handler - iret -%endmacro - -extern exception_handler -isr_no_err_stub 0 -isr_no_err_stub 1 -isr_no_err_stub 2 -isr_no_err_stub 3 -isr_no_err_stub 4 -isr_no_err_stub 5 -isr_no_err_stub 6 -isr_no_err_stub 7 -isr_err_stub 8 -isr_no_err_stub 9 -isr_err_stub 10 -isr_err_stub 11 -isr_err_stub 12 -isr_err_stub 13 -isr_err_stub 14 -isr_no_err_stub 15 -isr_no_err_stub 16 -isr_err_stub 17 -isr_no_err_stub 18 -isr_no_err_stub 19 -isr_no_err_stub 20 -isr_no_err_stub 21 -isr_no_err_stub 22 -isr_no_err_stub 23 -isr_no_err_stub 24 -isr_no_err_stub 25 -isr_no_err_stub 26 -isr_no_err_stub 27 -isr_no_err_stub 28 -isr_no_err_stub 29 -isr_err_stub 30 -isr_no_err_stub 31 - -global isr_stub_table -isr_stub_table: -%assign i 0 -%rep 32 - dd isr_stub_%+i ; use DQ instead if targeting 64-bit -%assign i i+1 -%endrep - diff --git a/src/kernel/platform/ports.c b/src/kernel/platform/ports.c new file mode 100644 index 0000000..34a48db --- /dev/null +++ b/src/kernel/platform/ports.c @@ -0,0 +1,26 @@ +/* + * Read 1 byte from specified port + */ +unsigned char port_byte_in(unsigned short port) { + unsigned char result; + // source and dest are backwards. + // "=a (result)" set the C variable to the value of register e'a'x + // '"d" (port) map the C variable port into e'd'x register + __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); +} + +void port_byte_out(unsigned short port, unsigned char data) { + // both regs are C vars, nothing is returned, so no '=' in asm syntax + // comma because two vars in input area and none in return area + __asm__("out %%al, %%dx" : : "a" (data), "d" (port)); +} + +unsigned short port_word_in(unsigned short port) { + unsigned short result; + __asm__("in %%dx, %%ax" : "=a" (result) : "d" (port)); + return result; +} + +void port_word_out(unsigned short port, unsigned short data) { + __asm__("out %%ax, %%dx" : : "a" (data), "d" (port)); +} \ No newline at end of file diff --git a/src/kernel/print.c b/src/kernel/print.c index 014de03..0ee30b7 100644 --- a/src/kernel/print.c +++ b/src/kernel/print.c @@ -1,5 +1,5 @@ -#include "print.h" -#include "./platform/drivers/ports.h" +#include +#include int row = 0; int col = 0; diff --git a/src/kernel/util.c b/src/kernel/util.c index e945d94..5063a05 100644 --- a/src/kernel/util.c +++ b/src/kernel/util.c @@ -1,4 +1,4 @@ -#include "util.h" +#include void memcpy(char *source, char *dest, int nbytes) { int i; diff --git a/src/libc/strings.c b/src/libc/strings.c new file mode 100644 index 0000000..d148672 --- /dev/null +++ b/src/libc/strings.c @@ -0,0 +1,48 @@ +#include +#include + +void itoa(int n, char str[]) { + int i, sign; + if ((sign = n) < 0) n = -n; + i = 0; + do { + str[i++] = n % 10 + '0'; + } while ((n /= 10) > 0); + + if (sign < 0) str[i++] = '-'; + str[i] = '\0'; + + strrev(str); +} + +/* K&R */ +void strrev(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; + } +} + +/* K&R */ +int strlen(char s[]) { + int i = 0; + while (s[i] != '\0') ++i; + return i; +} + +char* strcpy(char* strDest, const char* strSrc) { + if ( (strDest == NULL) || (strSrc == NULL) ) { + return NULL; + } + char* strDestCopy = strDest; + while ((*strDest++=*strSrc++)!='\0'); + return strDestCopy; +} + +char* strcnc(char* str1, char* str2) { + char* str_dest; + strcpy(str_dest, str1); + strcpy(str_dest, str2); +} \ No newline at end of file diff --git a/src/linker.ld b/src/linker.ld new file mode 100644 index 0000000..289a33b --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,30 @@ +ENTRY(entry_x86) + +SECTIONS { + . = 1M; + + .text BLOCK(4K) : ALIGN(4K) + { + *(.mb2_header) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } +} \ No newline at end of file