diff --git a/prototypes-rework/Makefile b/prototypes-rework/Makefile new file mode 100644 index 0000000..20ca601 --- /dev/null +++ b/prototypes-rework/Makefile @@ -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 \ No newline at end of file diff --git a/prototypes-rework/boot.img b/prototypes-rework/boot.img new file mode 100644 index 0000000..4d22536 Binary files /dev/null and b/prototypes-rework/boot.img differ diff --git a/prototypes-rework/common.mk b/prototypes-rework/common.mk new file mode 100644 index 0000000..e1a9661 --- /dev/null +++ b/prototypes-rework/common.mk @@ -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/ \ No newline at end of file diff --git a/prototypes-rework/config.mk b/prototypes-rework/config.mk new file mode 100644 index 0000000..7975fa0 --- /dev/null +++ b/prototypes-rework/config.mk @@ -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 \ No newline at end of file diff --git a/prototypes-rework/include/asm.hpp b/prototypes-rework/include/asm.hpp new file mode 100644 index 0000000..6073347 --- /dev/null +++ b/prototypes-rework/include/asm.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +#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)); + } +} \ No newline at end of file diff --git a/prototypes-rework/include/compat.h b/prototypes-rework/include/compat.h new file mode 100644 index 0000000..747de12 --- /dev/null +++ b/prototypes-rework/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-rework/include/console.hpp b/prototypes-rework/include/console.hpp new file mode 100644 index 0000000..331c555 --- /dev/null +++ b/prototypes-rework/include/console.hpp @@ -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 +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 + auto hex(T value) { return NumericFormat(value, 16); } + + template + auto dec(T value) { return NumericFormat(value, 10); } + + template + auto oct(T value) { return NumericFormat(value, 8); } + + template + auto bin(T value) { return NumericFormat(value, 2); } + + template + auto nbase(T value, uint32_t base) { return NumericFormat(value, base); } + + template + auto pad(NumericFormat value, int32_t padding, char c = ' ') { + value.padding = padding; + return value; + } + + template + auto pad(T value, int32_t padding, char c = ' ') { + return pad(NumericFormat(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 + Console & operator << (pointer ptr); + + template + Console & operator << (const NumericFormat &fmt); +}; \ No newline at end of file diff --git a/prototypes-rework/include/cpustate.hpp b/prototypes-rework/include/cpustate.hpp new file mode 100644 index 0000000..e2e907b --- /dev/null +++ b/prototypes-rework/include/cpustate.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +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."); \ No newline at end of file diff --git a/prototypes-rework/include/driver/pic.hpp b/prototypes-rework/include/driver/pic.hpp new file mode 100644 index 0000000..f9adc58 --- /dev/null +++ b/prototypes-rework/include/driver/pic.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +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; \ No newline at end of file diff --git a/prototypes-rework/include/elf.hpp b/prototypes-rework/include/elf.hpp new file mode 100644 index 0000000..9bd9834 --- /dev/null +++ b/prototypes-rework/include/elf.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +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)); +} \ No newline at end of file diff --git a/prototypes-rework/include/enums.hpp b/prototypes-rework/include/enums.hpp new file mode 100644 index 0000000..a8b6035 --- /dev/null +++ b/prototypes-rework/include/enums.hpp @@ -0,0 +1,18 @@ +#pragma once + +#define ENUM_CLASS_OPERATORS(type) static inline type operator | (type lhs, type rhs) { \ + return static_cast(static_cast(lhs) | static_cast(rhs)); \ +} \ +static inline type operator & (type lhs, type rhs) { \ + return static_cast(static_cast(lhs) & static_cast(rhs)); \ +} \ +static inline bool operator * (type lhs, type rhs) { \ + return (static_cast(lhs) & static_cast(rhs)) != 0; \ +} \ +static inline type & operator |=(type & lhs, type rhs) { \ + reinterpret_cast(lhs) |= static_cast(rhs); \ + return lhs; \ +} + + + diff --git a/prototypes-rework/include/errors.hpp b/prototypes-rework/include/errors.hpp new file mode 100644 index 0000000..8e02797 --- /dev/null +++ b/prototypes-rework/include/errors.hpp @@ -0,0 +1,8 @@ +#pragma once + +enum class Error +{ +#define ERROR(num, ident, desc) ident = num, +#include "errors.lst" +#undef ERROR +}; \ No newline at end of file diff --git a/prototypes-rework/include/exceptions.hpp b/prototypes-rework/include/exceptions.hpp new file mode 100644 index 0000000..c288ec6 --- /dev/null +++ b/prototypes-rework/include/exceptions.hpp @@ -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 +}; \ No newline at end of file diff --git a/prototypes-rework/include/io.hpp b/prototypes-rework/include/io.hpp new file mode 100644 index 0000000..3265fe2 --- /dev/null +++ b/prototypes-rework/include/io.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "asm.hpp" + +// Import functions into global namespace +using ASM::inb; +using ASM::outb; \ No newline at end of file diff --git a/prototypes-rework/include/kernel/bsod.hpp b/prototypes-rework/include/kernel/bsod.hpp new file mode 100644 index 0000000..9009bf1 --- /dev/null +++ b/prototypes-rework/include/kernel/bsod.hpp @@ -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); + +}; \ No newline at end of file diff --git a/prototypes-rework/include/kernel/gdt.hpp b/prototypes-rework/include/kernel/gdt.hpp new file mode 100644 index 0000000..77f55a1 --- /dev/null +++ b/prototypes-rework/include/kernel/gdt.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include +#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(flags) & 0x0F; + } + + SegmentFlags flags() const + { + return static_cast(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); +}; \ No newline at end of file diff --git a/prototypes-rework/include/kernel/idt.hpp b/prototypes-rework/include/kernel/idt.hpp new file mode 100644 index 0000000..10410b2 --- /dev/null +++ b/prototypes-rework/include/kernel/idt.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include +#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(); + +}; \ No newline at end of file diff --git a/prototypes-rework/include/kernel/pagedirectory.hpp b/prototypes-rework/include/kernel/pagedirectory.hpp new file mode 100644 index 0000000..ef6f3fb --- /dev/null +++ b/prototypes-rework/include/kernel/pagedirectory.hpp @@ -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"); \ No newline at end of file diff --git a/prototypes-rework/include/kernel/pagetable.hpp b/prototypes-rework/include/kernel/pagetable.hpp new file mode 100644 index 0000000..e7c4fc8 --- /dev/null +++ b/prototypes-rework/include/kernel/pagetable.hpp @@ -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"); \ No newline at end of file diff --git a/prototypes-rework/include/kernel/pmm.hpp b/prototypes-rework/include/kernel/pmm.hpp new file mode 100644 index 0000000..e5aa39b --- /dev/null +++ b/prototypes-rework/include/kernel/pmm.hpp @@ -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(); +}; \ No newline at end of file diff --git a/prototypes-rework/include/kernel/vmm.hpp b/prototypes-rework/include/kernel/vmm.hpp new file mode 100644 index 0000000..d01d288 --- /dev/null +++ b/prototypes-rework/include/kernel/vmm.hpp @@ -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); +}; diff --git a/prototypes-rework/include/lists/errors.lst b/prototypes-rework/include/lists/errors.lst new file mode 100644 index 0000000..661dc88 --- /dev/null +++ b/prototypes-rework/include/lists/errors.lst @@ -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.) \ No newline at end of file diff --git a/prototypes-rework/include/lists/exceptions.lst b/prototypes-rework/include/lists/exceptions.lst new file mode 100644 index 0000000..3fcea29 --- /dev/null +++ b/prototypes-rework/include/lists/exceptions.lst @@ -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) \ No newline at end of file diff --git a/prototypes-rework/include/lists/interrupts.lst b/prototypes-rework/include/lists/interrupts.lst new file mode 100644 index 0000000..2f1022e --- /dev/null +++ b/prototypes-rework/include/lists/interrupts.lst @@ -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) diff --git a/prototypes-rework/include/lists/irqs.lst b/prototypes-rework/include/lists/irqs.lst new file mode 100644 index 0000000..bb09567 --- /dev/null +++ b/prototypes-rework/include/lists/irqs.lst @@ -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) \ No newline at end of file diff --git a/prototypes-rework/include/multiboot.hpp b/prototypes-rework/include/multiboot.hpp new file mode 100644 index 0000000..23c66de --- /dev/null +++ b/prototypes-rework/include/multiboot.hpp @@ -0,0 +1,169 @@ +#pragma once + +#include +#include +#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 + 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, 8); + MB_ASSERT_SIZE(mbarray, 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(reinterpret_cast(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 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 memoryMaps; + mbarray 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); + +} \ No newline at end of file diff --git a/prototypes-rework/include/numeric.hpp b/prototypes-rework/include/numeric.hpp new file mode 100644 index 0000000..5ca83c7 --- /dev/null +++ b/prototypes-rework/include/numeric.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +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); +}; \ No newline at end of file diff --git a/prototypes-rework/include/pointer.hpp b/prototypes-rework/include/pointer.hpp new file mode 100644 index 0000000..557e23b --- /dev/null +++ b/prototypes-rework/include/pointer.hpp @@ -0,0 +1,116 @@ +#pragma once + +#include + +/** + * 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 +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(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(this->ptr); + } + + /** + * Returns the pointer as a raw typed pointer. + */ + template + T * data () const { + return reinterpret_cast(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 +pointer pointer::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; + +/** + * A pointer pointing to virtual memory. + */ +using virtual_t = pointer; + + +static_assert(sizeof(physical_t) == 4, "pointer is not 4 byte wide."); \ No newline at end of file diff --git a/prototypes-rework/include/screen.hpp b/prototypes-rework/include/screen.hpp new file mode 100644 index 0000000..ab4c612 --- /dev/null +++ b/prototypes-rework/include/screen.hpp @@ -0,0 +1,64 @@ +#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; +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]; + } +}; \ No newline at end of file diff --git a/prototypes-rework/kernel.mk b/prototypes-rework/kernel.mk new file mode 100644 index 0000000..f51bd1e --- /dev/null +++ b/prototypes-rework/kernel.mk @@ -0,0 +1,7 @@ + + +$(KERNEL): $(OBJS) + $(LD) -T../linker.ld -o ../kernels/$@ $(addprefix obj/, $^) $(LDFLAGS) $(LIBS) + +deploy: $(KERNEL) + cp ../kernels/$(KERNEL) /srv/tftp/$(KERNEL) diff --git a/prototypes-rework/libbase/Makefile b/prototypes-rework/libbase/Makefile new file mode 100644 index 0000000..1a28c46 --- /dev/null +++ b/prototypes-rework/libbase/Makefile @@ -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 \ No newline at end of file diff --git a/prototypes-rework/libbase/src/string.c b/prototypes-rework/libbase/src/string.c new file mode 100644 index 0000000..eb16ca2 --- /dev/null +++ b/prototypes-rework/libbase/src/string.c @@ -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; +} diff --git a/prototypes-rework/libboot/Makefile b/prototypes-rework/libboot/Makefile new file mode 100644 index 0000000..b1dddb0 --- /dev/null +++ b/prototypes-rework/libboot/Makefile @@ -0,0 +1,12 @@ +## +# Build multiboot entry point library. +## + +include ../config.mk + +LIBRARY = libboot.a + +all: builddir $(LIBRARY) + +include ../common.mk +include ../library.mk \ No newline at end of file diff --git a/prototypes-rework/libboot/compat.c b/prototypes-rework/libboot/compat.c new file mode 100644 index 0000000..1af8b91 --- /dev/null +++ b/prototypes-rework/libboot/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-rework/libboot/entrypoint.S b/prototypes-rework/libboot/entrypoint.S new file mode 100644 index 0000000..ba94dae --- /dev/null +++ b/prototypes-rework/libboot/entrypoint.S @@ -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: \ No newline at end of file diff --git a/prototypes-rework/library.mk b/prototypes-rework/library.mk new file mode 100644 index 0000000..e5b1479 --- /dev/null +++ b/prototypes-rework/library.mk @@ -0,0 +1,3 @@ + +$(LIBRARY): $(OBJS) + $(AR) rcs ../libs/$(LIBRARY) $(addprefix obj/, $^) \ No newline at end of file diff --git a/prototypes-rework/linker.ld b/prototypes-rework/linker.ld new file mode 100644 index 0000000..ed97bd5 --- /dev/null +++ b/prototypes-rework/linker.ld @@ -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 = .; +} \ No newline at end of file diff --git a/prototypes-rework/syslinux.cfg b/prototypes-rework/syslinux.cfg new file mode 100644 index 0000000..7ae1522 --- /dev/null +++ b/prototypes-rework/syslinux.cfg @@ -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 diff --git a/prototypes-rework/video/Makefile b/prototypes-rework/video/Makefile new file mode 100644 index 0000000..1d6b872 --- /dev/null +++ b/prototypes-rework/video/Makefile @@ -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 \ No newline at end of file diff --git a/prototypes-rework/video/multiboot.S b/prototypes-rework/video/multiboot.S new file mode 100644 index 0000000..f5af759 --- /dev/null +++ b/prototypes-rework/video/multiboot.S @@ -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 \ No newline at end of file diff --git a/prototypes-rework/video/src/init.cpp b/prototypes-rework/video/src/init.cpp new file mode 100644 index 0000000..2c93696 --- /dev/null +++ b/prototypes-rework/video/src/init.cpp @@ -0,0 +1,95 @@ +#include + +#include +#include + +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); +}