From 0bd937afb59a41b1f459cbdac4a69b85a1b43286 Mon Sep 17 00:00:00 2001 From: Fergal Moran Date: Sun, 7 Jun 2020 23:10:34 +0100 Subject: [PATCH] Global descriptor table added --- Makefile | 10 ++--- include/gdt.h | 54 +++++++++++++++++++++++++ types.h => include/types.h | 8 ++++ src/gdt.cpp | 78 ++++++++++++++++++++++++++++++++++++ kernel.cpp => src/kernel.cpp | 14 +++++-- loader.s => src/loader.s | 0 6 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 include/gdt.h rename types.h => include/types.h (69%) create mode 100644 src/gdt.cpp rename kernel.cpp => src/kernel.cpp (70%) rename loader.s => src/loader.s (100%) diff --git a/Makefile b/Makefile index bb8f1b5..8a80308 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,12 @@ GPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-excep ASPARAMS = --32 LDPARAMS = -melf_i386 -objs = loader.o kernel.o +objs = loader.o gdt.o kernel.o -%.o: %.cpp +%.o: src/%.cpp g++ $(GPPPARAMS) -o $@ -c $< -%.o: %.s +%.o: src/%.s as $(ASPARAMS) -o $@ $< ferglos.bin: linker.ld $(objs) @@ -21,7 +21,7 @@ ferglos.iso: ferglos.bin echo 'set timeout=0' > iso/boot/grub/grub.cfg echo 'set default=0' >> iso/boot/grub/grub.cfg echo '' >> iso/boot/grub/grub.cfg - echo 'menuentry "My Operating System" {' >> iso/boot/grub/grub.cfg + echo 'menuentry "FerglOS" {' >> iso/boot/grub/grub.cfg echo ' multiboot /boot/ferglos.bin' >> iso/boot/grub/grub.cfg echo ' boot' >> iso/boot/grub/grub.cfg echo '}' >> iso/boot/grub/grub.cfg @@ -29,7 +29,7 @@ ferglos.iso: ferglos.bin rm -rf iso run: ferglos.iso - /usr/lib/virtualbox/VirtualBoxVM --startvm FerglOS + /usr/lib/virtualbox/VirtualBoxVM --startvm ferglos clean: rm -rfv iso *.o *.bin diff --git a/include/gdt.h b/include/gdt.h new file mode 100644 index 0000000..2a3393c --- /dev/null +++ b/include/gdt.h @@ -0,0 +1,54 @@ +/* + * gdt.h + * Author: Fergal Moran + * Copyright: 2020 Fergal Moran + * + * BSD License - do what you want + */ + +#ifndef __GDT_H +#define __GDT_H +#include "types.h" + +/* + The Global Descriptor Table (GDT) is a data structure used by Intel x86-family processors + starting with the 80286 in order to define the characteristics of the various memory areas + used during program execution, including the base address, the size, and access privileges + like executability and writability. + These memory areas are called segments in Intel terminology. + + https://en.wikipedia.org/wiki/Global_Descriptor_Table + +*/ + +class GlobalDescriptorTable { + public: + class SegmentDescriptor { + private: + uint16_t limit_lo; + uint16_t base_lo; + uint8_t base_hi; + uint8_t type; + uint8_t limit_hi_flags; + uint8_t base_vhi; + + public: + SegmentDescriptor(uint32_t base, uint32_t limit, uint8_t flags); + uint32_t Base(); + uint32_t Limit(); + + } __attribute__((packed)); + + SegmentDescriptor nullSegmentSelector; + SegmentDescriptor unusedSegmentSelector; + SegmentDescriptor codeSegmentSelector; + SegmentDescriptor dataSegmentSelector; + + GlobalDescriptorTable(); + ~GlobalDescriptorTable(); + + uint16_t CodeSegmentSelector(); + uint16_t DataSegmentSelector(); +}; + +#endif \ No newline at end of file diff --git a/types.h b/include/types.h similarity index 69% rename from types.h rename to include/types.h index cfa2465..0f53c93 100644 --- a/types.h +++ b/include/types.h @@ -1,3 +1,11 @@ +/* + * types.h + * Author: Fergal Moran + * Copyright: 2020 Fergal Moran + * + * BSD License - do what you want + */ + #ifndef __TYPES_H #define __TYPES_H diff --git a/src/gdt.cpp b/src/gdt.cpp new file mode 100644 index 0000000..b06efc4 --- /dev/null +++ b/src/gdt.cpp @@ -0,0 +1,78 @@ +/* + * gdt.cpp + * Author: Fergal Moran + * Copyright: 2020 Fergal Moran + * + * BSD License - do what you want + */ + +#include "../include/gdt.h" + +GlobalDescriptorTable::GlobalDescriptorTable() : nullSegmentSelector(0, 0, 0), + unusedSegmentSelector(0, 0, 0), + codeSegmentSelector(0, 64 * 1024 * 1024, 0x9A), + dataSegmentSelector(0, 64 * 1024 * 1024, 0x92) { + uint32_t i[2]; + i[1] = (uint32_t)this; + i[0] = sizeof(GlobalDescriptorTable) << 16; + + asm volatile("lgdt (%0)" + : + : "p"(((uint8_t *)i) + 2)); +} +GlobalDescriptorTable::~GlobalDescriptorTable() { +} + +uint16_t GlobalDescriptorTable::DataSegmentSelector() { + return (uint8_t *)&dataSegmentSelector - (uint8_t *)this; +} + +uint16_t GlobalDescriptorTable::CodeSegmentSelector() { + return (uint8_t *)&codeSegmentSelector - (uint8_t *)this; +} + +GlobalDescriptorTable::SegmentDescriptor::SegmentDescriptor(uint32_t base, uint32_t limit, uint8_t flags) { + uint8_t *target = (uint8_t *)this; + if (limit <= 65536) { + target[6] = 0x40; + } else { + if ((limit % 0xFFF) != 0xFFF) { + limit = (limit >> 12) - 1; + } else { + limit = limit >> 12; + } + target[6] = 0xC0; + } + target[0] = limit & 0xFF; + target[1] = limit >> 8 & 0xFF; + target[6] |= (limit >> 16) & 0xFF; + + target[2] = base & 0xFF; + target[3] = (base >> 8) & 0xFF; + target[4] = (base >> 16) & 0xFF; + target[7] = (base >> 24) & 0xFF; + + target[5] = flags; +} +uint32_t GlobalDescriptorTable::SegmentDescriptor::Base() { + uint8_t *target = (uint8_t *)this; + uint32_t result = target[7]; + + result = (result << 8) + target[4]; + result = (result << 8) + target[3]; + result = (result << 8) + target[2]; + + return result; +} +uint32_t GlobalDescriptorTable::SegmentDescriptor::Limit() { + uint8_t *target = (uint8_t *)this; + uint32_t result = target[6] & 0xF; + + result = (result << 8) + target[1]; + result = (result << 8) + target[0]; + + if ((target[6] & 0xC0) == 0xC0) { + result = (result << 12) | 0xFFF; + } + return result; +} diff --git a/kernel.cpp b/src/kernel.cpp similarity index 70% rename from kernel.cpp rename to src/kernel.cpp index dba7938..a2e0c44 100644 --- a/kernel.cpp +++ b/src/kernel.cpp @@ -1,4 +1,13 @@ -#include "types.h" +/* + * kernel.cpp + * Author: Fergal Moran + * Copyright: 2020 Fergal Moran + * + * BSD License - do what you want + */ + +#include "../include/gdt.h" +#include "../include/types.h" void printf(char* str) { static uint16_t* VideoMemory = (uint16_t*)0xb8000; @@ -16,8 +25,7 @@ extern "C" void call_constructors() { } extern "C" void ferglos_Main(const void* multiboot_structure, uint32_t /*mb_mag*/) { - printf("Hello, Sailor!"); - + printf("Welcome to FerglOS v0.0.1!"); while (1) ; } \ No newline at end of file diff --git a/loader.s b/src/loader.s similarity index 100% rename from loader.s rename to src/loader.s