diff options
-rw-r--r-- | Makefile | 10 | ||||
-rwxr-xr-x | run | 201 | ||||
-rw-r--r-- | src/drivers/cpu.c | 40 | ||||
-rw-r--r-- | src/drivers/serial.c | 32 | ||||
-rw-r--r-- | src/inc/boot.h | 16 | ||||
-rw-r--r-- | src/inc/cpu.h | 16 | ||||
-rw-r--r-- | src/inc/serial.h | 9 | ||||
-rw-r--r-- | src/inc/vesa.h | 7 | ||||
-rw-r--r-- | src/lib/inc/def.h (renamed from src/lib/def.h) | 2 | ||||
-rw-r--r-- | src/lib/inc/string.h | 10 | ||||
-rw-r--r-- | src/lib/string.c | 11 | ||||
-rw-r--r-- | src/main.c | 11 |
12 files changed, 256 insertions, 109 deletions
@@ -1,10 +1,16 @@ +# MIT License, Copyright (c) 2020 Marvin Borner + COBJS = src/main.o \ - src/drivers/vesa.o + src/drivers/vesa.o \ + src/drivers/cpu.o \ + src/drivers/serial.o \ + src/lib/string.o CC = cross/opt/bin/i686-elf-gcc LD = cross/opt/bin/i686-elf-ld AS = nasm -CFLAGS = -Wall -Wextra -nostdlib -nostdinc -ffreestanding -std=c99 -pedantic-errors -Isrc/lib/ -Isrc/inc/ -c +# TODO: Use lib as external library +CFLAGS = -Wall -Wextra -nostdlib -nostdinc -ffreestanding -std=c99 -pedantic-errors -Isrc/lib/inc/ -Isrc/inc/ -c all: compile clean @@ -1,4 +1,5 @@ #!/usr/bin/env sh +# MIT License, Copyright (c) 2020 Marvin Borner set -e @@ -9,145 +10,145 @@ no_ask="${2}" network="rtl8139" qemu_with_flags() { - if [ "${mode}" = "image" ] || [ "${mode}" = "image_debug" ]; then - # TODO: Find out why kvm install is incredibly slow - SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-i386 -no-reboot -vga std -smp "$(nproc)" -serial mon:stdio -rtc base=localtime -m 256M -net nic,model=${network},macaddr=42:42:42:42:42:42 -net user "$@" - else - SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-i386 -no-reboot -vga std -serial stdio -rtc base=localtime -m 256M -net nic,model=${network},macaddr=42:42:42:42:42:42 -net user "$@" - fi + if [ "${mode}" = "image" ] || [ "${mode}" = "image_debug" ]; then + # TODO: Find out why kvm install is incredibly slow + SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-i386 -no-reboot -vga std -smp "$(nproc)" -serial mon:stdio -rtc base=localtime -m 256M -net nic,model=${network},macaddr=42:42:42:42:42:42 -net user "$@" + else + SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-i386 -no-reboot -vga std -serial stdio -rtc base=localtime -m 256M -net nic,model=${network},macaddr=42:42:42:42:42:42 -net user "$@" + fi } make_cross() { - if [ ! -d "./cross/" ]; then - # Create directory - mkdir -p cross - cd cross - DIR=$(pwd) - - # Get sources - mkdir "${DIR}/src" && cd "${DIR}/src" - echo "Downloading..." - curl -sSL "https://ftp.gnu.org/gnu/binutils/binutils-2.34.tar.xz" | tar xJ - curl -sSL "https://ftp.gnu.org/gnu/gcc/gcc-9.3.0/gcc-9.3.0.tar.xz" | tar xJ - - # Prepare compiling - mkdir -p "${DIR}/opt/bin" - export PREFIX="${DIR}/opt" - export TARGET=i686-elf - export PATH="$PREFIX/bin:$PATH" - - # Compile binutils - mkdir "${DIR}/src/build-binutils" && cd "${DIR}/src/build-binutils" - ../binutils-2.34/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror - make - make install - - # Compile GCC - mkdir "${DIR}/src/build-gcc" && cd "${DIR}/src/build-gcc" - ../gcc-9.3.0/configure --target="$TARGET" --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers - make all-gcc - make all-target-libgcc - make install-gcc - make install-target-libgcc - - cd "${DIR}/.." - else - cd cross - DIR=$(pwd) - export PREFIX="${DIR}/opt" - export TARGET=i686-elf - export PATH="$PREFIX/bin:$PATH" - cd .. - fi + if [ ! -d "./cross/" ]; then + # Create directory + mkdir -p cross + cd cross + DIR=$(pwd) + + # Get sources + mkdir "${DIR}/src" && cd "${DIR}/src" + echo "Downloading..." + curl -sSL "https://ftp.gnu.org/gnu/binutils/binutils-2.34.tar.xz" | tar xJ + curl -sSL "https://ftp.gnu.org/gnu/gcc/gcc-9.3.0/gcc-9.3.0.tar.xz" | tar xJ + + # Prepare compiling + mkdir -p "${DIR}/opt/bin" + export PREFIX="${DIR}/opt" + export TARGET=i686-elf + export PATH="$PREFIX/bin:$PATH" + + # Compile binutils + mkdir "${DIR}/src/build-binutils" && cd "${DIR}/src/build-binutils" + ../binutils-2.34/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror + make + make install + + # Compile GCC + mkdir "${DIR}/src/build-gcc" && cd "${DIR}/src/build-gcc" + ../gcc-9.3.0/configure --target="$TARGET" --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers + make all-gcc + make all-target-libgcc + make install-gcc + make install-target-libgcc + + cd "${DIR}/.." + else + cd cross + DIR=$(pwd) + export PREFIX="${DIR}/opt" + export TARGET=i686-elf + export PATH="$PREFIX/bin:$PATH" + cd .. + fi } make_build() { - mkdir -p build/ - rm -rf build/* + mkdir -p build/ + rm -rf build/* - echo "Building..." - make + echo "Building..." + make - # Create disk image - dd if=/dev/zero of=build/disk.img bs=1k count=16k - sudo mke2fs build/disk.img >/dev/null - dd if=build/boot.bin of=build/disk.img conv=notrunc - ./ext2util/ext2util -x build/disk.img -wf build/kernel.bin -i 5 >/dev/null + # Create disk image + dd if=/dev/zero of=build/disk.img bs=1k count=16k + sudo mke2fs build/disk.img >/dev/null + dd if=build/boot.bin of=build/disk.img conv=notrunc + ./ext2util/ext2util -x build/disk.img -wf build/kernel.bin -i 5 >/dev/null - printf "Build finshed successfully!\n\n" + printf "Build finshed successfully!\n\n" } make_test() { - qemu_with_flags -hdb build/disk.img + qemu_with_flags -hdb build/disk.img } make_debug() { - qemu_with_flags -hdb build/disk.img -s -S + qemu_with_flags -hdb build/disk.img -s -S } make_disasm() { - objdump -drwC -Mintel build/melvix.bin --visualize-jumps=color | less -R - #hexdump -C build/melvix.bin | less -R + objdump -drwC -Mintel build/melvix.bin --visualize-jumps=color | less -R + #hexdump -C build/melvix.bin | less -R } make_sync() { - ctags -R --exclude=.git --exclude=build --exclude=iso --exclude=cross . + ctags -R --exclude=.git --exclude=build --exclude=iso --exclude=cross . - make --always-make --dry-run | - grep -wE 'gcc' | - grep -w '\-c' | - jq -nR '[inputs|{directory:"'"$(pwd)"'", command:., file: match(" [^ ]+$").string[1:]}]' \ - >compile_commands.json + make --always-make --dry-run | + grep -wE 'gcc' | + grep -w '\-c' | + jq -nR '[inputs|{directory:"'"$(pwd)"'", command:., file: match(" [^ ]+$").string[1:]}]' \ + >compile_commands.json } make_tidy() { - shfmt -w ./run - find ./src -type f -regex '.*\.\(c\|h\)' -exec clang-format -i {} \; - # This may or may not work - find ./src -type f -print0 | xargs -0 -l -i sh -c '[ -n "$(tail -c1 {})" ] && printf "\n" >> {}' + shfmt -w ./run + find ./src -type f -regex '.*\.\(c\|h\)' -exec clang-format -i {} \; + # This may or may not work + find ./src -type f -print0 | xargs -0 -l -i sh -c '[ -n "$(tail -c1 {})" ] && printf "\n" >> {}' } make_clean() { - rm -rf ./build/ + rm -rf ./build/ } if [ "${mode}" = "cross" ]; then - make_cross + make_cross elif [ "${mode}" = "build" ]; then - make_cross - make_clean - make_build + make_cross + make_clean + make_build elif [ "${mode}" = "clean" ]; then - make_clean + make_clean elif [ "${mode}" = "test" ]; then - make_cross - make_clean - make_build - make_sync & - make_test + make_cross + make_clean + make_build + make_sync & + make_test elif [ "${mode}" = "debug" ]; then - make_cross - make_build - make_sync & - make_debug + make_cross + make_build + make_sync & + make_debug elif [ "${mode}" = "again" ]; then - make_test + make_test elif [ "${mode}" = "disasm" ]; then - make_cross - make_build - make_disasm + make_cross + make_build + make_disasm elif [ "${mode}" = "sync" ]; then - make_sync + make_sync elif [ "${mode}" = "tidy" ]; then - make_tidy + make_tidy elif [ "${mode}" = "" ]; then # TODO: Prevent code duplication in build script via functions? - make_cross - make_clean - make_build - make_sync & - make_test + make_cross + make_clean + make_build + make_sync & + make_test else - echo "Please use the following syntax:" - echo "./run {cross | build | clean | test | disasm | sync | tidy} [-y]" - echo "The default option is 'test'" + echo "Please use the following syntax:" + echo "./run {cross | build | clean | test | disasm | sync | tidy} [-y]" + echo "The default option is 'test'" fi diff --git a/src/drivers/cpu.c b/src/drivers/cpu.c new file mode 100644 index 0000000..eb96562 --- /dev/null +++ b/src/drivers/cpu.c @@ -0,0 +1,40 @@ +// MIT License, Copyright (c) 2020 Marvin Borner +// This file is a wrapper around some CPU asm calls + +#include <def.h> + +u8 inb(u16 port) +{ + u8 value; + __asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +u16 inw(u16 port) +{ + u16 value; + __asm__ volatile("inw %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +u32 inl(u16 port) +{ + u32 value; + __asm__ volatile("inl %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} + +void outb(u16 port, u8 data) +{ + __asm__ volatile("outb %0, %1" ::"a"(data), "Nd"(port)); +} + +void outw(u16 port, u16 data) +{ + __asm__ volatile("outw %0, %1" ::"a"(data), "Nd"(port)); +} + +void outl(u16 port, u32 data) +{ + __asm__ volatile("outl %0, %1" ::"a"(data), "Nd"(port)); +} diff --git a/src/drivers/serial.c b/src/drivers/serial.c new file mode 100644 index 0000000..1ef424a --- /dev/null +++ b/src/drivers/serial.c @@ -0,0 +1,32 @@ +#include <cpu.h> +#include <def.h> +#include <string.h> + +void serial_install() +{ + outb(0x3f8 + 1, 0x00); + outb(0x3f8 + 3, 0x80); + outb(0x3f8 + 0, 0x03); + outb(0x3f8 + 1, 0x00); + outb(0x3f8 + 3, 0x03); + outb(0x3f8 + 2, 0xC7); + outb(0x3f8 + 4, 0x0B); +} + +int is_transmit_empty() +{ + return inb(0x3f8 + 5) & 0x20; +} + +void serial_put(char ch) +{ + while (is_transmit_empty() == 0) + ; + outb(0x3f8, (u8)ch); +} + +void serial_print(const char *data) +{ + for (u32 i = 0; i < strlen(data); i++) + serial_put(data[i]); +} diff --git a/src/inc/boot.h b/src/inc/boot.h new file mode 100644 index 0000000..30ddfb7 --- /dev/null +++ b/src/inc/boot.h @@ -0,0 +1,16 @@ +// MIT License, Copyright (c) 2020 Marvin Borner +// This file specifies the structs passed by the bootloader + +#include <def.h> +#include <vesa.h> + +struct vid_info { + u32 mode; + struct vbe *info; +}; + +struct mem_info { + u64 base; + u64 len; + u64 type; +}; diff --git a/src/inc/cpu.h b/src/inc/cpu.h new file mode 100644 index 0000000..ad83896 --- /dev/null +++ b/src/inc/cpu.h @@ -0,0 +1,16 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#ifndef CPU_H +#define CPU_H + +#include <def.h> + +u8 inb(u16 port); +u16 inw(u16 port); +u32 inl(u16 port); + +void outb(u16 port, u8 data); +void outw(u16 port, u16 data); +void outl(u16 port, u32 data); + +#endif diff --git a/src/inc/serial.h b/src/inc/serial.h new file mode 100644 index 0000000..6511952 --- /dev/null +++ b/src/inc/serial.h @@ -0,0 +1,9 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#ifndef SERIAL_H +#define SERIAL_H + +void serial_install(); +void serial_print(const char *data); + +#endif diff --git a/src/inc/vesa.h b/src/inc/vesa.h index e2ac4e5..661ab16 100644 --- a/src/inc/vesa.h +++ b/src/inc/vesa.h @@ -1,3 +1,5 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + #ifndef VBE_H #define VBE_H @@ -41,11 +43,6 @@ struct vbe { u8 reserved1[206]; }; -struct vid_info { - u32 mode; - struct vbe *info; -}; - struct vbe *vbe; void vesa_clear(const u32 color[3]); diff --git a/src/lib/def.h b/src/lib/inc/def.h index dc3cc55..69b43e3 100644 --- a/src/lib/def.h +++ b/src/lib/inc/def.h @@ -1,3 +1,5 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + #ifndef DEF_H #define DEF_H diff --git a/src/lib/inc/string.h b/src/lib/inc/string.h new file mode 100644 index 0000000..c97fada --- /dev/null +++ b/src/lib/inc/string.h @@ -0,0 +1,10 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#ifndef STRING_H +#define STRING_H + +#include <def.h> + +u32 strlen(const char *str); + +#endif diff --git a/src/lib/string.c b/src/lib/string.c new file mode 100644 index 0000000..1b7a2b8 --- /dev/null +++ b/src/lib/string.c @@ -0,0 +1,11 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#include <def.h> + +u32 strlen(const char *str) +{ + u32 len = 0; + while (str[len]) + len++; + return len; +} @@ -1,14 +1,21 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#include <boot.h> #include <def.h> +#include <serial.h> #include <vesa.h> -void main(u32 *mem_info, struct vid_info *vid_info) +void main(struct mem_info *mem_info, struct vid_info *vid_info) { - mem_info++; // TODO: Use the mmap! + mem_info++; // TODO: Use the mmap (or remove)! vbe = vid_info->info; u32 terminal_background[3] = { 0x1d, 0x1f, 0x24 }; vesa_clear(terminal_background); + serial_install(); + serial_print("hello\n"); + while (1) { }; } |