Rework of project structure.

This commit is contained in:
Felix Queißner 2016-06-26 14:36:32 +02:00
parent 28bad4c5ac
commit b873c662c8
41 changed files with 1825 additions and 0 deletions

View file

@ -0,0 +1,27 @@
##
# Build all projects
##
PROJECTS = $(shell ls --file-type --ignore=libs --ignore=kernels --ignore=include | grep / | sed "s|/||")
all: $(PROJECTS) boot.img
.PHONY: $(PROJECTS)
$(PROJECTS):
make -C $@ $(ARGS)
boot.img: $(PROJECTS)
mformat -C -f 1440 -v VIDEO -i boot.img ::
mcopy -i boot.img \
kernels/* \
syslinux.cfg \
/boot/syslinux/libcom32.c32 \
/boot/syslinux/libutil.c32 \
/boot/syslinux/menu.c32 \
/boot/syslinux/mboot.c32 \
::
syslinux boot.img
mdir -i boot.img ::
run: boot.img
qemu-system-i386 boot.img

BIN
prototypes-rework/boot.img Normal file

Binary file not shown.

View file

@ -0,0 +1,36 @@
##
# DasOS common Makefile targets
##
INCLUDE_DIRS += ../include/ /opt/lib/gcc/i686-elf/6.1.0/include/
FLAGS = -ffreestanding -mno-sse -Werror -Wall -iquote include $(addprefix -I, $(INCLUDE_DIRS)) -O3 -g
ASFLAGS = $(FLAGS)
CFLAGS = $(FLAGS)
CXXFLAGS = $(FLAGS) -std=c++14 -fno-rtti -fno-exceptions -fno-leading-underscore -fno-use-cxa-atexit -nostdlib -fno-builtin
LDFLAGS = -L../libs/
SRCS = $(shell find -regextype egrep -regex '.*/.*\.(cpp|S|c)')
OBJS = $(addsuffix .o, $(notdir $(basename $(SRCS))))
%.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: src/%.c
$(CC) $(ASFLAGS) -c -o obj/$@ $<
%.o: src/%.S
$(AS) $(CFLAGS) -c -o obj/$@ $<
builddir:
mkdir -p ./obj/

View file

@ -0,0 +1,10 @@
##
# DasOS Makefile configuration
##
# Configure for target platform
CC=/opt/bin/i686-elf-gcc
CXX=/opt/bin/i686-elf-g++
LD=/opt/i686-elf/bin/ld
AR=/opt/i686-elf/bin/ar
AS=/opt/bin/i686-elf-gcc

View file

@ -0,0 +1,50 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#define ASM_READ_REG(reg, var) asm volatile("mov %%" #reg ", %0" : "=r" (var));
#define ASM_WRITE_REG(reg, var) asm volatile("mov %0, %%" #reg : : "r" (var));
namespace ASM
{
static inline void sti()
{
__asm__ volatile ("sti");
}
static inline void cli()
{
__asm__ volatile ("cli");
}
static inline void outb(uint16_t port, uint8_t data)
{
asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
}
static inline uint8_t inb(uint16_t port)
{
uint8_t data;
asm volatile ("inb %1, %0" : "=a" (data) : "d" (port));
return data;
}
static inline void invlpg(void* m)
{
/* Clobber memory to avoid optimizer re-ordering access before invlpg, which may cause nasty bugs. */
asm volatile ( "invlpg (%0)" : : "b"(m) : "memory" );
}
static inline void lidt(void *idt, size_t length)
{
struct {
uint16_t limit;
void* pointer;
} __attribute__((packed)) idtp = {
.limit = uint16_t(length * 8 - 1),
.pointer = idt,
};
asm volatile("lidt %0" : : "m" (idtp));
}
}

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,188 @@
#pragma once
#include "screen.hpp"
#include "pointer.hpp"
struct FColor
{
FColor() : color(Color::White) { }
FColor(Color color) : color(color) { }
Color color;
};
struct BColor
{
BColor() : color(Color::Black) { }
BColor(Color color) : color(color) { }
Color color;
};
template<typename T>
struct NumericFormat
{
T value;
uint32_t base;
/**
* Applies a padding to the number.
* A positive number will apply padding the right side,
* a negative number will pad the left side.
*/
int32_t padding = 0;
char padchar = ' ';
NumericFormat(T value) : value(value), base(10) { }
NumericFormat(T value, uint32_t base) : value(value), base(base) { }
};
namespace console_tools
{
template<typename T>
auto hex(T value) { return NumericFormat<T>(value, 16); }
template<typename T>
auto dec(T value) { return NumericFormat<T>(value, 10); }
template<typename T>
auto oct(T value) { return NumericFormat<T>(value, 8); }
template<typename T>
auto bin(T value) { return NumericFormat<T>(value, 2); }
template<typename T>
auto nbase(T value, uint32_t base) { return NumericFormat<T>(value, base); }
template<typename T>
auto pad(NumericFormat<T> value, int32_t padding, char c = ' ') {
value.padding = padding;
return value;
}
template<typename T>
auto pad(T value, int32_t padding, char c = ' ') {
return pad(NumericFormat<T>(value), padding, c);
}
}
class Console
{
public:
static Console main;
private:
Screen * const screen;
int x;
int y;
Color fg, bg;
bool caretEnabled;
private:
/**
* Moves the hardware caret.
*/
void updateCaret();
/**
* Prints the prefix for a given numeric base.
* @returns the prefix length.
*/
uint32_t printNumericPrefix(uint32_t base);
/**
* Prints a character several times.
*/
void putrep(char c, uint32_t repetitions);
public:
Console(Screen *screen);
/**
* Clears the console.
*/
void clear();
/**
* Puts a character on the screen.
*/
void put(char c);
/**
* Inserts a line break and returns the cursor to the start.
*/
void newline();
/**
* Scrolls screen a line upwards
*/
void scroll();
/**
* Moves the cursor to the given position
*/
void setCursor(int x, int y);
/**
* Sets the visibility of the caret.
*/
void setCaretVisible(bool visible = true);
/**
* Sets the text foreground color
*/
void setForeground(Color c) {
this->fg = c;
}
/**
* Sets the text background color
*/
void setBackground(Color c) {
this->bg = c;
}
/**
* Sets the text colors.
*/
void setColors(Color bg, Color fg) {
this->fg = fg;
this->bg = bg;
}
inline Console & operator << (char c)
{
this->put(c);
return *this;
}
inline Console & operator << (const char *str)
{
while(*str) {
*this << *str++;
}
return *this;
}
inline Console & operator << (const FColor &color)
{
this->fg = color.color;
return *this;
}
inline Console & operator << (const BColor &color)
{
this->bg = color.color;
return *this;
}
Console & operator << (uint32_t value);
Console & operator << (int32_t value);
Console & operator << (void *value);
Console & operator << (bool value);
template<typename T>
Console & operator << (pointer<T> ptr);
template<typename T>
Console & operator << (const NumericFormat<T> &fmt);
};

