Added basic GDT and (very) basic IDT. And serial output.

This commit is contained in:
Patrick 2024-01-17 02:22:48 +01:00
parent ab4ab761f0
commit e2c4fdb312
11 changed files with 447 additions and 314 deletions

View File

@ -5,6 +5,7 @@
#define BAD_APPLE_OS_ARRAY_INCLUDED #define BAD_APPLE_OS_ARRAY_INCLUDED
#include <cstddef> #include <cstddef>
#include <initializer_list>
#include <stdexcept> #include <stdexcept>
#include <utility> #include <utility>
@ -141,6 +142,9 @@ public:
} }
} }
}; };
template<typename T, typename... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
} }
#endif // !defined(BAD_APPLE_OS_ARRAY_INCLUDED) #endif // !defined(BAD_APPLE_OS_ARRAY_INCLUDED)

16
bastl/include/bit Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#if !defined(BAD_APPLE_OS_BIT_INCLUDED)
#define BAD_APPLE_OS_BIT_INCLUDED
namespace std
{
template<typename TTo, typename TFrom>
const TTo bit_cast(const TFrom& from) noexcept
{
return __builtin_bit_cast(TTo, from);
}
}
#endif // !defined(BAD_APPLE_OS_BIT_INCLUDED)

21
bastl/include/cstdint Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#if !defined(BAD_APPLE_OS_CSTDINT_INCLUDED)
#define BAD_APPLE_OS_CSTDINT_INCLUDED
#include <stdint.h>
namespace std
{
using ::int8_t;
using ::int16_t;
using ::int32_t;
using ::int64_t;
using ::uint8_t;
using ::uint16_t;
using ::uint32_t;
using ::uint64_t;
}
#endif // !defined(BAD_APPLE_OS_CSTDINT_INCLUDED)

View File

@ -0,0 +1,44 @@
#pragma once
#if !defined(BAD_APPLE_OS_INITIALIZER_LIST_INCLUDED)
#define BAD_APPLE_OS_INITIALIZER_LIST_INCLUDED
#include <cstddef>
namespace std
{
template<typename T>
class initializer_list
{
public:
using value_type = T;
using reference = const value_type&;
using const_reference = const value_type&;
using iterator = const value_type*;
using const_iterator = const value_type*;
private:
const T* _begin = nullptr;
std::size_t _size = 0;
constexpr initializer_list(T* begin, std::size_t size) noexcept : _begin(begin), _size(size) {}
public:
constexpr initializer_list() noexcept = default;
[[nodiscard]] std::size_t size() const noexcept { return _size; }
[[nodiscard]] iterator begin() const noexcept { return _begin; }
[[nodiscard]] iterator end() const noexcept { return _begin + _size; }
};
template<typename T>
const T* begin(initializer_list<T> initList) noexcept
{
return initList.begin();
}
template<typename T>
const T* end(initializer_list<T> initList) noexcept
{
return initList.end();
}
}
#endif // !defined(BAD_APPLE_OS_INITIALIZER_LIST_INCLUDED)

4
os.log Normal file
View File

