Adds linker script, C++ support and a simple screen class.

This commit is contained in:
Felix Queißner 2016-05-01 20:22:12 +02:00
parent cd5d85f99c
commit f85042a9c7
10 changed files with 206 additions and 46 deletions

View file

@ -1,21 +1,24 @@
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)
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/$@ $<
@ -23,5 +26,16 @@ kernel-base.ker: $(OBJS)
%.o: %.S
$(AS) $(CFLAGS) -c -o obj/$@ $<
%.o: %.cpp
$(CPP) $(CXXFLAGS) -c -o obj/$@ $<
%.o: src/%.cpp
$(CXX) $(CXXFLAGS) -c -o obj/$@ $<
%.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

View file

@ -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
call compat_call_ctors
call init
call compat_call_dtors
// 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.)
_stop:
cli
hlt
cli
hlt
jmp _stop
// 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
.section .bss
.space 8192
kernel_stack:

View file

@ -0,0 +1,13 @@
#pragma once
#if defined(__cplusplus)
extern "C" {
#endif
void compat_call_ctors();
void compat_call_dtors();
#if defined(__cplusplus)
}
#endif

View file

@ -0,0 +1,63 @@
#pragma once
#include <inttypes.h>
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];
}
};

View file

@ -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;
}
}

21
prototypes/base/init.cpp Normal file
View file

@ -0,0 +1,21 @@
#include <inttypes.h>
#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;
}
}

37
prototypes/base/linker.ld Normal file
View file

@ -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 = .;
}

View file

@ -1,4 +1,4 @@
.section .text
.section multiboot
#define MB_MAGIC 0x1badb002
#define MB_FLAGS 0x0

View file

@ -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()
{
}

View file

@ -0,0 +1,19 @@
#include <inttypes.h>
#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 = ' ';
}
}