View file

@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
struct CpuState
{
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t interrupt;
uint32_t error;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
} __attribute__((packed));
static_assert(sizeof(CpuState) == 56, "CpuState must be 56 bytes large.");

View file

@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
class PIC
{
private:
uint16_t port;
public:
PIC(uint16_t port);
/**
* Sends an initialization code to the PIC.s
*/
void initialize(uint16_t irqBase, uint16_t icw3, uint16_t icw4);
/**
* Disables all interrupts where the corresponding bit in mask is set.
*/
void maskInterrupts(uint8_t mask);
/**
* Sends an end-of-interrupt to the PIC.
*/
void sendEndOfInterrupt();
};
extern PIC masterPIC, slavePIC;

View file

@ -0,0 +1,36 @@
#pragma once
#include <stdint.h>
namespace elf
{
static const uint32_t MAGIC = 0x464C457F;
struct Header {
uint32_t magic;
uint32_t version;
uint64_t reserved;
uint64_t version2;
uint32_t entry;
uint32_t ph_offset;
uint32_t sh_offset;
uint32_t flags;
uint16_t header_size;
uint16_t ph_entry_size;
uint16_t ph_entry_count;
uint16_t sh_entry_size;
uint16_t sh_entry_count;
uint16_t sh_str_table_index;
} __attribute__((packed));
struct ProgramHeader {
uint32_t type;
uint32_t offset;
uint32_t virt_addr;
uint32_t phys_addr;
uint32_t file_size;
uint32_t mem_size;
uint32_t flags;
uint32_t alignment;
} __attribute__((packed));
}

View file

@ -0,0 +1,18 @@
#pragma once
#define ENUM_CLASS_OPERATORS(type) static inline type operator | (type lhs, type rhs) { \
return static_cast<type>(static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs)); \
} \
static inline type operator & (type lhs, type rhs) { \
return static_cast<type>(static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)); \
} \
static inline bool operator * (type lhs, type rhs) { \
return (static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)) != 0; \
} \
static inline type & operator |=(type & lhs, type rhs) { \
reinterpret_cast<uint32_t&>(lhs) |= static_cast<uint32_t>(rhs); \
return lhs; \
}

View file

@ -0,0 +1,8 @@
#pragma once
enum class Error
{
#define ERROR(num, ident, desc) ident = num,
#include "errors.lst"
#undef ERROR
};

View file

@ -0,0 +1,10 @@
#pragma once
#include "enums.hpp"
enum class Exception
{
#define EXCEPTION(num, shorthand, ident, desc, type) ident = num,
#include "exceptions.lst"
#undef EXCEPTION
};

View file

@ -0,0 +1,7 @@
#pragma once
#include "asm.hpp"
// Import functions into global namespace
using ASM::inb;
using ASM::outb;

View file

@ -0,0 +1,26 @@
#pragma once
#include "errors.hpp"
#include "cpustate.hpp"
/**
* This class provides the blue screen of death.
* Discaimer: Color may vary!
*/
class BSOD
{
private:
BSOD() = delete;
public:
/**
* Dies with a simple message and error code display.
*/
static void die(Error code, const char *msg);
/**
* Dies with a simple message and error code display.
*/
static void die(Error code, const char *msg, CpuState *cpu);
};

