Improve multiboot info

This commit is contained in:
Enrico Fraccaroli
2019-05-16 16:19:26 +02:00
parent 552e2a073f
commit 25ffb602ea
4 changed files with 225 additions and 103 deletions
+22 -14
View File
@@ -7,20 +7,26 @@
[BITS 32] ; All instructions should be 32-bit.
[EXTERN kmain] ; The start point of our C code
; Grub is informed with this flag to load
; the kernel and kernel modules on a page boundary.
MBOOT_PAGE_ALIGN equ 1<<0
; Grub is informed with this flag to provide the kernel
; with memory information.
MBOOT_MEM_INFO equ 1<<1
; This is the multiboot magic value.
MBOOT_HEADER_MAGIC equ 0x1BADB002
; The magic field should contain this.
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
; This should be in %eax.
MULTIBOOT_BOOTLOADER_MAGIC equ 0x2BADB002
; = Specify what GRUB should PROVIDE =========================================
; Align the kernel and kernel modules on i386 page (4KB) boundaries.
MULTIBOOT_PAGE_ALIGN equ 0x00000001
; Provide the kernel with memory information.
MULTIBOOT_MEMORY_INFO equ 0x00000002
; Must pass video information to OS.
MULTIBOOT_VIDEO_MODE equ 0x00000004
; -----------------------------------------------------------------------------
; This is the flag combination that we prepare for Grub
; to read at kernel load time.
MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO
MULTIBOOT_HEADER_FLAGS equ (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_VIDEO_MODE)
; Grub reads this value to make sure it loads a kernel
; and not just garbage.
MBOOT_CHECKSUM equ - (MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
LOAD_MEMORY_ADDRESS equ 0x00000000
; reserve (1024*1024) for the stack on a doubleword boundary
@@ -33,9 +39,12 @@ section .multiboot_header
align 4
; This is the GRUB Multiboot header.
multiboot_header:
dd MBOOT_HEADER_MAGIC
dd MBOOT_HEADER_FLAGS
dd MBOOT_CHECKSUM
; magic
dd MULTIBOOT_HEADER_MAGIC
; flags
dd MULTIBOOT_HEADER_FLAGS
; checksum
dd MULTIBOOT_CHECKSUM
; -----------------------------------------------------------------------------
; SECTION (data)
@@ -61,7 +70,6 @@ kernel_entry:
mov esp, stack_top
; pass the initial ESP
push esp
;mov ebp, esp
; pass Multiboot info structure
push ebx
; pass Multiboot magic number
-3
View File
@@ -21,9 +21,6 @@
/// The maximum number of modules.
#define MAX_MODULES 10
/// This should be in %eax.
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/// Our kernel now loads at 0xC0000000, so what low memory address such as
/// 0xb800 you used to access, should be LOAD_MEMORY_ADDRESS + 0xb800
#define LOAD_MEMORY_ADDRESS 0x00000000
+40 -32
View File
@@ -10,42 +10,45 @@
#include "stdint.h"
#define MULTIBOOT_FLAG_MEM 0x001
// The magic field should contain this.
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
// This should be in %eax.
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#define MULTIBOOT_FLAG_DEVICE 0x002
#define MULTIBOOT_FLAG_CMDLINE 0x004
#define MULTIBOOT_FLAG_MODS 0x008
#define MULTIBOOT_FLAG_AOUT 0x010
#define MULTIBOOT_FLAG_ELF 0x020
#define MULTIBOOT_FLAG_MMAP 0x040
#define MULTIBOOT_FLAG_CONFIG 0x080
#define MULTIBOOT_FLAG_LOADER 0x100
#define MULTIBOOT_FLAG_APM 0x200
#define MULTIBOOT_FLAG_VBE 0x400
/// Is there basic lower/upper memory information?
#define MULTIBOOT_FLAG_MEM 0x00000001U
/// is there a boot device set?
#define MULTIBOOT_FLAG_DEVICE 0x00000002U
/// is the command-line defined?
#define MULTIBOOT_FLAG_CMDLINE 0x00000004U
/// are there modules to do something with?
#define MULTIBOOT_FLAG_MODS 0x00000008U
/// is there a symbol table loaded?
#define MULTIBOOT_FLAG_AOUT 0x00000010U
/// is there an ELF section header table?
#define MULTIBOOT_FLAG_ELF 0x00000020U
/// is there a full memory map?
#define MULTIBOOT_FLAG_MMAP 0x00000040U
/// Is there drive info?
#define MULTIBOOT_FLAG_DRIVE_INFO 0x00000080U
/// Is there a config table?
#define MULTIBOOT_FLAG_CONFIG_TABLE 0x00000100U
/// Is there a boot loader name?
#define MULTIBOOT_FLAG_BOOT_LOADER_NAME 0x00000200U
/// Is there a APM table?
#define MULTIBOOT_FLAG_APM_TABLE 0x00000400U
/// Is there video information?
#define MULTIBOOT_FLAG_VBE_INFO 0x00000800U
#define MULTIBOOT_FLAG_FRAMEBUFFER_INFO 0x00001000U
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
// +-------------------+
@@ -109,7 +112,7 @@ typedef struct multiboot_elf_section_header_table {
} multiboot_elf_section_header_table_t;
// TODO: doxygen comment.
typedef struct multiboot_mod_list {
typedef struct multiboot_module {
// The memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive.
uint32_t mod_start;
uint32_t mod_end;
@@ -119,13 +122,18 @@ typedef struct multiboot_mod_list {
uint32_t pad;
} multiboot_module_t;
// TODO: doxygen comment.
typedef struct multiboot_mmap_entry {
typedef struct multiboot_memory_map {
uint32_t size;
uint64_t addr;
uint64_t len;
uint32_t base_addr_low, base_addr_high;
uint32_t length_low, length_high;
uint32_t type;
} __attribute__((packed)) multiboot_memory_map_t;
} multiboot_memory_map_t;
typedef struct multiboot_color {
uint8_t red;
uint8_t green;
uint8_t blue;
} multiboot_color_t;
// TODO: doxygen comment.
typedef struct multiboot_info {
+163 -54
View File
@@ -7,74 +7,183 @@
#include "multiboot.h"
#include "bitops.h"
#include "debug.h"
#include "panic.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
static inline multiboot_memory_map_t *first_mmap_entry(multiboot_info_t *info)
{
if (!has_flag(info->flags, MULTIBOOT_FLAG_MMAP))
return NULL;
return (multiboot_memory_map_t *)((uintptr_t)info->mmap_addr);
}
static inline multiboot_memory_map_t *
next_mmap_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;
}
static inline multiboot_memory_map_t *
next_mmap_entry_of_type(multiboot_info_t *info, multiboot_memory_map_t *entry,
uint32_t type)
{
do {
entry = next_mmap_entry(info, entry);
} while (entry && entry->type != type);
return entry;
}
static inline multiboot_memory_map_t *
first_mmap_entry_of_type(multiboot_info_t *info, uint32_t type)
{
multiboot_memory_map_t *entry = first_mmap_entry(info);
if (entry && (entry->type == type))
return entry;
return next_mmap_entry_of_type(info, entry, type);
}
static inline 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";
}
static inline multiboot_module_t *first_module(multiboot_info_t *info)
{
if (!has_flag(info->flags, MULTIBOOT_FLAG_MODS))
return NULL;
if (!info->mods_count)
return NULL;
return (multiboot_module_t *)(uintptr_t)info->mods_addr;
}
static inline 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)
{
dbg_print("\n--------------------------------------------------\n");
dbg_print("MULTIBOOT header at 0x%x:\n", mbi);
dbg_print("Flags : 0x%x\n", mbi->flags);
// Print out the flags.
dbg_print("flags = 0x%x\n", mbi->flags);
// Are mem_* valid?
if (has_flag(mbi->flags, MULTIBOOT_FLAG_MEM)) {
dbg_print("Mem Lo: 0x%x\n", mbi->mem_lower * K);
dbg_print("Mem Hi: 0x%x (%dMB)\n", mbi->mem_upper * K,
(mbi->mem_upper / 1024));
dbg_print("mem_lower = %u Kb (%u Mb), "
"mem_upper = %u Kb (%u Mb), "
"total = %u Kb (%u Mb)\n",
mbi->mem_lower, mbi->mem_lower / K, mbi->mem_upper,
mbi->mem_upper / K, mbi->mem_lower + mbi->mem_upper,
(mbi->mem_lower + mbi->mem_upper) / K);
}
// Is boot_device valid?
if (has_flag(mbi->flags, MULTIBOOT_FLAG_DEVICE)) {
dbg_print("Boot d: 0x%x\n", mbi->boot_device);
}
if (has_flag(mbi->flags, MULTIBOOT_FLAG_CMDLINE)) {
dbg_print("cmdlin: 0x%x (%s)\n", mbi->cmdline, (char *)mbi->cmdline);
}
if (has_flag(mbi->flags, MULTIBOOT_FLAG_MODS)) {
dbg_print("Mods : 0x%x\n", mbi->mods_count);
multiboot_module_t *mod = (multiboot_module_t *)mbi->mods_addr;
if (mbi->mods_count > 0) {
for (uint32_t i = 0; i < mbi->mods_count && i < MAX_MODULES;
i++, mod++) {
uint32_t start = mod->mod_start;
uint32_t end = mod->mod_end;
dbg_print("\tModule %d is at 0x%x:0x%x\n", i + 1, start, end);
}
/* Last implementation
for (uint32_t i = 0; i < mbi->mods_count; ++i)
{
// uint32_t start = *((uint32_t *) (mbi->mods_addr + 8 * i));
uint32_t start = mbi->mods_addr + 8 * i;
// uint32_t end = *((uint32_t *) (mbi->mods_addr + 8 * i + 4));
uint32_t end = mbi->mods_addr + 8 * i + 4;
dbg_print("\tModule %d is at 0x%x:0x%x\n", i + 1, start, end);
}
*/
dbg_print("boot_device = 0x%x (0x%x)", mbi->boot_device,
((mbi->boot_device) & 0xFF000000));
switch ((mbi->boot_device) & 0xFF000000) {
case 0x00000000:
dbg_print("(floppy)\n");
break;
case 0x80000000:
dbg_print("(disk)\n");
break;
default:
dbg_print("(unknown)\n");
}
}
// Is the command line passed?
if (has_flag(mbi->flags, MULTIBOOT_FLAG_CMDLINE)) {
dbg_print("cmdline: %s\n", (char *)mbi->cmdline);
}
// Are mods_* valid?
if (has_flag(mbi->flags, MULTIBOOT_FLAG_MODS)) {
dbg_print("mods_count = %d, mods_addr = 0x%x\n", (int)mbi->mods_count,
(int)mbi->mods_addr);
multiboot_module_t *mod = first_module(mbi);
for (int i = 0; mod; ++i, mod = next_module(mbi, mod)) {
dbg_print(" [%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 (has_flag(mbi->flags, MULTIBOOT_FLAG_AOUT) &&
has_flag(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 (has_flag(mbi->flags, MULTIBOOT_FLAG_AOUT)) {
dbg_print("AOUT t : 0x%x\n", mbi->u.aout_sym.tabsize);
dbg_print("AOUT s : 0x%x\n", mbi->u.aout_sym.strsize);
dbg_print("AOUT a : 0x%x\n", mbi->u.aout_sym.addr);
dbg_print("AOUT r : 0x%x\n", mbi->u.aout_sym.reserved);
multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
dbg_print("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 (has_flag(mbi->flags, MULTIBOOT_FLAG_ELF)) {
dbg_print("ELF n : 0x%x\n", mbi->u.elf_sec.num);
dbg_print("ELF s : 0x%x\n", mbi->u.elf_sec.size);
dbg_print("ELF a : 0x%x\n", mbi->u.elf_sec.addr);
dbg_print("ELF h : 0x%x\n", mbi->u.elf_sec.shndx);
multiboot_elf_section_header_table_t *multiboot_elf_sec =
&(mbi->u.elf_sec);
dbg_print("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 (has_flag(mbi->flags, MULTIBOOT_FLAG_MMAP)) {
dbg_print("mmap_addr = 0x%x, mmap_length = 0x%x\n", mbi->mmap_addr,
mbi->mmap_length);
multiboot_memory_map_t *mmap = first_mmap_entry(mbi);
for (int i = 0; mmap; ++i, mmap = next_mmap_entry(mbi, mmap)) {
dbg_print(" [%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 (has_flag(mbi->flags, MULTIBOOT_FLAG_DRIVE_INFO)) {
dbg_print("Drives: 0x%x\n", mbi->drives_length);
dbg_print("Addr : 0x%x\n", mbi->drives_addr);
}
if (has_flag(mbi->flags, MULTIBOOT_FLAG_CONFIG_TABLE)) {
dbg_print("Config: 0x%x\n", mbi->config_table);
}
if (has_flag(mbi->flags, MULTIBOOT_FLAG_BOOT_LOADER_NAME)) {
dbg_print("boot_loader_name: %s\n", (char *)mbi->boot_loader_name);
}
if (has_flag(mbi->flags, MULTIBOOT_FLAG_APM_TABLE)) {
dbg_print("APM : 0x%x\n", mbi->apm_table);
}
if (has_flag(mbi->flags, MULTIBOOT_FLAG_VBE_INFO)) {
dbg_print("VBE Co: 0x%x\n", mbi->vbe_control_info);
dbg_print("VBE Mo: 0x%x\n", mbi->vbe_mode_info);
dbg_print("VBE In: 0x%x\n", mbi->vbe_mode);
dbg_print("VBE se: 0x%x\n", mbi->vbe_interface_seg);
dbg_print("VBE of: 0x%x\n", mbi->vbe_interface_off);
dbg_print("VBE le: 0x%x\n", mbi->vbe_interface_len);
}
dbg_print("MMap : 0x%x\n", mbi->mmap_length);
dbg_print("Addr : 0x%x\n", mbi->mmap_addr);
dbg_print("Drives: 0x%x\n", mbi->drives_length);
dbg_print("Addr : 0x%x\n", mbi->drives_addr);
dbg_print("Config: 0x%x\n", mbi->config_table);
dbg_print("Loader: 0x%x (%s)\n", mbi->boot_loader_name,
(char *)mbi->boot_loader_name);
dbg_print("APM : 0x%x\n", mbi->apm_table);
dbg_print("VBE Co: 0x%x\n", mbi->vbe_control_info);
dbg_print("VBE Mo: 0x%x\n", mbi->vbe_mode_info);
dbg_print("VBE In: 0x%x\n", mbi->vbe_mode);
dbg_print("VBE se: 0x%x\n", mbi->vbe_interface_seg);
dbg_print("VBE of: 0x%x\n", mbi->vbe_interface_off);
dbg_print("VBE le: 0x%x\n", mbi->vbe_interface_len);
dbg_print("--------------------------------------------------\n");
dbg_print("\n");
}