diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c80dc43 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +CMakeFiles/ +CMakeCache.txt +Makefile +cmake_install.cmake +.vscode/ +./OwOS.bin diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt new file mode 100644 index 0000000..e6d1da2 --- /dev/null +++ b/build/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.9) +project(OwOS) + +enable_language(ASM) + +set(CMAKE_ASM_COMPILER "i686-elf-as") +set(CMAKE_C_COMPILER "i686-elf-gcc") +set(CMAKE_CXX_COMPILER "i686-elf-g++") + +set(CMAKE_CXX_FLAGS "-ffreestanding -O2 -fno-rtti -Wno-write-strings -Wno-multichar -Wno-unused-parameter -Wno-overflow -Wno-narrowing -fno-exceptions -Wno-trigraphs ${CMAKE_CXX_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "-T ../linker.ld -ffreestanding -O2 -nostdlib -lgcc -Wwrite-strings ${CMAKE_EXE_LINKER_FLAGS}") + +include_directories(OwOS "../src") + +# Kernel source +file(GLOB KERN_SRC + "../src/*.cpp" + "../src/*.asm" + "../*.asm" + "../*.cpp" +) + +set(SRCS ${KERN_SRC}) + +add_executable(OwOS ${SRCS}) + +set_target_properties(OwOS PROPERTIES OUTPUT_NAME "OwOS.bin") + +add_custom_target(iso COMMAND cp OwOS.bin ../iso/boot/OwOS.bin && grub-mkrescue -o OwOS.iso ../iso) +add_dependencies(iso OwOS) diff --git a/build/OwOS.bin b/build/OwOS.bin new file mode 100644 index 0000000..22516b5 Binary files /dev/null and b/build/OwOS.bin differ diff --git a/build/OwOS.iso b/build/OwOS.iso new file mode 100644 index 0000000..a970ce7 Binary files /dev/null and b/build/OwOS.iso differ diff --git a/install-crosscompiler.sh b/install-crosscompiler.sh new file mode 100644 index 0000000..8b4e3a2 --- /dev/null +++ b/install-crosscompiler.sh @@ -0,0 +1,41 @@ +# Install requirements +sudo apt install build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo xorriso grub-pc-bin + +# Configuration +export PREFIX="$HOME/opt/cross" +export TARGET=i686-elf +export PATH="$PREFIX/bin:$PATH" + +# Create directories +mkdir $HOME/src + +# Download binutils + gcc +wget https://ftp.nluug.nl/pub/gnu/binutils/binutils-2.31.tar.xz -O $HOME/src/binutils-2.31.tar.xz +wget https://ftp.gnu.org/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.xz -O $HOME/src/gcc-8.2.0.tar.xz + +# Decompress +cd $HOME/src +tar -xf binutils-2.31.tar.xz +tar -xf gcc-8.2.0.tar.xz + +# Build binutils +cd $HOME/src +mkdir build-binutils +cd build-binutils +../binutils-2.31/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror +make -j4 +make install + +# Build GCC +cd $HOME/src +which -- $TARGET-as || echo $TARGET-as is not in the PATH +mkdir build-gcc +cd build-gcc +../gcc-8.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers +make all-gcc -j4 +make all-target-libgcc -j4 +make install-gcc +make install-target-libgcc + +export PATH="$HOME/opt/cross/bin:$PATH" +echo "Done!" diff --git a/iso/boot/OwOS.bin b/iso/boot/OwOS.bin new file mode 100644 index 0000000..22516b5 Binary files /dev/null and b/iso/boot/OwOS.bin differ diff --git a/iso/boot/grub/grub.cfg b/iso/boot/grub/grub.cfg new file mode 100644 index 0000000..79eba8b --- /dev/null +++ b/iso/boot/grub/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 + +menuentry "OwOS v0.01" { + multiboot /boot/OwOS.bin + boot +} diff --git a/kernel.asm b/kernel.asm new file mode 100644 index 0000000..18270d6 --- /dev/null +++ b/kernel.asm @@ -0,0 +1,61 @@ +# OwOS +# Copyright Benjamin Kyd (c) 2019 + +# declare constants for the multiboot header +.set ALIGN, 1<<0 # align loaded modules on page boundaries +.set MEMINFO, 1<<1 # provide memory map +.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field +.set MAGIC, 0x1BADB002 #'magic number' lets bootloader find the header +.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot + +.section .multiboot +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + +.section .bss +.align 16 +stack_bottom: +.skip 16384 # 16 KiB +stack_top: + +.section .text +.global _start +.type _start, @function + +_start: + # Settup stack + mov $stack_top, %esp + push %ebx + push %eax + + # FPU Config + VAL_037F: + .hword 0x037F + VAL_037E: + .hword 0x037E + VAL_037A: + .hword 0x037A + # Configure FPU + cli + mov %cr0, %eax + or $0b00110010, %eax + and $0xFFFFFFFB, %eax + mov %eax, %cr0 + fldcw VAL_037F + fldcw VAL_037E + fldcw VAL_037A + fninit + + call kernel_main + + cli +1: hlt + jmp 1b + +_hang: + hlt + jmp _hang + +.size _start, . - _start diff --git a/kernel.cpp b/kernel.cpp new file mode 100644 index 0000000..8bc41a1 --- /dev/null +++ b/kernel.cpp @@ -0,0 +1,41 @@ +#define TERM_WIDTH 80 +#define TERM_HEIGHT 25 + +struct VGAChar_t { + char c; + char foreground:4; + char background:4; +}__attribute__((packed)); + +VGAChar_t* framebuffer = (VGAChar_t*)0xB8000; + +void putcar(int x, int y, char c, char foreground, char background) { + framebuffer[(y * TERM_WIDTH) + x].c = c; + framebuffer[(y * TERM_WIDTH) + x].foreground = foreground; + framebuffer[(y * TERM_WIDTH) + x].background = background; +} + +extern "C" + +int kernel_main() { + + for (int x = 0; x < TERM_WIDTH; x++) + for (int y = 0; y < TERM_HEIGHT; y++) + putcar(x, y, ' ', 0x00, 0x00); + + putcar(0, 0, 'H', 0x01, 0x07); + putcar(1, 0, 'A', 0x01, 0x07); + putcar(2, 0, 'H', 0x01, 0x07); + putcar(3, 0, 'A', 0x01, 0x07); + putcar(4, 0, '!', 0x01, 0x07); + putcar(5, 0, ' ', 0x01, 0x07); + putcar(6, 0, 'P', 0x01, 0x07); + putcar(7, 0, 'E', 0x01, 0x07); + putcar(8, 0, 'N', 0x01, 0x07); + putcar(9, 0, 'I', 0x01, 0x07); + putcar(10, 0, 'S', 0x01, 0x07); + putcar(11, 0, '!', 0x01, 0x07); + + for (;;) + asm("hlt"); +} diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..137a43a --- /dev/null +++ b/linker.ld @@ -0,0 +1,49 @@ +/* The bootloader will look at this image and start execution at the symbol + designated as the entry point. */ +ENTRY(_start) + +/* Tell where the various sections of the object files will be put in the final + kernel image. */ +SECTIONS +{ + /* Begin putting sections at 1 MiB, a conventional place for kernels to be + loaded at by the bootloader. */ + . = 1M; + + /* First put the multiboot header, as it is required to be put very early + early in the image or the bootloader won't recognize the file format. + Next we'll put the .text section. */ + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.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) + } + + /* Kernel size detection */ + .sizedetect BLOCK(4K) : ALIGN(4K) + { + *(.sizedetect) + } + + /* The compiler may produce other sections, by default it will put them in + a segment with the same name. Simply add stuff here as needed. */ +} \ No newline at end of file