View file

@ -0,0 +1,118 @@
#pragma once
#include <stdint.h>
#include "enums.hpp"
enum class SegmentAccess : uint8_t
{
None = 0,
Accessed = (1<<0),
Readable = (1<<1),
Writeable = (1<<1),
Direction = (1<<2),
Conforming = (1<<2),
Executable = (1<<3),
Segment = (1<<4),
Ring0 = 0,
Ring1 = (1<<5),
Ring2 = (1<<6),
Ring3 = (1<<5) | (1<<6),
Present = (1<<7),
};
ENUM_CLASS_OPERATORS(SegmentAccess)
enum class SegmentFlags : uint8_t
{
None = 0,
Available = (1<<0),
LongMode = (1<<1),
Use32Bit = (1<<2),
Use4KSize = (1<<3),
};
ENUM_CLASS_OPERATORS(SegmentFlags)
struct SegmentDescriptor
{
uint16_t limit0;
uint16_t base0;
uint8_t base1;
SegmentAccess access;
uint8_t limit1 : 4;
uint8_t flags0 : 4;
uint8_t base2;
SegmentDescriptor() :
limit0(0), base0(0), base1(0),
access(SegmentAccess::None),
limit1(0), flags0(0), base2(0)
{
}
SegmentDescriptor(
uint32_t base,
uint32_t length,
SegmentAccess access,
SegmentFlags flags) :
access(access)
{
this->setBase(base);
this->setFlags(flags);
if(this->flags() * SegmentFlags::Use4KSize) {
this->setLimit(length >> 12);
} else {
this->setLimit(length);
}
}
void setFlags(SegmentFlags flags)
{
this->flags0 = static_cast<uint8_t>(flags) & 0x0F;
}
SegmentFlags flags() const
{
return static_cast<SegmentFlags>(this->flags0);
}
uint32_t limit() const
{
return this->limit0 | (this->limit1 << 16);
}
void setLimit(uint32_t value)
{
this->limit0 = (value & 0x0FFFF) >> 0;
this->limit1 = (value & 0xFFFFF) >> 16;
}
uint32_t base() const
{
return this->base0 | (this->base1 << 16) | (this->base2 << 24);
}
void setBase(uint32_t value)
{
this->base0 = (value & 0x0000FFFF) >> 0;
this->base1 = (value & 0x00FF0000) >> 16;
this->base2 = (value & 0xFF000000) >> 24;
}
} __attribute__((packed));
static_assert(sizeof(SegmentDescriptor) == 8, "SegmentDescriptor must be 8 bytes large.");
class GDT
{
public:
static const uint32_t length = 8;
private:
static SegmentDescriptor descriptors[length];
GDT() = delete;
public:
static void initialize();
static SegmentDescriptor & descriptor(uint32_t index);
};

View file

@ -0,0 +1,92 @@
#pragma once
#include <stdint.h>
#include "enums.hpp"
#include "cpustate.hpp"
enum class InterruptFlags : uint8_t
{
None = 0x00,
Interrupt = 0x06,
TrapGate = 0x07,
TaskGate = 0x05,
Use32Bit = 0x08,
Ring0 = 0x00,
Ring1 = 0x20,
Ring2 = 0x40,
Ring3 = 0x60,
Present = 0x80,
};
ENUM_CLASS_OPERATORS(InterruptFlags)
struct InterruptDescriptor
{
uint16_t offset0;
uint16_t selector;
uint8_t zero;
InterruptFlags flags;
uint16_t offset1;
InterruptDescriptor();
InterruptDescriptor(uint32_t offset, uint32_t selector, InterruptFlags flags);
uint32_t offset() const;
void setOffset(uint32_t offset);
} __attribute__((packed));
static_assert(sizeof(InterruptDescriptor) == 8, "InterruptDescriptor must be 8 byte large.");
/**
* An interrupt that specifies
* a handler and if the interrupt is
* enabled. Any non-enabled interrupt
* causes a BSOD.
*/
class Interrupt
{
friend class IDT;
using Handler = void (*)(CpuState * & cpu);
private:
bool isEnabled;
Handler handler;
public:
Interrupt();
explicit Interrupt(Handler handler);
};
class IDT
{
public:
static const uint32_t length = 256;
static Interrupt interrupts[length];
private:
static InterruptDescriptor descriptors[length];
IDT() = delete;
static CpuState * dispatch(CpuState *cpu);
static void setupPIC();
public:
/**
* Accessor to an interrupt handler.
*/
static Interrupt & interrupt(uint32_t index);
/**
* Gets an interrupt descriptor
*/
static InterruptDescriptor & descriptor(uint32_t idx);
/**
* Initializes the interrupt table and sets up the PIC.
*/
static void initialize();
};

View file

@ -0,0 +1,18 @@
#pragma once
#include "pagetable.hpp"
class PageDirectory
{
private:
uint32_t tables[1024];
public:
PageDirectory();
~PageDirectory();
uint32_t & table(uint32_t index) {
return this->tables[index];
}
};
static_assert(sizeof(PageDirectory) == 4096, "PageDirectory must be 4096 bytes large");

