From 0f3efdf25b5e5a1639be90af5e44ebd8e489ec06 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 19 Mar 2023 22:01:55 +0200 Subject: [PATCH 1/7] Test mb2 --- Architecture/amd64/Bootstrap/MB2.asm | 70 ++++ Architecture/amd64/Bootstrap/MB2Detection.asm | 40 +++ Architecture/amd64/Bootstrap/MB2Header.asm | 42 +++ Architecture/amd64/Bootstrap/MB2PageTable.asm | 14 + Architecture/amd64/Bootstrap/MB2Switch.asm | 0 Architecture/amd64/Bootstrap/Multiboot2.cpp | 339 ++++++++++++++++++ Architecture/amd64/linker.ld | 26 +- 7 files changed, 523 insertions(+), 8 deletions(-) create mode 100644 Architecture/amd64/Bootstrap/MB2.asm create mode 100644 Architecture/amd64/Bootstrap/MB2Detection.asm create mode 100644 Architecture/amd64/Bootstrap/MB2Header.asm create mode 100644 Architecture/amd64/Bootstrap/MB2PageTable.asm create mode 100644 Architecture/amd64/Bootstrap/MB2Switch.asm create mode 100644 Architecture/amd64/Bootstrap/Multiboot2.cpp diff --git a/Architecture/amd64/Bootstrap/MB2.asm b/Architecture/amd64/Bootstrap/MB2.asm new file mode 100644 index 00000000..6b8fd55a --- /dev/null +++ b/Architecture/amd64/Bootstrap/MB2.asm @@ -0,0 +1,70 @@ +; https://wiki.osdev.org/Creating_a_64-bit_kernel +; https://wiki.osdev.org/Entering_Long_Mode_Directly + +KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB +KERNEL_LMA equ 0x1000000 ; 16MB +KERNEL_STACK_SIZE equ 0x4000 ; 16KB + +extern Multiboot2Entry +extern BootPageTable +extern DetectCPUID +extern Detect64Bit +global MB2_start + +[bits 32] +section .text +MB2_start: + cli + + mov word [0xb8F00], 0x072E ; . + + call DetectCPUID + call Detect64Bit + + mov ecx, cr4 + or ecx, 0x00000010 ; Set PSE in CR4 + mov cr4, ecx + + mov word [0xb8F02], 0x072E ; . + + mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE) + mov cr3, ecx + + mov ecx, cr0 + or ecx, 0x80000000 ; Set PG in CR0 + mov cr0, ecx + + cli + hlt + + mov word [0xb8F04], 0x072E ; . + + + mov word [0xb8F06], 0x072E ; . + + cli + hlt + + ; lea ecx, [HigherHalfStart] + ; jmp ecx + +[bits 64] +HigherHalfStart: + mov word [0xb8F08], 0x072E ; . + mov dword [BootPageTable], 0 + invlpg [0] + + mov rsp, KernelStack + KERNEL_STACK_SIZE + + push rax ; Multiboot2 Magic + add rbx, KERNEL_VIRTUAL_BASE + push rbx ; Multiboot2 Header + call Multiboot2Entry +Loop: + hlt + jmp Loop + +section .bss +align 16 +KernelStack: + resb KERNEL_STACK_SIZE diff --git a/Architecture/amd64/Bootstrap/MB2Detection.asm b/Architecture/amd64/Bootstrap/MB2Detection.asm new file mode 100644 index 00000000..22ba2959 --- /dev/null +++ b/Architecture/amd64/Bootstrap/MB2Detection.asm @@ -0,0 +1,40 @@ +[bits 32] +global DetectCPUID +DetectCPUID: + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 + push eax + popfd + pushfd + pop eax + push ecx + popfd + xor eax, ecx + jz .NoCPUID + ret +.NoCPUID: + mov word [0xb8F00], 0xF00F ; . +.Loop: + cli + hlt + jmp .Loop + +global Detect64Bit +Detect64Bit: + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .NoLongMode + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz .NoLongMode + ret +.NoLongMode: + mov word [0xb8F00], 0xF00A ; . +.Loop: + cli + hlt + jmp .Loop diff --git a/Architecture/amd64/Bootstrap/MB2Header.asm b/Architecture/amd64/Bootstrap/MB2Header.asm new file mode 100644 index 00000000..b05828df --- /dev/null +++ b/Architecture/amd64/Bootstrap/MB2Header.asm @@ -0,0 +1,42 @@ +[bits 32] +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/MB2PageTable.asm b/Architecture/amd64/Bootstrap/MB2PageTable.asm new file mode 100644 index 00000000..4a66ac4b --- /dev/null +++ b/Architecture/amd64/Bootstrap/MB2PageTable.asm @@ -0,0 +1,14 @@ +%define KERNEL_OFFSET 0xFFFFFFFF80000000 +%define V2P(a) ((a) - KERNEL_OFFSET) + +%define PAGE_PRESENT 0x001 +%define PAGE_WRITE 0x002 +%define PAGE_GLOBAL 0x100 + +%define PAGE_SIZE 0x1000 +%define ENTRIES_PER_PT 512 + +section .data +align PAGE_SIZE +global BootPageTable +BootPageTable: diff --git a/Architecture/amd64/Bootstrap/MB2Switch.asm b/Architecture/amd64/Bootstrap/MB2Switch.asm new file mode 100644 index 00000000..e69de29b diff --git a/Architecture/amd64/Bootstrap/Multiboot2.cpp b/Architecture/amd64/Bootstrap/Multiboot2.cpp new file mode 100644 index 00000000..99ed39a4 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot2.cpp @@ -0,0 +1,339 @@ +#include + +#include +#include +#include + +#include "../../../kernel.h" + +BootInfo mb2binfo; + +enum VideoType +{ + VIDEO_TYPE_NONE = 0x00, + VIDEO_TYPE_COLOUR = 0x20, + VIDEO_TYPE_MONOCHROME = 0x30, +}; + +uint16_t GetBiosAreaHardware() +{ + const uint16_t *BIOSDataAreaDetectedHardware = (const uint16_t *)0x410; + return *BIOSDataAreaDetectedHardware; +} + +enum VideoType GetVideoType() { return (enum VideoType)(GetBiosAreaHardware() & 0x30); } + +void GetSMBIOS() +{ + unsigned char *SMBIOSAddress = (unsigned char *)0xF0000; + while ((unsigned int)(unsigned long)SMBIOSAddress < 0x100000) + { + if (SMBIOSAddress[0] == '_' && + SMBIOSAddress[1] == 'S' && + SMBIOSAddress[2] == 'M' && + SMBIOSAddress[3] == '_') + { + unsigned char Checksum = 0; + int Length = SMBIOSAddress[5]; + for (int i = 0; i < Length; i++) + Checksum += SMBIOSAddress[i]; + + if (Checksum == 0) + break; + } + SMBIOSAddress += 16; + } + + if ((unsigned int)(unsigned long)SMBIOSAddress == 0x100000) + { + // No SMBIOS found + } +} + +void ProcessMB2(unsigned long Info) +{ + uint8_t *VideoBuffer = (uint8_t *)0xB8F00 + 0xC0000000; + 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))) + { + VideoBuffer[pos++] = '.'; + VideoBuffer[pos++] = 0x2; + + 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 *)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; + mb2binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type; + switch (fb->common.framebuffer_type) + { + case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: + { + fixme("indexed"); + break; + } + case MULTIBOOT_FRAMEBUFFER_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: + { + fixme("ega_text"); + break; + } + } + debug("Framebuffer %d: %dx%d %d bpp", Tag, 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 *)load_base_addr->load_base_addr; + mb2binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000); + debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); + break; + } + default: + { + error("Unknown multiboot2 tag type: %d", Tag->type); + break; + } + } + } +} + +EXTERNC void Multiboot2Entry(unsigned long Info, unsigned int Magic) +{ + 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); + + ProcessMB2(Info); + + tmp = inb(0x61) & 0xFC; + outb(0x61, tmp); + + CPU::Stop(); + Entry(&mb2binfo); +} diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 357c4cdc..9407e8ba 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -1,35 +1,45 @@ OUTPUT_FORMAT(elf64-x86-64) OUTPUT_ARCH(i386:x86-64) -ENTRY(_start) +KERNEL_LMA = 16M; +KERNEL_VMA = 0xFFFFFFFF80000000; + +ENTRY(MB2_start) SECTIONS { - . = 0xffffffff80000000; + . = KERNEL_LMA; + + .multiboot2 : + { + *(.multiboot2 .multiboot2.*) + } + + . += 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)) @@ -37,7 +47,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.*))) @@ -46,7 +56,7 @@ SECTIONS } . += CONSTANT(MAXPAGESIZE); - .bss : + .bss : AT(ADDR(.bss) - KERNEL_VMA) { *(COMMON) *(.bss .bss.*) From 8ff3623ee4cf199600208c6c0f57e1a1a90c7dd9 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 19 Mar 2023 21:59:38 +0200 Subject: [PATCH 2/7] Move bootloader code to a separate directory --- Architecture/amd64/{ => Bootstrap}/Limine.c | 4 +- Architecture/amd64/runtime/crt1.c | 1 - Architecture/i686/Bootstrap/MB2.asm | 54 +++++++++ Architecture/i686/Bootstrap/MB2Header.asm | 41 +++++++ Architecture/i686/Bootstrap/MB2PageTable.asm | 13 +++ .../i686/{ => Bootstrap}/Multiboot2.cpp | 4 +- Architecture/i686/linker.ld | 2 +- Architecture/i686/runtime/crt1.asm | 104 ------------------ Architecture/i686/runtime/crt1.c | 15 +++ 9 files changed, 128 insertions(+), 110 deletions(-) rename Architecture/amd64/{ => Bootstrap}/Limine.c (99%) create mode 100644 Architecture/i686/Bootstrap/MB2.asm create mode 100644 Architecture/i686/Bootstrap/MB2Header.asm create mode 100644 Architecture/i686/Bootstrap/MB2PageTable.asm rename Architecture/i686/{ => Bootstrap}/Multiboot2.cpp (99%) delete mode 100644 Architecture/i686/runtime/crt1.asm create mode 100644 Architecture/i686/runtime/crt1.c diff --git a/Architecture/amd64/Limine.c b/Architecture/amd64/Bootstrap/Limine.c similarity index 99% rename from Architecture/amd64/Limine.c rename to Architecture/amd64/Bootstrap/Limine.c index 34566548..40acbfd3 100644 --- a/Architecture/amd64/Limine.c +++ b/Architecture/amd64/Bootstrap/Limine.c @@ -3,8 +3,8 @@ #include #include -#include "../../../tools/limine/limine.h" -#include "../../kernel.h" +#include "../../../../tools/limine/limine.h" +#include "../../../kernel.h" void init_limine(); diff --git a/Architecture/amd64/runtime/crt1.c b/Architecture/amd64/runtime/crt1.c index 17a6144c..bcc936a5 100644 --- a/Architecture/amd64/runtime/crt1.c +++ b/Architecture/amd64/runtime/crt1.c @@ -13,4 +13,3 @@ void _start(void *Raw) Entry(NULL); return; } -// C stuff \ No newline at end of file diff --git a/Architecture/i686/Bootstrap/MB2.asm b/Architecture/i686/Bootstrap/MB2.asm new file mode 100644 index 00000000..85d1c81f --- /dev/null +++ b/Architecture/i686/Bootstrap/MB2.asm @@ -0,0 +1,54 @@ +; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones +; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones_(Backup) + +KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB +KERNEL_STACK_SIZE equ 0x4000 ; 16KB + +extern Multiboot2Entry +extern BootPageTable +global MB2_start + +section .text +MB2_start: + cli + mov word [0xb8F00], 0x072E ; . + + mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE) + mov cr3, ecx + + mov word [0xb8F02], 0x072E ; . + + mov ecx, cr4 + or ecx, 0x00000010 ; Set PSE in CR4 + mov cr4, ecx + + mov word [0xb8F04], 0x072E ; . + + mov ecx, cr0 + or ecx, 0x80000000 ; Set PG in CR0 + mov cr0, ecx + + mov word [0xb8F06], 0x072E ; . + + lea ecx, [HigherHalfStart] + jmp ecx + +HigherHalfStart: + mov word [0xb8F08], 0x072E ; . + mov dword [BootPageTable], 0 + invlpg [0] + + mov esp, KernelStack + KERNEL_STACK_SIZE + + push eax ; Multiboot2 Magic + add ebx, KERNEL_VIRTUAL_BASE + push ebx ; Multiboot2 Header + call Multiboot2Entry +Loop: + hlt + jmp Loop + +section .bss +align 16 +KernelStack: + resb KERNEL_STACK_SIZE diff --git a/Architecture/i686/Bootstrap/MB2Header.asm b/Architecture/i686/Bootstrap/MB2Header.asm new file mode 100644 index 00000000..a0a9a71e --- /dev/null +++ b/Architecture/i686/Bootstrap/MB2Header.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/i686/Bootstrap/MB2PageTable.asm b/Architecture/i686/Bootstrap/MB2PageTable.asm new file mode 100644 index 00000000..9989867d --- /dev/null +++ b/Architecture/i686/Bootstrap/MB2PageTable.asm @@ -0,0 +1,13 @@ +KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB +KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768 + +section .data +global BootPageTable +align 0x1000 +BootPageTable: + dd 0x00000083 + dd 0x00000083 + times (KERNEL_PAGE_NUMBER - 2) dd 0 + dd 0x00000083 + dd 0x00000083 + times (1024 - KERNEL_PAGE_NUMBER - 2) dd 0 diff --git a/Architecture/i686/Multiboot2.cpp b/Architecture/i686/Bootstrap/Multiboot2.cpp similarity index 99% rename from Architecture/i686/Multiboot2.cpp rename to Architecture/i686/Bootstrap/Multiboot2.cpp index 0fe6fabb..99ed39a4 100644 --- a/Architecture/i686/Multiboot2.cpp +++ b/Architecture/i686/Bootstrap/Multiboot2.cpp @@ -4,7 +4,7 @@ #include #include -#include "../../kernel.h" +#include "../../../kernel.h" BootInfo mb2binfo; @@ -305,7 +305,7 @@ void ProcessMB2(unsigned long Info) } } -EXTERNC void x32Multiboot2Entry(unsigned long Info, unsigned int Magic) +EXTERNC void Multiboot2Entry(unsigned long Info, unsigned int Magic) { if (Info == NULL || Magic == NULL) { diff --git a/Architecture/i686/linker.ld b/Architecture/i686/linker.ld index 1917158d..a1a6e947 100644 --- a/Architecture/i686/linker.ld +++ b/Architecture/i686/linker.ld @@ -1,7 +1,7 @@ OUTPUT_FORMAT(elf32-i386) OUTPUT_ARCH(i386) -ENTRY(_start) +ENTRY(MB2_start) SECTIONS { diff --git a/Architecture/i686/runtime/crt1.asm b/Architecture/i686/runtime/crt1.asm deleted file mode 100644 index 42dddbc8..00000000 --- a/Architecture/i686/runtime/crt1.asm +++ /dev/null @@ -1,104 +0,0 @@ -; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones -; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones_(Backup) -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: - -KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB -KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768 -KERNEL_STACK_SIZE equ 0x4000 ; 16KB - -extern x32Multiboot2Entry -global _start - -section .data -align 0x1000 -BootPageTable: - dd 0x00000083 - dd 0x00000083 - times (KERNEL_PAGE_NUMBER - 2) dd 0 - dd 0x00000083 - dd 0x00000083 - times (1024 - KERNEL_PAGE_NUMBER - 2) dd 0 - -section .text -_start: - mov word [0xb8F00], 0x072E ; . - - mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE) - mov cr3, ecx - - mov word [0xb8F02], 0x072E ; . - - mov ecx, cr4 - or ecx, 0x00000010 ; Set PSE in CR4 - mov cr4, ecx - - mov word [0xb8F04], 0x072E ; . - - mov ecx, cr0 - or ecx, 0x80000000 ; Set PG in CR0 - mov cr0, ecx - - mov word [0xb8F06], 0x072E ; . - - lea ecx, [HigherHalfStart] - jmp ecx - -HigherHalfStart: - mov word [0xb8F08], 0x072E ; . - mov dword [BootPageTable], 0 - invlpg [0] - - mov esp, KernelStack + KERNEL_STACK_SIZE - - push eax ; Multiboot2 Magic - add ebx, KERNEL_VIRTUAL_BASE - push ebx ; Multiboot2 Header - call x32Multiboot2Entry -Loop: - hlt - jmp Loop - -section .bss -align 16 -KernelStack : - resb KERNEL_STACK_SIZE diff --git a/Architecture/i686/runtime/crt1.c b/Architecture/i686/runtime/crt1.c new file mode 100644 index 00000000..bcc936a5 --- /dev/null +++ b/Architecture/i686/runtime/crt1.c @@ -0,0 +1,15 @@ +#include + +#include + +int Entry(void *Info); + +void _start(void *Raw) +{ + UNUSED(Raw); + error("ERROR! INVALID BOOT PROTOCOL!"); + while (1) + asmv("hlt"); + Entry(NULL); + return; +} From 298c6b392193e762b8764346599be9c72717e318 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 19 Mar 2023 22:14:11 +0200 Subject: [PATCH 3/7] Update page table code --- Architecture/amd64/Bootstrap/MB2PageTable.asm | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Architecture/amd64/Bootstrap/MB2PageTable.asm b/Architecture/amd64/Bootstrap/MB2PageTable.asm index 4a66ac4b..16c0d867 100644 --- a/Architecture/amd64/Bootstrap/MB2PageTable.asm +++ b/Architecture/amd64/Bootstrap/MB2PageTable.asm @@ -1,14 +1,10 @@ -%define KERNEL_OFFSET 0xFFFFFFFF80000000 -%define V2P(a) ((a) - KERNEL_OFFSET) - -%define PAGE_PRESENT 0x001 -%define PAGE_WRITE 0x002 -%define PAGE_GLOBAL 0x100 - -%define PAGE_SIZE 0x1000 -%define ENTRIES_PER_PT 512 - section .data -align PAGE_SIZE +align 0x1000 global BootPageTable BootPageTable: + dq 0x0000000000000083 + dq 0x0000000000000083 + TIMES (512-2) dq 0 + dq 0x0000000000000083 + dq 0x0000000000000083 + TIMES (512-2) dq 0 \ No newline at end of file From 73f38799ebf26ff56c55843c6734bfa17a6b2399 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 29 Mar 2023 10:56:23 +0300 Subject: [PATCH 4/7] Update multiboot2 bootstrap code --- Architecture/amd64/Bootstrap/MB2.asm | 70 --------- Architecture/amd64/Bootstrap/MB2PageTable.asm | 10 -- Architecture/amd64/Bootstrap/MB2Switch.asm | 0 .../Detection.asm} | 1 + .../amd64/Bootstrap/Multiboot2/Entry.asm | 139 ++++++++++++++++++ .../amd64/Bootstrap/Multiboot2/GDT32.asm | 47 ++++++ .../{MB2Header.asm => Multiboot2/Header.asm} | 0 .../Bootstrap/{ => Multiboot2}/Multiboot2.cpp | 2 +- .../amd64/Bootstrap/Multiboot2/PageTable.asm | 85 +++++++++++ Architecture/amd64/linker.ld | 8 + 10 files changed, 281 insertions(+), 81 deletions(-) delete mode 100644 Architecture/amd64/Bootstrap/MB2.asm delete mode 100644 Architecture/amd64/Bootstrap/MB2PageTable.asm delete mode 100644 Architecture/amd64/Bootstrap/MB2Switch.asm rename Architecture/amd64/Bootstrap/{MB2Detection.asm => Multiboot2/Detection.asm} (95%) create mode 100644 Architecture/amd64/Bootstrap/Multiboot2/Entry.asm create mode 100644 Architecture/amd64/Bootstrap/Multiboot2/GDT32.asm rename Architecture/amd64/Bootstrap/{MB2Header.asm => Multiboot2/Header.asm} (100%) rename Architecture/amd64/Bootstrap/{ => Multiboot2}/Multiboot2.cpp (99%) create mode 100644 Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm diff --git a/Architecture/amd64/Bootstrap/MB2.asm b/Architecture/amd64/Bootstrap/MB2.asm deleted file mode 100644 index 6b8fd55a..00000000 --- a/Architecture/amd64/Bootstrap/MB2.asm +++ /dev/null @@ -1,70 +0,0 @@ -; https://wiki.osdev.org/Creating_a_64-bit_kernel -; https://wiki.osdev.org/Entering_Long_Mode_Directly - -KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB -KERNEL_LMA equ 0x1000000 ; 16MB -KERNEL_STACK_SIZE equ 0x4000 ; 16KB - -extern Multiboot2Entry -extern BootPageTable -extern DetectCPUID -extern Detect64Bit -global MB2_start - -[bits 32] -section .text -MB2_start: - cli - - mov word [0xb8F00], 0x072E ; . - - call DetectCPUID - call Detect64Bit - - mov ecx, cr4 - or ecx, 0x00000010 ; Set PSE in CR4 - mov cr4, ecx - - mov word [0xb8F02], 0x072E ; . - - mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE) - mov cr3, ecx - - mov ecx, cr0 - or ecx, 0x80000000 ; Set PG in CR0 - mov cr0, ecx - - cli - hlt - - mov word [0xb8F04], 0x072E ; . - - - mov word [0xb8F06], 0x072E ; . - - cli - hlt - - ; lea ecx, [HigherHalfStart] - ; jmp ecx - -[bits 64] -HigherHalfStart: - mov word [0xb8F08], 0x072E ; . - mov dword [BootPageTable], 0 - invlpg [0] - - mov rsp, KernelStack + KERNEL_STACK_SIZE - - push rax ; Multiboot2 Magic - add rbx, KERNEL_VIRTUAL_BASE - push rbx ; Multiboot2 Header - call Multiboot2Entry -Loop: - hlt - jmp Loop - -section .bss -align 16 -KernelStack: - resb KERNEL_STACK_SIZE diff --git a/Architecture/amd64/Bootstrap/MB2PageTable.asm b/Architecture/amd64/Bootstrap/MB2PageTable.asm deleted file mode 100644 index 16c0d867..00000000 --- a/Architecture/amd64/Bootstrap/MB2PageTable.asm +++ /dev/null @@ -1,10 +0,0 @@ -section .data -align 0x1000 -global BootPageTable -BootPageTable: - dq 0x0000000000000083 - dq 0x0000000000000083 - TIMES (512-2) dq 0 - dq 0x0000000000000083 - dq 0x0000000000000083 - TIMES (512-2) dq 0 \ No newline at end of file diff --git a/Architecture/amd64/Bootstrap/MB2Switch.asm b/Architecture/amd64/Bootstrap/MB2Switch.asm deleted file mode 100644 index e69de29b..00000000 diff --git a/Architecture/amd64/Bootstrap/MB2Detection.asm b/Architecture/amd64/Bootstrap/Multiboot2/Detection.asm similarity index 95% rename from Architecture/amd64/Bootstrap/MB2Detection.asm rename to Architecture/amd64/Bootstrap/Multiboot2/Detection.asm index 22ba2959..ee6166a7 100644 --- a/Architecture/amd64/Bootstrap/MB2Detection.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/Detection.asm @@ -1,4 +1,5 @@ [bits 32] +section .bootstrap.text global DetectCPUID DetectCPUID: pushfd diff --git a/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm b/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm new file mode 100644 index 00000000..ddcf1df6 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm @@ -0,0 +1,139 @@ +; https://wiki.osdev.org/Creating_a_64-bit_kernel +; https://wiki.osdev.org/Entering_Long_Mode_Directly + +KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB +KERNEL_LMA equ 0x1000000 ; 16MB +KERNEL_STACK_SIZE equ 0x4000 ; 16KB + +extern Multiboot2Entry +extern BootPageTable +extern UpdatePageTable +extern UpdatePageTable64 +extern DetectCPUID +extern Detect64Bit +extern LoadGDT32 +global MB2_start +extern MB2_start_c + +[bits 32] +section .bootstrap.text +MB2_start: + cli + mov word [0xb8F00], 0x072E ; . + + ; We need to check if the CPU supports 64-bit mode + call DetectCPUID + call Detect64Bit + + mov word [0xb8F02], 0x072E ; . + + mov ecx, cr0 + and ecx, 0x7fffffff ; Clear PG + mov cr0, ecx + + mov ecx, cr4 + or ecx, 0x10 ; Set PSE + or ecx, 0x20 ; Set PAE + mov cr4, ecx + + ; Load the GDT and update the page table + call LoadGDT32 + call UpdatePageTable + + ; Load the new page table + mov edi, BootPageTable + mov cr3, edi + + mov word [0xb8F04], 0x072E ; . + + ; Enable long mode + 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 + mov cr0, ecx + + + lgdt [GDT64.Ptr] + ; xor eax, eax + ; sgdt [eax] + ; test eax, eax + ; jz .InvalidGDT + + ; .InvalidGDT: + ; mov word [0xb8F07], 0x4 ; Red + ; hlt + + jmp GDT64.code:HigherHalfStart + +[bits 64] +HigherHalfStart: + cli + mov word [0xb8F06], 0x072E ; . + call UpdatePageTable64 + + ; Load the new page table + mov rdi, BootPageTable + mov cr3, rdi + + mov ax, GDT64.data + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + mov word [0xb8F08], 0x072E ; . + mov rsp, (KernelStack + KERNEL_STACK_SIZE) + + push rax ; Multiboot2 Magic + add rbx, KERNEL_VIRTUAL_BASE + push rbx ; Multiboot2 Header + call Multiboot2Entry + .Loop: + hlt + jmp .Loop + +section .bootstrap.bss +align 16 +KernelStack: + resb KERNEL_STACK_SIZE + +; 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 diff --git a/Architecture/amd64/Bootstrap/Multiboot2/GDT32.asm b/Architecture/amd64/Bootstrap/Multiboot2/GDT32.asm new file mode 100644 index 00000000..e9fa9804 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot2/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/MB2Header.asm b/Architecture/amd64/Bootstrap/Multiboot2/Header.asm similarity index 100% rename from Architecture/amd64/Bootstrap/MB2Header.asm rename to Architecture/amd64/Bootstrap/Multiboot2/Header.asm diff --git a/Architecture/amd64/Bootstrap/Multiboot2.cpp b/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp similarity index 99% rename from Architecture/amd64/Bootstrap/Multiboot2.cpp rename to Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp index 99ed39a4..f85ac3b0 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp @@ -4,7 +4,7 @@ #include #include -#include "../../../kernel.h" +#include "../../../../kernel.h" BootInfo mb2binfo; diff --git a/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm b/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm new file mode 100644 index 00000000..f6525d54 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm @@ -0,0 +1,85 @@ +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) + + mov eax, (BootPageTable + 0x1000) + or eax, 0x3 + mov dword [edi], eax + + mov ecx, PAGE_TABLE_SIZE + mov edi, (BootPageTable + 0x1000) + mov eax, (BootPageTable + 0x2000) + or eax, 0x3 + mov ebx, 0x0 + + .FillPageTableLevel3: + mov dword [edi], eax + mov dword [edi + 4], ebx + add eax, 1 << 12 + adc ebx, 0 + add edi, 8 + loop .FillPageTableLevel3 + + mov ecx, (512 * PAGE_TABLE_SIZE) + mov edi, (BootPageTable + 0x2000) + mov eax, 0x0 | 0x3 | 1 << 7 + mov ebx, 0x0 + + .FillPageTableLevel2: + mov dword [edi], eax + mov dword [edi + 4], ebx + add eax, 1 << 21 + adc ebx, 0 + add edi, 8 + loop .FillPageTableLevel2 + + ret + +[bits 64] +section .bootstrap.text +global UpdatePageTable64 +UpdatePageTable64: + mov rdi, (BootPageTable + 0x0000) + + mov rax, (BootPageTable + 0x1000) + or rax, 0x3 + mov [rdi], rax + + mov rcx, PAGE_TABLE_SIZE + mov rdi, (BootPageTable + 0x1000) + mov rax, (BootPageTable + 0x2000) + or rax, 0x3 + mov rbx, 0x0 + + .FillPageTableLevel3: + mov [rdi], rax + mov [rdi + 4], rbx + add rax, 1 << 12 + adc rbx, 0 + add rdi, 8 + loop .FillPageTableLevel3 + + mov rcx, (512 * PAGE_TABLE_SIZE) + mov rdi, (BootPageTable + 0x2000) + mov rax, 0x0 | 0x3 | 1 << 7 + mov rbx, 0x0 + + .FillPageTableLevel2: + mov [rdi], rax + mov [rdi + 4], rbx + add rax, 1 << 21 + adc rbx, 0 + add rdi, 8 + loop .FillPageTableLevel2 + + ret diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 9407e8ba..96e0e549 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -15,6 +15,14 @@ SECTIONS *(.multiboot2 .multiboot2.*) } + .bootstrap : + { + *(.bootstrap.text .bootstrap.text.*) + *(.bootstrap.data .bootstrap.data.*) + *(.bootstrap.rodata .bootstrap.rodata.*) + *(.bootstrap.bss .bootstrap.bss.*) + } + . += KERNEL_VMA; _kernel_start = .; From b6f9a644a780fda73e0f6f9c6bf3518abd01bba2 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 30 Mar 2023 19:21:14 +0300 Subject: [PATCH 5/7] Map the kernel too --- .../amd64/Bootstrap/Multiboot2/Entry.asm | 19 +- .../Bootstrap/Multiboot2/MB2MemoryMapper.cpp | 281 ++++++++++++++++++ .../amd64/Bootstrap/Multiboot2/Multiboot2.cpp | 75 +++-- .../amd64/Bootstrap/Multiboot2/PageTable.asm | 90 ++---- Core/Memory/Memory.cpp | 4 +- include/boot/binfo.h | 14 +- 6 files changed, 373 insertions(+), 110 deletions(-) create mode 100644 Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp diff --git a/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm b/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm index ddcf1df6..6c7c0d95 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm @@ -16,10 +16,22 @@ global MB2_start extern MB2_start_c [bits 32] + +section .bootstrap.data +global MB2_HeaderMagic +MB2_HeaderMagic: + times (0x64) dq 0 + +global MB2_HeaderInfo +MB2_HeaderInfo: + times (0x64) dq 0 + section .bootstrap.text MB2_start: cli mov word [0xb8F00], 0x072E ; . + mov [MB2_HeaderMagic], eax + mov [MB2_HeaderInfo], ebx ; We need to check if the CPU supports 64-bit mode call DetectCPUID @@ -88,10 +100,11 @@ HigherHalfStart: mov word [0xb8F08], 0x072E ; . mov rsp, (KernelStack + KERNEL_STACK_SIZE) + mov rbp, (KernelStack + KERNEL_STACK_SIZE) + + cld + cli - push rax ; Multiboot2 Magic - add rbx, KERNEL_VIRTUAL_BASE - push rbx ; Multiboot2 Header call Multiboot2Entry .Loop: hlt diff --git a/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp b/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp new file mode 100644 index 00000000..a128b496 --- /dev/null +++ b/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.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/Multiboot2/Multiboot2.cpp b/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp index f85ac3b0..f7748b97 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp @@ -6,8 +6,6 @@ #include "../../../../kernel.h" -BootInfo mb2binfo; - enum VideoType { VIDEO_TYPE_NONE = 0x00, @@ -50,9 +48,37 @@ void GetSMBIOS() } } -void ProcessMB2(unsigned long Info) +extern "C" unsigned int MB2_HeaderMagic; +extern "C" unsigned long MB2_HeaderInfo; + +EXTERNC void Multiboot2Entry() { - uint8_t *VideoBuffer = (uint8_t *)0xB8F00 + 0xC0000000; + unsigned long Info = MB2_HeaderInfo; + unsigned int Magic = MB2_HeaderMagic; + 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; + uint8_t *VideoBuffer = (uint8_t *)0xB8F00; int pos = 0; auto InfoAddress = Info; for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); @@ -90,7 +116,7 @@ void ProcessMB2(unsigned long Info) { multiboot_tag_module *module = (multiboot_tag_module *)Tag; static int module_count = 0; - mb2binfo.Modules[module_count++].Address = (void *)module->mod_start; + 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, @@ -187,11 +213,12 @@ void ProcessMB2(unsigned long Info) { case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: { - fixme("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; @@ -202,11 +229,11 @@ void ProcessMB2(unsigned long Info) } case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: { - fixme("ega_text"); + mb2binfo.Framebuffer[fb_count].Type = EGA; break; } } - debug("Framebuffer %d: %dx%d %d bpp", Tag, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); + 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, @@ -291,8 +318,8 @@ void ProcessMB2(unsigned long Info) 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 *)load_base_addr->load_base_addr; - mb2binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000); + 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; } @@ -303,37 +330,9 @@ void ProcessMB2(unsigned long Info) } } } -} - -EXTERNC void Multiboot2Entry(unsigned long Info, unsigned int Magic) -{ - 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); - - ProcessMB2(Info); tmp = inb(0x61) & 0xFC; outb(0x61, tmp); - CPU::Stop(); Entry(&mb2binfo); } diff --git a/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm b/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm index f6525d54..eba5546c 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm @@ -10,76 +10,36 @@ BootPageTable: section .bootstrap.text global UpdatePageTable UpdatePageTable: - mov edi, (BootPageTable + 0x0000) + 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 eax, (BootPageTable + 0x1000) - or eax, 0x3 - mov dword [edi], eax - - mov ecx, PAGE_TABLE_SIZE - mov edi, (BootPageTable + 0x1000) - mov eax, (BootPageTable + 0x2000) - or eax, 0x3 - mov ebx, 0x0 + 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 - mov dword [edi + 4], ebx - add eax, 1 << 12 - adc ebx, 0 - add edi, 8 - loop .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 ecx, (512 * PAGE_TABLE_SIZE) - mov edi, (BootPageTable + 0x2000) - mov eax, 0x0 | 0x3 | 1 << 7 - mov ebx, 0x0 + mov edi, (BootPageTable + 0x2000) ; First PDE + mov eax, 11b | 10000000b ; 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 - mov dword [edi + 4], ebx - add eax, 1 << 21 - adc ebx, 0 - add edi, 8 - loop .FillPageTableLevel2 - - ret - -[bits 64] -section .bootstrap.text -global UpdatePageTable64 -UpdatePageTable64: - mov rdi, (BootPageTable + 0x0000) - - mov rax, (BootPageTable + 0x1000) - or rax, 0x3 - mov [rdi], rax - - mov rcx, PAGE_TABLE_SIZE - mov rdi, (BootPageTable + 0x1000) - mov rax, (BootPageTable + 0x2000) - or rax, 0x3 - mov rbx, 0x0 - - .FillPageTableLevel3: - mov [rdi], rax - mov [rdi + 4], rbx - add rax, 1 << 12 - adc rbx, 0 - add rdi, 8 - loop .FillPageTableLevel3 - - mov rcx, (512 * PAGE_TABLE_SIZE) - mov rdi, (BootPageTable + 0x2000) - mov rax, 0x0 | 0x3 | 1 << 7 - mov rbx, 0x0 - - .FillPageTableLevel2: - mov [rdi], rax - mov [rdi + 4], rbx - add rax, 1 << 21 - adc rbx, 0 - add rdi, 8 - loop .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/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index 968072ea..1dca2f74 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -71,8 +71,8 @@ NIF void MapFromZero(PageTable4 *PT, BootInfo *Info) for (size_t t = 0; t < MemSize; t += PAGE_SIZE) { va.Map((void *)t, (void *)t, PTFlag::RW /* | PTFlag::US */); - va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */); - VirtualOffsetNormalVMA += PAGE_SIZE; + // va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */); + // VirtualOffsetNormalVMA += PAGE_SIZE; } } else diff --git a/include/boot/binfo.h b/include/boot/binfo.h index 944b7f03..01947c7e 100644 --- a/include/boot/binfo.h +++ b/include/boot/binfo.h @@ -3,7 +3,7 @@ enum MemoryType { - Unknown, + Unknown_Memory_Type, Usable, Reserved, ACPIReclaimable, @@ -11,7 +11,16 @@ enum MemoryType BadMemory, BootloaderReclaimable, KernelAndModules, - Framebuffer + Framebuffer, + Unknown +}; + +enum FramebufferType +{ + Unknown_Framebuffer_Type, + Indexed, + RGB, + EGA }; #define MAX_FRAMEBUFFERS 16 @@ -22,6 +31,7 @@ struct BootInfo { struct FramebufferInfo { + enum FramebufferType Type; void *BaseAddress; __UINT64_TYPE__ Width; __UINT64_TYPE__ Height; From fea5485958f6a4dae7d5c29db24a4a4292c96610 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 19 Apr 2023 04:17:11 +0300 Subject: [PATCH 6/7] todo MB2MemoryMapper.cpp --- .../amd64/Bootstrap/Multiboot2/Detection.asm | 4 ++-- .../amd64/Bootstrap/Multiboot2/Entry.asm | 10 +++++----- .../amd64/Bootstrap/Multiboot2/Header.asm | 18 ++++++++++++++++++ .../Bootstrap/Multiboot2/MB2MemoryMapper.cpp | 4 ++++ .../amd64/Bootstrap/Multiboot2/PageTable.asm | 4 ++-- Architecture/amd64/linker.ld | 2 +- Core/Memory/PhysicalMemoryManager.cpp | 6 +++++- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Architecture/amd64/Bootstrap/Multiboot2/Detection.asm b/Architecture/amd64/Bootstrap/Multiboot2/Detection.asm index ee6166a7..f0ba7021 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/Detection.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/Detection.asm @@ -16,7 +16,7 @@ DetectCPUID: jz .NoCPUID ret .NoCPUID: - mov word [0xb8F00], 0xF00F ; . + ; mov word [0xb8F00], 0xF00F ; . .Loop: cli hlt @@ -34,7 +34,7 @@ Detect64Bit: jz .NoLongMode ret .NoLongMode: - mov word [0xb8F00], 0xF00A ; . + ; mov word [0xb8F00], 0xF00A ; . .Loop: cli hlt diff --git a/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm b/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm index 6c7c0d95..7a169234 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/Entry.asm @@ -29,7 +29,7 @@ MB2_HeaderInfo: section .bootstrap.text MB2_start: cli - mov word [0xb8F00], 0x072E ; . + ; mov word [0xb8F00], 0x072E ; . mov [MB2_HeaderMagic], eax mov [MB2_HeaderInfo], ebx @@ -37,7 +37,7 @@ MB2_start: call DetectCPUID call Detect64Bit - mov word [0xb8F02], 0x072E ; . + ; mov word [0xb8F02], 0x072E ; . mov ecx, cr0 and ecx, 0x7fffffff ; Clear PG @@ -56,7 +56,7 @@ MB2_start: mov edi, BootPageTable mov cr3, edi - mov word [0xb8F04], 0x072E ; . + ; mov word [0xb8F04], 0x072E ; . ; Enable long mode mov ecx, 0xC0000080 ; EFER @@ -84,7 +84,7 @@ MB2_start: [bits 64] HigherHalfStart: cli - mov word [0xb8F06], 0x072E ; . + ; mov word [0xb8F06], 0x072E ; . call UpdatePageTable64 ; Load the new page table @@ -98,7 +98,7 @@ HigherHalfStart: mov gs, ax mov ss, ax - mov word [0xb8F08], 0x072E ; . + ; mov word [0xb8F08], 0x072E ; . mov rsp, (KernelStack + KERNEL_STACK_SIZE) mov rbp, (KernelStack + KERNEL_STACK_SIZE) diff --git a/Architecture/amd64/Bootstrap/Multiboot2/Header.asm b/Architecture/amd64/Bootstrap/Multiboot2/Header.asm index b05828df..844b61d7 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/Header.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/Header.asm @@ -1,3 +1,5 @@ +extern MB2_start + [bits 32] section .multiboot2 align 4096 @@ -34,6 +36,22 @@ MB2_INFO_REQUEST_TAG_START: dd 21 ; Load Base Address MB2_INFO_REQUEST_TAG_END: align 8 +MB2_ENTRY_TAG: + dw 3 + dw 0 + dd MB2_ENTRY_TAG_END - MB2_ENTRY_TAG + dd MB2_start +MB2_ENTRY_TAG_END: +align 8 +MB2_FRAMEBUFFER_TAG_START: + dw 5 + dw 1 + dd MB2_FRAMEBUFFER_TAG_END - MB2_FRAMEBUFFER_TAG_START + dd 1280 ; Width + dd 720 ; Height + dd 32 ; Depth +MB2_FRAMEBUFFER_TAG_END: +align 8 MB2_TAG_START: dw 0 dw 0 diff --git a/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp b/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp index a128b496..fb3b16b0 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot2/MB2MemoryMapper.cpp @@ -259,6 +259,10 @@ __always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *Phy EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64() { + /* + TODO: this code corrupts the page table + */ + BPTable = (PageTable4 *)BootPageTable; // for (size_t i = 0; i < 0x10000000; i += 0x1000) diff --git a/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm b/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm index eba5546c..11982e26 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm +++ b/Architecture/amd64/Bootstrap/Multiboot2/PageTable.asm @@ -1,7 +1,7 @@ -PAGE_TABLE_SIZE equ 0x4 ; 1GB +PAGE_TABLE_SIZE equ 0x8 ; 2GB [bits 32] -section .bootstrap.data +section .bootstrap.bss align 0x1000 global BootPageTable BootPageTable: diff --git a/Architecture/amd64/linker.ld b/Architecture/amd64/linker.ld index 96e0e549..9a938bae 100644 --- a/Architecture/amd64/linker.ld +++ b/Architecture/amd64/linker.ld @@ -4,7 +4,7 @@ OUTPUT_ARCH(i386:x86-64) KERNEL_LMA = 16M; KERNEL_VMA = 0xFFFFFFFF80000000; -ENTRY(MB2_start) +ENTRY(_start) SECTIONS { diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index 0da3ab13..21424d73 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -7,6 +7,8 @@ #include "../../kernel.h" +extern "C" char BootPageTable[]; // 0x10000 in length + namespace Memory { uint64_t Physical::GetTotalMemory() @@ -371,8 +373,10 @@ namespace Memory for (uint64_t i = 0; i < Info->Memory.Entries; i++) if (Info->Memory.Entry[i].Type != Usable) this->ReservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1); - trace("Locking bitmap pages..."); + this->ReservePages(0, 0x100); + this->ReservePages(BootPageTable, TO_PAGES(0x10000)); + trace("Locking bitmap pages..."); this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1); } From 1a3bdbb843500339a4e2a23addaf46ed5b5c9d2d Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 29 Apr 2023 07:02:57 +0300 Subject: [PATCH 7/7] Display &elf->sections too --- Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp b/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp index f7748b97..08f4cf64 100644 --- a/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot2/Multiboot2.cpp @@ -244,8 +244,8 @@ EXTERNC void Multiboot2Entry() 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); + fixme("elf_sections->[sections=%#lx num=%d, size=%d, entsize=%d, shndx=%d]", + &elf->sections, elf->num, elf->size, elf->entsize, elf->shndx); break; } case MULTIBOOT_TAG_TYPE_APM: