From 2fbb8e3df2643f7a658feab1faf795de524b1cbf Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 30 Apr 2023 20:01:38 +0300 Subject: [PATCH 1/4] Add multiboot stub (currently broken) --- Architecture/amd64/Bootstrap/GDT32.asm | 47 +++ .../amd64/Bootstrap/Header_Multiboot.asm | 5 + .../amd64/Bootstrap/Header_Multiboot2.asm | 41 +++ Architecture/amd64/Bootstrap/Multiboot.cpp | 287 ++++++++++++++++++ .../amd64/Bootstrap/Multiboot64bitMap.cpp | 281 +++++++++++++++++ .../amd64/Bootstrap/Multiboot_Init.asm | 114 +++++++ .../amd64/Bootstrap/Multiboot_PageTable.asm | 45 +++ Architecture/amd64/linker.ld | 46 ++- Architecture/amd64/runtime/crt1.c | 18 +- .../i386/Bootstrap/Header_Multiboot.asm | 5 + .../i386/Bootstrap/Header_Multiboot2.asm | 41 +++ Architecture/i386/Bootstrap/Multiboot.cpp | 286 +++++++++++++++++ .../i386/Bootstrap/Multiboot_Init.asm | 50 +++ .../i386/Bootstrap/Multiboot_PageTable.asm | 10 + .../i386/cpu/SymmetricMultiprocessing.cpp | 2 +- Architecture/i386/linker.ld | 12 +- Architecture/i386/runtime/crt1.c | 18 +- Core/Memory/PhysicalMemoryManager.cpp | 28 +- include/memory.hpp | 1 + 19 files changed, 1287 insertions(+), 50 deletions(-) create mode 100644 Architecture/amd64/Bootstrap/GDT32.asm create mode 100644 Architecture/amd64/Bootstrap/Header_Multiboot.asm create mode 100644 Architecture/amd64/Bootstrap/Header_Multiboot2.asm create mode 100644 Architecture/amd64/Bootstrap/Multiboot.cpp create mode 100644 Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp create mode 100644 Architecture/amd64/Bootstrap/Multiboot_Init.asm create mode 100644 Architecture/amd64/Bootstrap/Multiboot_PageTable.asm create mode 100644 Architecture/i386/Bootstrap/Header_Multiboot.asm create mode 100644 Architecture/i386/Bootstrap/Header_Multiboot2.asm create mode 100644 Architecture/i386/Bootstrap/Multiboot.cpp create mode 100644 Architecture/i386/Bootstrap/Multiboot_Init.asm create mode 100644 Architecture/i386/Bootstrap/Multiboot_PageTable.asm diff --git a/Architecture/amd64/Bootstrap/GDT32.asm b/Architecture/amd64/Bootstrap/GDT32.asm new file mode 100644 index 00000000..e9fa9804 --- /dev/null +++ b/Architecture/amd64/Bootstrap/GDT32.asm @@ -0,0 +1,47 @@ +[bits 32] +section .bootstrap.text + +align 32 +global gdtr +gdtr: + dw GDT32_END - GDT32 - 1 + dd GDT32 + +align 32 +GDT32: + dq 0x0 + + dw 0xffff + dw 0x0000 + db 0x00 + dw 0xcf9a + db 0x00 + + dw 0xffff + dw 0x0000 + db 0x00 + dw 0xcf92 + db 0x00 + + dw 0x0100 + dw 0x1000 + db 0x00 + dw 0x4092 + db 0x00 +GDT32_END: + +global LoadGDT32 +LoadGDT32: + lgdt [gdtr] + + jmp 0x8:ActivateGDT + ActivateGDT: + mov cx, 0x10 + mov ss, cx + mov ds, cx + mov es, cx + mov fs, cx + mov cx, 0x18 + mov gs, cx + + ret diff --git a/Architecture/amd64/Bootstrap/Header_Multiboot.asm b/Architecture/amd64/Bootstrap/Header_Multiboot.asm new file mode 100644 index 00000000..71a6efe8 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Header_Multiboot.asm @@ -0,0 +1,5 @@ +section .multiboot +align 4 + dd 0x1BADB002 + dd 1 << 0 | 1 << 1 + dd -(0x1BADB002 + (1 << 0 | 1 << 1)) diff --git a/Architecture/amd64/Bootstrap/Header_Multiboot2.asm b/Architecture/amd64/Bootstrap/Header_Multiboot2.asm new file mode 100644 index 00000000..a0a9a71e --- /dev/null +++ b/Architecture/amd64/Bootstrap/Header_Multiboot2.asm @@ -0,0 +1,41 @@ +section .multiboot2 +align 4096 +HEADER_START: + dd 0xE85250D6 + dd 0 + dd (HEADER_END - HEADER_START) + dd 0x100000000 - (HEADER_END - HEADER_START) - 0 - 0xE85250D6 +align 8 +MB2_INFO_REQUEST_TAG_START: + dw 1 + dw 0 + dd MB2_INFO_REQUEST_TAG_END - MB2_INFO_REQUEST_TAG_START + dd 1 ; Command Line + dd 2 ; Boot Loader Name + dd 3 ; Module + dd 4 ; Basic Memory Information + dd 5 ; BIOS Boot Device + dd 6 ; Memory Map + dd 7 ; VBE + dd 8 ; Framebuffer + dd 9 ; ELF Sections + dd 10 ; APM Table + dd 11 ; EFI 32-bit System Table Pointer + dd 12 ; EFI 64-bit System Table Pointer + ; dd 13 ; SMBIOS + dd 14 ; ACPI Old + dd 15 ; ACPI New + dd 16 ; Network + dd 17 ; EFI Memory Map + dd 18 ; EFI Boot Services Notifier + dd 19 ; EFI 32-bit Image Handle Pointer + dd 20 ; EFI 64-bit Image Handle Pointer + dd 21 ; Load Base Address +MB2_INFO_REQUEST_TAG_END: +align 8 +MB2_TAG_START: + dw 0 + dw 0 + dd MB2_TAG_END - MB2_TAG_START +MB2_TAG_END: +HEADER_END: diff --git a/Architecture/amd64/Bootstrap/Multiboot.cpp b/Architecture/amd64/Bootstrap/Multiboot.cpp new file mode 100644 index 00000000..9c9d676a --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot.cpp @@ -0,0 +1,287 @@ +#include + +#include +#include +#include + +#include "../../../kernel.h" + +EXTERNC void multiboot_main(uint64_t Magic, uint64_t Info) +{ + if (Info == NULL || Magic == NULL) + { + if (Magic == NULL) + error("Multiboot magic is NULL"); + if (Info == NULL) + error("Multiboot info is NULL"); + CPU::Stop(); + } + else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC) + { + error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC); + CPU::Stop(); + } + + uint64_t div = 1193180 / 1000; + outb(0x43, 0xB6); + outb(0x42, (uint8_t)div); + outb(0x42, (uint8_t)(div >> 8)); + uint8_t tmp = inb(0x61); + if (tmp != (tmp | 3)) + outb(0x61, tmp | 3); + + BootInfo mb2binfo; + int pos = 0; + auto InfoAddress = Info; + for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); + ; + Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) + { + if (Tag->type == MULTIBOOT_TAG_TYPE_END) + { + debug("End of multiboot2 tags"); + break; + } + + switch (Tag->type) + { + case MULTIBOOT_TAG_TYPE_CMDLINE: + { + strncpy(mb2binfo.Kernel.CommandLine, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); + break; + } + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + { + strncpy(mb2binfo.Bootloader.Name, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Bootloader name: %s", mb2binfo.Bootloader.Name); + break; + } + case MULTIBOOT_TAG_TYPE_MODULE: + { + multiboot_tag_module *module = (multiboot_tag_module *)Tag; + static int module_count = 0; + mb2binfo.Modules[module_count++].Address = (void *)(uint64_t)module->mod_start; + mb2binfo.Modules[module_count++].Size = module->size; + strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6); + strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline, + strlen(module->cmdline)); + debug("Module: %s", mb2binfo.Modules[module_count++].Path); + break; + } + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: + { + multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; + fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", + meminfo->mem_lower, meminfo->mem_upper); + break; + } + case MULTIBOOT_TAG_TYPE_BOOTDEV: + { + multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; + fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", + bootdev->biosdev, bootdev->slice, bootdev->part); + break; + } + case MULTIBOOT_TAG_TYPE_MMAP: + { + multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; + uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); + mb2binfo.Memory.Entries = EntryCount; + for (uint32_t i = 0; i < EntryCount; i++) + { + if (EntryCount > MAX_MEMORY_ENTRIES) + { + warn("Too many memory entries, skipping the rest..."); + break; + } + multiboot_mmap_entry entry = mmap->entries[i]; + mb2binfo.Memory.Size += entry.len; + switch (entry.type) + { + case MULTIBOOT_MEMORY_AVAILABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Usable; + break; + case MULTIBOOT_MEMORY_RESERVED: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Reserved; + break; + case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; + break; + case MULTIBOOT_MEMORY_NVS: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPINVS; + break; + case MULTIBOOT_MEMORY_BADRAM: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = BadMemory; + break; + default: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Unknown; + break; + } + debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", + mb2binfo.Memory.Entry[i].BaseAddress, + mb2binfo.Memory.Entry[i].Length, + mb2binfo.Memory.Entry[i].Type); + } + break; + } + case MULTIBOOT_TAG_TYPE_VBE: + { + multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; + fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", + vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); + break; + } + case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: + { + multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; + static int fb_count = 0; + mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; + mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; + mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; + mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; + mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; + switch (fb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + mb2binfo.Framebuffer[fb_count].Type = Indexed; + break; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: + { + mb2binfo.Framebuffer[fb_count].Type = RGB; + mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; + mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; + mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; + mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; + mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; + mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; + break; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: + { + mb2binfo.Framebuffer[fb_count].Type = EGA; + break; + } + } + debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); + debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", + fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, + fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, + fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); + fb_count++; + break; + } + case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: + { + multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; + fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]", + elf->num, elf->size, elf->entsize, elf->shndx); + break; + } + case MULTIBOOT_TAG_TYPE_APM: + { + multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; + fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", + apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32: + { + multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; + fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64: + { + multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; + fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); + break; + } + case MULTIBOOT_TAG_TYPE_SMBIOS: + { + multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; + fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_OLD: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; + debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_NEW: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; + debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_NETWORK: + { + multiboot_tag_network *net = (multiboot_tag_network *)Tag; + fixme("network->[dhcpack: %p]", net->dhcpack); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_MMAP: + { + multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; + fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", + efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_BS: + { + fixme("efi_bs->[%p] (unknown structure)", Tag); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32_IH: + { + multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; + fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64_IH: + { + multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; + fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: + { + multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; + mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; + mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); + mb2binfo.Kernel.Size = &_kernel_end - &_kernel_start; + debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); + break; + } + default: + { + error("Unknown multiboot2 tag type: %d", Tag->type); + break; + } + } + } + + tmp = inb(0x61) & 0xFC; + outb(0x61, tmp); + + Entry(&mb2binfo); +} diff --git a/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp b/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp new file mode 100644 index 00000000..a128b496 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp @@ -0,0 +1,281 @@ +#include + +union __attribute__((packed)) PageTableEntry +{ + struct + { + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Dirty : 1; // 6 + bool PageAttributeTable : 1; // 7 + bool Global : 1; // 8 + uint8_t Available0 : 3; // 9-11 + uint64_t Address : 40; // 12-51 + uint32_t Available1 : 7; // 52-58 + uint8_t ProtectionKey : 4; // 59-62 + bool ExecuteDisable : 1; // 63 + }; + uint64_t raw; + + __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) + { + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); + } + + __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } +}; + +struct __attribute__((packed)) PageTableEntryPtr +{ + PageTableEntry Entries[511]; +}; + +union __attribute__((packed)) PageDirectoryEntry +{ + struct + { + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Available0 : 1; // 6 + bool PageSize : 1; // 7 + uint8_t Available1 : 4; // 8-11 + uint64_t Address : 40; // 12-51 + uint32_t Available2 : 11; // 52-62 + bool ExecuteDisable : 1; // 63 + }; + uint64_t raw; + + __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) + { + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); + } + + __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } +}; + +struct __attribute__((packed)) PageDirectoryEntryPtr +{ + PageDirectoryEntry Entries[511]; +}; + +union __attribute__((packed)) PageDirectoryPointerTableEntry +{ + struct + { + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Available0 : 1; // 6 + bool PageSize : 1; // 7 + uint8_t Available1 : 4; // 8-11 + uint64_t Address : 40; // 12-51 + uint32_t Available2 : 11; // 52-62 + bool ExecuteDisable : 1; // 63 + }; + uint64_t raw; + + __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) + { + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); + } + + __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } +}; + +struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr +{ + PageDirectoryPointerTableEntry Entries[511]; +}; + +union __attribute__((packed)) PageMapLevel4 +{ + struct + { + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Available0 : 1; // 6 + bool Reserved0 : 1; // 7 + uint8_t Available1 : 4; // 8-11 + uint64_t Address : 40; // 12-51 + uint32_t Available2 : 11; // 52-62 + bool ExecuteDisable : 1; // 63 + }; + uint64_t raw; + + __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) + { + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); + } + + __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } +}; + +struct PageTable4 +{ + PageMapLevel4 Entries[511]; +} __attribute__((aligned(0x1000))); + +extern "C" char BootPageTable[]; +extern uintptr_t _kernel_start, _kernel_end; + +__attribute__((section(".bootstrap.data"))) static PageTable4 *BPTable = (PageTable4 *)BootPageTable; +__attribute__((section(".bootstrap.data"))) static size_t BPT_Allocated = 0x4000; + +__always_inline inline SafeFunction NIF void *RequestPage() +{ + void *Page = (void *)(BootPageTable + BPT_Allocated); + BPT_Allocated += 0x1000; + if (BPT_Allocated >= 0x10000) /* The length of BootPageTable */ + { + while (true) + ; + } + return Page; +} + +class PageMapIndexer +{ +public: + uintptr_t PMLIndex = 0; + uintptr_t PDPTEIndex = 0; + uintptr_t PDEIndex = 0; + uintptr_t PTEIndex = 0; + __always_inline inline SafeFunction NIF PageMapIndexer(uintptr_t VirtualAddress) + { + uintptr_t Address = VirtualAddress; + Address >>= 12; + this->PTEIndex = Address & 0x1FF; + Address >>= 9; + this->PDEIndex = Address & 0x1FF; + Address >>= 9; + this->PDPTEIndex = Address & 0x1FF; + Address >>= 9; + this->PMLIndex = Address & 0x1FF; + } +}; + +__always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) +{ + PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); + // Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only + uint64_t DirectoryFlags = Flags & 0x3F; + + PageMapLevel4 PML4 = BPTable->Entries[Index.PMLIndex]; + PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr; + if (!PML4.Present) + { + PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage(); + { + void *ptr = PDPTEPtr; + int value = 0; + size_t num = 0x1000; + uint8_t *p = (uint8_t *)ptr; + for (size_t i = 0; i < num; i++) + p[i] = value; + } + PML4.Present = true; + PML4.SetAddress((uintptr_t)PDPTEPtr >> 12); + } + else + PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); + PML4.raw |= DirectoryFlags; + BPTable->Entries[Index.PMLIndex] = PML4; + + PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex]; + PageDirectoryEntryPtr *PDEPtr = nullptr; + if (!PDPTE.Present) + { + PDEPtr = (PageDirectoryEntryPtr *)RequestPage(); + { + void *ptr = PDEPtr; + int value = 0; + size_t num = 0x1000; + uint8_t *p = (uint8_t *)ptr; + for (size_t i = 0; i < num; i++) + p[i] = value; + } + PDPTE.Present = true; + PDPTE.SetAddress((uintptr_t)PDEPtr >> 12); + } + else + PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12); + PDPTE.raw |= DirectoryFlags; + PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE; + + PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex]; + PageTableEntryPtr *PTEPtr = nullptr; + if (!PDE.Present) + { + PTEPtr = (PageTableEntryPtr *)RequestPage(); + { + void *ptr = PTEPtr; + int value = 0; + size_t num = 0x1000; + uint8_t *p = (uint8_t *)ptr; + for (size_t i = 0; i < num; i++) + p[i] = value; + } + PDE.Present = true; + PDE.SetAddress((uintptr_t)PTEPtr >> 12); + } + else + PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12); + PDE.raw |= DirectoryFlags; + PDEPtr->Entries[Index.PDEIndex] = PDE; + + PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; + PTE.Present = true; + PTE.raw |= Flags; + PTE.SetAddress((uintptr_t)PhysicalAddress >> 12); + PTEPtr->Entries[Index.PTEIndex] = PTE; + asmv("invlpg (%0)" + : + : "r"(VirtualAddress) + : "memory"); +} + +EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64() +{ + BPTable = (PageTable4 *)BootPageTable; + + // for (size_t i = 0; i < 0x10000000; i += 0x1000) + // Map((void *)i, (void *)i, 0x3); + + uintptr_t KernelStart = (uintptr_t)&_kernel_start; + uintptr_t KernelEnd = (uintptr_t)&_kernel_end; + uintptr_t PhysicalStart = KernelStart - 0xFFFFFFFF80000000; + for (uintptr_t i = KernelStart; i < KernelEnd; i += 0x1000) + { + Map((void *)i, (void *)PhysicalStart, 0x3); + PhysicalStart += 0x1000; + } + + asmv("mov %%cr3, %%rax\n" + "mov %%rax, %%cr3\n" + : + : + : "rax"); +} diff --git a/Architecture/amd64/Bootstrap/Multiboot_Init.asm b/Architecture/amd64/Bootstrap/Multiboot_Init.asm new file mode 100644 index 00000000..a72c3fcc --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot_Init.asm @@ -0,0 +1,114 @@ +[bits 32] +KERNEL_STACK_SIZE equ 0x4000 ; 16KB + +extern multiboot_main +extern LoadGDT32 +extern BootPageTable +extern UpdatePageTable + +section .bootstrap.data + +MB_HeaderMagic: + dq 0 + +MB_HeaderInfo: + dq 0 + +section .bootstrap.text + +global _start +_start: + cli + + mov [MB_HeaderMagic], eax + mov [MB_HeaderInfo], ebx + + mov ecx, cr4 + or ecx, 0x00000010 ; Set PSE in CR4 + or ecx, 0x00000020 ; Set PAE in CR4 + mov cr4, ecx + + call LoadGDT32 + call UpdatePageTable + + mov ecx, BootPageTable + mov cr3, ecx + + mov ecx, 0xC0000080 ; EFER + rdmsr + or eax, 0x800 | 0x100 | 0x1 ; Set LME, LMA, SCE + wrmsr + + mov ecx, cr0 + or ecx, 0x80000000 | 0x1 ; Set PG and PE in CR0 + mov cr0, ecx + + lgdt [GDT64.Ptr] + + jmp GDT64.code:HigherHalfStart + +extern UpdatePageTable64 + +[bits 64] +HigherHalfStart: + mov ax, GDT64.data + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + call UpdatePageTable64 + + mov rsp, KernelStack + KERNEL_STACK_SIZE + mov rdi, [MB_HeaderMagic] + mov rsi, [MB_HeaderInfo] + push rsi + push rdi + call multiboot_main +.Hang: + hlt + jmp .Hang + + + +; Access bits +PRESENT equ 1 << 7 +NOT_SYS equ 1 << 4 +EXEC equ 1 << 3 +DC equ 1 << 2 +RW equ 1 << 1 +ACCESSED equ 1 << 0 + +; Flags bits +GRAN_4K equ 1 << 7 +SZ_32 equ 1 << 6 +LONG_MODE equ 1 << 5 + +section .bootstrap.data +GDT64: + .null: equ $ - GDT64 + dq 0 + .code: equ $ - GDT64 + dd 0xFFFF + db 0 + db PRESENT | NOT_SYS | EXEC | RW + db GRAN_4K | LONG_MODE | 0xF + db 0 + .data: equ $ - GDT64 + dd 0xFFFF + db 0 + db PRESENT | NOT_SYS | RW + db GRAN_4K | SZ_32 | 0xF + db 0 + .tss: equ $ - GDT64 + dd 0x00000068 + dd 0x00CF8900 + .Ptr: + dw $ - GDT64 - 1 + dq GDT64 + +section .bootstrap.bss +align 16 +KernelStack: + resb KERNEL_STACK_SIZE diff --git a/Architecture/amd64/Bootstrap/Multiboot_PageTable.asm b/Architecture/amd64/Bootstrap/Multiboot_PageTable.asm new file mode 100644 index 00000000..cc5caf3f --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot_PageTable.asm @@ -0,0 +1,45 @@ +PAGE_TABLE_SIZE equ 0x4 ; 1GB +[bits 32] + +section .bootstrap.data +align 0x1000 +global BootPageTable +BootPageTable: + times (0x10000) dq 0 ; 0x4000 + +section .bootstrap.text +global UpdatePageTable +UpdatePageTable: + mov edi, (BootPageTable + 0x0000) ; First PML4E + mov eax, (BootPageTable + 0x1000) ; First PDPTE + or eax, 11b ; Bitwise OR on rax (PDPTE) with 11b (Present, Write) + mov dword [edi], eax ; Write 11b to PML4E + + mov edi, (BootPageTable + 0x1000) ; First PDPTE + mov eax, (BootPageTable + 0x2000) ; First PDE + or eax, 11b ; Bitwise OR on rax (PDE) with 11b (Present, Write) + + mov ecx, PAGE_TABLE_SIZE ; For loop instruction + mov ebx, 0x0 ; Value to store in the next 4 bytes + .FillPageTableLevel3: + mov dword [edi], eax ; Store modified PDE in PDPTE + mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes + add eax, 0x1000 ; Increment (page size) + adc ebx, 0 ; Add 0 to carry flag + add edi, 8 ; Add 8 to rdi (next PDE) + loop .FillPageTableLevel3 ; Loop until rcx is 0 + + mov edi, (BootPageTable + 0x2000) ; First PDE + mov eax, 10000011b ; Present, Write, Large Page + + mov ecx, (512 * PAGE_TABLE_SIZE) ; For loop instruction + mov ebx, 0x0 ; Value to store in the next 4 bytes + .FillPageTableLevel2: + mov dword [edi], eax ; Store modified PDE in PDPTE + mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes + add eax, 1 << 21 ; Increment (page size) + adc ebx, 0 ; Add 0 (carry flag) to rbx to increment if there was a carry + add edi, 8 ; Add 8 to rdi (next PDE) + loop .FillPageTableLevel2 ; Loop until rcx is 0 + + ret diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 554fbedf..140f3780 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -1,52 +1,48 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - OUTPUT_FORMAT(elf64-x86-64) OUTPUT_ARCH(i386:x86-64) +KERNEL_VMA = 0xFFFFFFFF80000000; + ENTRY(_start) SECTIONS { - . = 0xffffffff80000000; + . = 0x100000; + + _bootstrap_start = .; + .bootstrap : + { + *(.multiboot) + *(.multiboot2) + *(.bootstrap .bootstrap.*) + } + _bootstrap_end = .; + + . += KERNEL_VMA; _kernel_start = .; - .text : + .text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) } _kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .data : + .data : AT(ADDR(.data) - KERNEL_VMA) { *(.data .data.*) } _kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .rodata : + .rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) } _kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .init_array : + .init_array : AT(ADDR(.init_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__init_array_start = .); KEEP(*(.init_array .ctors)) @@ -54,7 +50,7 @@ SECTIONS PROVIDE_HIDDEN (__init_array_end = .); } - .fini_array : + .fini_array : AT(ADDR(.fini_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__fini_array_start = .); KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) @@ -63,7 +59,7 @@ SECTIONS } . += CONSTANT(MAXPAGESIZE); - .bss : + .bss : AT(ADDR(.bss) - KERNEL_VMA) { *(COMMON) *(.bss .bss.*) @@ -76,4 +72,4 @@ SECTIONS *(.comment*) *(.note*) } -} +} \ No newline at end of file diff --git a/Architecture/amd64/runtime/crt1.c b/Architecture/amd64/runtime/crt1.c index bcc936a5..1369bfeb 100644 --- a/Architecture/amd64/runtime/crt1.c +++ b/Architecture/amd64/runtime/crt1.c @@ -4,12 +4,12 @@ int Entry(void *Info); -void _start(void *Raw) -{ - UNUSED(Raw); - error("ERROR! INVALID BOOT PROTOCOL!"); - while (1) - asmv("hlt"); - Entry(NULL); - return; -} +// void _start(void *Raw) +// { +// UNUSED(Raw); +// error("ERROR! INVALID BOOT PROTOCOL!"); +// while (1) +// asmv("hlt"); +// Entry(NULL); +// return; +// } diff --git a/Architecture/i386/Bootstrap/Header_Multiboot.asm b/Architecture/i386/Bootstrap/Header_Multiboot.asm new file mode 100644 index 00000000..71a6efe8 --- /dev/null +++ b/Architecture/i386/Bootstrap/Header_Multiboot.asm @@ -0,0 +1,5 @@ +section .multiboot +align 4 + dd 0x1BADB002 + dd 1 << 0 | 1 << 1 + dd -(0x1BADB002 + (1 << 0 | 1 << 1)) diff --git a/Architecture/i386/Bootstrap/Header_Multiboot2.asm b/Architecture/i386/Bootstrap/Header_Multiboot2.asm new file mode 100644 index 00000000..a0a9a71e --- /dev/null +++ b/Architecture/i386/Bootstrap/Header_Multiboot2.asm @@ -0,0 +1,41 @@ +section .multiboot2 +align 4096 +HEADER_START: + dd 0xE85250D6 + dd 0 + dd (HEADER_END - HEADER_START) + dd 0x100000000 - (HEADER_END - HEADER_START) - 0 - 0xE85250D6 +align 8 +MB2_INFO_REQUEST_TAG_START: + dw 1 + dw 0 + dd MB2_INFO_REQUEST_TAG_END - MB2_INFO_REQUEST_TAG_START + dd 1 ; Command Line + dd 2 ; Boot Loader Name + dd 3 ; Module + dd 4 ; Basic Memory Information + dd 5 ; BIOS Boot Device + dd 6 ; Memory Map + dd 7 ; VBE + dd 8 ; Framebuffer + dd 9 ; ELF Sections + dd 10 ; APM Table + dd 11 ; EFI 32-bit System Table Pointer + dd 12 ; EFI 64-bit System Table Pointer + ; dd 13 ; SMBIOS + dd 14 ; ACPI Old + dd 15 ; ACPI New + dd 16 ; Network + dd 17 ; EFI Memory Map + dd 18 ; EFI Boot Services Notifier + dd 19 ; EFI 32-bit Image Handle Pointer + dd 20 ; EFI 64-bit Image Handle Pointer + dd 21 ; Load Base Address +MB2_INFO_REQUEST_TAG_END: +align 8 +MB2_TAG_START: + dw 0 + dw 0 + dd MB2_TAG_END - MB2_TAG_START +MB2_TAG_END: +HEADER_END: diff --git a/Architecture/i386/Bootstrap/Multiboot.cpp b/Architecture/i386/Bootstrap/Multiboot.cpp new file mode 100644 index 00000000..a048bdf9 --- /dev/null +++ b/Architecture/i386/Bootstrap/Multiboot.cpp @@ -0,0 +1,286 @@ +#include + +#include +#include +#include + +#include "../../../kernel.h" + +EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info) +{ + if (Info == NULL || Magic == NULL) + { + if (Magic == NULL) + error("Multiboot magic is NULL"); + if (Info == NULL) + error("Multiboot info is NULL"); + CPU::Stop(); + } + else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC) + { + error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC); + CPU::Stop(); + } + + uint64_t div = 1193180 / 1000; + outb(0x43, 0xB6); + outb(0x42, (uint8_t)div); + outb(0x42, (uint8_t)(div >> 8)); + uint8_t tmp = inb(0x61); + if (tmp != (tmp | 3)) + outb(0x61, tmp | 3); + + BootInfo mb2binfo; + int pos = 0; + auto InfoAddress = Info; + for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); + ; + Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) + { + if (Tag->type == MULTIBOOT_TAG_TYPE_END) + { + debug("End of multiboot2 tags"); + break; + } + + switch (Tag->type) + { + case MULTIBOOT_TAG_TYPE_CMDLINE: + { + strncpy(mb2binfo.Kernel.CommandLine, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); + break; + } + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + { + strncpy(mb2binfo.Bootloader.Name, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Bootloader name: %s", mb2binfo.Bootloader.Name); + break; + } + case MULTIBOOT_TAG_TYPE_MODULE: + { + multiboot_tag_module *module = (multiboot_tag_module *)Tag; + static int module_count = 0; + mb2binfo.Modules[module_count++].Address = (void *)(uint64_t)module->mod_start; + mb2binfo.Modules[module_count++].Size = module->size; + strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6); + strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline, + strlen(module->cmdline)); + debug("Module: %s", mb2binfo.Modules[module_count++].Path); + break; + } + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: + { + multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; + fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", + meminfo->mem_lower, meminfo->mem_upper); + break; + } + case MULTIBOOT_TAG_TYPE_BOOTDEV: + { + multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; + fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", + bootdev->biosdev, bootdev->slice, bootdev->part); + break; + } + case MULTIBOOT_TAG_TYPE_MMAP: + { + multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; + uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); + mb2binfo.Memory.Entries = EntryCount; + for (uint32_t i = 0; i < EntryCount; i++) + { + if (EntryCount > MAX_MEMORY_ENTRIES) + { + warn("Too many memory entries, skipping the rest..."); + break; + } + multiboot_mmap_entry entry = mmap->entries[i]; + mb2binfo.Memory.Size += entry.len; + switch (entry.type) + { + case MULTIBOOT_MEMORY_AVAILABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Usable; + break; + case MULTIBOOT_MEMORY_RESERVED: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Reserved; + break; + case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; + break; + case MULTIBOOT_MEMORY_NVS: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPINVS; + break; + case MULTIBOOT_MEMORY_BADRAM: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = BadMemory; + break; + default: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Unknown; + break; + } + debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", + mb2binfo.Memory.Entry[i].BaseAddress, + mb2binfo.Memory.Entry[i].Length, + mb2binfo.Memory.Entry[i].Type); + } + break; + } + case MULTIBOOT_TAG_TYPE_VBE: + { + multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; + fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", + vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); + break; + } + case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: + { + multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; + static int fb_count = 0; + mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; + mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; + mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; + mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; + mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; + switch (fb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + mb2binfo.Framebuffer[fb_count].Type = Indexed; + break; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: + { + mb2binfo.Framebuffer[fb_count].Type = RGB; + mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; + mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; + mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; + mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; + mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; + mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; + break; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: + { + mb2binfo.Framebuffer[fb_count].Type = EGA; + break; + } + } + debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); + debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", + fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, + fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, + fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); + fb_count++; + break; + } + case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: + { + multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; + fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]", + elf->num, elf->size, elf->entsize, elf->shndx); + break; + } + case MULTIBOOT_TAG_TYPE_APM: + { + multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; + fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", + apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32: + { + multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; + fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64: + { + multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; + fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); + break; + } + case MULTIBOOT_TAG_TYPE_SMBIOS: + { + multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; + fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_OLD: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; + debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_NEW: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; + debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_NETWORK: + { + multiboot_tag_network *net = (multiboot_tag_network *)Tag; + fixme("network->[dhcpack: %p]", net->dhcpack); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_MMAP: + { + multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; + fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", + efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_BS: + { + fixme("efi_bs->[%p] (unknown structure)", Tag); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32_IH: + { + multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; + fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64_IH: + { + multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; + fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: + { + multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; + mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; + mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); + debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); + break; + } + default: + { + error("Unknown multiboot2 tag type: %d", Tag->type); + break; + } + } + } + + tmp = inb(0x61) & 0xFC; + outb(0x61, tmp); + + Entry(&mb2binfo); +} diff --git a/Architecture/i386/Bootstrap/Multiboot_Init.asm b/Architecture/i386/Bootstrap/Multiboot_Init.asm new file mode 100644 index 00000000..c8212a96 --- /dev/null +++ b/Architecture/i386/Bootstrap/Multiboot_Init.asm @@ -0,0 +1,50 @@ +[bits 32] +KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB +KERNEL_STACK_SIZE equ 0x4000 ; 16KB + +extern multiboot_main +extern BootPageTable +global _start + +section .text + +MB_HeaderMagic: + dq 0 + +MB_HeaderInfo: + dq 0 + +_start: + cli + mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE) + mov cr3, ecx + + mov ecx, cr4 + or ecx, 0x00000010 ; Set PSE in CR4 + mov cr4, ecx + + mov ecx, cr0 + or ecx, 0x80000000 ; Set PG in CR0 + mov cr0, ecx + + lea ecx, [HigherHalfStart] + jmp ecx + +HigherHalfStart: + mov [MB_HeaderMagic], eax + mov [MB_HeaderInfo], ebx + mov esp, KernelStack + KERNEL_STACK_SIZE + mov eax, [MB_HeaderMagic] + mov ebx, [MB_HeaderInfo] + push ebx ; Multiboot2 Header + add ebx, KERNEL_VIRTUAL_BASE + push eax ; Multiboot2 Magic + call multiboot_main +.Hang: + hlt + jmp .Hang + +section .bss +align 16 +KernelStack: + resb KERNEL_STACK_SIZE diff --git a/Architecture/i386/Bootstrap/Multiboot_PageTable.asm b/Architecture/i386/Bootstrap/Multiboot_PageTable.asm new file mode 100644 index 00000000..9df80899 --- /dev/null +++ b/Architecture/i386/Bootstrap/Multiboot_PageTable.asm @@ -0,0 +1,10 @@ +KERNEL_PAGE_NUMBER equ 768 ; 0xC0000000 + +section .data +global BootPageTable +align 0x1000 +BootPageTable: + dd 0x00000083 + times (KERNEL_PAGE_NUMBER - 1) dd 0 + dd 0x00000083 + times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0 diff --git a/Architecture/i386/cpu/SymmetricMultiprocessing.cpp b/Architecture/i386/cpu/SymmetricMultiprocessing.cpp index a60692f2..eff12718 100644 --- a/Architecture/i386/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/i386/cpu/SymmetricMultiprocessing.cpp @@ -36,7 +36,7 @@ CPUData *GetCurrentCPU() uint64_t ret = 0; if (!(&CPUs[ret])->IsActive) { - error("CPU %d is not active!", ret); + // error("CPU %d is not active!", ret); return &CPUs[0]; } assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM); diff --git a/Architecture/i386/linker.ld b/Architecture/i386/linker.ld index 165ea54a..292c465b 100644 --- a/Architecture/i386/linker.ld +++ b/Architecture/i386/linker.ld @@ -22,24 +22,26 @@ ENTRY(_start) SECTIONS { - . = 0xC0000000; + . = 0xC0100000; _kernel_start = .; - .text : + .text ALIGN(4K) : AT(ADDR(.text) - 0xC0000000) { + *(.multiboot) + *(.multiboot2) *(.text .text.*) } _kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .data : + .data ALIGN(4K) : AT(ADDR(.data) - 0xC0000000) { *(.data .data.*) } _kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .rodata : + .rodata ALIGN(4K) : AT(ADDR(.rodata) - 0xC0000000) { *(.rodata .rodata.*) } @@ -63,7 +65,7 @@ SECTIONS } . += CONSTANT(MAXPAGESIZE); - .bss : + .bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000) { *(COMMON) *(.bss .bss.*) diff --git a/Architecture/i386/runtime/crt1.c b/Architecture/i386/runtime/crt1.c index bcc936a5..1369bfeb 100644 --- a/Architecture/i386/runtime/crt1.c +++ b/Architecture/i386/runtime/crt1.c @@ -4,12 +4,12 @@ int Entry(void *Info); -void _start(void *Raw) -{ - UNUSED(Raw); - error("ERROR! INVALID BOOT PROTOCOL!"); - while (1) - asmv("hlt"); - Entry(NULL); - return; -} +// void _start(void *Raw) +// { +// UNUSED(Raw); +// error("ERROR! INVALID BOOT PROTOCOL!"); +// while (1) +// asmv("hlt"); +// Entry(NULL); +// return; +// } diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index df6dda35..1f4704ed 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -388,7 +388,10 @@ namespace Memory { /* We don't want to use 0 as a memory address. */ if (Info->Memory.Entry[i].BaseAddress == 0x0) + { + debug("Ignoring memory segment at 0x0"); continue; + } LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress; LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length; @@ -400,6 +403,29 @@ namespace Memory } } +#define ROUND_UP(N, S) ((((N) + (S)-1) / (S)) * (S)) + if (LargestFreeMemorySegment >= Info->Kernel.PhysicalBase && + LargestFreeMemorySegment <= (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size)) + { + void *NewLargestFreeMemorySegment = (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size); + void *RoundNewLargestFreeMemorySegment = (void *)ROUND_UP((uintptr_t)NewLargestFreeMemorySegment, PAGE_SIZE); + + debug("Rounding %p to %p", NewLargestFreeMemorySegment, RoundNewLargestFreeMemorySegment); + info("Largest free memory segment is in the kernel, moving it to %p", RoundNewLargestFreeMemorySegment); + LargestFreeMemorySegment = RoundNewLargestFreeMemorySegment; + + if (RoundNewLargestFreeMemorySegment >= &_bootstrap_start && + RoundNewLargestFreeMemorySegment <= (void *)((uintptr_t)&_bootstrap_end + &_bootstrap_start)) + { + void *NewNewLargestFreeMemorySegment = (void *)((uintptr_t)&_bootstrap_end + &_bootstrap_start); + void *RoundNewNewLargestFreeMemorySegment = (void *)ROUND_UP((uintptr_t)NewNewLargestFreeMemorySegment, PAGE_SIZE); + debug("Rounding %p to %p", NewNewLargestFreeMemorySegment, RoundNewNewLargestFreeMemorySegment); + info("Largest free memory segment is in the bootstrap, moving it to %p", RoundNewNewLargestFreeMemorySegment); + LargestFreeMemorySegment = RoundNewNewLargestFreeMemorySegment; + } + } +#undef ROUND_UP + if (LargestFreeMemorySegment == nullptr) { error("No free memory found!"); @@ -429,7 +455,7 @@ namespace Memory } debug("Reserving pages for SMP..."); - this->ReservePage((void *)0x0); /* Trampoline stack, gdt, idt, etc... */ + this->ReservePage((void *)0x0); /* Trampoline stack, gdt, idt, etc... */ this->ReservePages((void *)0x2000, 4); /* TRAMPOLINE_START */ debug("Reserving bitmap pages..."); diff --git a/include/memory.hpp b/include/memory.hpp index b3d28457..b338e852 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -30,6 +30,7 @@ #ifdef __cplusplus extern uintptr_t _kernel_start, _kernel_end; +extern uintptr_t _bootstrap_start, _bootstrap_end; extern uintptr_t _kernel_text_end, _kernel_data_end, _kernel_rodata_end; // kilobyte From abb9ff0517543b91a47087f11b1956531fec1ac2 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 30 Apr 2023 21:26:57 +0300 Subject: [PATCH 2/4] Update linkers --- Architecture/amd64/linker.ld | 19 ++++++++++++++++++- Architecture/i386/linker.ld | 27 +++++++++++++++++++-------- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 140f3780..39ce7dbc 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -1,3 +1,20 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + OUTPUT_FORMAT(elf64-x86-64) OUTPUT_ARCH(i386:x86-64) @@ -72,4 +89,4 @@ SECTIONS *(.comment*) *(.note*) } -} \ No newline at end of file +} diff --git a/Architecture/i386/linker.ld b/Architecture/i386/linker.ld index 292c465b..576b36aa 100644 --- a/Architecture/i386/linker.ld +++ b/Architecture/i386/linker.ld @@ -18,37 +18,48 @@ OUTPUT_FORMAT(elf32-i386) OUTPUT_ARCH(i386) +KERNEL_VMA = 0xC0000000; + ENTRY(_start) SECTIONS { - . = 0xC0100000; + . = 0x100000; - _kernel_start = .; - .text ALIGN(4K) : AT(ADDR(.text) - 0xC0000000) + _bootstrap_start = .; + .bootstrap : { *(.multiboot) *(.multiboot2) + *(.bootstrap .bootstrap.*) + } + _bootstrap_end = .; + + . += KERNEL_VMA; + + _kernel_start = .; + .text : AT(ADDR(.text) - KERNEL_VMA) + { *(.text .text.*) } _kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .data ALIGN(4K) : AT(ADDR(.data) - 0xC0000000) + .data : AT(ADDR(.data) - KERNEL_VMA) { *(.data .data.*) } _kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .rodata ALIGN(4K) : AT(ADDR(.rodata) - 0xC0000000) + .rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) } _kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); - .init_array : + .init_array : AT(ADDR(.init_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__init_array_start = .); KEEP(*(.init_array .ctors)) @@ -56,7 +67,7 @@ SECTIONS PROVIDE_HIDDEN (__init_array_end = .); } - .fini_array : + .fini_array : AT(ADDR(.fini_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__fini_array_start = .); KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) @@ -65,7 +76,7 @@ SECTIONS } . += CONSTANT(MAXPAGESIZE); - .bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000) + .bss : AT(ADDR(.bss) - KERNEL_VMA) { *(COMMON) *(.bss .bss.*) From c4798a69b14c78285d013ff45a39c6fa007614ce Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 30 Apr 2023 21:38:20 +0300 Subject: [PATCH 3/4] Update code --- Architecture/amd64/linker.ld | 7 ++++--- Architecture/i386/linker.ld | 7 ++++--- Core/Memory/PhysicalMemoryManager.cpp | 8 +++++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 39ce7dbc..04aeafef 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -33,11 +33,12 @@ SECTIONS *(.multiboot2) *(.bootstrap .bootstrap.*) } - _bootstrap_end = .; + . += CONSTANT(MAXPAGESIZE); + _bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += KERNEL_VMA; - - _kernel_start = .; + . += CONSTANT(MAXPAGESIZE); + _kernel_start = ALIGN(CONSTANT(MAXPAGESIZE)); .text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) diff --git a/Architecture/i386/linker.ld b/Architecture/i386/linker.ld index 576b36aa..2e427dd4 100644 --- a/Architecture/i386/linker.ld +++ b/Architecture/i386/linker.ld @@ -33,11 +33,12 @@ SECTIONS *(.multiboot2) *(.bootstrap .bootstrap.*) } - _bootstrap_end = .; + . += CONSTANT(MAXPAGESIZE); + _bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += KERNEL_VMA; - - _kernel_start = .; + . += CONSTANT(MAXPAGESIZE); + _kernel_start = ALIGN(CONSTANT(MAXPAGESIZE)); .text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index 1f4704ed..15b3d93e 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -24,6 +24,8 @@ #include "../../kernel.h" +extern "C" char BootPageTable[]; // 0x10000 in length + namespace Memory { uint64_t Physical::GetTotalMemory() @@ -450,7 +452,7 @@ namespace Memory for (uint64_t i = 0; i < Info->Memory.Entries; i++) { - if (Info->Memory.Entry[i].Type == Usable) + if (Info->Memory.Entry[i].Type == Usable && Info->Memory.Entry[i].BaseAddress != 0x0) this->UnreservePages(Info->Memory.Entry[i].BaseAddress, TO_PAGES(Info->Memory.Entry[i].Length)); } @@ -460,6 +462,10 @@ namespace Memory debug("Reserving bitmap pages..."); this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size)); + debug("Reserving kernel..."); + this->ReservePages(BootPageTable, TO_PAGES(0x10000)); + this->ReservePages(&_bootstrap_start, TO_PAGES((uintptr_t)&_bootstrap_end - (uintptr_t)&_bootstrap_start)); + this->ReservePages(&_kernel_start, TO_PAGES((uintptr_t)&_kernel_end - (uintptr_t)&_kernel_start)); } Physical::Physical() {} From 7811c2197107301990065fcf2d600738ca223792 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 8 May 2023 00:27:12 +0300 Subject: [PATCH 4/4] Kernel is now able to boot from mb2 --- .../amd64/Bootstrap/Header_Multiboot2.asm | 23 + Architecture/amd64/Bootstrap/Multiboot.cpp | 482 +++++++++--------- .../amd64/Bootstrap/Multiboot64bitMap.cpp | 26 +- Architecture/amd64/linker.ld | 3 +- Core/Memory/Memory.cpp | 41 +- Core/Memory/PhysicalMemoryManager.cpp | 134 +++-- Core/Symbols.cpp | 7 + Kernel.cpp | 22 +- SystemCalls/Native.cpp | 210 ++++---- include/memory.hpp | 10 +- 10 files changed, 558 insertions(+), 400 deletions(-) diff --git a/Architecture/amd64/Bootstrap/Header_Multiboot2.asm b/Architecture/amd64/Bootstrap/Header_Multiboot2.asm index a0a9a71e..756dcb89 100644 --- a/Architecture/amd64/Bootstrap/Header_Multiboot2.asm +++ b/Architecture/amd64/Bootstrap/Header_Multiboot2.asm @@ -1,3 +1,4 @@ +; https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html section .multiboot2 align 4096 HEADER_START: @@ -33,6 +34,28 @@ MB2_INFO_REQUEST_TAG_START: dd 21 ; Load Base Address MB2_INFO_REQUEST_TAG_END: align 8 +MB2_FRAMEBUFFER_TAG_START: + dw 5 + dw 1 + dd MB2_FRAMEBUFFER_TAG_END - MB2_FRAMEBUFFER_TAG_START + dd 0 + dd 0 + dd 32 +MB2_FRAMEBUFFER_TAG_END: +align 8 +MB2_EGA_SUPPORT_TAG_START: + dw 4 + dw 0 + dd MB2_EGA_SUPPORT_TAG_END - MB2_EGA_SUPPORT_TAG_START + dd 1 ; https://www.gnu.org/software/grub/manual/multiboot2/html_node/Console-header-tags.html +MB2_EGA_SUPPORT_TAG_END: +align 8 +MB2_MODULE_ALIGN_TAG_START: + dw 6 + dw 0 + dd MB2_MODULE_ALIGN_TAG_END - MB2_MODULE_ALIGN_TAG_START +MB2_MODULE_ALIGN_TAG_END: +align 8 MB2_TAG_START: dw 0 dw 0 diff --git a/Architecture/amd64/Bootstrap/Multiboot.cpp b/Architecture/amd64/Bootstrap/Multiboot.cpp index 9c9d676a..68657920 100644 --- a/Architecture/amd64/Bootstrap/Multiboot.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot.cpp @@ -22,266 +22,278 @@ EXTERNC void multiboot_main(uint64_t Magic, uint64_t Info) CPU::Stop(); } - uint64_t div = 1193180 / 1000; - outb(0x43, 0xB6); - outb(0x42, (uint8_t)div); - outb(0x42, (uint8_t)(div >> 8)); - uint8_t tmp = inb(0x61); - if (tmp != (tmp | 3)) - outb(0x61, tmp | 3); + BootInfo mb2binfo{}; + + // Clear the BSS + // memset_unsafe(&_kernel_rodata_end, 0, &_kernel_end - &_kernel_rodata_end); - BootInfo mb2binfo; - int pos = 0; - auto InfoAddress = Info; - for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); - ; - Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) { - if (Tag->type == MULTIBOOT_TAG_TYPE_END) - { - debug("End of multiboot2 tags"); - break; - } + uint64_t div = 1193180 / 1000; + outb(0x43, 0xB6); + outb(0x42, (uint8_t)div); + outb(0x42, (uint8_t)(div >> 8)); + uint8_t tmp = inb(0x61); + if (tmp != (tmp | 3)) + outb(0x61, tmp | 3); - switch (Tag->type) + int pos = 0; + auto InfoAddress = Info; + for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); + ; + Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) { - case MULTIBOOT_TAG_TYPE_CMDLINE: - { - strncpy(mb2binfo.Kernel.CommandLine, - ((multiboot_tag_string *)Tag)->string, - strlen(((multiboot_tag_string *)Tag)->string)); - debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); - break; - } - case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: - { - strncpy(mb2binfo.Bootloader.Name, - ((multiboot_tag_string *)Tag)->string, - strlen(((multiboot_tag_string *)Tag)->string)); - debug("Bootloader name: %s", mb2binfo.Bootloader.Name); - break; - } - case MULTIBOOT_TAG_TYPE_MODULE: - { - multiboot_tag_module *module = (multiboot_tag_module *)Tag; - static int module_count = 0; - mb2binfo.Modules[module_count++].Address = (void *)(uint64_t)module->mod_start; - mb2binfo.Modules[module_count++].Size = module->size; - strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6); - strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline, - strlen(module->cmdline)); - debug("Module: %s", mb2binfo.Modules[module_count++].Path); - break; - } - case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: - { - multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; - fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", - meminfo->mem_lower, meminfo->mem_upper); - break; - } - case MULTIBOOT_TAG_TYPE_BOOTDEV: - { - multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; - fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", - bootdev->biosdev, bootdev->slice, bootdev->part); - break; - } - case MULTIBOOT_TAG_TYPE_MMAP: - { - multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; - uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); - mb2binfo.Memory.Entries = EntryCount; - for (uint32_t i = 0; i < EntryCount; i++) + if (Tag->type == MULTIBOOT_TAG_TYPE_END) { - if (EntryCount > MAX_MEMORY_ENTRIES) + debug("End of multiboot2 tags"); + break; + } + + switch (Tag->type) + { + case MULTIBOOT_TAG_TYPE_CMDLINE: + { + strncpy(mb2binfo.Kernel.CommandLine, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); + break; + } + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + { + strncpy(mb2binfo.Bootloader.Name, + ((multiboot_tag_string *)Tag)->string, + strlen(((multiboot_tag_string *)Tag)->string)); + debug("Bootloader name: %s", mb2binfo.Bootloader.Name); + break; + } + case MULTIBOOT_TAG_TYPE_MODULE: + { + multiboot_tag_module *module = (multiboot_tag_module *)Tag; + static int module_count = 0; + mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start; + mb2binfo.Modules[module_count].Size = module->size; + strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6); + strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline, + strlen(module->cmdline)); + debug("Module: %s", mb2binfo.Modules[module_count].Path); + module_count++; + break; + } + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: + { + multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; + fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", + meminfo->mem_lower, meminfo->mem_upper); + break; + } + case MULTIBOOT_TAG_TYPE_BOOTDEV: + { + multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; + fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", + bootdev->biosdev, bootdev->slice, bootdev->part); + break; + } + case MULTIBOOT_TAG_TYPE_MMAP: + { + multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; + size_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); + mb2binfo.Memory.Entries = EntryCount; + for (uint32_t i = 0; i < EntryCount; i++) { - warn("Too many memory entries, skipping the rest..."); + if (EntryCount > MAX_MEMORY_ENTRIES) + { + warn("Too many memory entries, skipping the rest..."); + break; + } + multiboot_mmap_entry entry = mmap->entries[i]; + mb2binfo.Memory.Size += entry.len; + switch (entry.type) + { + case MULTIBOOT_MEMORY_AVAILABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Usable; + break; + case MULTIBOOT_MEMORY_RESERVED: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Reserved; + break; + case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; + break; + case MULTIBOOT_MEMORY_NVS: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = ACPINVS; + break; + case MULTIBOOT_MEMORY_BADRAM: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = BadMemory; + break; + default: + mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; + mb2binfo.Memory.Entry[i].Length = entry.len; + mb2binfo.Memory.Entry[i].Type = Unknown; + break; + } + debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", + mb2binfo.Memory.Entry[i].BaseAddress, + mb2binfo.Memory.Entry[i].Length, + mb2binfo.Memory.Entry[i].Type); + } + break; + } + case MULTIBOOT_TAG_TYPE_VBE: + { + multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; + fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", + vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); + break; + } + case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: + { + multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; + static int fb_count = 0; + mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; + mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; + mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; + mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; + mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; + switch (fb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + mb2binfo.Framebuffer[fb_count].Type = Indexed; break; } - multiboot_mmap_entry entry = mmap->entries[i]; - mb2binfo.Memory.Size += entry.len; - switch (entry.type) + case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: { - case MULTIBOOT_MEMORY_AVAILABLE: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = Usable; + mb2binfo.Framebuffer[fb_count].Type = RGB; + mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; + mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; + mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; + mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; + mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; + mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; break; - case MULTIBOOT_MEMORY_RESERVED: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = Reserved; - break; - case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; - break; - case MULTIBOOT_MEMORY_NVS: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = ACPINVS; - break; - case MULTIBOOT_MEMORY_BADRAM: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = BadMemory; + } + case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: + { + mb2binfo.Framebuffer[fb_count].Type = EGA; break; + } default: - mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; - mb2binfo.Memory.Entry[i].Length = entry.len; - mb2binfo.Memory.Entry[i].Type = Unknown; + { + mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type; break; } - debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", - mb2binfo.Memory.Entry[i].BaseAddress, - mb2binfo.Memory.Entry[i].Length, - mb2binfo.Memory.Entry[i].Type); - } - break; - } - case MULTIBOOT_TAG_TYPE_VBE: - { - multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; - fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", - vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); - break; - } - case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: - { - multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; - static int fb_count = 0; - mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; - mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; - mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; - mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; - mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; - switch (fb->common.framebuffer_type) - { - case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: - { - mb2binfo.Framebuffer[fb_count].Type = Indexed; + } + debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); + debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", + fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, + fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, + fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); + fb_count++; break; } - case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: + case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: { - mb2binfo.Framebuffer[fb_count].Type = RGB; - mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; - mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; - mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; - mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; - mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; - mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; + multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; + fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]", + elf->num, elf->size, elf->entsize, elf->shndx); break; } - case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: + case MULTIBOOT_TAG_TYPE_APM: { - mb2binfo.Framebuffer[fb_count].Type = EGA; + multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; + fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", + apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32: + { + multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; + fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64: + { + multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; + fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); + break; + } + case MULTIBOOT_TAG_TYPE_SMBIOS: + { + multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; + fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_OLD: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; + debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_ACPI_NEW: + { + mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; + debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); + break; + } + case MULTIBOOT_TAG_TYPE_NETWORK: + { + multiboot_tag_network *net = (multiboot_tag_network *)Tag; + fixme("network->[dhcpack: %p]", net->dhcpack); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_MMAP: + { + multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; + fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", + efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); + break; + } + case MULTIBOOT_TAG_TYPE_EFI_BS: + { + fixme("efi_bs->[%p] (unknown structure)", Tag); + break; + } + case MULTIBOOT_TAG_TYPE_EFI32_IH: + { + multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; + fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_EFI64_IH: + { + multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; + fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); + break; + } + case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: + { + multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; + mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; + mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); + mb2binfo.Kernel.Size = ((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start); + debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); + break; + } + default: + { + error("Unknown multiboot2 tag type: %d", Tag->type); break; } } - debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); - debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", - fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, - fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, - fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); - fb_count++; - break; } - case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: - { - multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; - fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]", - elf->num, elf->size, elf->entsize, elf->shndx); - break; - } - case MULTIBOOT_TAG_TYPE_APM: - { - multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; - fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", - apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); - break; - } - case MULTIBOOT_TAG_TYPE_EFI32: - { - multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; - fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); - break; - } - case MULTIBOOT_TAG_TYPE_EFI64: - { - multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; - fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); - break; - } - case MULTIBOOT_TAG_TYPE_SMBIOS: - { - multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; - fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); - break; - } - case MULTIBOOT_TAG_TYPE_ACPI_OLD: - { - mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; - debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); - break; - } - case MULTIBOOT_TAG_TYPE_ACPI_NEW: - { - mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; - debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); - break; - } - case MULTIBOOT_TAG_TYPE_NETWORK: - { - multiboot_tag_network *net = (multiboot_tag_network *)Tag; - fixme("network->[dhcpack: %p]", net->dhcpack); - break; - } - case MULTIBOOT_TAG_TYPE_EFI_MMAP: - { - multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; - fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", - efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); - break; - } - case MULTIBOOT_TAG_TYPE_EFI_BS: - { - fixme("efi_bs->[%p] (unknown structure)", Tag); - break; - } - case MULTIBOOT_TAG_TYPE_EFI32_IH: - { - multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; - fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); - break; - } - case MULTIBOOT_TAG_TYPE_EFI64_IH: - { - multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; - fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); - break; - } - case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: - { - multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; - mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; - mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); - mb2binfo.Kernel.Size = &_kernel_end - &_kernel_start; - debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); - break; - } - default: - { - error("Unknown multiboot2 tag type: %d", Tag->type); - break; - } - } - } - tmp = inb(0x61) & 0xFC; - outb(0x61, tmp); + tmp = inb(0x61) & 0xFC; + outb(0x61, tmp); + } Entry(&mb2binfo); } diff --git a/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp b/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp index a128b496..9cfcac91 100644 --- a/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot64bitMap.cpp @@ -33,7 +33,7 @@ union __attribute__((packed)) PageTableEntry struct __attribute__((packed)) PageTableEntryPtr { - PageTableEntry Entries[511]; + PageTableEntry Entries[512]; }; union __attribute__((packed)) PageDirectoryEntry @@ -67,7 +67,7 @@ union __attribute__((packed)) PageDirectoryEntry struct __attribute__((packed)) PageDirectoryEntryPtr { - PageDirectoryEntry Entries[511]; + PageDirectoryEntry Entries[512]; }; union __attribute__((packed)) PageDirectoryPointerTableEntry @@ -101,7 +101,7 @@ union __attribute__((packed)) PageDirectoryPointerTableEntry struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr { - PageDirectoryPointerTableEntry Entries[511]; + PageDirectoryPointerTableEntry Entries[512]; }; union __attribute__((packed)) PageMapLevel4 @@ -135,7 +135,7 @@ union __attribute__((packed)) PageMapLevel4 struct PageTable4 { - PageMapLevel4 Entries[511]; + PageMapLevel4 Entries[512]; } __attribute__((aligned(0x1000))); extern "C" char BootPageTable[]; @@ -177,7 +177,7 @@ public: } }; -__always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) +__attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) { PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); // Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only @@ -188,9 +188,11 @@ __always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *Phy if (!PML4.Present) { PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage(); + if (PDPTEPtr == nullptr) + return; { void *ptr = PDPTEPtr; - int value = 0; + uint8_t value = 0; size_t num = 0x1000; uint8_t *p = (uint8_t *)ptr; for (size_t i = 0; i < num; i++) @@ -209,9 +211,11 @@ __always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *Phy if (!PDPTE.Present) { PDEPtr = (PageDirectoryEntryPtr *)RequestPage(); + if (PDEPtr == nullptr) + return; { void *ptr = PDEPtr; - int value = 0; + uint8_t value = 0; size_t num = 0x1000; uint8_t *p = (uint8_t *)ptr; for (size_t i = 0; i < num; i++) @@ -230,9 +234,11 @@ __always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *Phy if (!PDE.Present) { PTEPtr = (PageTableEntryPtr *)RequestPage(); + if (PTEPtr == nullptr) + return; { void *ptr = PTEPtr; - int value = 0; + uint8_t value = 0; size_t num = 0x1000; uint8_t *p = (uint8_t *)ptr; for (size_t i = 0; i < num; i++) @@ -262,14 +268,14 @@ EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute BPTable = (PageTable4 *)BootPageTable; // for (size_t i = 0; i < 0x10000000; i += 0x1000) - // Map((void *)i, (void *)i, 0x3); + // MB2_64_Map((void *)i, (void *)i, 0x3); uintptr_t KernelStart = (uintptr_t)&_kernel_start; uintptr_t KernelEnd = (uintptr_t)&_kernel_end; uintptr_t PhysicalStart = KernelStart - 0xFFFFFFFF80000000; for (uintptr_t i = KernelStart; i < KernelEnd; i += 0x1000) { - Map((void *)i, (void *)PhysicalStart, 0x3); + MB2_64_Map((void *)i, (void *)PhysicalStart, 0x3); PhysicalStart += 0x1000; } diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 04aeafef..47dbe0e5 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -57,8 +57,6 @@ SECTIONS { *(.rodata .rodata.*) } - _kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE)); - . += CONSTANT(MAXPAGESIZE); .init_array : AT(ADDR(.init_array) - KERNEL_VMA) { @@ -75,6 +73,7 @@ SECTIONS KEEP(*(.fini_array .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } + _kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE)); . += CONSTANT(MAXPAGESIZE); .bss : AT(ADDR(.bss) - KERNEL_VMA) diff --git a/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index 827bee59..4ad7c63b 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -146,6 +146,7 @@ NIF void MapFramebuffer(PageTable4 *PT, BootInfo *Info) NIF void MapKernel(PageTable4 *PT, BootInfo *Info) { debug("Mapping Kernel"); + uintptr_t BootstrapStart = (uintptr_t)&_bootstrap_start; uintptr_t KernelStart = (uintptr_t)&_kernel_start; uintptr_t KernelTextEnd = (uintptr_t)&_kernel_text_end; uintptr_t KernelDataEnd = (uintptr_t)&_kernel_data_end; @@ -154,6 +155,9 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info) uintptr_t KernelFileStart = (uintptr_t)Info->Kernel.FileBase; uintptr_t KernelFileEnd = KernelFileStart + Info->Kernel.Size; + debug("Kernel physical address: %#lx - %#lx", Info->Kernel.PhysicalBase, (uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size); + debug("Kernel file base: %#lx - %#lx", KernelFileStart, KernelFileEnd); + debug("File size: %ld KB", TO_KB(Info->Kernel.Size)); debug(".text size: %ld KB", TO_KB(KernelTextEnd - KernelStart)); debug(".data size: %ld KB", TO_KB(KernelDataEnd - KernelTextEnd)); @@ -164,9 +168,23 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info) uintptr_t k; Virtual va = Virtual(PT); + /* Bootstrap section */ + for (k = BootstrapStart; k < KernelStart - KERNEL_VMA_OFFSET; k += PAGE_SIZE) + { +#ifdef DEBUG /* vscode debugging */ + void *BKMA = (void *)BaseKernelMapAddress, *K_ = (void *)k; +#endif + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); + KernelAllocator.ReservePage((void *)BaseKernelMapAddress); + BaseKernelMapAddress += PAGE_SIZE; + } + /* Text section */ for (k = KernelStart; k < KernelTextEnd; k += PAGE_SIZE) { +#ifdef DEBUG /* vscode debugging */ + void *BKMA = (void *)BaseKernelMapAddress, *K_ = (void *)k; +#endif va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); KernelAllocator.ReservePage((void *)BaseKernelMapAddress); BaseKernelMapAddress += PAGE_SIZE; @@ -175,6 +193,9 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info) /* Data section */ for (k = KernelTextEnd; k < KernelDataEnd; k += PAGE_SIZE) { +#ifdef DEBUG /* vscode debugging */ + void *BKMA = (void *)BaseKernelMapAddress, *K_ = (void *)k; +#endif va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); KernelAllocator.ReservePage((void *)BaseKernelMapAddress); BaseKernelMapAddress += PAGE_SIZE; @@ -183,6 +204,9 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info) /* Read only data section */ for (k = KernelDataEnd; k < KernelRoDataEnd; k += PAGE_SIZE) { +#ifdef DEBUG /* vscode debugging */ + void *BKMA = (void *)BaseKernelMapAddress, *K_ = (void *)k; +#endif va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::G); KernelAllocator.ReservePage((void *)BaseKernelMapAddress); BaseKernelMapAddress += PAGE_SIZE; @@ -191,17 +215,23 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info) /* BSS section */ for (k = KernelRoDataEnd; k < KernelEnd; k += PAGE_SIZE) { +#ifdef DEBUG /* vscode debugging */ + void *BKMA = (void *)BaseKernelMapAddress, *K_ = (void *)k; +#endif va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); KernelAllocator.ReservePage((void *)BaseKernelMapAddress); BaseKernelMapAddress += PAGE_SIZE; } + debug("BaseKernelMapAddress: %#lx - %#lx", Info->Kernel.PhysicalBase, BaseKernelMapAddress); + /* Kernel file */ - for (k = KernelFileStart; k < KernelFileEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)k, PTFlag::G); - KernelAllocator.ReservePage((void *)k); - } + if (KernelFileStart != 0) + for (k = KernelFileStart; k < KernelFileEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)k, PTFlag::G); + KernelAllocator.ReservePage((void *)k); + } #ifdef DEBUG if (EnableExternalMemoryTracer) @@ -304,6 +334,7 @@ NIF void InitializeMemoryManagement(BootInfo *Info) trace("Initializing Virtual Memory Manager"); KernelPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE + 1)); + debug("Page table allocated at %#lx", KernelPageTable); memset(KernelPageTable, 0, PAGE_SIZE); if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index 15b3d93e..67e3280b 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -22,6 +22,8 @@ #include #endif +#include "../../Architecture/amd64/acpi.hpp" + #include "../../kernel.h" extern "C" char BootPageTable[]; // 0x10000 in length @@ -379,6 +381,7 @@ namespace Memory TotalMemory = MemorySize; FreeMemory = MemorySize; + size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1; void *LargestFreeMemorySegment = nullptr; uint64_t LargestFreeMemorySegmentSize = 0; @@ -395,39 +398,54 @@ namespace Memory continue; } - LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress; - LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length; + if (Info->Memory.Entry[i].Length > BitmapSize + 0x1000) + { + LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress; + LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length; - debug("Largest free memory segment: %llp (%lldMB)", - (void *)Info->Memory.Entry[i].BaseAddress, - TO_MB(Info->Memory.Entry[i].Length)); +#define ROUND_UP(N, S) ((((N) + (S)-1) / (S)) * (S)) + if (LargestFreeMemorySegment >= Info->Kernel.PhysicalBase && + LargestFreeMemorySegment <= (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size)) + { + debug("Kernel range: %#lx-%#lx", Info->Kernel.PhysicalBase, (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size)); + + void *NewLargestFreeMemorySegment = (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size); + void *RoundNewLargestFreeMemorySegment = (void *)ROUND_UP((uintptr_t)NewLargestFreeMemorySegment, PAGE_SIZE); + RoundNewLargestFreeMemorySegment = (void *)((uintptr_t)RoundNewLargestFreeMemorySegment + PAGE_SIZE); /* Leave a page between the kernel and the bitmap */ + + debug("Rounding %p to %p", NewLargestFreeMemorySegment, RoundNewLargestFreeMemorySegment); + info("Memory bitmap's memory segment is in the kernel, moving it to %p", RoundNewLargestFreeMemorySegment); + LargestFreeMemorySegmentSize = (uintptr_t)LargestFreeMemorySegmentSize - ((uintptr_t)RoundNewLargestFreeMemorySegment - (uintptr_t)LargestFreeMemorySegment); + LargestFreeMemorySegment = RoundNewLargestFreeMemorySegment; + } +#undef ROUND_UP + + if (LargestFreeMemorySegmentSize < BitmapSize + 0x1000) + { + trace("Largest free memory segment is too small (%lld bytes), skipping...", + LargestFreeMemorySegmentSize); + continue; + } + + debug("Found a memory segment of %lld bytes (%lldMB) at %llp (out segment is %lld bytes (%lldKB)))", + LargestFreeMemorySegmentSize, + TO_MB(LargestFreeMemorySegmentSize), + LargestFreeMemorySegment, + BitmapSize, + TO_KB(BitmapSize)); + break; + } + + // LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress; + // LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length; + + // debug("Largest free memory segment: %llp (%lldMB)", + // (void *)Info->Memory.Entry[i].BaseAddress, + // TO_MB(Info->Memory.Entry[i].Length)); } } } -#define ROUND_UP(N, S) ((((N) + (S)-1) / (S)) * (S)) - if (LargestFreeMemorySegment >= Info->Kernel.PhysicalBase && - LargestFreeMemorySegment <= (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size)) - { - void *NewLargestFreeMemorySegment = (void *)((uintptr_t)Info->Kernel.PhysicalBase + Info->Kernel.Size); - void *RoundNewLargestFreeMemorySegment = (void *)ROUND_UP((uintptr_t)NewLargestFreeMemorySegment, PAGE_SIZE); - - debug("Rounding %p to %p", NewLargestFreeMemorySegment, RoundNewLargestFreeMemorySegment); - info("Largest free memory segment is in the kernel, moving it to %p", RoundNewLargestFreeMemorySegment); - LargestFreeMemorySegment = RoundNewLargestFreeMemorySegment; - - if (RoundNewLargestFreeMemorySegment >= &_bootstrap_start && - RoundNewLargestFreeMemorySegment <= (void *)((uintptr_t)&_bootstrap_end + &_bootstrap_start)) - { - void *NewNewLargestFreeMemorySegment = (void *)((uintptr_t)&_bootstrap_end + &_bootstrap_start); - void *RoundNewNewLargestFreeMemorySegment = (void *)ROUND_UP((uintptr_t)NewNewLargestFreeMemorySegment, PAGE_SIZE); - debug("Rounding %p to %p", NewNewLargestFreeMemorySegment, RoundNewNewLargestFreeMemorySegment); - info("Largest free memory segment is in the bootstrap, moving it to %p", RoundNewNewLargestFreeMemorySegment); - LargestFreeMemorySegment = RoundNewNewLargestFreeMemorySegment; - } - } -#undef ROUND_UP - if (LargestFreeMemorySegment == nullptr) { error("No free memory found!"); @@ -435,7 +453,6 @@ namespace Memory } /* TODO: Read swap config and make the configure the bitmap size correctly */ - size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1; debug("Initializing Bitmap at %llp-%llp (%lld Bytes)", LargestFreeMemorySegment, (void *)((uintptr_t)LargestFreeMemorySegment + BitmapSize), @@ -460,12 +477,63 @@ namespace Memory this->ReservePage((void *)0x0); /* Trampoline stack, gdt, idt, etc... */ this->ReservePages((void *)0x2000, 4); /* TRAMPOLINE_START */ - debug("Reserving bitmap pages..."); + debug("Reserving bitmap region %#lx-%#lx...", PageBitmap.Buffer, (void *)((uintptr_t)PageBitmap.Buffer + PageBitmap.Size)); this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size)); - debug("Reserving kernel..."); - this->ReservePages(BootPageTable, TO_PAGES(0x10000)); + // debug("Reserving page table..."); + // this->ReservePages(BootPageTable, TO_PAGES(0x10000)); << in the bootstrap region + debug("Reserving kernel bootstrap region %#lx-%#lx...", &_bootstrap_start, &_bootstrap_end); this->ReservePages(&_bootstrap_start, TO_PAGES((uintptr_t)&_bootstrap_end - (uintptr_t)&_bootstrap_start)); - this->ReservePages(&_kernel_start, TO_PAGES((uintptr_t)&_kernel_end - (uintptr_t)&_kernel_start)); + void *KernelPhysicalStart = (void *)(((uintptr_t)&_kernel_start - KERNEL_VMA_OFFSET)); + void *KernelPhysicalEnd = (void *)(((uintptr_t)&_kernel_end - KERNEL_VMA_OFFSET)); + debug("Reserving kernel region %#lx-%#lx...", KernelPhysicalStart, KernelPhysicalEnd); + this->ReservePages((void *)KernelPhysicalStart, TO_PAGES((uintptr_t)&_kernel_end - (uintptr_t)&_kernel_start)); + + ACPI::ACPI::ACPIHeader *hdr = nullptr; + bool XSDT = false; + + if (Info->RSDP->Revision >= 2 && Info->RSDP->XSDTAddress) + { + hdr = (ACPI::ACPI::ACPIHeader *)(Info->RSDP->XSDTAddress); + XSDT = true; + } + else + { + hdr = (ACPI::ACPI::ACPIHeader *)(uintptr_t)Info->RSDP->RSDTAddress; + } + + debug("Reserving RSDT..."); + this->ReservePages((void*)Info->RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo))); + + debug("Reserving ACPI tables..."); + + uint64_t TableSize = ((hdr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4)); + debug("Table size: %lld", TableSize); + + for (uint64_t t = 0; t < TableSize; t++) + { + // TODO: Should I be concerned about unaligned memory access? + ACPI::ACPI::ACPIHeader *SDTHdr = nullptr; + if (XSDT) + SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)hdr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 8))); + else + SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)hdr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 4))); + + this->ReservePages(SDTHdr, TO_PAGES(SDTHdr->Length)); + } + + debug("Reserving kernel modules..."); + + for (uint64_t i = 0; i < MAX_MODULES; i++) + { + if (Info->Modules[i].Address == 0x0) + continue; + + debug("Reserving module %s (%#lx-%#lx)...", Info->Modules[i].CommandLine, + Info->Modules[i].Address, (void *)((uintptr_t)Info->Modules[i].Address + Info->Modules[i].Size)); + + this->ReservePages((void *)Info->Modules[i].Address, TO_PAGES(Info->Modules[i].Size)); + } + } Physical::Physical() {} diff --git a/Core/Symbols.cpp b/Core/Symbols.cpp index 5745e15d..6d362b9d 100644 --- a/Core/Symbols.cpp +++ b/Core/Symbols.cpp @@ -28,6 +28,13 @@ namespace SymbolResolver Symbols::Symbols(uintptr_t ImageAddress) { debug("Solving symbols for address: %#llx", ImageAddress); + + if (ImageAddress == 0) + { + error("Invalid image address"); + return; + } + Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress; if (Header->e_ident[0] != 0x7F && Header->e_ident[1] != 'E' && diff --git a/Kernel.cpp b/Kernel.cpp index bc9b56b8..b367f0bd 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -255,9 +255,6 @@ EXTERNC void KPrint(const char *Format, ...) EXTERNC NIF void Main(BootInfo *Info) { - memcpy(&bInfo, Info, sizeof(BootInfo)); - debug("BootInfo structure is at %p", bInfo); - Display = new Video::Display(bInfo.Framebuffer[0]); KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT); KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name()); @@ -270,7 +267,7 @@ EXTERNC NIF void Main(BootInfo *Info) Interrupts::Initialize(0); KPrint("Loading Kernel Symbols"); - KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)Info->Kernel.FileBase); + KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase); KPrint("Reading Kernel Parameters"); ParseConfig((char *)bInfo.Kernel.CommandLine, &Config); @@ -496,8 +493,23 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info) TestMemoryAllocation(); #endif + /* This is allocated in RAM. */ + static BootInfo *bootInfo_temp = nullptr; + bootInfo_temp = Info; /* Info will be lost after changing the rsp and bsp. */ + + /* NO RETURN BEYOND THIS POINT */ + void *KernelStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)); + asmv("mov %0, %%rsp" + : + : "r"(KernelStack) + : "memory"); + asmv("mov $0, %rbp"); + + memcpy(&bInfo, bootInfo_temp, sizeof(BootInfo)); + debug("BootInfo structure is at %p", &bInfo); + EnableProfiler = true; - Main(Info); + Main(bootInfo_temp); } #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index e8f42ba9..2e34d325 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -25,7 +25,6 @@ #include "../syscalls.h" #include "../kernel.h" -#include "../../Userspace/libs/include/sysbase.h" #include "../ipc.h" using InterProcessCommunication::IPC; @@ -111,124 +110,125 @@ static int sys_detach_address(SyscallsFrame *Frame, uintptr_t Address) return SYSCALL_OK; } -static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) +static uintptr_t sys_kernelctl(SyscallsFrame *Frame, uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) { if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) return SYSCALL_ACCESS_DENIED; - switch (Command) - { - case KCTL_GET_PID: - return TaskManager->GetCurrentThread()->Parent->ID; - case KCTL_GET_TID: - return TaskManager->GetCurrentThread()->ID; - case KCTL_GET_PAGE_SIZE: - return PAGE_SIZE; - case KCTL_IS_CRITICAL: - return TaskManager->GetCurrentThread()->Security.IsCritical; - case KCTL_REGISTER_ELF_LIB: - { - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - char *Identifier = (char *)Arg1; - const char *Path = (const char *)Arg2; + return SYSCALL_NOT_IMPLEMENTED; - if (!Identifier || !Path) - return SYSCALL_INVALID_ARGUMENT; + // switch (Command) + // { + // case KCTL_GET_PID: + // return TaskManager->GetCurrentThread()->Parent->ID; + // case KCTL_GET_TID: + // return TaskManager->GetCurrentThread()->ID; + // case KCTL_GET_PAGE_SIZE: + // return PAGE_SIZE; + // case KCTL_IS_CRITICAL: + // return TaskManager->GetCurrentThread()->Security.IsCritical; + // case KCTL_REGISTER_ELF_LIB: + // { + // if (!CheckTrust(TrustedByKernel | Trusted)) + // return SYSCALL_ACCESS_DENIED; + // char *Identifier = (char *)Arg1; + // const char *Path = (const char *)Arg2; - std::string FullPath = Path; - int retries = 0; - RetryReadPath: - debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", FullPath.c_str()); - VirtualFileSystem::File f = vfs->Open(FullPath.c_str()); + // if (!Identifier || !Path) + // return SYSCALL_INVALID_ARGUMENT; - if (!f.IsOK()) - { - FullPath.clear(); - switch (retries) - { - case 0: - FullPath = "/system/lib/"; - break; - case 1: - FullPath = "/system/lib64/"; - break; - case 2: - FullPath = "/system/"; - break; - case 3: - { - // TODO: Check process binary path - break; - } - default: - { - vfs->Close(f); - return SYSCALL_INVALID_ARGUMENT; - } - } - FullPath += Path; - vfs->Close(f); - retries++; - goto RetryReadPath; - } + // std::string FullPath = Path; + // int retries = 0; + // RetryReadPath: + // debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", FullPath.c_str()); + // VirtualFileSystem::File f = vfs->Open(FullPath.c_str()); - vfs->Close(f); - if (Execute::AddLibrary(Identifier, (void *)f.node->Address, f.node->Length)) - return SYSCALL_OK; - else - return SYSCALL_INTERNAL_ERROR; - } - case KCTL_GET_ELF_LIB_FILE: - { - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - char *Identifier = (char *)Arg1; - if (!Identifier) - return 0; + // if (!f.IsOK()) + // { + // FullPath.clear(); + // switch (retries) + // { + // case 0: + // FullPath = "/system/lib/"; + // break; + // case 1: + // FullPath = "/system/lib64/"; + // break; + // case 2: + // FullPath = "/system/"; + // break; + // case 3: + // { + // // TODO: Check process binary path + // break; + // } + // default: + // { + // vfs->Close(f); + // return SYSCALL_INVALID_ARGUMENT; + // } + // } + // FullPath += Path; + // vfs->Close(f); + // retries++; + // goto RetryReadPath; + // } - Execute::SharedLibraries lib = Execute::GetLibrary(Identifier); - if (!lib.Address) - { - debug("Failed to get library address %#lx", (uintptr_t)lib.Address); - } + // vfs->Close(f); + // if (Execute::AddLibrary(Identifier, (void *)f.node->Address, f.node->Length)) + // return SYSCALL_OK; + // else + // return SYSCALL_INTERNAL_ERROR; + // } + // case KCTL_GET_ELF_LIB_FILE: + // { + // if (!CheckTrust(TrustedByKernel | Trusted)) + // return SYSCALL_ACCESS_DENIED; + // char *Identifier = (char *)Arg1; + // if (!Identifier) + // return 0; - debug("Returning library address %#lx (%s)", (uintptr_t)lib.Address, Identifier); - return (uintptr_t)lib.Address; - } - case KCTL_GET_ELF_LIB_MEMORY_IMAGE: - { - if (!CheckTrust(TrustedByKernel | Trusted)) - return SYSCALL_ACCESS_DENIED; - char *Identifier = (char *)Arg1; - if (!Identifier) - return 0; + // Execute::SharedLibraries lib = Execute::GetLibrary(Identifier); + // if (!lib.Address) + // { + // debug("Failed to get library address %#lx", (uintptr_t)lib.Address); + // } - Execute::SharedLibraries lib = Execute::GetLibrary(Identifier); + // debug("Returning library address %#lx (%s)", (uintptr_t)lib.Address, Identifier); + // return (uintptr_t)lib.Address; + // } + // case KCTL_GET_ELF_LIB_MEMORY_IMAGE: + // { + // if (!CheckTrust(TrustedByKernel | Trusted)) + // return SYSCALL_ACCESS_DENIED; + // char *Identifier = (char *)Arg1; + // if (!Identifier) + // return 0; - if (!lib.MemoryImage) - { - debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage); - } + // Execute::SharedLibraries lib = Execute::GetLibrary(Identifier); - debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier); - return (uintptr_t)lib.MemoryImage; - } - case KCTL_GET_FRAMEBUFFER_BUFFER: - return r_cst(uint64_t, Display->GetBuffer(0)->Buffer); - case KCTL_GET_FRAMEBUFFER_WIDTH: - return Display->GetBuffer(0)->Width; - case KCTL_GET_FRAMEBUFFER_HEIGHT: - return Display->GetBuffer(0)->Height; - case KCTL_GET_FRAMEBUFFER_SIZE: - return Display->GetBuffer(0)->Size; + // if (!lib.MemoryImage) + // { + // debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage); + // } - default: - { - warn("KernelCTL: Unknown command: %lld", Command); - return SYSCALL_INVALID_ARGUMENT; - } - } + // debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier); + // return (uintptr_t)lib.MemoryImage; + // } + // case KCTL_GET_FRAMEBUFFER_BUFFER: + // return r_cst(uint64_t, Display->GetBuffer(0)->Buffer); + // case KCTL_GET_FRAMEBUFFER_WIDTH: + // return Display->GetBuffer(0)->Width; + // case KCTL_GET_FRAMEBUFFER_HEIGHT: + // return Display->GetBuffer(0)->Height; + // case KCTL_GET_FRAMEBUFFER_SIZE: + // return Display->GetBuffer(0)->Size; + // default: + // { + // warn("KernelCTL: Unknown command: %lld", Command); + // return SYSCALL_INVALID_ARGUMENT; + // } + // } UNUSED(Arg1); UNUSED(Arg2); diff --git a/include/memory.hpp b/include/memory.hpp index b338e852..f8884b5f 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -229,7 +229,7 @@ namespace Memory struct __packed PageTableEntryPtr { - PageTableEntry Entries[511]; + PageTableEntry Entries[512]; }; union __packed PageDirectoryEntry @@ -305,7 +305,7 @@ namespace Memory struct __packed PageDirectoryEntryPtr { - PageDirectoryEntry Entries[511]; + PageDirectoryEntry Entries[512]; }; union __packed PageDirectoryPointerTableEntry @@ -381,7 +381,7 @@ namespace Memory struct __packed PageDirectoryPointerTableEntryPtr { - PageDirectoryPointerTableEntry Entries[511]; + PageDirectoryPointerTableEntry Entries[512]; }; union __packed PageMapLevel4 @@ -436,7 +436,7 @@ namespace Memory struct PageTable4 { - PageMapLevel4 Entries[511]; + PageMapLevel4 Entries[512]; /** * @brief Update CR3 with this PageTable4 @@ -458,7 +458,7 @@ namespace Memory struct PageTable5 { - PageMapLevel5 Entries[511]; + PageMapLevel5 Entries[512]; } __aligned(0x1000); class Physical