View file

@ -0,0 +1,17 @@
#pragma once
class PageTable
{
private:
uint32_t pages[1024];
public:
PageTable();
~PageTable();
uint32_t & pageDescriptor(uint32_t pageIndex)
{
return this->pages[pageIndex];
}
};
static_assert(sizeof(PageTable) == 4096, "PageDirectory must be 4096 bytes large");

View file

@ -0,0 +1,38 @@
#pragma once
#include "pointer.hpp"
/**
* Physical memory management tool.
*/
class PMM
{
private:
PMM() = delete;
public:
/**
* Marks a page as free by external memory management.
*/
static void markFree(physical_t page);
/**
* Marks a page as used by external memory management.
*/
static void markUsed(physical_t page);
/**
* Allocates a single page.
* @remarks This method will either return a valid value or die with a BSOD if out of memory.
*/
static physical_t alloc();
/**
* Frees a given page by pointer.
*/
static void free(physical_t page);
/**
* Returns the free memory.
*/
static uint32_t getFreeMemory();
};

View file

@ -0,0 +1,62 @@
#pragma once
#include "pmm.hpp"
#include "enums.hpp"
#include "pagedirectory.hpp"
enum class VMMFlags
{
None = 0,
Present = (1<<0),
Writable = (1<<1),
UserSpace = (1<<2),
SystemAllocated = (1<<3),
};
ENUM_CLASS_OPERATORS(VMMFlags)
class VMMContext
{
friend class VMM;
private:
PageDirectory *directory;
/**
* Gets the uint32_t that describes the given virtual address
*/
uint32_t & getPageDescriptor(virtual_t virt);
public:
VMMContext();
~VMMContext();
/**
* Maps an arbitrary page into the virtual memory.
*/
void provide(virtual_t virt, VMMFlags flags);
/**
* Maps a given page into the virtual memory.
*/
void map(virtual_t virt, physical_t phys, VMMFlags flags);
/**
* Unmaps a given page from the virtual memory.
*/
void unmap(virtual_t virt);
};
class VMM
{
private:
VMM() = delete;
public:
/**
* Enables paging
*/
static void enable();
/**
* Sets the given context as the current context.
*/
static void activate(VMMContext & context);
};

View file

@ -0,0 +1,7 @@
ERROR(0, Success, Nothing went wrong. This should never encounter.)
ERROR(1, OutOfMemory, The system has run out of memory.)
ERROR(2, UnhandledException, An unhandled exception has occurred.)
ERROR(3, UnhandledInterrupt, An unhandled interrupt has occurred.)
ERROR(4, DriverAlreadyInstalled, A driver was already installed.)
ERROR(5, InvalidELFImage, The file beeing loaded is not a valid ELF file.)
ERROR(6, VMError, The virtual machine has failed.)

View file

@ -0,0 +1,32 @@
EXCEPTION(0x00, DE, DiviceByZero, Divide by Zero, Fault)
EXCEPTION(0x01, DB, Debug, Debug, Fault | Trap)
EXCEPTION(0x02, NMI, NonMaskableInterrupt, Non Maskable Interrupt, None)
EXCEPTION(0x03, BP, Breakpoint, Breakpoint, Trap)
EXCEPTION(0x04, OF, Overflow, Overflow, Trap)
EXCEPTION(0x05, BR, BoundRange, Bound Range, Fault)
EXCEPTION(0x06, UD, InvalidOpcode, Invalid Opcode, Fault)
EXCEPTION(0x07, NM, DeviceNotAvailable, Device Not Available, Fault)
EXCEPTION(0x08, DF, DoubleFault, Double Fault, Abort)
EXCEPTION(0x09, CSO, CoprocessorSegmentOverrun, Coprocessor Segment Overrun, None)
EXCEPTION(0x0a, TS, InvalidTSS, Invalid TSS, Fault)
EXCEPTION(0x0b, NP, SegmentNotPresent, Segment not Present, Fault)
EXCEPTION(0x0c, SS, StackFault, Stack Fault, Fault)
EXCEPTION(0x0d, GP, GeneralProtectionFault, General Protection, Fault)
EXCEPTION(0x0e, PF, PageFault, Page Fault, Fault)
EXCEPTION(0x0f, XX, Reserved0, Reserved, None)
EXCEPTION(0x10, MF, x87FloatingPoint, x87 Floating Point, Fault)
EXCEPTION(0x11, AC, AlignmentCheck, Alignment Check, Fault)
EXCEPTION(0x12, MC, MachineCheck, Machine Check, Abort)
EXCEPTION(0x13, XF, SIMDFloatingPoint, SIMD Floating Point, Fault)
EXCEPTION(0x14, XX, Reserved1, Reserved, None)
EXCEPTION(0x15, XX, Reserved2, Reserved, None)
EXCEPTION(0x16, XX, Reserved3, Reserved, None)
EXCEPTION(0x17, XX, Reserved4, Reserved, None)
EXCEPTION(0x18, XX, Reserved5, Reserved, None)
EXCEPTION(0x19, XX, Reserved6, Reserved, None)
EXCEPTION(0x1a, XX, Reserved7, Reserved, None)
EXCEPTION(0x1b, XX, Reserved8, Reserved, None)
EXCEPTION(0x1c, XX, Reserved9, Reserved, None)
EXCEPTION(0x1d, XX, Reserved10, Reserved, None)
EXCEPTION(0x1e, SX, SecuritySensitive, Security-sensitive event in Host, Fault)
EXCEPTION(0x1f, XX, Reserved11, Reserved, None)

