Improve multiboot info
This commit is contained in:
+22
-14
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user