From f85042a9c77de1065453069800f96e392c26c5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Sun, 1 May 2016 20:22:12 +0200 Subject: [PATCH] Adds linker script, C++ support and a simple screen class. --- prototypes/base/Makefile | 34 +++++++++++----- prototypes/base/entrypoint.S | 30 ++++++-------- prototypes/base/include/compat.h | 13 ++++++ prototypes/base/include/screen.hpp | 63 ++++++++++++++++++++++++++++++ prototypes/base/init.c | 16 -------- prototypes/base/init.cpp | 21 ++++++++++ prototypes/base/linker.ld | 37 ++++++++++++++++++ prototypes/base/multiboot.S | 2 +- prototypes/base/src/compat.c | 17 ++++++++ prototypes/base/src/screen.cpp | 19 +++++++++ 10 files changed, 206 insertions(+), 46 deletions(-) create mode 100644 prototypes/base/include/compat.h create mode 100644 prototypes/base/include/screen.hpp delete mode 100644 prototypes/base/init.c create mode 100644 prototypes/base/init.cpp create mode 100644 prototypes/base/linker.ld create mode 100644 prototypes/base/src/compat.c create mode 100644 prototypes/base/src/screen.cpp diff --git a/prototypes/base/Makefile b/prototypes/base/Makefile index d64c87b..0602ce8 100644 --- a/prototypes/base/Makefile +++ b/prototypes/base/Makefile @@ -1,27 +1,41 @@ -AS=clang -CC=clang -CXX=clang++ +AS=gcc +CC=gcc +CXX=g++ LD=ld -FLAGS = -ffreestanding -m32 +FLAGS = -ffreestanding -m32 -Wall -iquote include ASFLAGS = $(FLAGS) -CFLAGS = $(FLAGS) -CXXFLAGS = $(FLAGS) +CFLAGS = $(FLAGS) +CXXFLAGS = $(FLAGS) -std=c++14 -fno-rtti -fno-exceptions -fno-leading-underscore -fno-use-cxa-atexit -nostdlib -fno-builtin -SRCS = $(shell find -name '*.[cS]') +SRCS = $(shell find -regextype egrep -regex '.*/.*\.(cpp|S|c)') OBJS = $(addsuffix .o, $(notdir $(basename $(SRCS)))) all: kernel-base.ker kernel-base.ker: $(OBJS) - $(LD) -melf_i386 -Ttext=0x1000000 -o kernel-base.ker $(addprefix obj/, $^) + $(LD) -melf_i386 -Tlinker.ld -o kernel-base.ker $(addprefix obj/, $^) +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o obj/$@ $< + %.o: %.c $(CC) $(ASFLAGS) -c -o obj/$@ $< %.o: %.S $(AS) $(CFLAGS) -c -o obj/$@ $< + +%.o: src/%.cpp + $(CXX) $(CXXFLAGS) -c -o obj/$@ $< -%.o: %.cpp - $(CPP) $(CXXFLAGS) -c -o obj/$@ $< \ No newline at end of file +%.o: src/%.c + $(CC) $(ASFLAGS) -c -o obj/$@ $< + +%.o: src/%.S + $(AS) $(CFLAGS) -c -o obj/$@ $< + +run: + qemu-system-i386 -kernel kernel-base.ker + +bnr: kernel-base.ker run \ No newline at end of file diff --git a/prototypes/base/entrypoint.S b/prototypes/base/entrypoint.S index eb5dfc0..b25bc1e 100644 --- a/prototypes/base/entrypoint.S +++ b/prototypes/base/entrypoint.S @@ -1,30 +1,22 @@ .section .text -// Init ist eine Funktion aus init.c .extern init +.extern compat_call_ctors +.extern compat_call_dtors -// _start muss global sein, damit der Linker es findet und als Einsprungspunkt -// benutzen kann (alle Labels, die nicht global sind, sind nur in dieser Datei -// sichtbar) .global _start _start: - // Stack initialisieren - mov $kernel_stack, %esp + mov $kernel_stack, %esp - // C-Code aufrufen - call init - - // Falls wir jemals aus init zurueckkommen sollten, sperren wir die Interrupts und - // halten einfach den Prozessor an. (man braucht ihn ja nicht unnötig heißlaufen lassen.) + call compat_call_ctors + call init + call compat_call_dtors + _stop: - cli - hlt - - // Sollte es doch weitergehen, probieren wir erneut die CPU schlafen zu lassen - jmp _stop - -// 8 kB Stack fuer den Kernel. Das Label steht hinter dem freien Speicher, -// weil der Stack nach unten waechst + cli + hlt + jmp _stop + .section .bss .space 8192 kernel_stack: \ No newline at end of file diff --git a/prototypes/base/include/compat.h b/prototypes/base/include/compat.h new file mode 100644 index 0000000..747de12 --- /dev/null +++ b/prototypes/base/include/compat.h @@ -0,0 +1,13 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +void compat_call_ctors(); + +void compat_call_dtors(); + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/prototypes/base/include/screen.hpp b/prototypes/base/include/screen.hpp new file mode 100644 index 0000000..9ad42fa --- /dev/null +++ b/prototypes/base/include/screen.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +enum class Color : uint8_t +{ + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + Gray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + LightMagenta = 13, + Yellow = 14, + White = 15, +}; + +using ColorInteger = uint8_t; + +struct ScreenChar +{ + char c; + struct { + ColorInteger fg : 4; + ColorInteger bg : 4; + }; +}; + +class Screen +{ +private: + static ScreenChar outOfScreen; +private: + ScreenChar * const buffer; + const int width; + const int height; +public: + static Screen main; +public: + Screen(ScreenChar *buffer, int width, int height); + + void clear(); + + ScreenChar & operator ()(int x, int y) { + if(x < 0 || y < 0 || x >= this->width || y >= this->height) { + // return Screen::outOfScreen; + } + return this->buffer[this->width * y + x]; + } + ScreenChar const & operator ()(int x, int y) const { + if(x < 0 || y < 0 || x >= this->width || y >= this->height) { + return Screen::outOfScreen; + } + return this->buffer[this->width * y + x]; + } +}; \ No newline at end of file diff --git a/prototypes/base/init.c b/prototypes/base/init.c deleted file mode 100644 index 2835935..0000000 --- a/prototypes/base/init.c +++ /dev/null @@ -1,16 +0,0 @@ -void init(void) -{ - const char hw[] = "Hello World!"; - int i; - char* video = (char*) 0xb8000; - - // C-Strings haben ein Nullbyte als Abschluss - for (i = 0; hw[i] != '\0'; i++) { - - // Zeichen i in den Videospeicher kopieren - video[i * 2] = hw[i]; - - // 0x07 = Hellgrau auf Schwarz - video[i * 2 + 1] = 0x07; - } -} \ No newline at end of file diff --git a/prototypes/base/init.cpp b/prototypes/base/init.cpp new file mode 100644 index 0000000..46e9834 --- /dev/null +++ b/prototypes/base/init.cpp @@ -0,0 +1,21 @@ +#include + +#include "screen.hpp" +#include "compat.h" + +extern "C" void init(void) +{ + const char hw[] = "Hello World!"; + int i; + + // C-Strings haben ein Nullbyte als Abschluss + for (i = 0; hw[i] != '\0'; i++) { + + // Zeichen i in den Videospeicher kopieren + Screen::main(i,0).c = hw[i]; + + // 0x07 = Hellgrau auf Schwarz + Screen::main(i,0).fg = (int)Color::Black; + Screen::main(i,0).bg = (int)Color::LightRed; + } +} diff --git a/prototypes/base/linker.ld b/prototypes/base/linker.ld new file mode 100644 index 0000000..fd6acd8 --- /dev/null +++ b/prototypes/base/linker.ld @@ -0,0 +1,37 @@ +ENTRY(_start) +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386:i386) + +SECTIONS +{ + . = 0x100000; + + kernelStart = .; + + .text : { + *(multiboot) + *(.text) + } + .data ALIGN(4096) : { + start_ctors = .; + KEEP(*( .init_array )); + KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* ))); + end_ctors = .; + + start_dtors = .; + KEEP(*( .fini_array )); + end_dtors = .; + + *(.data) + } + .rodata ALIGN(4096) : { + *(.rodata) + } + .bss ALIGN(4096) : { + *(.bss) + } + + /* Align the end of the kernel to the page size */ + . = ALIGN(4096); + kernelEnd = .; +} \ No newline at end of file diff --git a/prototypes/base/multiboot.S b/prototypes/base/multiboot.S index a968c1d..f96d476 100644 --- a/prototypes/base/multiboot.S +++ b/prototypes/base/multiboot.S @@ -1,4 +1,4 @@ -.section .text +.section multiboot #define MB_MAGIC 0x1badb002 #define MB_FLAGS 0x0 diff --git a/prototypes/base/src/compat.c b/prototypes/base/src/compat.c new file mode 100644 index 0000000..1af8b91 --- /dev/null +++ b/prototypes/base/src/compat.c @@ -0,0 +1,17 @@ +#include "compat.h" + +typedef void (*constructor)(); + +constructor start_ctors; +constructor end_ctors; + +void compat_call_ctors() +{ + for (constructor* i = &start_ctors;i != &end_ctors;++i) + (*i)(); +} + +void compat_call_dtors() +{ + +} \ No newline at end of file diff --git a/prototypes/base/src/screen.cpp b/prototypes/base/src/screen.cpp new file mode 100644 index 0000000..53ae230 --- /dev/null +++ b/prototypes/base/src/screen.cpp @@ -0,0 +1,19 @@ +#include +#include "screen.hpp" + +ScreenChar Screen::outOfScreen; +Screen Screen::main((ScreenChar*)0xb8000, 80, 25); + +Screen::Screen(ScreenChar *buffer, int width, int height) : + buffer(buffer), + width(width), + height(height) +{ + this->clear(); +} + +void Screen::clear() { + for(int i = 0; i < this->width * this->height; i++) { + this->buffer[i].c = ' '; + } +}