View file

@ -0,0 +1,257 @@
ISR(0)
ISR(1)
ISR(2)
ISR(3)
ISR(4)
ISR(5)
ISR(6)
ISR(7)
ISR_ERR(8)
ISR(9)
ISR_ERR(10)
ISR_ERR(11)
ISR_ERR(12)
ISR_ERR(13)
ISR_ERR(14)
ISR(15)
ISR(16)
ISR_ERR(17)
ISR(18)
ISR(19)
ISR(20)
ISR(21)
ISR(22)
ISR(23)
ISR(24)
ISR(25)
ISR(26)
ISR(27)
ISR(28)
ISR(29)
ISR(30)
ISR(31)
ISR(32)
ISR(33)
ISR(34)
ISR(35)
ISR(36)
ISR(37)
ISR(38)
ISR(39)
ISR(40)
ISR(41)
ISR(42)
ISR(43)
ISR(44)
ISR(45)
ISR(46)
ISR(47)
ISR(48)
ISR(49)
ISR(50)
ISR(51)
ISR(52)
ISR(53)
ISR(54)
ISR(55)
ISR(56)
ISR(57)
ISR(58)
ISR(59)
ISR(60)
ISR(61)
ISR(62)
ISR(63)
ISR(64)
ISR(65)
ISR(66)
ISR(67)
ISR(68)
ISR(69)
ISR(70)
ISR(71)
ISR(72)
ISR(73)
ISR(74)
ISR(75)
ISR(76)
ISR(77)
ISR(78)
ISR(79)
ISR(80)
ISR(81)
ISR(82)
ISR(83)
ISR(84)
ISR(85)
ISR(86)
ISR(87)
ISR(88)
ISR(89)
ISR(90)
ISR(91)
ISR(92)
ISR(93)
ISR(94)
ISR(95)
ISR(96)
ISR(97)
ISR(98)
ISR(99)
ISR(100)
ISR(101)
ISR(102)
ISR(103)
ISR(104)
ISR(105)
ISR(106)
ISR(107)
ISR(108)
ISR(109)
ISR(110)
ISR(111)
ISR(112)
ISR(113)
ISR(114)
ISR(115)
ISR(116)
ISR(117)
ISR(118)
ISR(119)
ISR(120)
ISR(121)
ISR(122)
ISR(123)
ISR(124)
ISR(125)
ISR(126)
ISR(127)
ISR(128)
ISR(129)
ISR(130)
ISR(131)
ISR(132)
ISR(133)
ISR(134)
ISR(135)
ISR(136)
ISR(137)
ISR(138)
ISR(139)
ISR(140)
ISR(141)
ISR(142)
ISR(143)
ISR(144)
ISR(145)
ISR(146)
ISR(147)
ISR(148)
ISR(149)
ISR(150)
ISR(151)
ISR(152)
ISR(153)
ISR(154)
ISR(155)
ISR(156)
ISR(157)
ISR(158)
ISR(159)
ISR(160)
ISR(161)
ISR(162)
ISR(163)
ISR(164)
ISR(165)
ISR(166)
ISR(167)
ISR(168)
ISR(169)
ISR(170)
ISR(171)
ISR(172)
ISR(173)
ISR(174)
ISR(175)
ISR(176)
ISR(177)
ISR(178)
ISR(179)
ISR(180)
ISR(181)
ISR(182)
ISR(183)
ISR(184)
ISR(185)
ISR(186)
ISR(187)
ISR(188)
ISR(189)
ISR(190)
ISR(191)
ISR(192)
ISR(193)
ISR(194)
ISR(195)
ISR(196)
ISR(197)
ISR(198)
ISR(199)
ISR(200)
ISR(201)
ISR(202)
ISR(203)
ISR(204)
ISR(205)
ISR(206)
ISR(207)
ISR(208)
ISR(209)
ISR(210)
ISR(211)
ISR(212)
ISR(213)
ISR(214)
ISR(215)
ISR(216)
ISR(217)
ISR(218)
ISR(219)
ISR(220)
ISR(221)
ISR(222)
ISR(223)
ISR(224)
ISR(225)
ISR(226)
ISR(227)
ISR(228)
ISR(229)
ISR(230)
ISR(231)
ISR(232)
ISR(233)
ISR(234)
ISR(235)
ISR(236)
ISR(237)
ISR(238)
ISR(239)
ISR(240)
ISR(241)
ISR(242)
ISR(243)
ISR(244)
ISR(245)
ISR(246)
ISR(247)
ISR(248)
ISR(249)
ISR(250)
ISR(251)
ISR(252)
ISR(253)
ISR(254)
ISR(255)

