Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //GDT Entry
- class EntryGDT {
- private:
- uint32_t limit_low : 16; //The lower 16 bits of the limit
- uint32_t base_low : 24; //The lower 24 bits of base
- public:
- //Access byte used in GDT entries
- // See http://files.osdev.org/mirrors/geezer/os/pm.htm:
- // discr_type bit: 1 is code/data selector, 0 is TSS, LDT, or Gate (but also says earlier the same as the below):
- // See http://wiki.osdev.org/Global_Descriptor_Table:
- // discr_type bit: 1 is code selector, 0 is data selector
- // See http://wiki.osdev.org/Segmentation
- // discr_type bit: 1 is code/data selector, 0 is system
- union Access {
- class AccessByte { public:
- bool accessed : 1; //Initialized to 0; CPU sets when segment is accessed
- bool rw : 1; //Writable bit for data selectors / Readable bit for code selectors
- bool dir_conf : 1; //For data selectors, 0 the segment grows up, 1 the segment grows down. For code selectors, 0 only executable by processes with exactly privilege, 1 lower is okay too
- bool discr_type : 1; //See above
- bool unused : 1; //Initialized to 1
- uint8_t privilege : 2; //Ring
- bool present : 1; //Must be 1 for all valid selectors
- static AccessByte get_null(void);
- static AccessByte get_selector_datacode(uint8_t ring);
- } flags; //Will be packed since EntryGDT is packed
- uint8_t byte : 8;
- } access;
- private:
- uint32_t limit_high : 4; //The upper 4 bits of the limit
- public:
- //Flags. Can't be in a struct because it is not byte-aligned and it would screw up the packing.
- int flags_unused : 2; //(at least on x86)
- bool flags_size : 1; //0 is 16-bit protected mode, 1 is 32-bit protected mode
- bool flags_granularity : 1; //If 0 the limit is in 1B blocks (byte granularity), if 1 the limit is in 4KiB blocks (page granularity).
- private:
- uint32_t base_high : 8; //The upper 8 bits of the base.
- public:
- void set_limit(uint32_t limit);
- uint32_t get_limit(void) const;
- void set_base(uint32_t base);
- uint32_t get_base(void) const;
- static void construct(EntryGDT* entry, uint32_t base, uint32_t limit, Access::AccessByte access);
- } __attribute__((packed));
- EntryGDT::Access::AccessByte EntryGDT::Access::AccessByte::get_null(void) {
- EntryGDT::Access::AccessByte result;
- result. accessed = 0;
- result. rw = 0;
- result. dir_conf = 0;
- result.discr_type = 0;
- result. unused = 0;
- result. privilege = 0;
- result. present = 0;
- return result;
- }
- EntryGDT::Access::AccessByte EntryGDT::Access::AccessByte::get_selector_datacode(uint8_t ring) {
- EntryGDT::Access::AccessByte result;
- result. accessed = 0;
- result. rw = 1;
- result. dir_conf = 0;
- result.discr_type = 1;
- result. unused = 1;
- result. privilege = ring;
- result. present = 1;
- return result;
- }
- void EntryGDT::set_limit(uint32_t limit) {
- limit_low = limit & 0x0FFFF ;
- limit_high = (limit & 0xF0000)>>16;
- }
- uint32_t EntryGDT::get_limit(void) const {
- return (limit_high<<16) | limit_low;
- }
- void EntryGDT::set_base(uint32_t base) {
- base_low = base & 0x00FFFFFF ;
- base_high = (base & 0xFF000000)>>24;
- }
- uint32_t EntryGDT::get_base(void) const {
- return (base_high<<24) | base_low;
- }
- void EntryGDT::construct(EntryGDT* entry, uint32_t base, uint32_t limit, Access::AccessByte access) {
- entry->set_base(base);
- entry->set_limit(limit);
- entry->access.flags = access;
- entry-> flags_unused = 0;
- entry-> flags_size = 1; //32-bit mode segment
- entry->flags_granularity = 0; //The limit is a 32-bit number and represents the number of bytes, NOT the number of 4KiB blocks
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement