diff --git a/Makefile b/Makefile index 1d7164b..fbf99ed 100644 --- a/Makefile +++ b/Makefile @@ -1,54 +1,67 @@ -ASM ?= nasm +ASM := nasm + CC := x86_64-elf-gcc -GDB := gdb +CCFLAGS := + LD := x86_64-elf-ld +LDFLAGS := -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)) +INCLUDE := include/ -KERNEL_O_FILES = ${CO_FILES} ${AO_FILES} +# 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) -BOOT_O_FILES = obj/entry.o obj/entry64.o obj/mb2.o obj/vga-print.o -BOOT_SRC_FILES = obj/entry.asm obj/entry64.asm obj/mb2.asm obj/vga-print.asm +# 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) -iso: bin/shade.iso +# 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) -bin/shade.bin: ${BOOT_O_FILES} ${KERNEL_O_FILES} - mkdir -p bin - $(LD) -T src/linker.ld $^ -o $@ - grub-file --is-x86-multiboot2 bin/shade.bin +shade_bin_ldfile = src/linker.ld + +default: run bin/shade.iso: bin/shade.bin - mkdir -p isodir/boot/grub - cp bin/shade.bin isodir/boot/shade.bin - cp src/iso/grub.cfg isodir/boot/grub/grub.cfg - grub-mkrescue -o bin/shade.iso isodir - rm -rf isodir + 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)" - $(CC) -ffreestanding -O2 -Wall -Wextra -c $< -o $@ + $(CC) $(CCFLAGS) -I $(INCLUDE) -ffreestanding -c $< -o $@ +# ASM obj/%.o: src/%.asm mkdir -p "$(@D)" - $(ASM) -f elf64 $< -o $@ - + $(ASM) -felf64 $< -o $@ +# Other run: clean bin/shade.iso - qemu-system-x86_64 -hdd bin/shade.iso -d int -no-reboot - -debug: clean bin/shade.iso bin/shade.bin - qemu-system-x86_64 -s -S -hdd bin/shade.iso -d int -no-reboot & - ${GDB} os-image.bin -ex "set arch i386:x86-64" -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234" - + 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 - rm -rf isodir \ No newline at end of file + rm -rf bin/* + rm -rf obj/* \ No newline at end of file diff --git a/bin/shade.bin b/bin/shade.bin index 8b749db..fe77f8c 100755 Binary files a/bin/shade.bin and b/bin/shade.bin differ diff --git a/bin/shade.iso b/bin/shade.iso index a3e044b..43a4f47 100644 Binary files a/bin/shade.iso and b/bin/shade.iso differ diff --git a/bin/shade.iso.lock b/bin/shade.iso.lock deleted file mode 100644 index e69de29..0000000 diff --git a/include/shade/platform/ports.h b/include/shade/platform/ports.h new file mode 100644 index 0000000..d616f0e --- /dev/null +++ b/include/shade/platform/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/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/obj/kernel/kernel.o b/obj/kernel/kernel.o index 3f1f673..66bfda7 100644 Binary files a/obj/kernel/kernel.o and b/obj/kernel/kernel.o differ diff --git a/obj/kernel/print.o b/obj/kernel/print.o index 91008f8..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 07d9acf..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 7cc7d31..7032cdd 100644 Binary files a/obj/kernel/util.o and b/obj/kernel/util.o 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/iso/grub.cfg b/src/iso/grub.cfg deleted file mode 100644 index 1fdb214..0000000 --- a/src/iso/grub.cfg +++ /dev/null @@ -1,6 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "shadeOS Dev Build" { - multiboot /boot/shade.bin -} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index dbb52be..84b5789 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,7 +1,5 @@ -#include "./platform/ports.h" -#include "print.h" - -void dummy_test_entrypoint() {} +#include +#include void kernel_welcome() { print_str("Welcome to "); @@ -44,4 +42,5 @@ void kmain() { 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"); + } \ No newline at end of file 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 85bde11..0ee30b7 100644 --- a/src/kernel/print.c +++ b/src/kernel/print.c @@ -1,5 +1,5 @@ -#include "print.h" -#include "./platform/ports.h" +#include +#include int row = 0; int col = 0; @@ -87,10 +87,10 @@ void print_set_color(char foreground, char background) { void set_cursor_pos(int col, int row) { int offset = col + NUM_COLS * row; - outb(REG_SCREEN_CTRL, 14); - outb(REG_SCREEN_DATA, (unsigned char)(offset >> 8)); - outb(REG_SCREEN_CTRL, 15); - outb(REG_SCREEN_DATA, (unsigned char)(offset & 0xff)); + 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) { 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/kernel/strings.c b/src/libc/strings.c similarity index 97% rename from src/kernel/strings.c rename to src/libc/strings.c index eef8e40..d148672 100644 --- a/src/kernel/strings.c +++ b/src/libc/strings.c @@ -1,4 +1,4 @@ -#include "strings.h" +#include #include void itoa(int n, char str[]) { diff --git a/src/linker.ld b/src/linker.ld index f5b8dcd..289a33b 100644 --- a/src/linker.ld +++ b/src/linker.ld @@ -1,23 +1,30 @@ - ENTRY(entry_x86) -SECTIONS -{ - . = 1M; +SECTIONS { + . = 1M; - .boot : + .text BLOCK(4K) : ALIGN(4K) + { + *(.mb2_header) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) { - KEEP(*(.mb2_header)) + *(.rodata) } - - .text : + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) { - *(.text) + *(.data) } - - .idt BLOCK(0x1000) : ALIGN(0x1000) + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) { - _idt = .; - . = . + 0x1000; + *(COMMON) + *(.bss) } } \ No newline at end of file