View file

@ -0,0 +1,16 @@
IRQ(0, Timer, Programmable Interval Timer)
IRQ(1, PrimaryPS2, First PS/2 port / Keyboard Controller)
IRQ(2, SecondaryPIC, Connection to secondary PIC)
IRQ(3, RS232Even, RS-232 Port 2/4)
IRQ(4, RS232Odd, RS-232 Port 1/3)
IRQ(5, SecondaryLPT, LPT 2)
IRQ(6, Floppy, Floppy Disk Controller)
IRQ(7, PrimaryLPT, LPT 1 / Spurious Interrupt)
IRQ(8, RTC, RTC (CMOS Real Time Clock))
IRQ(9, Free, Free)
IRQ(10, FourthIDE, Fourth ATA/ATAPI/(E)IDE)
IRQ(11, ThirdIDE, Third ATA/ATAPI/(E)IDE)
IRQ(12, SecondaryPS2, Second PS/2 Port / Mouse Controller)
IRQ(13, FPU, FPU)
IRQ(14, PrimaryIDE, Primary ATA/ATAPI/(E)IDE)
IRQ(15, SecondaryIDE, Secundary ATA/ATAPI/(E)IDE / Spurious Interrupt)

View file

@ -0,0 +1,169 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "pointer.hpp"
#define MB_MEMSIZE (1<<0)
#define MB_BOOTDEVICE (1<<1)
#define MB_COMMANDLINE (1<<2)
#define MB_MODULES (1<<3)
#define MB_SYMS_AOUT (1<<4)
#define MB_SYMS_ELF (1<<5)
#define MB_MEMORYMAP (1<<6)
#define MB_DRIVES (1<<7)
#define MB_CONFIG_TABLE (1<<8)
#define MB_BOOTLOADER_NAME (1<<9)
#define MB_APS_TABLE (1<<10)
#define MB_VBE (1<<11)
#define MB_ASSERT_SIZE(type, len) static_assert(sizeof(type) == len, "multiboot::" #type " must be " #len " bytes large.")
namespace multiboot
{
template<typename T>
class mbarray
{
public:
const uint32_t length;
private:
T *data;
mbarray() = delete;
public:
T const & operator [](size_t idx) const {
return this->data[idx];
}
const T *begin() const {
return &data[0];
}
const T *end() const {
return &data[length];
}
} __attribute__((packed));
// Make sure the size is not dependend on the template parameter
MB_ASSERT_SIZE(mbarray<uint8_t>, 8);
MB_ASSERT_SIZE(mbarray<uint32_t>, 8);
struct MemoryMap
{
uint32_t entry_size;
uint64_t base;
uint64_t length;
uint32_t type;
bool isFree() const {
return this->type == 1;
}
} __attribute__((packed));
MB_ASSERT_SIZE(MemoryMap, 24);
struct Module
{
physical_t start;
physical_t end;
const char * name;
uint32_t reserved;
uint32_t size() const {
return this->end.numeric() - this->start.numeric();
}
} __attribute__((packed));
MB_ASSERT_SIZE(Module, 16);
struct Drive
{
uint32_t size;
uint8_t number;
uint8_t mode;
uint16_t cylinders;
uint8_t heads;
uint8_t sectors;
// 0x10 size-0x10 drive_ports I/O-Ports, die von diesem Gerät benutzt werden
// uint16_t ports[0];
/**
* Gets the number of ports used by this drive.
*/
uint32_t portCount() const {
return (this->size - 0x10) / sizeof(uint16_t);
}
/**
* Gets the given port.
* @return The port #idx or 0 if out of range.
*/
uint16_t port(size_t idx) const {
uint16_t const * ports = reinterpret_cast<uint16_t const *>(reinterpret_cast<uint8_t const *>(this) + 0x10);
if(idx >= this->portCount()) {
return 0;
}
return ports[idx];
}
} __attribute__((packed));
static_assert(sizeof(Drive) >= 10, "multiboot::Drive must be at least 12 bytes large.");
struct APMTable
{
uint16_t version;
uint16_t cseg;
uint32_t offset;
uint16_t cseg_16;
uint16_t dseg;
uint16_t flags;
uint16_t cseg_len;
uint16_t cseg_16_len;
uint16_t dseg_len;
} __attribute__((packed));
MB_ASSERT_SIZE(APMTable, 20);
struct Structure
{
uint32_t flags;
physical_t memLower;
physical_t memUpper;
uint32_t bootDevice;
const char * commandline;
mbarray<Module> modules;
union {
struct {
uint32_t tabsize;
uint32_t strsize;
uint32_t addr;
uint32_t reserved;
} __attribute__((packed)) symsAssemblerOut;
struct {
uint32_t num;
uint32_t size;
uintptr_t addr;
uintptr_t shndx;
} __attribute__((packed)) symsELF;
};
mbarray<MemoryMap> memoryMaps;
mbarray<Drive> drives;
physical_t configTable;
const char * bootLoaderName;
const APMTable * apmTable;
struct {
uint32_t controlInfo;
uint32_t modeInfo;
uint16_t mode;
uint16_t interfaceSegment;
uint16_t interfaceOffset;
uint16_t interfaceLength;
} __attribute__((packed)) vbe;
} __attribute__((packed));
MB_ASSERT_SIZE(Structure, 88);
}

