209 lines
7.2 KiB
C
209 lines
7.2 KiB
C
/// @file multiboot.c
|
|
/// @brief
|
|
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
|
/// See LICENSE.md for details.
|
|
|
|
// Include the kernel log levels.
|
|
#include "sys/kernel_levels.h"
|
|
/// Change the header.
|
|
#define __DEBUG_HEADER__ "[BOOT ]"
|
|
/// Set the log level.
|
|
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE
|
|
|
|
#include "multiboot.h"
|
|
#include "kernel.h"
|
|
#include "sys/bitops.h"
|
|
#include "stddef.h"
|
|
#include "io/debug.h"
|
|
#include "system/panic.h"
|
|
#include "stddef.h"
|
|
|
|
|
|
multiboot_memory_map_t *mmap_first_entry(multiboot_info_t *info)
|
|
{
|
|
if (!bitmask_check(info->flags, MULTIBOOT_FLAG_MMAP))
|
|
return NULL;
|
|
return (multiboot_memory_map_t *)((uintptr_t)info->mmap_addr);
|
|
}
|
|
|
|
multiboot_memory_map_t *mmap_first_entry_of_type(multiboot_info_t *info,
|
|
uint32_t type)
|
|
{
|
|
multiboot_memory_map_t *entry = mmap_first_entry(info);
|
|
if (entry && (entry->type == type))
|
|
return entry;
|
|
return mmap_next_entry_of_type(info, entry, type);
|
|
}
|
|
|
|
multiboot_memory_map_t *mmap_next_entry(multiboot_info_t *info,
|
|
multiboot_memory_map_t *entry)
|
|
{
|
|
uintptr_t next = ((uintptr_t)entry) + entry->size + sizeof(entry->size);
|
|
if (next >= (info->mmap_addr + info->mmap_length))
|
|
return NULL;
|
|
return (multiboot_memory_map_t *)next;
|
|
}
|
|
|
|
multiboot_memory_map_t *mmap_next_entry_of_type(multiboot_info_t *info,
|
|
multiboot_memory_map_t *entry,
|
|
uint32_t type)
|
|
{
|
|
do {
|
|
entry = mmap_next_entry(info, entry);
|
|
} while (entry && entry->type != type);
|
|
return entry;
|
|
}
|
|
|
|
char *mmap_type_name(multiboot_memory_map_t *entry)
|
|
{
|
|
if (entry->type == MULTIBOOT_MEMORY_AVAILABLE)
|
|
return "AVAILABLE";
|
|
if (entry->type == MULTIBOOT_MEMORY_RESERVED)
|
|
return "RESERVED";
|
|
return "NONE";
|
|
}
|
|
|
|
multiboot_module_t *first_module(multiboot_info_t *info)
|
|
{
|
|
if (!bitmask_check(info->flags, MULTIBOOT_FLAG_MODS))
|
|
return NULL;
|
|
if (!info->mods_count)
|
|
return NULL;
|
|
return (multiboot_module_t *)(uintptr_t)info->mods_addr;
|
|
}
|
|
|
|
multiboot_module_t *next_module(multiboot_info_t *info,
|
|
multiboot_module_t *mod)
|
|
{
|
|
multiboot_module_t *first = (multiboot_module_t *)((uintptr_t)info->mods_addr);
|
|
++mod;
|
|
if ((mod - first) >= info->mods_count)
|
|
return NULL;
|
|
return mod;
|
|
}
|
|
|
|
void dump_multiboot(multiboot_info_t *mbi)
|
|
{
|
|
pr_debug("\n--------------------------------------------------\n");
|
|
pr_debug("MULTIBOOT header at 0x%x:\n", mbi);
|
|
|
|
// Print out the flags.
|
|
pr_debug("%-16s = 0x%x\n", "flags", mbi->flags);
|
|
|
|
// Are mem_* valid?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_MEM)) {
|
|
pr_debug("%-16s = %u Kb (%u Mb)\n", "mem_lower", mbi->mem_lower,
|
|
mbi->mem_lower / K);
|
|
pr_debug("%-16s = %u Kb (%u Mb)\n", "mem_upper", mbi->mem_upper,
|
|
mbi->mem_upper / K);
|
|
pr_debug("%-16s = %u Kb (%u Mb)\n", "total",
|
|
mbi->mem_lower + mbi->mem_upper,
|
|
(mbi->mem_lower + mbi->mem_upper) / K);
|
|
}
|
|
|
|
// Is boot_device valid?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_DEVICE)) {
|
|
pr_debug("%-16s = 0x%x (0x%x)", "boot_device", mbi->boot_device);
|
|
switch ((mbi->boot_device) & 0xFF000000) {
|
|
case 0x00000000:
|
|
pr_debug("(floppy)\n");
|
|
break;
|
|
case 0x80000000:
|
|
pr_debug("(disk)\n");
|
|
break;
|
|
default:
|
|
pr_debug("(unknown)\n");
|
|
}
|
|
}
|
|
|
|
// Is the command line passed?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_CMDLINE)) {
|
|
pr_debug("%-16s = %s\n", "cmdline", (char *)mbi->cmdline);
|
|
}
|
|
|
|
// Are mods_* valid?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_MODS)) {
|
|
pr_debug("%-16s = %d\n", "mods_count", mbi->mods_count);
|
|
pr_debug("%-16s = 0x%x\n", "mods_addr", mbi->mods_addr);
|
|
multiboot_module_t *mod = first_module(mbi);
|
|
for (int i = 0; mod; ++i, mod = next_module(mbi, mod)) {
|
|
pr_debug(" [%2d] "
|
|
"mod_start = 0x%x, "
|
|
"mod_end = 0x%x, "
|
|
"cmdline = %s\n",
|
|
i, mod->mod_start, mod->mod_end, (char *)mod->cmdline);
|
|
}
|
|
}
|
|
// Bits 4 and 5 are mutually exclusive!
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_AOUT) &&
|
|
bitmask_check(mbi->flags, MULTIBOOT_FLAG_ELF)) {
|
|
kernel_panic("Both bits 4 and 5 are set.\n");
|
|
return;
|
|
}
|
|
|
|
// Is the symbol table of a.out valid?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_AOUT)) {
|
|
multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
|
|
pr_debug("multiboot_aout_symbol_table: tabsize = 0x%0x, "
|
|
"strsize = 0x%x, addr = 0x%x\n",
|
|
multiboot_aout_sym->tabsize, multiboot_aout_sym->strsize,
|
|
multiboot_aout_sym->addr);
|
|
}
|
|
|
|
// Is the section header table of ELF valid?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_ELF)) {
|
|
multiboot_elf_section_header_table_t *multiboot_elf_sec =
|
|
&(mbi->u.elf_sec);
|
|
pr_debug("multiboot_elf_sec: num = %u, size = 0x%x,"
|
|
" addr = 0x%x, shndx = 0x%x\n",
|
|
multiboot_elf_sec->num, multiboot_elf_sec->size,
|
|
multiboot_elf_sec->addr, multiboot_elf_sec->shndx);
|
|
}
|
|
|
|
// Are mmap_* valid?
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_MMAP)) {
|
|
pr_debug("%-16s = 0x%x\n", "mmap_addr", mbi->mmap_addr);
|
|
pr_debug("%-16s = 0x%x (%d entries)\n", "mmap_length",
|
|
mbi->mmap_length,
|
|
mbi->mmap_length / sizeof(multiboot_memory_map_t));
|
|
multiboot_memory_map_t *mmap = mmap_first_entry(mbi);
|
|
for (int i = 0; mmap; ++i, mmap = mmap_next_entry(mbi, mmap)) {
|
|
pr_debug(" [%2d] "
|
|
"base_addr = 0x%09x%09x, "
|
|
"length = 0x%09x%09x, "
|
|
"type = 0x%x (%s)\n",
|
|
i, mmap->base_addr_high, mmap->base_addr_low,
|
|
mmap->length_high, mmap->length_low, mmap->type,
|
|
mmap_type_name(mmap));
|
|
}
|
|
}
|
|
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_DRIVE_INFO)) {
|
|
pr_debug("Drives: 0x%x\n", mbi->drives_length);
|
|
pr_debug("Addr : 0x%x\n", mbi->drives_addr);
|
|
}
|
|
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_CONFIG_TABLE)) {
|
|
pr_debug("Config: 0x%x\n", mbi->config_table);
|
|
}
|
|
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_BOOT_LOADER_NAME)) {
|
|
pr_debug("boot_loader_name: %s\n", (char *)mbi->boot_loader_name);
|
|
}
|
|
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_APM_TABLE)) {
|
|
pr_debug("APM : 0x%x\n", mbi->apm_table);
|
|
}
|
|
|
|
if (bitmask_check(mbi->flags, MULTIBOOT_FLAG_VBE_INFO)) {
|
|
pr_debug("VBE Co: 0x%x\n", mbi->vbe_control_info);
|
|
pr_debug("VBE Mo: 0x%x\n", mbi->vbe_mode_info);
|
|
pr_debug("VBE In: 0x%x\n", mbi->vbe_mode);
|
|
pr_debug("VBE se: 0x%x\n", mbi->vbe_interface_seg);
|
|
pr_debug("VBE of: 0x%x\n", mbi->vbe_interface_off);
|
|
pr_debug("VBE le: 0x%x\n", mbi->vbe_interface_len);
|
|
}
|
|
pr_debug("--------------------------------------------------\n");
|
|
pr_debug("\n");
|
|
}
|