diff --git a/C/OperatingSystem/.gitignore b/C/OperatingSystem/.gitignore new file mode 100644 index 000000000..c74468ad0 --- /dev/null +++ b/C/OperatingSystem/.gitignore @@ -0,0 +1,3 @@ +/build/ +/dist/ +targets/x86_64/iso/boot/kernel.bin \ No newline at end of file diff --git a/C/OperatingSystem/Makefile b/C/OperatingSystem/Makefile new file mode 100644 index 000000000..a46d55e35 --- /dev/null +++ b/C/OperatingSystem/Makefile @@ -0,0 +1,29 @@ +kernel_source_files := $(shell find src/impl/kernel -name *.c) +kernel_object_files := $(patsubst src/impl/kernel/%.c, build/kernel/%.o, $(kernel_source_files)) + +x86_64_c_source_files := $(shell find src/impl/x86_64 -name *.c) +x86_64_c_object_files := $(patsubst src/impl/x86_64/%.c, build/x86_64/%.o, $(x86_64_c_source_files)) + +x86_64_asm_source_files := $(shell find src/impl/x86_64 -name *.asm) +x86_64_asm_object_files := $(patsubst src/impl/x86_64/%.asm, build/x86_64/%.o, $(x86_64_asm_source_files)) + +x86_64_object_files := $(x86_64_c_object_files) $(x86_64_asm_object_files) + +$(kernel_object_files): build/kernel/%.o : src/impl/kernel/%.c + mkdir -p $(dir $@) && \ + x86_64-elf-gcc -c -I src/intf -ffreestanding $(patsubst build/kernel/%.o, src/impl/kernel/%.c, $@) -o $@ + +$(x86_64_c_object_files): build/x86_64/%.o : src/impl/x86_64/%.c + mkdir -p $(dir $@) && \ + x86_64-elf-gcc -c -I src/intf -ffreestanding $(patsubst build/x86_64/%.o, src/impl/x86_64/%.c, $@) -o $@ + +$(x86_64_asm_object_files): build/x86_64/%.o : src/impl/x86_64/%.asm + mkdir -p $(dir $@) && \ + nasm -f elf64 $(patsubst build/x86_64/%.o, src/impl/x86_64/%.asm, $@) -o $@ + +.PHONY: build +build: $(kernel_object_files) $(x86_64_object_files) + mkdir -p dist/x86_64 && \ + x86_64-elf-ld -n -o dist/x86_64/kernel.bin -T targets/x86_64/linker.ld $(kernel_object_files) $(x86_64_object_files) && \ + cp dist/x86_64/kernel.bin targets/x86_64/iso/boot/kernel.bin && \ + grub-mkrescue /usr/lib/grub/i386-pc -o dist/x86_64/kernel.iso targets/x86_64/iso \ No newline at end of file diff --git a/C/OperatingSystem/buildenv/Dockerfile b/C/OperatingSystem/buildenv/Dockerfile new file mode 100644 index 000000000..8fe22108d --- /dev/null +++ b/C/OperatingSystem/buildenv/Dockerfile @@ -0,0 +1,11 @@ +FROM randomdude/gcc-cross-x86_64-elf + +RUN apt-get update +RUN apt-get upgrade -y +RUN apt-get install -y nasm +RUN apt-get install -y xorriso +RUN apt-get install -y grub-pc-bin +RUN apt-get install -y grub-common + +VOLUME /root/env +WORKDIR /root/env \ No newline at end of file diff --git a/C/OperatingSystem/buildenv/start.bat b/C/OperatingSystem/buildenv/start.bat new file mode 100644 index 000000000..277559892 --- /dev/null +++ b/C/OperatingSystem/buildenv/start.bat @@ -0,0 +1 @@ +docker run --rm -it -v D:\Programmierstuff\C\OperatingSystem:/root/env myos-buildenv \ No newline at end of file diff --git a/C/OperatingSystem/run.bat b/C/OperatingSystem/run.bat new file mode 100644 index 000000000..a6ca5d1c3 --- /dev/null +++ b/C/OperatingSystem/run.bat @@ -0,0 +1 @@ +"C:\Program Files\qemu\qemu-system-x86_64.exe" -cdrom .\dist\x86_64\kernel.iso \ No newline at end of file diff --git a/C/OperatingSystem/src/impl/kernel/main.c b/C/OperatingSystem/src/impl/kernel/main.c new file mode 100644 index 000000000..508a32572 --- /dev/null +++ b/C/OperatingSystem/src/impl/kernel/main.c @@ -0,0 +1,9 @@ +#include "print.h" + +void kernel_main() { + print_clear(); + print_set_color(PRINT_COLOR_LIGHT_BLUE, PRINT_COLOR_BLACK); + print_str("HoppeOS is starting up..."); + + // Startup operating system +} \ No newline at end of file diff --git a/C/OperatingSystem/src/impl/x86_64/boot/header.asm b/C/OperatingSystem/src/impl/x86_64/boot/header.asm new file mode 100644 index 000000000..1352e2d32 --- /dev/null +++ b/C/OperatingSystem/src/impl/x86_64/boot/header.asm @@ -0,0 +1,19 @@ +section .multiboot_header +header_start: + ; magic number + dd 0xE85250D6 ; multiboot2 + + ; architecture + dd 0 ; protected mode i386 + + ; header length + dd header_end - header_start + + ; checksum + dd 0x100000000 - (0xE85250D6 + 0 + (header_end - header_start)) + + ; end tag + dw 0 + dw 0 + dd 8 +header_end: \ No newline at end of file diff --git a/C/OperatingSystem/src/impl/x86_64/boot/main.asm b/C/OperatingSystem/src/impl/x86_64/boot/main.asm new file mode 100644 index 000000000..ad971a4e8 --- /dev/null +++ b/C/OperatingSystem/src/impl/x86_64/boot/main.asm @@ -0,0 +1,136 @@ +global start +extern long_mode_start + +section .text +bits 32 +start: + mov esp, stack_top + + call check_multiboot + call check_cpuid + call check_long_mode + + call setup_page_tables + call enable_paging + + lgdt [gdt64.pointer] + jmp gdt64.code_segment:long_mode_start + + hlt + +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, "M" + jmp error + +check_cpuid: + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 + push eax + popfd + pushfd + pop eax + push ecx + popfd + cmp eax, ecx + je .no_cpuid + ret +.no_cpuid: + mov al, "C" + jmp error + +check_long_mode: + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .no_long_mode + + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz .no_long_mode + + ret +.no_long_mode: + mov al, "L" + jmp error + +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: + dq 0 ; zero entry +.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/C/OperatingSystem/src/impl/x86_64/boot/main64.asm b/C/OperatingSystem/src/impl/x86_64/boot/main64.asm new file mode 100644 index 000000000..d71008afc --- /dev/null +++ b/C/OperatingSystem/src/impl/x86_64/boot/main64.asm @@ -0,0 +1,16 @@ +global long_mode_start +extern kernel_main + +section .text +bits 64 +long_mode_start: + ; load null into all data segment registers + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + call kernel_main + hlt \ No newline at end of file diff --git a/C/OperatingSystem/src/impl/x86_64/print.c b/C/OperatingSystem/src/impl/x86_64/print.c new file mode 100644 index 000000000..6bbfb7864 --- /dev/null +++ b/C/OperatingSystem/src/impl/x86_64/print.c @@ -0,0 +1,83 @@ +#include "print.h" + +const static size_t NUM_COLS = 80; +const static size_t NUM_ROWS = 25; + +struct Char { + uint8_t character; + uint8_t color; +}; + +struct Char* buffer = (struct Char*) 0xb8000; +size_t col = 0; +size_t row = 0; +uint8_t color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4; + +void clear_row(size_t row) { + struct Char empty = (struct Char) { + character: ' ', + color: color, + }; + + for (size_t col = 0; col < NUM_COLS; col++) { + buffer[col + NUM_COLS * row] = empty; + } +} + +void print_clear() { + for (size_t i = 0; i < NUM_ROWS; i++) { + clear_row(i); + } +} + +void print_newline() { + col = 0; + + if (row < NUM_ROWS - 1) { + row++; + return; + } + + for (size_t row = 1; row < NUM_ROWS; row++) { + for (size_t 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); +} + +void print_char(char character) { + if (character == '\n') { + print_newline(); + return; + } + + if (col > NUM_COLS) { + print_newline(); + } + + buffer[col + NUM_COLS * row] = (struct Char) { + character: (uint8_t) character, + color: color, + }; + + col++; +} + +void print_str(char* str) { + for (size_t i = 0; 1; i++) { + char character = (uint8_t) str[i]; + + if (character == '\0') { + return; + } + + print_char(character); + } +} + +void print_set_color(uint8_t foreground, uint8_t background) { + color = foreground + (background << 4); +} \ No newline at end of file diff --git a/C/OperatingSystem/src/intf/print.h b/C/OperatingSystem/src/intf/print.h new file mode 100644 index 000000000..6d5003f58 --- /dev/null +++ b/C/OperatingSystem/src/intf/print.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +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, +}; + +void print_clear(); +void print_char(char character); +void print_str(char* string); +void print_set_color(uint8_t foreground, uint8_t background); \ No newline at end of file diff --git a/C/OperatingSystem/targets/x86_64/iso/boot/grub/grub.cfg b/C/OperatingSystem/targets/x86_64/iso/boot/grub/grub.cfg new file mode 100644 index 000000000..d15a2f720 --- /dev/null +++ b/C/OperatingSystem/targets/x86_64/iso/boot/grub/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 + +menuentry "my os" { + multiboot2 /boot/kernel.bin + boot +} \ No newline at end of file diff --git a/C/OperatingSystem/targets/x86_64/linker.ld b/C/OperatingSystem/targets/x86_64/linker.ld new file mode 100644 index 000000000..5b5870c39 --- /dev/null +++ b/C/OperatingSystem/targets/x86_64/linker.ld @@ -0,0 +1,16 @@ +ENTRY(start) + +SECTIONS +{ + . = 1M; + + .boot : + { + KEEP(*(.multiboot_header)) + } + + .text : + { + *(.text) + } +} \ No newline at end of file