View file

@ -0,0 +1,49 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
class Numeric
{
private:
Numeric() = delete;
public:
/**
* Converts an unsigned number to a string.
* @param buffer The target buffer where the string should be stored.
* @param length The length of the buffer.
* @param number The number that should be converted.
* @param radix The numeric base for the printed number.
* @return The length of the converted strings.
*/
static size_t toString(
char *buffer,
size_t length,
uint32_t number,
uint32_t radix = 10);
static size_t toString(
char *buffer,
size_t length,
uint64_t number,
uint32_t radix = 10);
/**
* Converts a signed number to a string.
* @param buffer The target buffer where the string should be stored.
* @param length The length of the buffer.
* @param number The number that should be converted.
* @param radix The numeric base for the printed number.
* @return The length of the converted strings.
*/
static size_t toString(
char *buffer,
size_t length,
int32_t number,
uint32_t radix = 10);
static size_t toString(
char *buffer,
size_t length,
int64_t number,
uint32_t radix = 10);
};

View file

@ -0,0 +1,116 @@
#pragma once
#include <stdint.h>
/**
* Provides a strong pointer wrapper which can be used to address
* different memory types (physical, virtual, ...) and preventing
* a wrong assignment.
* @remarks The pointer size is fixed to 32 bits.
*/
template<typename TIdent>
class pointer
{
public:
/**
* A value that declares the pointer invalid.
*/
static pointer invalid;
private:
uint32_t ptr;
public:
/**
* Creates the pointer by giving a raw pointer.
*/
explicit pointer(void *ptr) :
ptr(reinterpret_cast<uint32_t>(ptr))
{
}
/**
* Creates the pointer by giving an integer value.
*/
explicit pointer(uint32_t value) :
ptr(value)
{
}
pointer(const pointer &) = default;
pointer(pointer &&) = default;
~pointer() = default;
pointer & operator = (const pointer & other) {
this->ptr = other.ptr;
return *this;
}
/**
* Returns the numeric integer value of the pointer.
*/
uint32_t numeric() const {
return this->ptr;
}
/**
* Returns the pointer as a raw pointer.
*/
void * data() const {
return reinterpret_cast<void*>(this->ptr);
}
/**
* Returns the pointer as a raw typed pointer.
*/
template<typename T>
T * data () const {
return reinterpret_cast<T*>(this->ptr);
}
/**
* Allow explicit conversion to a raw pointer.
*/
explicit operator void * () const {
return this->data();
}
/**
* Returns an aligned version of the pointer.
* Rounds the pointer to the memory bottom.
*/
pointer alignLower(uint32_t alignment) {
if(alignment == 0) return pointer::invalid;
return pointer(this->ptr & ~(alignment - 1));
}
/**
* Returns an aligned version of the pointer.
* Rounds the pointer to the memory top.
*/
pointer alignUpper(uint32_t alignment) {
if(alignment == 0) return pointer::invalid;
return pointer((this->ptr + (alignment - 1)) & ~(alignment - 1));
}
} __attribute__((packed));
template <class T>
pointer<T> pointer<T>::invalid(uint32_t(0xFFFFFFFF));
struct physical_t_ident;
struct virtual_t_ident;
// Add different memory pointer types here....
/**
* A pointer pointing to physical memory.
*/
using physical_t = pointer<physical_t_ident>;
/**
* A pointer pointing to virtual memory.
*/
using virtual_t = pointer<virtual_t_ident>;
static_assert(sizeof(physical_t) == 4, "pointer is not 4 byte wide.");

View file

@ -0,0 +1,64 @@
#pragma once
#include <stdint.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;
public:
static Screen main;
private:
ScreenChar * const buffer;
public:
const int width;
const int height;
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

@ -0,0 +1,7 @@
$(KERNEL): $(OBJS)
$(LD) -T../linker.ld -o ../kernels/$@ $(addprefix obj/, $^) $(LDFLAGS) $(LIBS)
deploy: $(KERNEL)
cp ../kernels/$(KERNEL) /srv/tftp/$(KERNEL)

View file

@ -0,0 +1,12 @@
##
# Build base library parts of the libc.
##
include ../config.mk
LIBRARY = libbase.a
all: builddir $(LIBRARY)
include ../common.mk
include ../library.mk

View file

@ -0,0 +1,19 @@
char * strcpy(char * dst, const char *src)
{
char * tmp = dst;
while(((*tmp++) = (*src++)));
return dst;
}
char *strcat(char * dst, const char *src)
{
char * tmp = dst;
while(*tmp++);
tmp--;
while(((*tmp++) = (*src++)));
return dst;
}

View file

