mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
Kernel is now able to boot from mb2
This commit is contained in:
parent
c4798a69b1
commit
7811c21971
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <uart.hpp>
|
||||
#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() {}
|
||||
|
@ -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' &&
|
||||
|
22
Kernel.cpp
22
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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user