From e2c4fdb31285497520290003548bd3b1e448f849 Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Wed, 17 Jan 2024 02:22:48 +0100 Subject: [PATCH] Added basic GDT and (very) basic IDT. And serial output. --- bastl/include/array | 4 + bastl/include/bit | 16 ++ bastl/include/cstdint | 21 ++ bastl/include/initializer_list | 44 +++++ os.log | 4 + targets/_any/include/os/serial.hpp | 76 +++++++ targets/_any/src/cstdlib/stdio.cpp | 40 +++- targets/x86_64/src/kernel/boot.s | 45 ++++- targets/x86_64/src/kernel/multiboot.h | 274 -------------------------- targets/x86_64/src/kernel/startup.cpp | 68 ++++--- targets/x86_64/src/kernel/x86_64.hpp | 169 ++++++++++++++++ 11 files changed, 447 insertions(+), 314 deletions(-) create mode 100644 bastl/include/bit create mode 100644 bastl/include/cstdint create mode 100644 bastl/include/initializer_list create mode 100644 os.log create mode 100644 targets/_any/include/os/serial.hpp delete mode 100644 targets/x86_64/src/kernel/multiboot.h create mode 100644 targets/x86_64/src/kernel/x86_64.hpp diff --git a/bastl/include/array b/bastl/include/array index f8f730b..f3bd822 100644 --- a/bastl/include/array +++ b/bastl/include/array @@ -5,6 +5,7 @@ #define BAD_APPLE_OS_ARRAY_INCLUDED #include +#include #include #include @@ -141,6 +142,9 @@ public: } } }; + +template +array(T, U...) -> array; } #endif // !defined(BAD_APPLE_OS_ARRAY_INCLUDED) diff --git a/bastl/include/bit b/bastl/include/bit new file mode 100644 index 0000000..facb578 --- /dev/null +++ b/bastl/include/bit @@ -0,0 +1,16 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_BIT_INCLUDED) +#define BAD_APPLE_OS_BIT_INCLUDED + +namespace std +{ +template +const TTo bit_cast(const TFrom& from) noexcept +{ + return __builtin_bit_cast(TTo, from); +} +} + +#endif // !defined(BAD_APPLE_OS_BIT_INCLUDED) diff --git a/bastl/include/cstdint b/bastl/include/cstdint new file mode 100644 index 0000000..3484804 --- /dev/null +++ b/bastl/include/cstdint @@ -0,0 +1,21 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_CSTDINT_INCLUDED) +#define BAD_APPLE_OS_CSTDINT_INCLUDED + +#include + +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) diff --git a/bastl/include/initializer_list b/bastl/include/initializer_list new file mode 100644 index 0000000..9014aac --- /dev/null +++ b/bastl/include/initializer_list @@ -0,0 +1,44 @@ +#pragma once + +#if !defined(BAD_APPLE_OS_INITIALIZER_LIST_INCLUDED) +#define BAD_APPLE_OS_INITIALIZER_LIST_INCLUDED + +#include + +namespace std +{ +template +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 +const T* begin(initializer_list initList) noexcept +{ + return initList.begin(); +} + +template +const T* end(initializer_list initList) noexcept +{ + return initList.end(); +} +} + +#endif // !defined(BAD_APPLE_OS_INITIALIZER_LIST_INCLUDED) diff --git a/os.log b/os.log new file mode 100644 index 0000000..497acbe --- /dev/null +++ b/os.log @@ -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! + diff --git a/targets/_any/include/os/serial.hpp b/targets/_any/include/os/serial.hpp new file mode 100644 index 0000000..0fd8fda --- /dev/null +++ b/targets/_any/include/os/serial.hpp @@ -0,0 +1,76 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_SERIAL_HPP_INCLUDED) +#define BAD_APPLE_OS_SERIAL_HPP_INCLUDED + +#include + +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) diff --git a/targets/_any/src/cstdlib/stdio.cpp b/targets/_any/src/cstdlib/stdio.cpp index 9815f94..109d101 100644 --- a/targets/_any/src/cstdlib/stdio.cpp +++ b/targets/_any/src/cstdlib/stdio.cpp @@ -4,13 +4,15 @@ #include #include #include +#include "os/serial.hpp" #include "os/tty.hpp" extern "C" { namespace { -int printInt(int value) + +int printInt(long value) { if (value == 0) { @@ -23,7 +25,7 @@ int printInt(int value) return printInt(-value) + 1; } - char digits[10]; // 2147483647 has 10 digits + char digits[19]; // 9223372036854775807 has 10 digits char* pos = &digits[0]; while (value > 0) @@ -131,13 +133,26 @@ int printByteSize(size_t bytes) int putchar(int chr) noexcept { tty::putChar(static_cast(chr)); + if (chr == '\n') + { + serialWrite(PORT_COM1, '\r'); + serialWrite(PORT_COM1, '\n'); + } + else + { + serialWrite(PORT_COM1, static_cast(chr)); + } return 0; } int puts(const char* str) noexcept { - tty::write(str); - tty::putChar('\n'); + while (*str) + { + putchar(*str); + ++str; + } + putchar('\n'); return 0; } @@ -191,6 +206,23 @@ int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT case 'X': result += printHexInt(va_arg(vlist, unsigned)); 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: assert(!"Invalid format string, unknown format identifier."); return -1; diff --git a/targets/x86_64/src/kernel/boot.s b/targets/x86_64/src/kernel/boot.s index 140bec8..7ffc2a8 100644 --- a/targets/x86_64/src/kernel/boot.s +++ b/targets/x86_64/src/kernel/boot.s @@ -3,34 +3,41 @@ .section .bss .align 16 stack_bottom: -.skip 16384 # 16 KiB + .skip 16384 # 16 KiB 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 .section .text .global _start .type _start, @function _start: + // clear interrupts, the kernel will enable them once it is done initializing + cli + // store the memory map mov %rbx, (gBootInfo) // setup stack mov $stack_top, %rsp + // init runtime call _init // enter high-level kernel call kernel_main -// // call the destructors -// mov $start_dtors, %ebx -// jmp .dtors_loop_end -//.dtors_loop_start: -// call *(%ebx) -// add 4, %ebx -//.dtors_loop_end: -// cmp $end_dtors, %ebx -// jb .dtors_loop_start + // cleanup runtime + call _fini // We are done. Clear interrupts and halt. cli @@ -38,6 +45,24 @@ _start: hlt 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. This is useful when debugging or when you implement call tracing. diff --git a/targets/x86_64/src/kernel/multiboot.h b/targets/x86_64/src/kernel/multiboot.h deleted file mode 100644 index f6302ea..0000000 --- a/targets/x86_64/src/kernel/multiboot.h +++ /dev/null @@ -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 */ diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index 7cf7bad..51218a1 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -1,10 +1,13 @@ -#include -#include #include "boot.hpp" +#include +#include + #include "os/draw.hpp" +#include "os/serial.hpp" #include "os/tty.hpp" +#include "./x86_64.hpp" extern "C" int gKernelEnd; @@ -82,18 +85,48 @@ void initGlobals() (*initFunc)(); } } + +constinit std::array GDT alignas(16) = { + SEGMENT_NULL, + SEGMENT_KERNEL_CODE, + SEGMENT_KERNEL_DATA, + SEGMENT_USER_CODE, + SEGMENT_USER_DATA +}; + +constinit std::array 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(handler); + IDT[index] = InterruptDescriptor{ + .offsetLow = static_cast(offset & 0xFFFF), + .selector = 1, // kernel code + .interruptStackTable = 0, + .gateType = InterruptGateType::INTERRUPT_GATE, + .privilegeLevel = 0, + .present = true, + .offsetHigh = (offset >> 16) + }; +} } extern "C" { EfiBootInfo* gBootInfo; -void _init(); -void _fini(); void main(); void kernel_main() { + __setGDT(sizeof(GDT), &GDT); + __setIDT(sizeof(IDT), &IDT); + + // done initializing OS stuff, enable interrupts + __asm__ __volatile__("sti"); + initGlobals(); // init the heap (required for the double buffer) @@ -110,32 +143,15 @@ void kernel_main() // initialize terminal interface tty::initialize(); - // std::printf("Kernel End: %p\n", &gKernelEnd); - 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}; - std::memcpy(&dest[1], &test[3], 2); - - for (int i = 0; i < 400; ++i) + if (!initSerialPort(PORT_COM1)) { - std::printf("Hello font %d!\n", i); + tty::write("Error initializing serial port.\n"); + return; } -#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(); + serialWriteString(PORT_COM1, "\r\n\r\n"); // write newlines to separate from UEFI output - /* Initialize the heap */ - // assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP); - // initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length); + std::puts("This is BadAppleOS and everything is fine!\n"); main(); - - _fini(); } } // extern "C" diff --git a/targets/x86_64/src/kernel/x86_64.hpp b/targets/x86_64/src/kernel/x86_64.hpp new file mode 100644 index 0000000..e1f0b7f --- /dev/null +++ b/targets/x86_64/src/kernel/x86_64.hpp @@ -0,0 +1,169 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_X86_64_HPP_INCLUDED) +#define BAD_APPLE_OS_X86_64_HPP_INCLUDED + +#include + +// --- 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)