@ -0,0 +1,12 @@
##
# Build multiboot entry point library.
##
include ../config.mk
LIBRARY = libboot.a
all: builddir $(LIBRARY)
include ../common.mk
include ../library.mk

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,23 @@
.section .text
.extern init
.extern compat_call_ctors
.extern compat_call_dtors
.global _start
_start:
mov $kernel_stack, %esp
push %ebx
call compat_call_ctors
call init
call compat_call_dtors
_stop:
cli
hlt
jmp _stop
.section .bss
.space 8192
kernel_stack:

View file

@ -0,0 +1,3 @@
$(LIBRARY): $(OBJS)
$(AR) rcs ../libs/$(LIBRARY) $(addprefix obj/, $^)

View file

@ -0,0 +1,37 @@
ENTRY(_start)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS
{
. = 0x100000;
kernelStartMarker = .;
.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);
kernelEndMarker = .;
}

View file

@ -0,0 +1,22 @@
DEFAULT menu.c32
prompt 0
MENU TITLE DasOS Boot Menu
MENU AUTOBOOT Starting DasOS in # seconds
TIMEOUT 300
TOTALTIMEOUT 9000
LABEL dasos
MENU DEFAULT
MENU LABEL DasOS
KERNEL mboot.c32
APPEND kernel-base.ker
LABEL video
MENU LABEL VBE Video Test
KERNEL mboot.c32
APPEND video.ker
LABEL poweroff
MENU LABEL Poweroff
KERNEL poweroff.c32

View file

@ -0,0 +1,13 @@
##
# Builds the video test kernel
##
include ../config.mk
KERNEL = video.ker
LIBS = -lboot
all: builddir $(KERNEL)
include ../common.mk
include ../kernel.mk

View file

@ -0,0 +1,28 @@
.section multiboot
#define MB_MAGIC 0x1badb002
#define MB_FLAGS 0x07
#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)
.align 4
// Offset Type Field Name Note
// 0 u32 magic required
// 4 u32 flags required
// 8 u32 checksum required
.int MB_MAGIC
.int MB_FLAGS
.int MB_CHECKSUM
// 12 u32 header_addr if flags[16] is set
// 16 u32 load_addr if flags[16] is set
// 20 u32 load_end_addr if flags[16] is set
// 24 u32 bss_end_addr if flags[16] is set
// 28 u32 entry_addr if flags[16] is set
.int 0, 0, 0, 0, 0
// 32 u32 mode_type if flags[2] is set
// 36 u32 width if flags[2] is set
// 40 u32 height if flags[2] is set
// 44 u32 depth if flags[2] is set
.int 0, 640, 480, 32

View file

@ -0,0 +1,95 @@
#include <stdint.h>
#include <multiboot.hpp>
#include <io.hpp>
struct dummy;
// Symbols generated by linker, no useful content in there...
extern dummy kernelStartMarker;
extern dummy kernelEndMarker;
uint16_t * video = (uint16_t*)0xB8000;
// Prüft, ob man bereits schreiben kann
static uint8_t is_transmit_empty(uint16_t base) {
return inb(base+5) & 0x20;
}
// Byte senden
static void write_com(uint16_t base, uint8_t chr) {
while (is_transmit_empty(base)==0);
outb(base,chr);
}
#define VBE_FAR(name) uint32_t name;
struct ModeInfoBlock {
uint16_t attributes;
uint8_t winA,winB;
uint16_t granularity;
uint16_t winsize;
uint16_t segmentA, segmentB;
VBE_FAR(realFctPtr);
uint16_t pitch; // bytes per scanline
uint16_t Xres, Yres;
uint8_t Wchar, Ychar, planes, bpp, banks;
uint8_t memory_model, bank_size, image_pages;
uint8_t reserved0;
uint8_t red_mask, red_position;
uint8_t green_mask, green_position;
uint8_t blue_mask, blue_position;
uint8_t rsv_mask, rsv_position;
uint8_t directcolor_attributes;
uint32_t physbase; // your LFB (Linear Framebuffer) address ;)
uint32_t reserved1;
uint16_t reserved2;
} __attribute__((packed));
static ModeInfoBlock mib;
static void setpixel(int x, int y, uint32_t color)
{
uint8_t *fb = (uint8_t*)mib.physbase;
fb[mib.pitch * y + 4 * x + 2] = (color >> 0) & 0xFF;
fb[mib.pitch * y + 4 * x + 1] = (color >> 8) & 0xFF;
fb[mib.pitch * y + 4 * x + 0] = (color >> 16) & 0xFF;
}
extern "C" void init(multiboot::Structure const & data)
{
write_com(0x3F8, 'H');
write_com(0x3F8, 'i');
write_com(0x3F8, '\n');
const char *msg = "You should not see this.";
while(*msg)
{
*(video++) = *msg++ | 0x0700;
}
mib = *(ModeInfoBlock*)data.vbe.modeInfo;
for(int y = 0; y < mib.Yres; y++)
{
for(int x = 0; x < mib.Xres; x++)
{
uint32_t r = x % 256;
uint32_t g = y % 256;
uint32_t b = 0x00;
setpixel(x, y, r | (g << 8) | (b << 16));
}
}
write_com(0x3F8, 'B');
write_com(0x3F8, 'y');
write_com(0x3F8, 'e');
write_com(0x3F8, '\n');
while(true);
}