+2007-07-24 Jerone Young <jerone@gmail.com>
+
+ * conf/i386-pc.rmk: Add Multiboot loader and multiboot 2 to multiboot
+ modules for compilation.
+ * conf/powerpc-ieee1275.rmk: Likewise.
+
+ * include/multiboot.h: Move multiboot definitions to one file. Rename
+ many definitions to not get grub specific.
+ * include/multiboot2.h: Create header with multiboot 2 definitions.
+ * include/grub/multiboot.h: Header for grub specific function
+ prototypes and definitions.
+ * include/grub/multiboot2.h: Likewise.
+ * include/grub/multiboot_loader.h: Likewise.
+ * include/grub/i386/pc/multiboot.h: Removed.
+ * include/grub/powerpc/ieee1275/multiboot.h: Removed.
+
+ * loader/multiboot_loader.c: Created to act as a proxy for multiboot 1
+ and 2 to allow for one multiboot and module commands.
+ * loader/multiboot2.c: Add multiboot2 functionality.
+ * loader/i386/pc/multiboot.c: Modify for new multiboot header location
+ and definition names.
+ * loader/i386/pc/multiboot2.c: Created to add i386 specific multiboot
+ 2 functions.
+ * loader/powerpc/ieee1275/multiboot2.c: Created to add powerpc
+ ieee1275 specific multiboot2 code.
+
+ * kern/i386/pc/startup.S: Change headers and definition names for
+ multiboot. Add function grub_multiboot2_real_boot for multiboot 2.
+
2007-07-22 Robert Millan <rmh@aybabtu.com>
* geninitheader.sh: Process file specified in first parameter rather
serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For _multiboot.mod.
-_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c \
+ loader/i386/pc/multiboot2.c \
+ loader/multiboot2.c \
+ loader/multiboot_loader.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_loader_normal.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
linux.mod \
normal.mod \
reboot.mod \
- suspend.mod
+ suspend.mod \
+ _multiboot.mod \
+ multiboot.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
halt_mod_CFLAGS = $(COMMON_CFLAGS)
halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For _multiboot.mod
+_multiboot_mod_SOURCES = loader/powerpc/ieee1275/multiboot2.c \
+ loader/multiboot2.c \
+ loader/multiboot_loader.c
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+
include $(srcdir)/conf/common.mk
#include <grub/types.h>
#include <grub/symbol.h>
-#include <grub/machine/multiboot.h>
+#include <grub/multiboot.h>
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));
void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
struct grub_multiboot_info *mbi)
__attribute__ ((noreturn));
+void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
+ struct grub_multiboot_info *mbi)
+ __attribute__ ((noreturn));
/* It is necessary to export these functions, because normal mode commands
reuse rescue mode commands. */
void grub_rescue_cmd_linux (int argc, char *argv[]);
void grub_rescue_cmd_initrd (int argc, char *argv[]);
-void grub_rescue_cmd_multiboot (int argc, char *argv[]);
-void grub_rescue_cmd_module (int argc, char *argv[]);
#endif /* ! GRUB_LOADER_MACHINE_HEADER */
-/* multiboot.h - multiboot header file. */
+/* multiboot.h - multiboot header file with grub definitions. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2007 Free Software Foundation, Inc.
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GRUB_MULTIBOOT_MACHINE_HEADER
-#define GRUB_MULTIBOOT_MACHINE_HEADER 1
+#ifndef GRUB_MULTIBOOT_HEADER
+#define GRUB_MULTIBOOT_HEADER 1
-/* How many bytes from the start of the file we search for the header. */
-#define GRUB_MB_SEARCH 8192
+#include <multiboot.h>
-/* 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
+void grub_multiboot (int argc, char *argv[]);
+void grub_module (int argc, char *argv[]);
#ifndef ASM_FILE
struct grub_multiboot_header
{
- /* Must be GRUB_MB_MAGIC - see above. */
+ /* Must be MULTIBOOT_MAGIC - see above. */
grub_uint32_t magic;
/* Feature 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. */
+ /* These are only valid if MULTIBOOT_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. */
+ /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
grub_uint32_t mode_type;
grub_uint32_t width;
grub_uint32_t height;
#endif /* ! ASM_FILE */
-#endif /* ! GRUB_MULTIBOOT_MACHINE_HEADER */
+#endif /* ! GRUB_MULTIBOOT_HEADER */
--- /dev/null
+/* multiboot2.h - multiboot2 header file with grub definitions. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MULTIBOOT2_HEADER
+#define GRUB_MULTIBOOT2_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/elf.h>
+
+struct multiboot_tag_header;
+
+grub_err_t
+grub_mb2_tag_alloc (grub_addr_t *addr, int key, grub_size_t len);
+
+grub_err_t
+grub_mb2_tags_arch_create (void);
+
+void
+grub_mb2_arch_boot (grub_addr_t entry, void *tags);
+
+void
+grub_mb2_arch_unload (struct multiboot_tag_header *tags);
+
+grub_err_t
+grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, grub_addr_t *addr);
+
+grub_err_t
+grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, grub_addr_t *addr);
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr);
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, grub_size_t size);
+
+void
+grub_multiboot2 (int argc, char *argv[]);
+
+void
+grub_module2 (int argc, char *argv[]);
+
+#define for_each_tag(tag, tags) \
+ for (tag = tags; \
+ tag && tag->key != MULTIBOOT2_TAG_END; \
+ tag = (struct multiboot_tag_header *)((char *)tag + tag->len))
+
+#endif /* ! GRUB_MULTIBOOT2_HEADER */
--- /dev/null
+/* multiboot_loader.h - multiboot loader header file. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GRUB_MULTIBOOT_LOADER_HEADER
+#define GRUB_MULTIBOOT_LOADER_HEADER 1
+
+/* Provided by the core ("rescue mode"). */
+void grub_rescue_cmd_multiboot_loader (int argc, char *argv[]);
+void grub_rescue_cmd_module_loader (int argc, char *argv[]);
+
+#endif /* ! GRUB_MULTIBOOT_LOADER_HEADER */
+++ /dev/null
-/* multiboot.h - multiboot header file. */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2004,2007 Free Software Foundation, Inc.
- *
- * GRUB 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 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#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 <grub/types.h>
-
-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 */
--- /dev/null
+/* multiboot.h - multiboot header file. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 8192
+
+/* The magic field should contain this. */
+#define MULTIBOOT_MAGIC 0x1BADB002
+
+/* This should be in %eax. */
+#define MULTIBOOT_MAGIC2 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
+
+/*
+ * Flags to be set in the 'flags' member of the multiboot info structure.
+ */
+
+/* is there basic lower/upper memory information? */
+#define MULTIBOOT_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MULTIBOOT_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MULTIBOOT_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MULTIBOOT_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MULTIBOOT_INFO_ELF_SHDR 0x00000020
+
+/* is there a full memory map? */
+#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MULTIBOOT_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800
+
+#endif /* ! MULTIBOOT_HEADER */
--- /dev/null
+/* multiboot2.h - multiboot 2 header file. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MULTIBOOT2_HEADER
+#define MULTIBOOT2_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT2_HEADER_SEARCH 8192
+
+/* The magic field should contain this. */
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+
+/* Passed from the bootloader to the kernel. */
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT2_MOD_ALIGN 0x00001000
+
+#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
+{
+ uint32_t magic;
+};
+
+struct multiboot_tag_header
+{
+ uint32_t key;
+ uint32_t len;
+};
+
+#define MULTIBOOT2_TAG_RESERVED1 0
+#define MULTIBOOT2_TAG_RESERVED2 (~0)
+
+#define MULTIBOOT2_TAG_START 1
+struct multiboot_tag_start
+{
+ struct multiboot_tag_header header;
+ multiboot_word size; /* Total size of all multiboot tags. */
+};
+
+#define MULTIBOOT2_TAG_NAME 2
+struct multiboot_tag_name
+{
+ struct multiboot_tag_header header;
+ char name[1];
+};
+
+#define MULTIBOOT2_TAG_MODULE 3
+struct multiboot_tag_module
+{
+ struct multiboot_tag_header header;
+ multiboot_word addr;
+ multiboot_word size;
+ unsigned char type[36];
+ unsigned char cmdline[1];
+};
+
+#define MULTIBOOT2_TAG_MEMORY 4
+struct multiboot_tag_memory
+{
+ struct multiboot_tag_header header;
+ multiboot_word addr;
+ multiboot_word size;
+ multiboot_word type;
+};
+
+#define MULTIBOOT2_TAG_UNUSED 5
+struct multiboot_tag_unused
+{
+ struct multiboot_tag_header header;
+};
+
+#define MULTIBOOT2_TAG_END 0xffff
+struct multiboot_tag_end
+{
+ struct multiboot_tag_header header;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT2_HEADER */
#include <grub/machine/console.h>
#include <grub/cpu/linux.h>
#include <grub/machine/kernel.h>
-#include <grub/machine/multiboot.h>
+#include <multiboot.h>
+#include <multiboot2.h>
#define ABS(x) ((x) - EXT_C(start) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
cli
/* Move the magic value into eax and jump to the kernel. */
- movl $GRUB_MB_MAGIC2,%eax
+ movl $MULTIBOOT_MAGIC2,%eax
popl %ecx
jmp *%ecx
-
+
+/*
+ * This starts the multiboot 2 kernel.
+ */
+
+FUNCTION(grub_multiboot2_real_boot)
+ /* Push the entry address on the stack. */
+ pushl %eax
+ /* Move the address of the multiboot information structure 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 $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
+ popl %ecx
+ jmp *%ecx
/*
* int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
#include <grub/loader.h>
#include <grub/machine/loader.h>
-#include <grub/machine/multiboot.h>
+#include <grub/multiboot.h>
#include <grub/machine/init.h>
#include <grub/elf.h>
#include <grub/file.h>
#include <grub/misc.h>
#include <grub/gzio.h>
-static grub_dl_t my_mod;
+extern grub_dl_t my_mod;
static struct grub_multiboot_info *mbi;
static grub_addr_t entry;
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)
+ if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
entry = ehdr->e_entry;
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)
+ if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
/* We still in 32-bit mode */
}
void
-grub_rescue_cmd_multiboot (int argc, char *argv[])
+grub_multiboot (int argc, char *argv[])
{
grub_file_t file = 0;
- char buffer[GRUB_MB_SEARCH], *cmdline = 0, *p;
+ char buffer[MULTIBOOT_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)
goto fail;
}
- len = grub_file_read (file, buffer, GRUB_MB_SEARCH);
+ len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_error (GRUB_ERR_BAD_OS, "File too small");
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct grub_multiboot_header *) ((char *) header + 4))
{
- if (header->magic == GRUB_MB_MAGIC
+ if (header->magic == MULTIBOOT_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
goto fail;
}
- if (header->flags & GRUB_MB_UNSUPPORTED)
+ if (header->flags & MULTIBOOT_UNSUPPORTED)
{
grub_error (GRUB_ERR_UNKNOWN_OS,
"Unsupported flag: 0x%x", header->flags);
if (! mbi)
goto fail;
- mbi->flags = GRUB_MB_INFO_MEMORY;
+ mbi->flags = MULTIBOOT_INFO_MEMORY;
/* Convert from bytes to kilobytes. */
mbi->mem_lower = grub_lower_mem / 1024;
/* Remove the space after the last word. */
*(--p) = '\0';
- mbi->flags |= GRUB_MB_INFO_CMDLINE;
+ mbi->flags |= MULTIBOOT_INFO_CMDLINE;
mbi->cmdline = (grub_uint32_t) cmdline;
- mbi->flags |= GRUB_MB_INFO_BOOT_LOADER_NAME;
+ mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING);
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
void
-grub_rescue_cmd_module (int argc, char *argv[])
+grub_module (int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size, len = 0;
goto fail;
size = grub_file_size (file);
- module = grub_memalign (GRUB_MB_MOD_ALIGN, size);
+ module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module)
goto fail;
/* Remove the space after the last word. */
*(--p) = '\0';
- if (mbi->flags & GRUB_MB_INFO_MODS)
+ if (mbi->flags & MULTIBOOT_INFO_MODS)
{
struct grub_mod_list *modlist = (struct grub_mod_list *) mbi->mods_addr;
modlist->pad = 0;
mbi->mods_count = 1;
mbi->mods_addr = (grub_uint32_t) modlist;
- mbi->flags |= GRUB_MB_INFO_MODS;
+ mbi->flags |= MULTIBOOT_INFO_MODS;
}
fail:
grub_free (cmdline);
}
}
-
-
-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");
-}
--- /dev/null
+/* multiboot2.c - boot a multiboot 2 OS image. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/multiboot2.h>
+#include <grub/elf.h>
+#include <grub/err.h>
+#include <grub/machine/loader.h>
+#include <grub/mm.h>
+
+grub_err_t
+grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+ Elf32_Addr paddr = phdr->p_paddr;
+
+ if ((paddr < grub_os_area_addr)
+ || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+ return grub_error(GRUB_ERR_OUT_OF_RANGE,"Address 0x%x is out of range",
+ paddr);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+ Elf64_Addr paddr = phdr->p_paddr;
+
+ if ((paddr < grub_os_area_addr)
+ || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+ return (GRUB_ERR_OUT_OF_RANGE,"Address 0x%x is out of range",
+ paddr);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
+{
+ grub_addr_t modaddr;
+
+ modaddr = grub_memalign (MULTIBOOT2_MOD_ALIGN, size);
+ if (! modaddr)
+ return grub_errno;
+
+ *addr = modaddr;
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, UNUSED grub_size_t size)
+{
+ grub_free((void *) addr);
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_mb2_arch_boot (grub_addr_t entry, void *tags)
+{
+ grub_multiboot2_real_boot (entry, tags);
+}
+
+void
+grub_mb2_arch_unload (struct multiboot_tag_header *tags)
+{
+ struct multiboot_tag_header *tag;
+
+ /* Free all module memory in the tag list. */
+ for_each_tag (tag, tags)
+ {
+ if (tag->key == MULTIBOOT2_TAG_MODULE)
+ {
+ struct multiboot_tag_module *module =
+ (struct multiboot_tag_module *) tag;
+ grub_free((void *) module->addr);
+ }
+ }
+}
+
+grub_err_t
+grub_mb2_tags_arch_create (void)
+{
+ /* XXX Create boot device et al. */
+ return GRUB_ERR_NONE;
+}
--- /dev/null
+/* multiboot2.c - boot a multiboot 2 OS image. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/multiboot2.h>
+#include <grub/elfload.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+
+static grub_addr_t entry;
+extern grub_dl_t my_mod;
+
+static char *grub_mb2_tags;
+static char *grub_mb2_tags_pos;
+static grub_size_t grub_mb2_tags_len;
+static int grub_mb2_tags_count;
+
+static void
+grub_mb2_tags_free (void)
+{
+ grub_dprintf ("loader", "Freeing all tags...\n");
+ grub_free (grub_mb2_tags);
+ grub_mb2_tags = 0;
+ grub_mb2_tags_pos = 0;
+ grub_mb2_tags_len = 0;
+ grub_mb2_tags_count = 0;
+}
+
+grub_err_t
+grub_mb2_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_mb2_tags_pos - grub_mb2_tags;
+ len = ALIGN_UP (len, sizeof (multiboot_word));
+
+ needed = used + len;
+
+ if (needed > grub_mb2_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_mb2_tags, grub_mb2_tags_len);
+ grub_free (grub_mb2_tags);
+
+ grub_mb2_tags_len = newsize;
+ grub_mb2_tags = newarea;
+ grub_mb2_tags_pos = newarea + used;
+ }
+
+ tag = (struct multiboot_tag_header *) grub_mb2_tags_pos;
+ grub_mb2_tags_pos += len;
+
+ tag->key = key;
+ tag->len = len;
+
+ if (addr)
+ *addr = (grub_addr_t) tag;
+
+ grub_mb2_tags_count++;
+
+ grub_dprintf ("loader", "Allocated tag %u at %p.\n", grub_mb2_tags_count, tag);
+
+ return 0;
+}
+
+static grub_err_t
+grub_mb2_tag_start_create (void)
+{
+ return grub_mb2_tag_alloc (0, MULTIBOOT2_TAG_START,
+ sizeof (struct multiboot_tag_start));
+}
+
+static grub_err_t
+grub_mb2_tag_name_create (void)
+{
+ struct multiboot_tag_name *name;
+ grub_addr_t name_addr;
+ grub_err_t err;
+ const char *grub_version = PACKAGE_STRING;
+
+ err = grub_mb2_tag_alloc (&name_addr, MULTIBOOT2_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;
+}
+
+typedef grub_err_t (*tag_create_t) (void);
+static tag_create_t grub_mb2_tag_creators[] = {
+ grub_mb2_tag_start_create,
+ grub_mb2_tag_name_create,
+ grub_mb2_tags_arch_create,
+ 0,
+};
+
+static grub_err_t
+grub_mb2_tags_create (void)
+{
+ tag_create_t *creator;
+ grub_err_t err;
+
+ for (creator = grub_mb2_tag_creators; *creator != 0; creator++)
+ {
+ err = (*creator) ();
+ if (err)
+ goto error;
+ }
+
+ return GRUB_ERR_NONE;
+
+error:
+ grub_error_push ();
+ grub_mb2_tags_free ();
+ grub_error_pop ();
+ return err;
+}
+
+static grub_err_t
+grub_mb2_tags_finish (void)
+{
+ struct multiboot_tag_start *start;
+ grub_err_t err;
+
+ /* Create the `end' tag. */
+ err = grub_mb2_tag_alloc (0, MULTIBOOT2_TAG_END,
+ sizeof (struct multiboot_tag_end));
+ if (err)
+ goto error;
+
+ /* We created the `start' tag first. Update it now. */
+ start = (struct multiboot_tag_start *) grub_mb2_tags;
+ start->size = grub_mb2_tags_pos - grub_mb2_tags;
+ return GRUB_ERR_NONE;
+
+error:
+ grub_error_push ();
+ grub_mb2_tags_free ();
+ grub_error_pop ();
+ return err;
+}
+
+static grub_err_t
+grub_mb2_boot (void)
+{
+ grub_mb2_tags_finish ();
+
+ grub_dprintf ("loader", "Tags at %p\n", grub_mb2_tags);
+ grub_mb2_arch_boot (entry, grub_mb2_tags);
+
+ /* Not reached. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_mb2_unload (void)
+{
+ struct multiboot_tag_header *tag;
+ struct multiboot_tag_header *tags =
+ (struct multiboot_tag_header *) grub_mb2_tags;
+
+ /* Free all module memory in the tag list. */
+ for_each_tag (tag, tags)
+ {
+ if (tag->key == MULTIBOOT2_TAG_MODULE)
+ {
+ struct multiboot_tag_module *module =
+ (struct multiboot_tag_module *) tag;
+ grub_free ((void *) module->addr);
+ }
+ }
+
+ /* Allow architecture to un-reserve memory. */
+ grub_mb2_arch_unload (tags);
+
+ /* Free the tags themselves. */
+ grub_mb2_tags_free ();
+
+ grub_dl_unref (my_mod);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_mb2_load_other (UNUSED grub_file_t file, UNUSED void *buffer)
+{
+ /* XXX Create module tag here. */
+ return grub_error (GRUB_ERR_UNKNOWN_OS, "currently only ELF is supported");
+}
+
+/* Create the tag containing the cmdline and the address of the module data. */
+static grub_err_t
+grub_mb2_tag_module_create (grub_addr_t modaddr, grub_size_t modsize,
+ char *type, int key, int argc, char *argv[])
+{
+ struct multiboot_tag_module *module;
+ grub_ssize_t argslen = 0;
+ grub_err_t err;
+ char *p;
+ grub_addr_t module_addr;
+ int i;
+
+ /* Allocate enough space for the arguments and spaces between them. */
+ for (i = 0; i < argc; i++)
+ argslen += grub_strlen (argv[i]) + 1;
+
+ /* Note: includes implicit 1-byte cmdline. */
+ err = grub_mb2_tag_alloc (&module_addr, key,
+ sizeof (struct multiboot_tag_module) + argslen);
+ if (err)
+ return grub_errno;
+
+ module = (struct multiboot_tag_module *) module_addr;
+ module->addr = modaddr;
+ module->size = modsize;
+ grub_strcpy(module->type, type);
+
+ /* Fill in the command line. */
+ p = module->cmdline;
+ for (i = 0; i < argc; i++)
+ {
+ p = grub_stpcpy (p, argv[i]);
+ *p++ = ' ';
+ }
+ module->cmdline[argslen] = '\0';
+
+ return GRUB_ERR_NONE;
+}
+
+/* Load ELF32 or ELF64. */
+static grub_err_t
+grub_mb2_load_elf (grub_elf_t elf, int argc, char *argv[])
+{
+ grub_addr_t kern_base;
+ grub_size_t kern_size;
+ grub_err_t err;
+
+ if (grub_elf_is_elf32 (elf))
+ {
+ entry = elf->ehdr.ehdr32.e_entry;
+ err = grub_elf32_load (elf, grub_mb2_arch_elf32_hook, &kern_base,
+ &kern_size);
+ }
+ else if (grub_elf_is_elf64 (elf))
+ {
+ entry = elf->ehdr.ehdr64.e_entry;
+ err = grub_elf64_load (elf, grub_mb2_arch_elf64_hook, &kern_base,
+ &kern_size);
+ }
+ else
+ err = grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
+
+ if (err)
+ goto fail;
+
+ grub_dprintf ("loader", "Entry point is 0x%lx.\n", (unsigned long) entry);
+
+ grub_mb2_tag_module_create (kern_base, kern_size, "kernel",
+ MULTIBOOT2_TAG_MODULE, argc, argv);
+
+fail:
+ return err;
+}
+
+void
+grub_multiboot2 (int argc, char *argv[])
+{
+ char *buffer;
+ grub_file_t file = 0;
+ grub_elf_t elf = 0;
+ struct multiboot_header *header = 0;
+ char *p;
+ grub_ssize_t len;
+ grub_err_t err;
+ int header_found = 0;
+
+ 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;
+ }
+
+ buffer = grub_malloc (MULTIBOOT2_HEADER_SEARCH);
+ if (! buffer)
+ return;
+
+ len = grub_file_read (file, buffer, MULTIBOOT2_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 == MULTIBOOT2_HEADER_MAGIC)
+ {
+ header_found = 1;
+ break;
+ }
+ }
+
+ if (! header_found)
+ grub_dprintf ("loader", "No multiboot 2 header found.\n");
+
+
+ /* Create the basic tags. */
+ grub_dprintf ("loader", "Creating multiboot 2 tags\n");
+ grub_mb2_tags_create ();
+
+ /* Load the kernel and create its tag. */
+ elf = grub_elf_file (file);
+ if (elf)
+ {
+ grub_dprintf ("loader", "Loading ELF multiboot 2 file.\n");
+ err = grub_mb2_load_elf (elf, argc-1, &argv[1]);
+ grub_elf_close (elf);
+ }
+ else
+ {
+ grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");
+
+ if (header)
+ err = grub_mb2_load_other (file, header);
+ else
+ err = grub_error (GRUB_ERR_BAD_OS,
+ "Need multiboot 2 header to load non-ELF files.");
+ grub_file_close (file);
+ }
+
+ grub_free (buffer);
+
+ if (err)
+ goto fail;
+
+ /* Good to go. */
+ grub_loader_set (grub_mb2_boot, grub_mb2_unload, 1);
+ return;
+
+fail:
+ grub_mb2_tags_free ();
+ grub_dl_unref (my_mod);
+}
+
+void
+grub_module2 (int argc, char *argv[])
+{
+ grub_file_t file;
+ grub_addr_t modaddr = 0;
+ grub_ssize_t modsize = 0;
+ grub_err_t err;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+ return;
+ }
+
+ if (argc == 1)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "No module type specified");
+ return;
+ }
+
+ if (entry == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "You need to load the multiboot kernel first");
+ return;
+ }
+
+ /* Load module data. */
+ file = grub_gzfile_open (argv[0], 1);
+ if (! file)
+ goto out;
+
+ modsize = grub_file_size (file);
+ err = grub_mb2_arch_module_alloc (modsize, &modaddr);
+ if (err)
+ goto out;
+
+ grub_dprintf ("loader", "Loading module at 0x%x - 0x%x\n", modaddr,
+ modaddr + modsize);
+ if (grub_file_read (file, (char *) modaddr, modsize) != modsize)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+ goto out;
+ }
+
+ /* Create the module tag. */
+ err = grub_mb2_tag_module_create (modaddr, modsize,
+ argv[1], MULTIBOOT2_TAG_MODULE,
+ argc-2, &argv[2]);
+ if (err)
+ goto out;
+
+out:
+ grub_error_push ();
+
+ if (file)
+ grub_file_close (file);
+
+ if (modaddr)
+ grub_mb2_arch_module_free (modaddr, modsize);
+
+ grub_error_pop ();
+}
--- /dev/null
+/* multiboot_loader.c - boot multiboot 1 or 2 OS image */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/multiboot_loader.h>
+#include <grub/multiboot.h>
+#include <grub/multiboot2.h>
+#include <grub/elf.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+
+grub_dl_t my_mod;
+
+/* This tracks which version of multiboot to use when using
+ * the module command. By default use multiboot version 1.
+ * values:
+ * 1 - Mulitboot version 1
+ * 2 - Mutliboot version 2
+ */
+
+static unsigned int module_version_status = 1;
+
+static int
+find_multi_boot1_header (grub_file_t file)
+{
+ struct grub_multiboot_header *header;
+ char buffer[MULTIBOOT_SEARCH];
+ int found_status = 0;
+ grub_ssize_t len;
+
+ len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
+ if (len < 32)
+ return found_status;
+
+ /* 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 == MULTIBOOT_MAGIC
+ && !(header->magic + header->flags + header->checksum))
+ {
+ found_status = 1;
+ break;
+ }
+ }
+
+ return found_status;
+}
+
+void
+grub_rescue_cmd_multiboot_loader (int argc, char *argv[])
+{
+
+ grub_file_t file = 0;
+ int header_multi_ver_found = 0;
+
+ grub_dl_ref (my_mod);
+
+ 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;
+ }
+
+ /* find which header is in the file */
+ if (find_multi_boot1_header(file))
+ header_multi_ver_found = 1;
+ else
+ {
+ /* The behavior is that if you don't find a multiboot 1 header
+ use multiboot 2 loader (as you do not have to have a header
+ to use multiboot 2 */
+ grub_dprintf ("multiboot_loader", "No multiboot 1 header found. \n \
+ Using multiboot 2 loader\n");
+ header_multi_ver_found = 0;
+ }
+
+ /* close file before calling functions */
+ if (file)
+ grub_file_close (file);
+
+ /* Launch multi boot with header */
+
+ /* XXX Find a better way to identify this.
+ This is for i386-pc */
+#ifdef __i386__
+ if (header_multi_ver_found == 1)
+ {
+ grub_dprintf ("multiboot_loader",
+ "Launching multiboot 1 grub_multiboot() function\n");
+ grub_multiboot (argc, argv);
+ module_version_status = 1;
+ }
+#endif
+ if (header_multi_ver_found == 0 || header_multi_ver_found == 2)
+ {
+ grub_dprintf ("multiboot_loader",
+ "Launching mulitboot 2 grub_multiboot2() function\n");
+ grub_multiboot2 (argc, argv);
+ module_version_status = 2;
+ }
+
+ return;
+
+fail:
+ if (file)
+ grub_file_close (file);
+
+ grub_dl_unref (my_mod);
+}
+
+void
+grub_rescue_cmd_module_loader (int argc, char *argv[])
+{
+
+#ifdef __i386__
+ if (module_version_status == 1)
+ {
+ grub_dprintf("multiboot_loader",
+ "Launching multiboot 1 grub_module() function\n");
+ grub_module (argc, argv);
+ }
+#endif
+ if (module_version_status == 2)
+ {
+ grub_dprintf("multiboot_loader",
+ "Launching multiboot 2 grub_module2() function\n");
+ grub_module2 (argc, argv);
+ }
+}
+
+GRUB_MOD_INIT(multiboot)
+{
+ grub_rescue_register_command ("multiboot", grub_rescue_cmd_multiboot_loader,
+ "load a multiboot kernel");
+ grub_rescue_register_command ("module", grub_rescue_cmd_module_loader,
+ "load a multiboot module");
+
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(multiboot)
+{
+ grub_rescue_unregister_command ("mulitboot");
+ grub_rescue_unregister_command ("module");
+}
--- /dev/null
+/* multiboot_loader_normal.c - boot another boot loader */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/multiboot_loader.h>
+
+static grub_err_t
+grub_normal_cmd_multiboot (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_rescue_cmd_multiboot_loader (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_loader (argc, args);
+ return grub_errno;
+}
+
+GRUB_MOD_INIT(multiboot_loader_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_loader_normal)
+{
+ grub_unregister_command ("multiboot");
+ grub_unregister_command ("module");
+}
--- /dev/null
+/* multiboot.c - boot a multiboot 2 OS image. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/loader.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/multiboot2.h>
+#include <grub/err.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/machine/kernel.h>
+
+typedef void (*kernel_entry_t) (unsigned long, void *, int (void *),
+ unsigned long, unsigned long);
+
+/* Claim the memory occupied by the multiboot kernel. */
+grub_err_t
+grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+ int rc;
+
+ rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
+ if (rc)
+ return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim %x - %x",
+ phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
+
+ grub_dprintf ("loader", "Loading segment at 0x%x - 0x%x\n", phdr->p_paddr,
+ phdr->p_paddr + phdr->p_memsz);
+
+ return GRUB_ERR_NONE;
+}
+
+/* Claim the memory occupied by the multiboot kernel. */
+grub_err_t
+grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+ int rc;
+
+ rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
+ if (rc)
+ return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim 0x%lx - 0x%lx",
+ phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
+
+ grub_dprintf ("loader", "Loading segment at 0x%lx - 0x%lx\n",
+ (unsigned long) phdr->p_paddr,
+ (unsigned long) (phdr->p_paddr + phdr->p_memsz));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
+{
+ int rc;
+
+ /* XXX Will need to map on some firmwares. */
+ rc = grub_ieee1275_claim (0, size, MULTIBOOT2_MOD_ALIGN, addr);
+ if (rc)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "Firmware couldn't allocate memory (size 0x%lx)", size);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, grub_size_t size)
+{
+ grub_ieee1275_release (addr, size);
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_tags_arch_create (void)
+{
+ /* Nothing special. */
+ return GRUB_ERR_NONE;
+}
+
+/* Release the memory we claimed from Open Firmware above. */
+void
+grub_mb2_arch_unload (struct multiboot_tag_header *tags)
+{
+ struct multiboot_tag_header *tag;
+
+ /* Free all module memory in the tag list. */
+ for_each_tag (tag, tags)
+ {
+ if (tag->key == MULTIBOOT2_TAG_MODULE)
+ {
+ struct multiboot_tag_module *module =
+ (struct multiboot_tag_module *) tag;
+ grub_ieee1275_release (module->addr, module->size);
+ }
+ }
+}
+
+void
+grub_mb2_arch_boot (grub_addr_t entry_addr, void *tags)
+{
+ kernel_entry_t entry = (kernel_entry_t) entry_addr;
+ entry (MULTIBOOT2_BOOTLOADER_MAGIC, tags, grub_ieee1275_entry_fn, 0, 0);
+}