@ -0,0 +1,4 @@
[=3h[=3h[=3hBdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0)
This is BadAppleOS and everything is fine!

View File

@ -0,0 +1,76 @@
#pragma once
#if !defined(BAD_APPLE_OS_SERIAL_HPP_INCLUDED)
#define BAD_APPLE_OS_SERIAL_HPP_INCLUDED
#include <cstdint>
inline constexpr std::uint16_t PORT_COM1 = 0x3F8;
inline constexpr std::uint16_t PORT_COM2 = 0x2F8;
inline constexpr std::uint16_t PORT_COM3 = 0x3E8;
inline constexpr std::uint16_t PORT_COM4 = 0x2E8;
inline constexpr std::uint16_t PORT_COM5 = 0x5F8;
inline constexpr std::uint16_t PORT_COM6 = 0x4F8;
inline constexpr std::uint16_t PORT_COM7 = 0x5E8;
inline constexpr std::uint16_t PORT_COM8 = 0x4E8;
inline void writePortByte(std::uint16_t port, std::uint8_t value) noexcept
{
__asm__ __volatile__(
"outb %0, %1"
:
: "a"(value), "Nd"(port)
);
}
inline std::uint8_t readPortByte(std::uint16_t port) noexcept
{
std::uint8_t value = 0;
__asm__ __volatile__(
"inb %1, %0"
: "=a"(value)
: "Nd"(port)
);
return value;
}
[[nodiscard]] inline bool initSerialPort(std::uint16_t port) noexcept
{
writePortByte(port + 1, 0x00); // Disable all interrupts
writePortByte(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
writePortByte(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
writePortByte(port + 1, 0x00); // (hi byte)
writePortByte(port + 3, 0x03); // 8 bits, no parity, one stop bit
writePortByte(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
writePortByte(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
writePortByte(port + 4, 0x1E); // Set in loopback mode, test the serial chip
writePortByte(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if(readPortByte(port + 0) != 0xAE) {
return false;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
writePortByte(port + 4, 0x0F);
return true;
}
inline void serialWrite(std::uint16_t port, std::uint8_t data) noexcept
{
while ((readPortByte(port + 5) & 0x20) == 0);
writePortByte(port, data);
}
inline void serialWriteString(std::uint16_t port, const char* str) noexcept
{
while (*str)
{
serialWrite(port, *str);
++str;
}
}
#endif // !defined(BAD_APPLE_OS_SERIAL_HPP_INCLUDED)

View File

@ -4,13 +4,15 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <stdarg.h> #include <stdarg.h>
#include "os/serial.hpp"
#include "os/tty.hpp" #include "os/tty.hpp"
extern "C" extern "C"
{ {
namespace namespace
{ {
int printInt(int value)
int printInt(long value)
{ {
if (value == 0) if (value == 0)
{ {
@ -23,7 +25,7 @@ int printInt(int value)
return printInt(-value) + 1; return printInt(-value) + 1;
} }
char digits[10]; // 2147483647 has 10 digits char digits[19]; // 9223372036854775807 has 10 digits
char* pos = &digits[0]; char* pos = &digits[0];
while (value > 0) while (value > 0)
@ -131,13 +133,26 @@ int printByteSize(size_t bytes)
int putchar(int chr) noexcept int putchar(int chr) noexcept
{ {
tty::putChar(static_cast<char>(chr)); tty::putChar(static_cast<char>(chr));
if (chr == '\n')
{
serialWrite(PORT_COM1, '\r');
serialWrite(PORT_COM1, '\n');
}
else
{
serialWrite(PORT_COM1, static_cast<std::uint8_t>(chr));
}
return 0; return 0;
} }
int puts(const char* str) noexcept int puts(const char* str) noexcept
{ {
tty::write(str); while (*str)
tty::putChar('\n'); {
putchar(*str);
++str;
}
putchar('\n');
return 0; return 0;
} }
@ -191,6 +206,23 @@ int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT
case 'X': case 'X':
result += printHexInt(va_arg(vlist, unsigned)); result += printHexInt(va_arg(vlist, unsigned));
break; break;
case 'l':
++pos;
switch (*pos)
{
case '\0':
assert(!"Invalid format string, ends with %l.");
return -1;
case 'd':
result += printInt(va_arg(vlist, long));
break;
case 'X':
result += printHexInt(va_arg(vlist, unsigned long));
break;
default:
return -1;
}
break;
default: default:
assert(!"Invalid format string, unknown format identifier."); assert(!"Invalid format string, unknown format identifier.");
return -1; return -1;

View File

@ -6,31 +6,38 @@ stack_bottom:
.skip 16384 # 16 KiB .skip 16384 # 16 KiB
stack_top: stack_top:
.align 16
__gdt_storage:
.word 0 // limit
.quad 0 // base
.align 16
__idt_storage:
.word 0 // limit
.quad 0 // base
// kernel entry point // kernel entry point
.section .text .section .text
.global _start .global _start
.type _start, @function .type _start, @function
_start: _start:
// clear interrupts, the kernel will enable them once it is done initializing
cli
// store the memory map // store the memory map
mov %rbx, (gBootInfo) mov %rbx, (gBootInfo)
// setup stack // setup stack
mov $stack_top, %rsp mov $stack_top, %rsp
// init runtime
call _init call _init
// enter high-level kernel // enter high-level kernel
call kernel_main call kernel_main
// // call the destructors // cleanup runtime
// mov $start_dtors, %ebx call _fini
// jmp .dtors_loop_end
//.dtors_loop_start:
// call *(%ebx)
// add 4, %ebx
//.dtors_loop_end:
// cmp $end_dtors, %ebx
// jb .dtors_loop_start
// We are done. Clear interrupts and halt. // We are done. Clear interrupts and halt.
cli cli
@ -38,6 +45,24 @@ _start:
hlt hlt
jmp .kernel_end jmp .kernel_end
.global __setGDT
.type __setGDT @function
// void __setGDT(uint16_t limit [%di], void* base [%rsi])
__setGDT:
movw %di, __gdt_storage
movq %rsi, (__gdt_storage + 2)
lgdt __gdt_storage
ret
.global __setIDT
.type __setIDT @function
// void __setIDT(uint16_t limit [%di], void* base [%rsi])
__setIDT:
movw %di, __idt_storage
movq %rsi, (__idt_storage + 2)
lidt __idt_storage
ret
/* /*
Set the size of the _start symbol to the current location '.' minus its start. Set the size of the _start symbol to the current location '.' minus its start.
This is useful when debugging or when you implement call tracing. This is useful when debugging or when you implement call tracing.

View File

@ -1,274 +0,0 @@
/* multiboot.h - Multiboot header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* This should be in %eax. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004
/* Flags set in the flags member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */
#define MULTIBOOT_PAGE_ALIGN 0x00000001
/* Must pass memory information to OS. */
#define MULTIBOOT_MEMORY_INFO 0x00000002
/* Must pass video information to OS. */
#define MULTIBOOT_VIDEO_MODE 0x00000004
/* This flag indicates the use of the address fields in the header. */
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
/* Flags to be set in the flags member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* Feature flags. */
multiboot_uint32_t flags;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr;
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table
{
multiboot_uint32_t tabsize;
multiboot_uint32_t strsize;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table
{
multiboot_uint32_t num;
multiboot_uint32_t size;
multiboot_uint32_t addr;
multiboot_uint32_t shndx;
};
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info
{
/* Multiboot info version number */
multiboot_uint32_t flags;
/* Available memory from BIOS */
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
/* "root" partition */
multiboot_uint32_t boot_device;
/* Kernel command line */
multiboot_uint32_t cmdline;
/* Boot-Module list */
multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr;
union
{
multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec;
} u;
/* Memory Mapping buffer */
multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
union
{
struct
{
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
};
struct
{
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list
{
/* the memory used goes from bytes mod_start to mod_end-1 inclusive */
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
/* Module command line */
multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad;
};
typedef struct multiboot_mod_list multiboot_module_t;
/* APM BIOS info. */
struct multiboot_apm_info
{
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

View File

@ -1,10 +1,13 @@
#include <cstdio>
#include <cstring>
#include "boot.hpp" #include "boot.hpp"
#include <bit>
#include <cstdio>
#include "os/draw.hpp" #include "os/draw.hpp"
#include "os/serial.hpp"
#include "os/tty.hpp" #include "os/tty.hpp"
#include "./x86_64.hpp"
extern "C" int gKernelEnd; extern "C" int gKernelEnd;
@ -82,18 +85,48 @@ void initGlobals()
(*initFunc)(); (*initFunc)();
} }
} }
constinit std::array GDT alignas(16) = {
SEGMENT_NULL,
SEGMENT_KERNEL_CODE,
SEGMENT_KERNEL_DATA,
SEGMENT_USER_CODE,
SEGMENT_USER_DATA
};
constinit std::array<InterruptDescriptor, 256> IDT alignas(16);
extern "C" void __setGDT(uint16_t limit, void* base);
extern "C" void __setIDT(uint16_t limit, void* base);
void setupInterrupt(std::uint8_t index, void* handler, std::uint8_t flags) noexcept
{
const std::uint64_t offset = std::bit_cast<std::uint64_t>(handler);
IDT[index] = InterruptDescriptor{
.offsetLow = static_cast<unsigned>(offset & 0xFFFF),
.selector = 1, // kernel code
.interruptStackTable = 0,
.gateType = InterruptGateType::INTERRUPT_GATE,
.privilegeLevel = 0,
.present = true,
.offsetHigh = (offset >> 16)
};
}
} }
extern "C" extern "C"
{ {
EfiBootInfo* gBootInfo; EfiBootInfo* gBootInfo;
void _init();
void _fini();
void main(); void main();
void kernel_main() void kernel_main()
{ {
__setGDT(sizeof(GDT), &GDT);
__setIDT(sizeof(IDT), &IDT);
// done initializing OS stuff, enable interrupts
__asm__ __volatile__("sti");
initGlobals(); initGlobals();
// init the heap (required for the double buffer) // init the heap (required for the double buffer)
@ -110,32 +143,15 @@ void kernel_main()
// initialize terminal interface // initialize terminal interface
tty::initialize(); tty::initialize();
// std::printf("Kernel End: %p\n", &gKernelEnd); if (!initSerialPort(PORT_COM1))
uint8_t test[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; {
uint8_t dest[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; tty::write("Error initializing serial port.\n");
std::memcpy(&dest[1], &test[3], 2); return;
}
serialWriteString(PORT_COM1, "\r\n\r\n"); // write newlines to separate from UEFI output
for (int i = 0; i < 400; ++i) std::puts("This is BadAppleOS and everything is fine!\n");
{
std::printf("Hello font %d!\n", i);
}
#if 0
for (int x = 0; x < 100; ++x)
{
for (int y = 0; y < 100; ++y)
{
draw::setPixelDirect(x, y, {.red = 255});
}
}
#endif
//draw::flushPixels();
/* Initialize the heap */
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
main(); main();
_fini();
} }
} // extern "C" } // extern "C"

View File

@ -0,0 +1,169 @@
#pragma once
#if !defined(BAD_APPLE_OS_X86_64_HPP_INCLUDED)
#define BAD_APPLE_OS_X86_64_HPP_INCLUDED
#include <cstdint>
// --- Segments --- //
enum class SegmentDescriptorType
{
SYSTEM = 0,
OTHER = 1
};
enum class SegmentGranularity
{
BYTE = 0,
PAGE = 1
};
inline const unsigned LIMIT_MAX = 0xFFFFF;
enum class SystemSegmentType
{
TSS_16_AVAILABLE = 1,
LDT = 2,
TSS_16_USED = 3,
CALL_GATE_16 = 4,
TASK_GATE = 5,
INTERRUPT_GATE_16 = 6,
TRAP_GATE_16 = 7,
TSS_32_AVAILABLE = 9,
TSS_32_USED = 11,
CALL_GATE_32 = 12,
INTERRUPT_GATE_32 = 14,
TRAP_GATE_32 = 15
};
struct UserDataSegment
{
bool expandDown : 1 = 0;
bool writable : 1 = 0;
bool accessed : 1 = 0;
constexpr operator unsigned() const noexcept
{
return (expandDown << 2) | (writable << 1) | (accessed << 0);
}
};
struct UserCodeSegment
{
bool conforming : 1 = 0;
bool readable : 1 = 0;
bool accessed : 1 = 0;
constexpr operator unsigned() const noexcept
{
return 0b1000 | (conforming << 2) | (readable << 1) | (accessed << 0);
}
};
struct SegmentDescriptor
{
/* 0 */ unsigned limitLow : 16 = 0;
/* 16 */ unsigned baseLow : 24 = 0;
/* 40 */ unsigned type : 4 = 0;
/* 44 */ SegmentDescriptorType descType : 1 = SegmentDescriptorType::SYSTEM;
/* 45 */ unsigned privilegeLevel : 2 = 0;
/* 47 */ bool present : 1 = false;
/* 48 */ unsigned limitHigh : 4 = 0;
/* 52 */ bool available : 1 = 0;
/* 53 */ bool long_ : 1 = 0;
/* 54 */ bool big : 1 = 0;
/* 55 */ SegmentGranularity granularity : 1 = SegmentGranularity::BYTE;
/* 56 */ unsigned baseHigh : 8 = 0;
} __attribute__((packed));
inline constexpr const SegmentDescriptor SEGMENT_NULL = {};
inline constexpr const SegmentDescriptor SEGMENT_KERNEL_CODE = {
.limitLow = 0xFFFF,
.baseLow = 0,
.type = UserCodeSegment{
.readable = true
},
.descType = SegmentDescriptorType::OTHER,
.privilegeLevel = 0,
.present = true,
.limitHigh = 0xF,
.long_ = true,
.big = false,
.granularity = SegmentGranularity::PAGE,
.baseHigh = 0,
};
inline constexpr const SegmentDescriptor SEGMENT_KERNEL_DATA = {
.limitLow = 0xFFFF,
.baseLow = 0,
.type = UserDataSegment{
.writable = true
},
.descType = SegmentDescriptorType::OTHER,
.privilegeLevel = 0,
.present = true,
.limitHigh = 0xF,
.long_ = true,
.big = false,
.granularity = SegmentGranularity::PAGE,
.baseHigh = 0,
};
inline constexpr const SegmentDescriptor SEGMENT_USER_CODE = {
.limitLow = 0xFFFF,
.baseLow = 0,
.type = UserCodeSegment{
.readable = true
},
.descType = SegmentDescriptorType::OTHER,
.privilegeLevel = 3,
.present = true,
.limitHigh = 0xF,
.long_ = true,
.big = false,
.granularity = SegmentGranularity::PAGE,
.baseHigh = 0,
};
inline constexpr const SegmentDescriptor SEGMENT_USER_DATA = {
.limitLow = 0xFFFF,
.baseLow = 0,
.type = UserDataSegment{
.writable = true
},
.descType = SegmentDescriptorType::OTHER,
.privilegeLevel = 3,
.present = true,
.limitHigh = 0xF,
.long_ = true,
.big = false,
.granularity = SegmentGranularity::PAGE,
.baseHigh = 0,
};
// --- Interrupts --- //
enum class InterruptGateType
{
INTERRUPT_GATE = 0xE,
TRAP_GATE = 0xF
};
struct InterruptDescriptor
{
/* 0 */ unsigned offsetLow : 16 = 0;
/* 16 */ unsigned selector : 16 = 0;
/* 32 */ unsigned interruptStackTable : 3 = 0;
/* 35 */ unsigned reserved0_ : 5 = 0;
/* 40 */ InterruptGateType gateType : 4 = InterruptGateType::INTERRUPT_GATE;
/* 44 */ unsigned reserved1_ : 1 = 0;
/* 45 */ unsigned privilegeLevel : 2 = 0;
/* 47 */ bool present : 1 = 0;
/* 48 */ unsigned long offsetHigh : 48 = 0;
/* 96 */ unsigned reserved2_ : 32 = 0;
} __attribute__((packed));
#endif // !defined(BAD_APPLE_OS_X86_64_HPP_INCLUDED)