diff --git a/mentos/boot.asm b/mentos/boot.asm index e5bc0de..0c26b1f 100644 --- a/mentos/boot.asm +++ b/mentos/boot.asm @@ -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 diff --git a/mentos/inc/kernel.h b/mentos/inc/kernel.h index 190b5ca..dd7c2f8 100644 --- a/mentos/inc/kernel.h +++ b/mentos/inc/kernel.h @@ -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 diff --git a/mentos/inc/multiboot.h b/mentos/inc/multiboot.h index 6a282d4..08450fa 100644 --- a/mentos/inc/multiboot.h +++ b/mentos/inc/multiboot.h @@ -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 { diff --git a/mentos/src/multiboot.c b/mentos/src/multiboot.c index 5fc60fa..daef81c 100644 --- a/mentos/src/multiboot.c +++ b/mentos/src/multiboot.c @@ -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"); }