Adds GDT initialization.
This commit is contained in:
parent
8e247ba638
commit
4e21175e8e
3 changed files with 173 additions and 56 deletions
|
@ -4,68 +4,127 @@
|
|||
|
||||
enum class SegmentAccess : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
Accessed = (1 << 0),
|
||||
|
||||
Readable = (1<<1),
|
||||
Writable = (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),
|
||||
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 SegmentFlags : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
Available = (1<<0),
|
||||
LongMode = (1<<1),
|
||||
Use32Bit = (1<<2),
|
||||
Use4KSize = (1<<3),
|
||||
};
|
||||
|
||||
static inline SegmentAccess operator | (SegmentAccess lhs, SegmentAccess rhs)
|
||||
{
|
||||
return static_cast<SegmentAccess>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
|
||||
return static_cast<SegmentAccess>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
static inline SegmentAccess operator & (SegmentAccess lhs, SegmentAccess rhs)
|
||||
{
|
||||
return static_cast<SegmentAccess>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
|
||||
return static_cast<SegmentAccess>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
static inline bool operator * (SegmentAccess lhs, SegmentAccess rhs)
|
||||
{
|
||||
return (static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs)) != 0;
|
||||
}
|
||||
|
||||
static inline SegmentFlags operator | (SegmentFlags lhs, SegmentFlags rhs)
|
||||
{
|
||||
return static_cast<SegmentFlags>(static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
static inline SegmentFlags operator & (SegmentFlags lhs, SegmentFlags rhs)
|
||||
{
|
||||
return static_cast<SegmentFlags>(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
static inline bool operator * (SegmentFlags lhs, SegmentFlags rhs)
|
||||
{
|
||||
return (static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs)) != 0;
|
||||
}
|
||||
|
||||
struct SegmentDescriptor
|
||||
{
|
||||
uint16_t limit0;
|
||||
uint16_t base0;
|
||||
uint8_t base1;
|
||||
SegmentAccess access;
|
||||
uint8_t limit1 : 4;
|
||||
uint8_t flags : 4;
|
||||
uint8_t base2;
|
||||
|
||||
uint32_t limit()
|
||||
{
|
||||
return this->limit0 | (this->limit1 << 16);
|
||||
}
|
||||
|
||||
void setLimit(uint32_t value)
|
||||
{
|
||||
this->limit0 = (value & 0x0FFFF) >> 0;
|
||||
this->limit1 = (value & 0xFFFFF) >> 16;
|
||||
}
|
||||
|
||||
uint32_t base()
|
||||
{
|
||||
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;
|
||||
}
|
||||
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.");
|
||||
|
@ -73,11 +132,12 @@ static_assert(sizeof(SegmentDescriptor) == 8, "SegmentDescriptor must be 8 bytes
|
|||
class GDT
|
||||
{
|
||||
public:
|
||||
static const uint32_t length = 8;
|
||||
static const uint32_t length = 8;
|
||||
private:
|
||||
static SegmentDescriptor descriptors[length];
|
||||
GDT() = delete;
|
||||
static SegmentDescriptor descriptors[length];
|
||||
GDT() = delete;
|
||||
public:
|
||||
|
||||
static SegmentDescriptor & descriptor(uint32_t index);
|
||||
static void initialize();
|
||||
|
||||
static SegmentDescriptor & descriptor(uint32_t index);
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
#include "numeric.hpp"
|
||||
#include "pointer.hpp"
|
||||
#include "multiboot.hpp"
|
||||
#include "gdt.hpp"
|
||||
#include "compat.h"
|
||||
|
||||
using namespace multiboot;
|
||||
|
@ -24,6 +25,8 @@ extern "C" void init(Structure const & data)
|
|||
<< BColor(Color::Blue) << "Hello blue!" << BColor() << "\n"
|
||||
<< "Hello default color.\n";
|
||||
|
||||
GDT::initialize();
|
||||
|
||||
Console::main
|
||||
<< "bootloader name: " << data.bootLoaderName << "\n"
|
||||
<< "command line: " << data.commandline << "\n"
|
||||
|
|
|
@ -1,12 +1,66 @@
|
|||
#include "gdt.hpp"
|
||||
|
||||
static SegmentDescriptor invalid;
|
||||
SegmentDescriptor GDT::descriptors[GDT::length];
|
||||
|
||||
SegmentDescriptor & GDT::descriptor(uint32_t index)
|
||||
{
|
||||
static SegmentDescriptor invalid;
|
||||
if(index >= GDT::length) {
|
||||
return invalid;
|
||||
}
|
||||
return GDT::descriptors[index];
|
||||
}
|
||||
|
||||
void GDT::initialize()
|
||||
{
|
||||
//Ein Nulldeskriptor (gdt[0] = 0)
|
||||
GDT::descriptor(0) = SegmentDescriptor();
|
||||
|
||||
//Ein Codesegment für den Kernel (Present, Ring 0, Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(1) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring0,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
//Ein Datensegment für den Kernel (Present, Ring 0, Non-Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(2) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Writeable | SegmentAccess::Segment | SegmentAccess::Ring0,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
//Ein Codesegment für den Userspace (Present, Ring 3, Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(3) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Executable | SegmentAccess::Segment | SegmentAccess::Ring3,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
//Ein Datensegment für den Userspace (Present, Ring 3, Non-Executable, 32 Bit; Basis 0, Limit 4 GiB)
|
||||
GDT::descriptor(4) = SegmentDescriptor(
|
||||
0x00000000,
|
||||
0xFFFFFFFF,
|
||||
SegmentAccess::Present | SegmentAccess::Writeable | SegmentAccess::Segment | SegmentAccess::Ring3,
|
||||
SegmentFlags::Use4KSize | SegmentFlags::Use32Bit);
|
||||
|
||||
struct
|
||||
{
|
||||
uint16_t limit;
|
||||
void* pointer;
|
||||
} __attribute__((packed)) gdtp =
|
||||
{
|
||||
.limit = GDT::length *sizeof(SegmentDescriptor) - 1,
|
||||
.pointer = &GDT::descriptors,
|
||||
};
|
||||
asm volatile("lgdt %0" : : "m" (gdtp));
|
||||
|
||||
asm volatile("mov $0x10, %ax");
|
||||
asm volatile("mov %ax, %ds");
|
||||
asm volatile("mov %ax, %es");
|
||||
asm volatile("mov %ax, %fs");
|
||||
asm volatile("mov %ax, %gs");
|
||||
asm volatile("mov %ax, %ss");
|
||||
asm volatile("ljmp $0x8, $.1");
|
||||
asm volatile(".1:");
|
||||
}
|
Loading…
Reference in a new issue