Merge remote-tracking branch 'Kernel/master'

This commit is contained in:
EnderIce2
2024-11-20 05:00:33 +02:00
468 changed files with 112800 additions and 1 deletions

View File

@ -0,0 +1,51 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.code32
KERNEL_VIRTUAL_BASE = 0xC0000000 /* 3GB */
KERNEL_PAGE_NUMBER = 768 /* KERNEL_VIRTUAL_BASE >> 22 */
.section .bootstrap.data, "a"
.align 0x1000
.global BootPageTable
BootPageTable:
.long 0x00000083
.long 0x00400083
.long 0x00800083
.long 0x00C00083
.long 0x01000083
.long 0x01400083
.long 0x01800083
.long 0x01C00083
.long 0x02000083
.long 0x02400083
.rept (KERNEL_PAGE_NUMBER - 10)
.long 0
.endr
.long 0x00000083
.long 0x00400083
.long 0x00800083
.long 0x00C00083
.long 0x01000083
.long 0x01400083
.long 0x01800083
.long 0x01C00083
.long 0x02000083
.long 0x02400083
.rept (1024 - KERNEL_PAGE_NUMBER - 10)
.long 0
.endr

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.code32
.extern Multiboot_start
.section .bootstrap.text, "a"
.global _start
_start:
/* Check for multiboot */
cmp $0x2BADB002, %eax
je .Multiboot
/* Unkown bootloader */
.Hang:
cli
hlt
jmp .Hang
/* Multiboot */
.Multiboot:
call Multiboot_start
jmp .Hang

View File

@ -0,0 +1,27 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.intel_syntax noprefix
.code32
.section .multiboot, "a"
.align 4
MULTIBOOT_HEADER:
.long 0x1BADB002
.long 1 << 0 | 1 << 1
.long -(0x1BADB002 + (1 << 0 | 1 << 1))

View File

@ -0,0 +1,93 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.intel_syntax noprefix
.code32
.extern Multiboot_start
/* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */
.section .multiboot2, "a"
.align 0x1000
MULTIBOOT2_HEADER_START:
.long 0xE85250D6
.long 0
.long (MULTIBOOT2_HEADER_END - MULTIBOOT2_HEADER_START)
.long 0x100000000 - (MULTIBOOT2_HEADER_END - MULTIBOOT2_HEADER_START) - 0 - 0xE85250D6
.align 8
InfoRequestTag_Start:
.word 1
.word 0
.long InfoRequestTag_End - InfoRequestTag_Start
.long 1 /* Command Line */
.long 2 /* Boot Loader Name */
.long 3 /* Module */
.long 4 /* Basic Memory Information */
.long 5 /* BIOS Boot Device */
.long 6 /* Memory Map */
.long 7 /* VBE */
.long 8 /* Framebuffer */
.long 9 /* ELF Sections */
.long 10 /* APM Table */
.long 11 /* EFI 32-bit System Table Pointer */
.long 12 /* EFI 64-bit System Table Pointer */
/* .long 13 */ /* SMBIOS */
.long 14 /* ACPI Old */
.long 15 /* ACPI New */
.long 16 /* Network */
.long 17 /* EFI Memory Map */
.long 18 /* EFI Boot Services Notifier */
.long 19 /* EFI 32-bit Image Handle Pointer */
.long 20 /* EFI 64-bit Image Handle Pointer */
.long 21 /* Load Base Address */
InfoRequestTag_End:
.align 8
FramebufferTag_Start:
.word 5
.word 1
.long FramebufferTag_End - FramebufferTag_Start
.long 0
.long 0
.long 32
FramebufferTag_End:
.align 8
EGATextSupportTag_Start:
.word 4
.word 0
.long EGATextSupportTag_End - EGATextSupportTag_Start
.long 0 /* https://www.gnu.org/software/grub/manual/multiboot2/html_node/Console-header-tags.html */
EGATextSupportTag_End:
.align 8
AlignedModulesTag_Start:
.word 6
.word 0
.long AlignedModulesTag_End - AlignedModulesTag_Start
AlignedModulesTag_End:
.align 8
EntryAddressTag_Start:
.word 3
.word 0
.long EntryAddressTag_End - EntryAddressTag_Start
.long Multiboot_start
EntryAddressTag_End:
.align 8
EndTag_Start:
.word 0
.word 0
.long EndTag_End - EndTag_Start
EndTag_End:
MULTIBOOT2_HEADER_END:

View File

@ -0,0 +1,81 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.intel_syntax noprefix
.code32
.section .bootstrap.text, "a"
.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
mov eax, 1
ret
.NoCPUID:
xor eax, eax
ret
.global Detect64Bit
Detect64Bit:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb .NoLongMode
mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz .NoLongMode
mov eax, 1
ret
.NoLongMode:
xor eax, eax
ret
.global DetectPSE
DetectPSE:
mov eax, 0x00000001
cpuid
test edx, 0x00000008
jz .NoPSE
mov eax, 1
ret
.NoPSE:
xor eax, eax
ret
.global DetectPAE
DetectPAE:
mov eax, 0x00000001
cpuid
test edx, 0x00000040
jz .NoPAE
mov eax, 1
ret
.NoPAE:
xor eax, eax
ret

View File

@ -0,0 +1,64 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.code32
.section .bootstrap.text, "a"
.align 32
.global gdtr
gdtr:
.word GDT32_END - GDT32 - 1
.long GDT32
.align 32
GDT32:
.quad 0x0
.word 0xFFFF
.word 0x0000
.byte 0x00
.word 0xCF9A
.byte 0x00
.word 0xFFFF
.word 0x0000
.byte 0x00
.word 0xCF92
.byte 0x00
.word 0x0100
.word 0x1000
.byte 0x00
.word 0x4092
.byte 0x00
GDT32_END:
nop
.global LoadGDT32
LoadGDT32:
lgdt [gdtr]
ljmp $0x8, $ActivateGDT
ActivateGDT:
mov $0x10, %cx
mov %cx, %ss
mov %cx, %ds
mov %cx, %es
mov %cx, %fs
mov $0x18, %cx
mov %cx, %gs
ret

View File

@ -0,0 +1,210 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <types.h>
#include <boot/protocol/multiboot.h>
#include <memory.hpp>
#include "../../../../kernel.h"
void multiboot_parse(BootInfo &mb2binfo, uintptr_t Magic, uintptr_t Info)
{
multiboot_info *InfoAddress = r_cst(multiboot_info *, Info);
if (InfoAddress->flags & MULTIBOOT_INFO_MEMORY)
{
fixme("mem_lower: %#x, mem_upper: %#x",
InfoAddress->mem_lower, InfoAddress->mem_upper);
}
if (InfoAddress->flags & MULTIBOOT_INFO_BOOTDEV)
{
fixme("boot_device: %#x",
InfoAddress->boot_device);
}
if (InfoAddress->flags & MULTIBOOT_INFO_CMDLINE)
{
strncpy(mb2binfo.Kernel.CommandLine,
r_cst(const char *, InfoAddress->cmdline),
strlen(r_cst(const char *, InfoAddress->cmdline)));
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
}
if (InfoAddress->flags & MULTIBOOT_INFO_MODS)
{
multiboot_mod_list *module = r_cst(multiboot_mod_list *, InfoAddress->mods_addr);
for (size_t i = 0; i < InfoAddress->mods_count; i++)
{
if (i > MAX_MODULES)
{
warn("Too many modules, skipping the rest...");
break;
}
mb2binfo.Modules[i].Address = (void *)(uint32_t)module[i].mod_start;
mb2binfo.Modules[i].Size = module[i].mod_end - module[i].mod_start;
strncpy(mb2binfo.Modules[i].Path, "(null)", 6);
strncpy(mb2binfo.Modules[i].CommandLine, r_cst(const char *, module[i].cmdline),
strlen(r_cst(const char *, module[i].cmdline)));
debug("Module: %s", mb2binfo.Modules[i].Path);
}
}
if (InfoAddress->flags & MULTIBOOT_INFO_AOUT_SYMS)
{
fixme("aout_sym: [tabsize: %#x, strsize: %#x, addr: %#x, reserved: %#x]",
InfoAddress->u.aout_sym.tabsize, InfoAddress->u.aout_sym.strsize,
InfoAddress->u.aout_sym.addr, InfoAddress->u.aout_sym.reserved);
}
if (InfoAddress->flags & MULTIBOOT_INFO_ELF_SHDR)
{
mb2binfo.Kernel.Symbols.Num = InfoAddress->u.elf_sec.num;
mb2binfo.Kernel.Symbols.EntSize = InfoAddress->u.elf_sec.size;
mb2binfo.Kernel.Symbols.Shndx = InfoAddress->u.elf_sec.shndx;
mb2binfo.Kernel.Symbols.Sections = s_cst(uintptr_t, InfoAddress->u.elf_sec.addr);
}
if (InfoAddress->flags & MULTIBOOT_INFO_MEM_MAP)
{
mb2binfo.Memory.Entries = InfoAddress->mmap_length / sizeof(multiboot_mmap_entry);
for (uint32_t i = 0; i < mb2binfo.Memory.Entries; i++)
{
if (i > MAX_MEMORY_ENTRIES)
{
warn("Too many memory entries, skipping the rest...");
break;
}
multiboot_mmap_entry entry = r_cst(multiboot_mmap_entry *, InfoAddress->mmap_addr)[i];
mb2binfo.Memory.Size += (__SIZE_TYPE__)entry.len;
switch (entry.type)
{
case MULTIBOOT_MEMORY_AVAILABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (__SIZE_TYPE__)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 = (__SIZE_TYPE__)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 = (__SIZE_TYPE__)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 = (__SIZE_TYPE__)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 = (__SIZE_TYPE__)entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory;
break;
default:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (__SIZE_TYPE__)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);
}
}
if (InfoAddress->flags & MULTIBOOT_INFO_DRIVE_INFO)
{
fixme("drives_length: %d, drives_addr: %#x",
InfoAddress->drives_length, InfoAddress->drives_addr);
}
if (InfoAddress->flags & MULTIBOOT_INFO_CONFIG_TABLE)
{
fixme("config_table: %#x",
InfoAddress->config_table);
}
if (InfoAddress->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME)
{
strncpy(mb2binfo.Bootloader.Name,
r_cst(const char *, InfoAddress->boot_loader_name),
strlen(r_cst(const char *, InfoAddress->boot_loader_name)));
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
}
if (InfoAddress->flags & MULTIBOOT_INFO_APM_TABLE)
{
fixme("apm_table: %#x",
InfoAddress->apm_table);
}
if (InfoAddress->flags & MULTIBOOT_INFO_VBE_INFO)
{
fixme("vbe_control_info: %#x, vbe_mode_info: %#x, vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x",
InfoAddress->vbe_control_info, InfoAddress->vbe_mode_info,
InfoAddress->vbe_mode, InfoAddress->vbe_interface_seg,
InfoAddress->vbe_interface_off, InfoAddress->vbe_interface_len);
}
if (InfoAddress->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO)
{
static int fb_count = 0;
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)InfoAddress->framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Width = InfoAddress->framebuffer_width;
mb2binfo.Framebuffer[fb_count].Height = InfoAddress->framebuffer_height;
mb2binfo.Framebuffer[fb_count].Pitch = InfoAddress->framebuffer_pitch;
mb2binfo.Framebuffer[fb_count].BitsPerPixel = InfoAddress->framebuffer_bpp;
switch (InfoAddress->framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{
mb2binfo.Framebuffer[fb_count].Type = Indexed;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{
mb2binfo.Framebuffer[fb_count].Type = RGB;
mb2binfo.Framebuffer[fb_count].RedMaskSize = InfoAddress->framebuffer_red_mask_size;
mb2binfo.Framebuffer[fb_count].RedMaskShift = InfoAddress->framebuffer_red_field_position;
mb2binfo.Framebuffer[fb_count].GreenMaskSize = InfoAddress->framebuffer_green_mask_size;
mb2binfo.Framebuffer[fb_count].GreenMaskShift = InfoAddress->framebuffer_green_field_position;
mb2binfo.Framebuffer[fb_count].BlueMaskSize = InfoAddress->framebuffer_blue_mask_size;
mb2binfo.Framebuffer[fb_count].BlueMaskShift = InfoAddress->framebuffer_blue_field_position;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{
mb2binfo.Framebuffer[fb_count].Type = EGA;
break;
}
default:
{
mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type;
break;
}
}
debug("Framebuffer %d: %dx%d %d bpp",
fb_count, InfoAddress->framebuffer_width,
InfoAddress->framebuffer_height,
InfoAddress->framebuffer_bpp);
debug("More info:\nAddress: %p\nPitch: %d\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d",
InfoAddress->framebuffer_addr, InfoAddress->framebuffer_pitch, InfoAddress->framebuffer_type,
InfoAddress->framebuffer_red_mask_size, InfoAddress->framebuffer_red_field_position, InfoAddress->framebuffer_green_mask_size,
InfoAddress->framebuffer_green_field_position, InfoAddress->framebuffer_blue_mask_size, InfoAddress->framebuffer_blue_field_position);
}
mb2binfo.Kernel.PhysicalBase = (void *)&_bootstrap_start;
mb2binfo.Kernel.VirtualBase = (void *)(uint32_t)((uint32_t)&_bootstrap_start + 0xC0000000);
mb2binfo.Kernel.Size = ((uint32_t)&_kernel_end - (uint32_t)&_kernel_start) + ((uint32_t)&_bootstrap_end - (uint32_t)&_bootstrap_start);
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
Entry(&mb2binfo);
}

View File

@ -0,0 +1,300 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <types.h>
#include <memory.hpp>
#include <boot/protocol/multiboot2.h>
#include "../../../../kernel.h"
void multiboot2_parse(BootInfo &mb2binfo, uintptr_t Magic, uintptr_t Info)
{
if (Info == NULL || Magic == NULL)
{
if (Magic == NULL)
error("Multiboot magic is NULL");
if (Info == NULL)
error("Multiboot info is NULL");
CPU::Stop();
}
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
CPU::Stop();
}
{
auto InfoAddress = Info;
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8);
;
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
{
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
{
debug("End of multiboot2 tags");
break;
}
switch (Tag->type)
{
case MULTIBOOT_TAG_TYPE_CMDLINE:
{
strncpy(mb2binfo.Kernel.CommandLine,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
break;
}
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
{
strncpy(mb2binfo.Bootloader.Name,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
break;
}
case MULTIBOOT_TAG_TYPE_MODULE:
{
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
static int module_count = 0;
mb2binfo.Modules[module_count].Address = (void *)(uint32_t)module->mod_start;
mb2binfo.Modules[module_count].Size = module->mod_end - module->mod_start;
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++)
{
if (i > MAX_MEMORY_ENTRIES)
{
warn("Too many memory entries, skipping the rest...");
break;
}
multiboot_mmap_entry entry = mmap->entries[i];
mb2binfo.Memory.Size += (size_t)entry.len;
switch (entry.type)
{
case MULTIBOOT_MEMORY_AVAILABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)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 = (size_t)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 = (size_t)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 = (size_t)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 = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory;
break;
default:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = Unknown;
break;
}
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
mb2binfo.Memory.Entry[i].BaseAddress,
mb2binfo.Memory.Entry[i].Length,
mb2binfo.Memory.Entry[i].Type);
}
break;
}
case MULTIBOOT_TAG_TYPE_VBE:
{
multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag;
fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]",
vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len);
break;
}
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
{
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
static int fb_count = 0;
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
switch (fb->common.framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{
mb2binfo.Framebuffer[fb_count].Type = Indexed;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{
mb2binfo.Framebuffer[fb_count].Type = RGB;
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{
mb2binfo.Framebuffer[fb_count].Type = EGA;
break;
}
default:
{
mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_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: %d\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;
mb2binfo.Kernel.Symbols.Num = elf->num;
mb2binfo.Kernel.Symbols.EntSize = elf->entsize;
mb2binfo.Kernel.Symbols.Shndx = elf->shndx;
mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections;
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 *)(uint32_t)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(uint32_t)(load_base_addr->load_base_addr + 0xC0000000);
mb2binfo.Kernel.Size = (size_t)(((uint32_t)&_kernel_end - (uint32_t)&_kernel_start) + ((uint32_t)&_bootstrap_end - (uint32_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;
}
}
}
}
Entry(&mb2binfo);
}

View File

@ -0,0 +1,53 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <types.h>
#include <memory.hpp>
#include "../../../../kernel.h"
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
void multiboot_parse(BootInfo &mb2binfo, uintptr_t Magic, uintptr_t Info);
void multiboot2_parse(BootInfo &mb2binfo, uintptr_t Magic, uintptr_t Info);
EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info)
{
BootInfo mb2binfo{};
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 == MULTIBOOT_BOOTLOADER_MAGIC)
multiboot_parse(mb2binfo, Magic, Info);
else if (Magic == MULTIBOOT2_BOOTLOADER_MAGIC)
multiboot2_parse(mb2binfo, Magic, Info);
else
{
error("Unknown multiboot magic %#x", Magic);
CPU::Stop();
}
}

View File

@ -0,0 +1,79 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.code32
KERNEL_STACK_SIZE = 0x4000 /* 16KB */
.extern DetectCPUID
.extern DetectPSE
.extern multiboot_main
.extern LoadGDT32
.extern BootPageTable
.section .bootstrap.data, "a"
MB_HeaderMagic:
.quad 0
MB_HeaderInfo:
.quad 0
.section .bootstrap.text, "a"
.global Multiboot_start
Multiboot_start:
cli
mov %eax, [MB_HeaderMagic]
mov %ebx, [MB_HeaderInfo]
call DetectCPUID
cmp $0, %eax
je .
call DetectPSE
cmp $0, %eax
je .
mov %cr4, %ecx
or $0x00000010, %ecx /* PSE */
mov %ecx, %cr4
call LoadGDT32
mov $BootPageTable, %ecx
mov %ecx, %cr3
mov %cr0, %ecx
or $0x80000000, %ecx /* PG */
mov %ecx, %cr0
mov $(KernelStack + KERNEL_STACK_SIZE), %esp
mov $0x0, %ebp
mov [MB_HeaderMagic], %eax
mov [MB_HeaderInfo], %ebx
push %ebx
push %eax
call multiboot_main
.Hang:
hlt
jmp .Hang
.section .bootstrap.bss, "a"
.align 16
KernelStack:
.space KERNEL_STACK_SIZE