Index: loader/powerpc/ieee1275/multiboot.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ loader/powerpc/ieee1275/multiboot.c 2006-11-13 18:59:21.000000000 -0600 @@ -0,0 +1,54 @@ +/* multiboot.c - boot a multiboot OS image. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +typedef void (*kernel_entry_t) (unsigned long, void *, int (void *), + unsigned long, unsigned long); + +int grub_multiboot_arch_load32_hook (UNUSED Elf32_Phdr *phdr, + UNUSED grub_addr_t *addr) +{ + return 0; +} + +int grub_multiboot_arch_load64_hook (UNUSED Elf64_Phdr *phdr, + UNUSED grub_addr_t *addr) +{ + return 0; +} + +void +grub_multiboot_arch_boot (grub_addr_t entry_addr, void *tags) +{ + kernel_entry_t entry = (kernel_entry_t) entry_addr; + entry (GRUB_MB_MAGIC2, tags, grub_ieee1275_entry_fn, 0, 0); +} + +grub_err_t +grub_multiboot_tags_arch_create (int argc, char *argv[]) +{ + /* Nothing special. */ + return GRUB_ERR_NONE; +} Index: include/grub/multiboot.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ include/grub/multiboot.h 2006-11-13 18:57:24.000000000 -0600 @@ -0,0 +1,39 @@ +/* multiboot.h - multiboot header file. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_MULTIBOOT_HEADER +#define GRUB_MULTIBOOT_HEADER 1 + +#include +#include +#include + +grub_err_t grub_mb_tag_alloc (grub_addr_t *addr, int key, grub_size_t len); +grub_err_t grub_mb_tags_arch_create (int argc, char *argv[]); + +void grub_mb_arch_boot (grub_addr_t entry, void *tags); +int grub_mb_arch_load32_hook (Elf32_Phdr *phdr, grub_addr_t *addr); +int grub_mb_arch_load64_hook (Elf64_Phdr *phdr, grub_addr_t *addr); + +/* Provided by the core to modules. */ +void grub_rescue_cmd_multiboot (int argc, char *argv[]); +void grub_rescue_cmd_module (int argc, char *argv[]); + +#endif /* ! GRUB_MULTIBOOT_HEADER */ Index: loader/multiboot.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ loader/multiboot.c 2006-11-13 18:57:24.000000000 -0600 @@ -0,0 +1,466 @@ +/* multiboot.c - boot a multiboot OS image. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_dl_t my_mod; +static grub_addr_t entry; + +static char *grub_mb_tags; +static char *grub_mb_tags_pos; +static grub_size_t grub_mb_tags_len; +static int grub_mb_tags_count; + +static void +grub_mb_tags_free (void) +{ + grub_dprintf ("loader", "Freeing all tags...\n"); + grub_free (grub_mb_tags); + grub_mb_tags = 0; + grub_mb_tags_pos = 0; + grub_mb_tags_len = 0; + grub_mb_tags_count = 0; +} + +grub_err_t +grub_mb_tag_alloc (grub_addr_t *addr, int key, grub_size_t len) +{ + struct multiboot_tag_header *tag; + grub_size_t used; + grub_size_t needed; + + grub_dprintf ("loader", "Allocating tag: key 0x%x, size 0x%lx.\n", + key, (unsigned long) len); + + used = grub_mb_tags_pos - grub_mb_tags; + len = ALIGN_UP(len, sizeof (multiboot_word)); + + needed = used + len; + + if (needed > grub_mb_tags_len) + { + /* Allocate new buffer. */ + grub_size_t newsize = needed * 2; + char *newarea; + + grub_dprintf ("loader", "Reallocating tag buffer (new size 0x%lx).\n", + (unsigned long) newsize); + + newarea = grub_malloc (newsize); + if (! newarea) + return grub_errno; + grub_memcpy (newarea, grub_mb_tags, grub_mb_tags_len); + grub_free (grub_mb_tags); + + grub_mb_tags_len = newsize; + grub_mb_tags = newarea; + grub_mb_tags_pos = newarea + used; + } + + tag = (struct multiboot_tag_header *) grub_mb_tags_pos; + grub_mb_tags_pos += len; + + tag->key = key; + tag->len = len; + + if (addr) + *addr = (grub_addr_t) tag; + + grub_mb_tags_count++; + + grub_dprintf ("loader", "Allocated tag %u at %p.\n", grub_mb_tags_count, tag); + + return 0; +} + +static grub_err_t +grub_mb_tag_start_create (UNUSED int argc, UNUSED char *argv[]) +{ + return grub_mb_tag_alloc (0, MULTIBOOT_TAG_START, + sizeof (struct multiboot_tag_start)); +} + +static grub_err_t +grub_mb_tag_name_create (UNUSED int argc, UNUSED char *argv[]) +{ + struct multiboot_tag_name *name; + grub_addr_t name_addr; + grub_err_t err; + const char *grub_version = PACKAGE_STRING; + + err = grub_mb_tag_alloc (&name_addr, MULTIBOOT_TAG_NAME, + sizeof (struct multiboot_tag_name) + + sizeof (grub_version) + 1); + if (err) + return err; + + name = (struct multiboot_tag_name *) name_addr; + grub_strcpy(name->name, grub_version); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_mb_tag_cmdline_create (int argc, char *argv[]) +{ + grub_addr_t cmdline_addr; + char *p; + grub_size_t len = 0; + grub_err_t err; + int i; + + for (i = 0; i < argc; i++) + len += grub_strlen (argv[i]) + 1; + + err = grub_mb_tag_alloc (&cmdline_addr, MULTIBOOT_TAG_CMDLINE, + sizeof (struct multiboot_tag_header) + len); + if (err) + return err; + + p = ((struct multiboot_tag_cmdline *) cmdline_addr)->cmdline; + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *(p++) = ' '; + } + + /* Remove the space after the last word. */ + *(--p) = '\0'; + + return GRUB_ERR_NONE; +} + +typedef grub_err_t (*tag_create_t) (int argc, char *argv[]); +static tag_create_t grub_mb_tag_creators[] = { + grub_mb_tag_start_create, + grub_mb_tag_name_create, + grub_mb_tag_cmdline_create, + grub_mb_tags_arch_create, + 0, +}; + +static grub_err_t +grub_mb_tags_create (int argc, char *argv[]) +{ + tag_create_t *creator; + grub_err_t err; + + for (creator = grub_mb_tag_creators; *creator != 0; creator++) + { + err = (*creator) (argc, argv); + if (err) + goto error; + } + + return GRUB_ERR_NONE; + +error: + grub_error_push (); + grub_mb_tags_free (); + grub_error_pop (); + return err; +} + +static grub_err_t +grub_mb_tags_finish (void) +{ + struct multiboot_tag_start *start; + grub_err_t err; + + err = grub_mb_tag_alloc (0, MULTIBOOT_TAG_END, sizeof (struct multiboot_tag_end)); + if (err) + goto error; + + /* We created the `start' tag first. */ + start = (struct multiboot_tag_start *) grub_mb_tags; + start->num = grub_mb_tags_count; + start->size = grub_mb_tags_pos - grub_mb_tags; + return GRUB_ERR_NONE; + +error: + grub_error_push (); + grub_mb_tags_free (); + grub_error_pop (); + return err; +} + +static grub_err_t +grub_mb_boot (void) +{ + grub_mb_tags_finish (); + + grub_dprintf ("loader", "Tags at %p\n", grub_mb_tags); + grub_mb_arch_boot (entry, grub_mb_tags); + + /* Not reached. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_mb_unload (void) +{ +#if 0 + if (mbi) + { + unsigned int i; + for (i = 0; i < mbi->mods_count; i++) + { + grub_free ((void *) + ((struct grub_mod_list *) mbi->mods_addr)[i].mod_start); + grub_free ((void *) + ((struct grub_mod_list *) mbi->mods_addr)[i].cmdline); + } + grub_free ((void *) mbi->mods_addr); + grub_free ((void *) mbi->cmdline); + grub_free (mbi); + } + + + mbi = 0; + grub_dl_unref (my_mod); +#endif + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_mb_load_other (UNUSED grub_file_t file, UNUSED void *buffer) +{ + return grub_error (GRUB_ERR_UNKNOWN_OS, "currently only ELF is supported"); +} + +/* Load ELF32 or ELF64. */ +static grub_err_t +grub_mb_load_elf (grub_elf_t elf) +{ + grub_err_t err; + + if (grub_elf_is_elf32 (elf)) + { + entry = elf->ehdr.ehdr32.e_entry; + err = grub_elf32_load (elf, grub_mb_arch_load32_hook); + } + else if (grub_elf_is_elf64 (elf)) + { + entry = elf->ehdr.ehdr64.e_entry; + err = grub_elf64_load (elf, grub_mb_arch_load64_hook); + } + else + err = grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); + + grub_dprintf ("loader", "Entry point is 0x%lx.\n", (unsigned long) entry); + + return err; +} + +void +grub_rescue_cmd_multiboot (int argc, char *argv[]) +{ + char buffer[MULTIBOOT_HEADER_SEARCH]; + grub_file_t file = 0; + grub_elf_t elf = 0; + grub_ssize_t len; + grub_err_t err; + struct multiboot_header *header; + int header_found = 0; + char *p; + + grub_dl_ref (my_mod); + + grub_loader_unset (); + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified"); + goto fail; + } + + file = grub_gzfile_open (argv[0], 1); + if (! file) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file"); + goto fail; + } + + len = grub_file_read (file, buffer, MULTIBOOT_HEADER_SEARCH); + if (len < 32) + { + grub_error (GRUB_ERR_BAD_OS, "File too small"); + goto fail; + } + + /* Look for the multiboot header in the buffer. The header should + be at least 12 bytes and aligned on a 4-byte boundary. */ + for (p = buffer; p <= buffer + len - 12; p += 4) + { + header = (struct multiboot_header *) p; + if (header->magic == MULTIBOOT_HEADER_MAGIC + && header->magic + header->flags + header->checksum == 0) + { + header_found = 1; + break; + } + } + + if (! header_found) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "No multiboot header found"); + goto fail; + } + + grub_dprintf ("loader", "Multiboot flags: 0x%x\n", header->flags); + + if (header->flags & MULTIBOOT_UNSUPPORTED) + { + grub_error (GRUB_ERR_UNKNOWN_OS, + "Unsupported flag: 0x%x", header->flags); + goto fail; + } + + elf = grub_elf_file (file); + if (elf) + { + grub_dprintf ("loader", "Loading ELF multiboot file.\n"); + err = grub_mb_load_elf (elf); + } + else + { + grub_dprintf ("loader", "Loading non-ELF multiboot file.\n"); + err = grub_mb_load_other (file, header); + } + if (err) + goto fail; + + grub_dprintf ("loader", "Creating multiboot tags\n"); + grub_mb_tags_create (argc, argv); + + grub_loader_set (grub_mb_boot, grub_mb_unload, 1); + + fail: + if (elf) + grub_elf_close (elf); + else if (file) + grub_file_close (file); + + if (grub_errno != GRUB_ERR_NONE) + { + grub_dl_unref (my_mod); + } +} + + +void +grub_rescue_cmd_module (int argc, char *argv[]) +{ + struct multiboot_tag_module *module; + grub_file_t file = 0; + grub_ssize_t modsize, argslen = 0; + grub_err_t err; + char *data = 0; + char *p; + grub_addr_t module_addr; + int i; + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); + goto fail; + } + + if (entry == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "You need to load the multiboot kernel first"); + goto fail; + } + + /* Load module data into the heap. */ + file = grub_gzfile_open (argv[0], 1); + if (! file) + goto fail; + + modsize = grub_file_size (file); + data = grub_memalign (MULTIBOOT_MOD_ALIGN, modsize); + if (! data) + goto fail; + + if (grub_file_read (file, data, modsize) != modsize) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); + goto fail; + } + + /* Create the tag containing the command line and the address of the data. */ + for (i = 0; i < argc; i++) + argslen += grub_strlen (argv[i]) + 1; + + err = grub_mb_tag_alloc (&module_addr, MULTIBOOT_TAG_MODULE, + sizeof (struct multiboot_tag_module) + argslen); + if (err) + goto fail; + + module = (struct multiboot_tag_module *) module_addr; + module->addr = (grub_addr_t) data; + module->size = modsize; + + p = module->cmdline; + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *(p++) = ' '; + } + + /* Remove the space after the last word. */ + *(--p) = '\0'; + + fail: + if (file) + grub_file_close (file); + + if (grub_errno != GRUB_ERR_NONE) + grub_free (data); +} + + +GRUB_MOD_INIT(multiboot) +{ + grub_rescue_register_command ("multiboot", grub_rescue_cmd_multiboot, + "load a multiboot kernel"); + grub_rescue_register_command ("module", grub_rescue_cmd_module, + "load a multiboot module"); + my_mod = mod; +} + +GRUB_MOD_FINI(multiboot) +{ + grub_rescue_unregister_command ("multiboot"); + grub_rescue_unregister_command ("module"); +} Index: loader/i386/pc/multiboot.c =================================================================== --- loader/i386/pc/multiboot.c 2006-11-13 18:57:22.000000000 -0600 +++ loader/i386/pc/multiboot.c 2006-11-13 18:57:24.000000000 -0600 @@ -1,7 +1,7 @@ /* multiboot.c - boot a multiboot OS image. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,436 +18,43 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * FIXME: The following features from the Multiboot specification still - * need to be implemented: - * - VBE support - * - a.out support - * - boot device - * - symbol table - * - memory map - * - drives table - * - ROM configuration table - * - APM table - */ - -#include -#include -#include -#include +#include #include -#include #include -#include -#include -#include -#include -#include - -static grub_dl_t my_mod; -static struct grub_multiboot_info *mbi; -static grub_addr_t entry; - -static grub_err_t -grub_multiboot_boot (void) -{ - grub_multiboot_real_boot (entry, mbi); - - /* Not reached. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_multiboot_unload (void) -{ - if (mbi) - { - unsigned int i; - for (i = 0; i < mbi->mods_count; i++) - { - grub_free ((void *) - ((struct grub_mod_list *) mbi->mods_addr)[i].mod_start); - grub_free ((void *) - ((struct grub_mod_list *) mbi->mods_addr)[i].cmdline); - } - grub_free ((void *) mbi->mods_addr); - grub_free ((void *) mbi->cmdline); - grub_free (mbi); - } - - - mbi = 0; - grub_dl_unref (my_mod); - - return GRUB_ERR_NONE; -} - -/* Check if BUFFER contains ELF32. */ -static int -grub_multiboot_is_elf32 (void *buffer) -{ - Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer; - - return ehdr->e_ident[EI_CLASS] == ELFCLASS32; -} - -static grub_err_t -grub_multiboot_load_elf32 (grub_file_t file, void *buffer) -{ - Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer; - Elf32_Phdr *phdr; - int i; - - if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); - - if (grub_dl_check_header (ehdr, sizeof(Elf32_Ehdr))) - return grub_error (GRUB_ERR_UNKNOWN_OS, "no valid ELF header found"); - - if (ehdr->e_type != ET_EXEC) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type"); - - /* FIXME: Should we support program headers at strange locations? */ - if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH) - return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); - - entry = ehdr->e_entry; - - /* Load every loadable segment in memory. */ - for (i = 0; i < ehdr->e_phnum; i++) - { - phdr = (Elf32_Phdr *) ((char *) buffer + ehdr->e_phoff - + i * ehdr->e_phentsize); - if (phdr->p_type == PT_LOAD) - { - /* The segment should fit in the area reserved for the OS. */ - if ((phdr->p_paddr < grub_os_area_addr) - || (phdr->p_paddr + phdr->p_memsz - > grub_os_area_addr + grub_os_area_size)) - return grub_error (GRUB_ERR_BAD_OS, - "segment doesn't fit in memory reserved for the OS"); - - if (grub_file_seek (file, (grub_off_t) phdr->p_offset) - == (grub_off_t) -1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); - - if (grub_file_read (file, (void *) phdr->p_paddr, phdr->p_filesz) - != (grub_ssize_t) phdr->p_filesz) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file"); - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((char *) phdr->p_paddr + phdr->p_filesz, 0, - phdr->p_memsz - phdr->p_filesz); - } - } - - return grub_errno; -} - -/* Check if BUFFER contains ELF64. */ -static int -grub_multiboot_is_elf64 (void *buffer) -{ - Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer; - - return ehdr->e_ident[EI_CLASS] == ELFCLASS64; -} +#include -static grub_err_t -grub_multiboot_load_elf64 (grub_file_t file, void *buffer) +int grub_mb_arch_load32_hook (Elf32_Phdr *phdr, + UNUSED grub_addr_t *addr) { - Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer; - Elf64_Phdr *phdr; - int i; - - if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); - - if (ehdr->e_ident[EI_MAG0] != ELFMAG0 - || ehdr->e_ident[EI_MAG1] != ELFMAG1 - || ehdr->e_ident[EI_MAG2] != ELFMAG2 - || ehdr->e_ident[EI_MAG3] != ELFMAG3 - || ehdr->e_version != EV_CURRENT - || ehdr->e_ident[EI_DATA] != ELFDATA2LSB - || ehdr->e_machine != EM_X86_64) - return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found"); - - if (ehdr->e_type != ET_EXEC) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type"); - - /* FIXME: Should we support program headers at strange locations? */ - if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH) - return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); + Elf32_Addr paddr = phdr->p_paddr; - /* We still in 32-bit mode */ - if (ehdr->e_entry > 0xffffffff) - return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64"); + if ((paddr < grub_os_area_addr) + || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size)) + return 1; - entry = ehdr->e_entry; - - /* Load every loadable segment in memory. */ - for (i = 0; i < ehdr->e_phnum; i++) - { - phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff - + i * ehdr->e_phentsize); - if (phdr->p_type == PT_LOAD) - { - /* The segment should fit in the area reserved for the OS. */ - if ((phdr->p_paddr < (grub_uint64_t) grub_os_area_addr) - || (phdr->p_paddr + phdr->p_memsz - > ((grub_uint64_t) grub_os_area_addr - + (grub_uint64_t) grub_os_area_size))) - return grub_error (GRUB_ERR_BAD_OS, - "segment doesn't fit in memory reserved for the OS"); - - if (grub_file_seek (file, (grub_off_t) phdr->p_offset) - == (grub_off_t) -1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); - - if (grub_file_read (file, (void *) ((grub_uint32_t) phdr->p_paddr), - phdr->p_filesz) - != (grub_ssize_t) phdr->p_filesz) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file"); - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset (((char *) ((grub_uint32_t) phdr->p_paddr) - + phdr->p_filesz), - 0, - phdr->p_memsz - phdr->p_filesz); - } - } - - return grub_errno; + return 0; } -/* Load ELF32 or ELF64. */ -static grub_err_t -grub_multiboot_load_elf (grub_file_t file, void *buffer) +int grub_mb_arch_load64_hook (Elf64_Phdr *phdr, + UNUSED grub_addr_t *addr) { - if (grub_multiboot_is_elf32 (buffer)) - return grub_multiboot_load_elf32 (file, buffer); - else if (grub_multiboot_is_elf64 (buffer)) - return grub_multiboot_load_elf64 (file, buffer); - - return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); -} - -void -grub_rescue_cmd_multiboot (int argc, char *argv[]) -{ - grub_file_t file = 0; - char buffer[GRUB_MB_SEARCH], *cmdline = 0, *p; - struct grub_multiboot_header *header; - grub_ssize_t len; - int i; - - grub_dl_ref (my_mod); - - grub_loader_unset (); - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified"); - goto fail; - } - - file = grub_gzfile_open (argv[0], 1); - if (! file) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file"); - goto fail; - } - - len = grub_file_read (file, buffer, GRUB_MB_SEARCH); - if (len < 32) - { - grub_error (GRUB_ERR_BAD_OS, "File too small"); - goto fail; - } - - /* Look for the multiboot header in the buffer. The header should - be at least 12 bytes and aligned on a 4-byte boundary. */ - for (header = (struct grub_multiboot_header *) buffer; - ((char *) header <= buffer + len - 12) || (header = 0); - header = (struct grub_multiboot_header *) ((char *) header + 4)) - { - if (header->magic == GRUB_MB_MAGIC - && !(header->magic + header->flags + header->checksum)) - break; - } - - if (header == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No multiboot header found"); - goto fail; - } - - if (header->flags & GRUB_MB_UNSUPPORTED) - { - grub_error (GRUB_ERR_UNKNOWN_OS, - "Unsupported flag: 0x%x", header->flags); - goto fail; - } - - if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE) - goto fail; - - mbi = grub_malloc (sizeof (struct grub_multiboot_info)); - if (! mbi) - goto fail; - - mbi->flags = GRUB_MB_INFO_MEMORY; - - /* Convert from bytes to kilobytes. */ - mbi->mem_lower = grub_lower_mem / 1024; - mbi->mem_upper = grub_upper_mem / 1024; - - for (i = 0, len = 0; i < argc; i++) - len += grub_strlen (argv[i]) + 1; - - cmdline = p = grub_malloc (len); - if (! cmdline) - goto fail; - - for (i = 0; i < argc; i++) - { - p = grub_stpcpy (p, argv[i]); - *(p++) = ' '; - } - - /* Remove the space after the last word. */ - *(--p) = '\0'; - - mbi->flags |= GRUB_MB_INFO_CMDLINE; - mbi->cmdline = (grub_uint32_t) cmdline; - - mbi->flags |= GRUB_MB_INFO_BOOT_LOADER_NAME; - mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING); + Elf64_Addr paddr = phdr->p_paddr; - grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1); + if ((paddr < grub_os_area_addr) + || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size)) + return 1; - fail: - if (file) - grub_file_close (file); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_free (cmdline); - grub_free (mbi); - grub_dl_unref (my_mod); - } + return 0; } - void -grub_rescue_cmd_module (int argc, char *argv[]) -{ - grub_file_t file = 0; - grub_ssize_t size, len = 0; - char *module = 0, *cmdline = 0, *p; - int i; - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); - goto fail; - } - - if (!mbi) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, - "You need to load the multiboot kernel first"); - goto fail; - } - - file = grub_gzfile_open (argv[0], 1); - if (! file) - goto fail; - - size = grub_file_size (file); - module = grub_memalign (GRUB_MB_MOD_ALIGN, size); - if (! module) - goto fail; - - if (grub_file_read (file, module, size) != size) - { - grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); - goto fail; - } - - for (i = 0; i < argc; i++) - len += grub_strlen (argv[i]) + 1; - - cmdline = p = grub_malloc (len); - if (! cmdline) - goto fail; - - for (i = 0; i < argc; i++) - { - p = grub_stpcpy (p, argv[i]); - *(p++) = ' '; - } - - /* Remove the space after the last word. */ - *(--p) = '\0'; - - if (mbi->flags & GRUB_MB_INFO_MODS) - { - struct grub_mod_list *modlist = (struct grub_mod_list *) mbi->mods_addr; - - modlist = grub_realloc (modlist, (mbi->mods_count + 1) - * sizeof (struct grub_mod_list)); - if (! modlist) - goto fail; - mbi->mods_addr = (grub_uint32_t) modlist; - modlist += mbi->mods_count; - modlist->mod_start = (grub_uint32_t) module; - modlist->mod_end = (grub_uint32_t) module + size; - modlist->cmdline = (grub_uint32_t) cmdline; - modlist->pad = 0; - mbi->mods_count++; - } - else - { - struct grub_mod_list *modlist = grub_malloc (sizeof (struct grub_mod_list)); - if (! modlist) - goto fail; - modlist->mod_start = (grub_uint32_t) module; - modlist->mod_end = (grub_uint32_t) module + size; - modlist->cmdline = (grub_uint32_t) cmdline; - modlist->pad = 0; - mbi->mods_count = 1; - mbi->mods_addr = (grub_uint32_t) modlist; - mbi->flags |= GRUB_MB_INFO_MODS; - } - - fail: - if (file) - grub_file_close (file); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_free (module); - grub_free (cmdline); - } -} - - -GRUB_MOD_INIT(multiboot) +grub_mb_arch_boot (grub_addr_t entry, void *tags) { - grub_rescue_register_command ("multiboot", grub_rescue_cmd_multiboot, - "load a multiboot kernel"); - grub_rescue_register_command ("module", grub_rescue_cmd_module, - "load a multiboot module"); - my_mod = mod; + grub_multiboot_real_boot (entry, tags); } -GRUB_MOD_FINI(multiboot) +grub_err_t +grub_mb_tags_arch_create (int argc, char *argv[]) { - grub_rescue_unregister_command ("multiboot"); - grub_rescue_unregister_command ("module"); + return GRUB_ERR_NONE; } Index: include/grub/misc.h =================================================================== --- include/grub/misc.h 2006-11-13 18:57:22.000000000 -0600 +++ include/grub/misc.h 2006-11-13 18:57:24.000000000 -0600 @@ -26,6 +26,8 @@ #include #include +#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1)) + #define grub_dprintf(condition, fmt, args...) grub_real_dprintf(__FILE__, __LINE__, condition, fmt, ## args); /* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */ #define grub_memcpy(d,s,n) grub_memmove ((d), (s), (n)) Index: util/powerpc/ieee1275/grub-mkimage.c =================================================================== --- util/powerpc/ieee1275/grub-mkimage.c 2006-11-13 18:57:22.000000000 -0600 +++ util/powerpc/ieee1275/grub-mkimage.c 2006-11-13 18:57:24.000000000 -0600 @@ -27,13 +27,12 @@ #include #include #include +#include #include #include #include #include -#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1)) - #define GRUB_IEEE1275_NOTE_NAME "PowerPC" #define GRUB_IEEE1275_NOTE_TYPE 0x1275 Index: loader/i386/pc/multiboot_normal.c =================================================================== --- loader/i386/pc/multiboot_normal.c 2006-11-13 18:57:22.000000000 -0600 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* multiboot_normal.c - boot another boot loader */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004,2005 Free Software Foundation, Inc. - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include - -static grub_err_t -grub_normal_cmd_multiboot (struct grub_arg_list *state __attribute__ ((unused)), - int argc, char **args) -{ - grub_rescue_cmd_multiboot (argc, args); - return grub_errno; -} - - -static grub_err_t -grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)), - int argc, char **args) -{ - grub_rescue_cmd_module (argc, args); - return grub_errno; -} - -GRUB_MOD_INIT(multiboot_normal) -{ - (void) mod; /* To stop warning. */ - grub_register_command ("multiboot", grub_normal_cmd_multiboot, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "multiboot FILE [ARGS...]", - "Load a Multiboot kernel.", 0); - - grub_register_command ("module", grub_normal_cmd_module, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "module FILE [ARGS...]", - "Load a Multiboot module.", 0); -} - -GRUB_MOD_FINI(multiboot_normal) -{ - grub_unregister_command ("multiboot"); - grub_unregister_command ("module"); -} Index: loader/multiboot_normal.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ loader/multiboot_normal.c 2006-11-13 18:57:24.000000000 -0600 @@ -0,0 +1,61 @@ +/* multiboot_normal.c - boot another boot loader */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2004,2005 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +static grub_err_t +grub_normal_cmd_multiboot (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_multiboot (argc, args); + return grub_errno; +} + + +static grub_err_t +grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_module (argc, args); + return grub_errno; +} + +GRUB_MOD_INIT(multiboot_normal) +{ + (void) mod; /* To stop warning. */ + grub_register_command ("multiboot", grub_normal_cmd_multiboot, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "multiboot FILE [ARGS...]", + "Load a Multiboot kernel.", 0); + + grub_register_command ("module", grub_normal_cmd_module, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "module FILE [ARGS...]", + "Load a Multiboot module.", 0); +} + +GRUB_MOD_FINI(multiboot_normal) +{ + grub_unregister_command ("multiboot"); + grub_unregister_command ("module"); +} Index: conf/i386-pc.rmk =================================================================== --- conf/i386-pc.rmk 2006-11-13 18:57:22.000000000 -0600 +++ conf/i386-pc.rmk 2006-11-13 18:57:24.000000000 -0600 @@ -164,12 +164,12 @@ serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) # For _multiboot.mod. -_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c +_multiboot_mod_SOURCES = loader/multiboot.c loader/i386/pc/multiboot.c _multiboot_mod_CFLAGS = $(COMMON_CFLAGS) _multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) # For multiboot.mod. -multiboot_mod_SOURCES = loader/i386/pc/multiboot_normal.c +multiboot_mod_SOURCES = loader/multiboot_normal.c multiboot_mod_CFLAGS = $(COMMON_CFLAGS) multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) Index: conf/powerpc-ieee1275.rmk =================================================================== --- conf/powerpc-ieee1275.rmk 2006-11-13 18:57:22.000000000 -0600 +++ conf/powerpc-ieee1275.rmk 2006-11-13 18:57:24.000000000 -0600 @@ -84,6 +84,8 @@ grub_install_SOURCES = util/powerpc/ieee pkgdata_MODULES = halt.mod \ _linux.mod \ linux.mod \ + _multiboot.mod \ + multiboot.mod \ normal.mod \ reboot.mod \ suspend.mod @@ -98,6 +100,16 @@ linux_mod_SOURCES = loader/powerpc/ieee1 linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For _multiboot.mod. +_multiboot_mod_SOURCES = loader/multiboot.c loader/powerpc/ieee1275/multiboot.c +_multiboot_mod_CFLAGS = $(COMMON_CFLAGS) +_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For multiboot.mod. +multiboot_mod_SOURCES = loader/multiboot_normal.c +multiboot_mod_CFLAGS = $(COMMON_CFLAGS) +multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For normal.mod. normal_mod_DEPENDENCIES = grub_script.tab.c grub_script.tab.h normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \ Index: include/grub/i386/pc/loader.h =================================================================== --- include/grub/i386/pc/loader.h 2006-11-13 18:57:22.000000000 -0600 +++ include/grub/i386/pc/loader.h 2006-11-13 18:57:24.000000000 -0600 @@ -22,11 +22,13 @@ #include #include -#include +#include extern grub_uint32_t EXPORT_VAR(grub_linux_prot_size); extern char *EXPORT_VAR(grub_linux_tmp_addr); extern char *EXPORT_VAR(grub_linux_real_addr); +extern grub_addr_t EXPORT_VAR(grub_os_area_addr); +extern grub_size_t EXPORT_VAR(grub_os_area_size); void EXPORT_FUNC(grub_linux_boot_zimage) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_linux_boot_bzimage) (void) __attribute__ ((noreturn)); @@ -35,8 +37,7 @@ void EXPORT_FUNC(grub_linux_boot_bzimage void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn)); /* The asm part of the multiboot loader. */ -void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry, - struct grub_multiboot_info *mbi) +void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry, void *tags) __attribute__ ((noreturn)); /* It is necessary to export these functions, because normal mode commands Index: include/grub/i386/pc/multiboot.h =================================================================== --- include/grub/i386/pc/multiboot.h 2006-11-13 18:57:22.000000000 -0600 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ -/* multiboot.h - multiboot header file. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003 Free Software Foundation, Inc. - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef GRUB_MULTIBOOT_MACHINE_HEADER -#define GRUB_MULTIBOOT_MACHINE_HEADER 1 - -/* How many bytes from the start of the file we search for the header. */ -#define GRUB_MB_SEARCH 8192 - -/* The magic field should contain this. */ -#define GRUB_MB_MAGIC 0x1BADB002 - -/* This should be in %eax. */ -#define GRUB_MB_MAGIC2 0x2BADB002 - -/* The bits in the required part of flags field we don't support. */ -#define GRUB_MB_UNSUPPORTED 0x0000fffc - -/* Alignment of multiboot modules. */ -#define GRUB_MB_MOD_ALIGN 0x00001000 - -/* - * Flags set in the 'flags' member of the multiboot header. - */ - -/* Align all boot modules on i386 page (4KB) boundaries. */ -#define GRUB_MB_PAGE_ALIGN 0x00000001 - -/* Must pass memory information to OS. */ -#define GRUB_MB_MEMORY_INFO 0x00000002 - -/* Must pass video information to OS. */ -#define GRUB_MB_VIDEO_MODE 0x00000004 - -/* This flag indicates the use of the address fields in the header. */ -#define GRUB_MB_AOUT_KLUDGE 0x00010000 - -/* - * Flags to be set in the 'flags' member of the multiboot info structure. - */ - -/* is there basic lower/upper memory information? */ -#define GRUB_MB_INFO_MEMORY 0x00000001 -/* is there a boot device set? */ -#define GRUB_MB_INFO_BOOTDEV 0x00000002 -/* is the command-line defined? */ -#define GRUB_MB_INFO_CMDLINE 0x00000004 -/* are there modules to do something with? */ -#define GRUB_MB_INFO_MODS 0x00000008 - -/* These next two are mutually exclusive */ - -/* is there a symbol table loaded? */ -#define GRUB_MB_INFO_AOUT_SYMS 0x00000010 -/* is there an ELF section header table? */ -#define GRUB_MB_INFO_ELF_SHDR 0x00000020 - -/* is there a full memory map? */ -#define GRUB_MB_INFO_MEM_MAP 0x00000040 - -/* Is there drive info? */ -#define GRUB_MB_INFO_DRIVE_INFO 0x00000080 - -/* Is there a config table? */ -#define GRUB_MB_INFO_CONFIG_TABLE 0x00000100 - -/* Is there a boot loader name? */ -#define GRUB_MB_INFO_BOOT_LOADER_NAME 0x00000200 - -/* Is there a APM table? */ -#define GRUB_MB_INFO_APM_TABLE 0x00000400 - -/* Is there video information? */ -#define GRUB_MB_INFO_VIDEO_INFO 0x00000800 - -#ifndef ASM_FILE - -#include - -struct grub_multiboot_header -{ - /* Must be GRUB_MB_MAGIC - see above. */ - grub_uint32_t magic; - - /* Feature flags. */ - grub_uint32_t flags; - - /* The above fields plus this one must equal 0 mod 2^32. */ - grub_uint32_t checksum; - - /* These are only valid if GRUB_MB_AOUT_KLUDGE is set. */ - grub_uint32_t header_addr; - grub_uint32_t load_addr; - grub_uint32_t load_end_addr; - grub_uint32_t bss_end_addr; - grub_uint32_t entry_addr; - - /* These are only valid if GRUB_MB_VIDEO_MODE is set. */ - grub_uint32_t mode_type; - grub_uint32_t width; - grub_uint32_t height; - grub_uint32_t depth; -}; - -struct grub_multiboot_info -{ - /* Multiboot info version number */ - grub_uint32_t flags; - - /* Available memory from BIOS */ - grub_uint32_t mem_lower; - grub_uint32_t mem_upper; - - /* "root" partition */ - grub_uint32_t boot_device; - - /* Kernel command line */ - grub_uint32_t cmdline; - - /* Boot-Module list */ - grub_uint32_t mods_count; - grub_uint32_t mods_addr; - - grub_uint32_t syms[4]; - - /* Memory Mapping buffer */ - grub_uint32_t mmap_length; - grub_uint32_t mmap_addr; - - /* Drive Info buffer */ - grub_uint32_t drives_length; - grub_uint32_t drives_addr; - - /* ROM configuration table */ - grub_uint32_t config_table; - - /* Boot Loader Name */ - grub_uint32_t boot_loader_name; - - /* APM table */ - grub_uint32_t apm_table; - - /* Video */ - grub_uint32_t vbe_control_info; - grub_uint32_t vbe_mode_info; - grub_uint16_t vbe_mode; - grub_uint16_t vbe_interface_seg; - grub_uint16_t vbe_interface_off; - grub_uint16_t vbe_interface_len; -}; - -struct grub_mod_list -{ - /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ - grub_uint32_t mod_start; - grub_uint32_t mod_end; - - /* Module command line */ - grub_uint32_t cmdline; - - /* padding to take it to 16 bytes (must be zero) */ - grub_uint32_t pad; -}; - -#endif /* ! ASM_FILE */ - -#endif /* ! GRUB_MULTIBOOT_MACHINE_HEADER */ Index: kern/i386/pc/startup.S =================================================================== --- kern/i386/pc/startup.S 2006-11-13 18:57:22.000000000 -0600 +++ kern/i386/pc/startup.S 2006-11-13 18:57:24.000000000 -0600 @@ -50,8 +50,8 @@ #include #include #include -#include - +#include + #define ABS(x) ((x) - EXT_C(start) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) .file "startup.S" @@ -803,18 +803,18 @@ linux_setup_seg: FUNCTION(grub_multiboot_real_boot) /* Push the entry address on the stack. */ pushl %eax - /* Move the address of the multiboot information structure to ebx. */ + /* Move the address of the multiboot tags to ebx. */ movl %edx,%ebx - + /* Unload all modules and stop the floppy driver. */ call EXT_C(grub_dl_unload_all) call EXT_C(grub_stop_floppy) /* Interrupts should be disabled. */ cli - + /* Move the magic value into eax and jump to the kernel. */ - movl $GRUB_MB_MAGIC2,%eax + movl $MULTIBOOT_BOOTLOADER_MAGIC,%eax popl %ecx jmp *%ecx Index: include/multiboot.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ include/multiboot.h 2006-11-13 18:57:24.000000000 -0600 @@ -0,0 +1,136 @@ +/* multiboot.h - multiboot header file. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_HEADER_SEARCH 8192 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The bits in the required part of flags field we don't support. */ +#define MULTIBOOT_UNSUPPORTED 0x0000fffc + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* + * Flags set in the 'flags' member of the multiboot header. + */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +#ifndef ASM_FILE + +#include "stdint.h" + +/* XXX not portable? */ +#if __WORDSIZE == 64 +typedef uint64_t multiboot_word; +#else +typedef uint32_t multiboot_word; +#endif + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + uint32_t magic; + + /* Feature flags. */ + uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; + uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + uint32_t mode_type; + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +struct multiboot_tag_header +{ + uint32_t key; + uint32_t len; +}; + +#define MULTIBOOT_TAG_START 0 +struct multiboot_tag_start +{ + struct multiboot_tag_header header; + multiboot_word size; /* Total size of all multiboot tags. */ + multiboot_word num; /* Number of multiboot tags. */ +}; + +#define MULTIBOOT_TAG_CMDLINE 1 +struct multiboot_tag_cmdline +{ + struct multiboot_tag_header header; + char cmdline[1]; +}; + +#define MULTIBOOT_TAG_MODULE 2 +struct multiboot_tag_module +{ + struct multiboot_tag_header header; + multiboot_word addr; + multiboot_word size; + char cmdline[1]; +}; + +#define MULTIBOOT_TAG_NAME 4 +struct multiboot_tag_name +{ + struct multiboot_tag_header header; + char name[1]; +}; + +#define MULTIBOOT_TAG_END 0xffff +struct multiboot_tag_end +{ + struct multiboot_tag_header header; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */