diff --git a/ChangeLog b/ChangeLog
index d7f219b..95ca160 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2009-08-02 Vladimir Serbinenko
+
+ Multiboot support on i386-efi.
+
+ * conf/i386-efi.rmk (pkglib_MODULES): Add multiboot.mod.
+ (multiboot_mod_SOURCES): New variable.
+ (multiboot_mod_CFLAGS): Likewise.
+ (multiboot_mod_LDFLAGS): Likewise.
+ (multiboot_mod_ASFLAGS): Likewise.
+ * include/grub/i386/multiboot.h (grub_multiboot_real_boot): Explicitly
+ declare as regparm (3).
+ (grub_multiboot2_real_boot): Likewise.
+ (grub_multiboot_boot): Finish boot services.
+ (grub_fill_multiboot_mmap): Explicitly parse memory map types.
+ (grub_multiboot): Declare as noreturn to avoid finishing console.
+ * loader/multiboot_loader.c (grub_cmd_multiboot_loader): Enable
+ multiboot1 on i386-efi and disable multiboot2 on this platform.
+ (grub_cmd_module_loader): Likewise.
+
2009-08-01 Vladimir Serbinenko
* util/hostfs.c (grub_hostfs_dir): Don't use DT_DIR: It doesn't work
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 9177b9d..248ad87 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -83,7 +83,15 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
linux.mod halt.mod reboot.mod pci.mod lspci.mod \
datetime.mod date.mod datehook.mod loadbios.mod \
- fixvideo.mod mmap.mod acpi.mod
+ fixvideo.mod mmap.mod acpi.mod multiboot.mod
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/i386/multiboot.c \
+ loader/i386/multiboot_helper.S \
+ loader/multiboot_loader.c
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
# For kernel.mod.
kernel_mod_EXPORTS = no
diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h
index 2dd7ec0..a6da360 100644
--- a/include/grub/i386/multiboot.h
+++ b/include/grub/i386/multiboot.h
@@ -22,10 +22,10 @@
/* The asm part of the multiboot loader. */
void grub_multiboot_real_boot (grub_addr_t entry,
struct grub_multiboot_info *mbi)
- __attribute__ ((noreturn));
+ __attribute__ ((noreturn,regparm (3)));
void grub_multiboot2_real_boot (grub_addr_t entry,
struct grub_multiboot_info *mbi)
- __attribute__ ((noreturn));
+ __attribute__ ((noreturn,regparm (3)));
extern grub_addr_t grub_multiboot_payload_orig;
extern grub_addr_t grub_multiboot_payload_dest;
diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c
index 87ffcae..f51a38d 100644
--- a/loader/i386/multiboot.c
+++ b/loader/i386/multiboot.c
@@ -30,8 +30,10 @@
#include
#include
#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -49,6 +51,13 @@
#include
#endif
+#include
+#include
+
+#ifdef GRUB_MACHINE_EFI
+#include
+#endif
+
extern grub_dl_t my_mod;
static struct grub_multiboot_info *mbi, *mbi_dest;
static grub_addr_t entry;
@@ -59,6 +68,11 @@ static grub_size_t code_size;
static grub_err_t
grub_multiboot_boot (void)
{
+#ifdef GRUB_MACHINE_EFI
+ if (! grub_efi_finish_boot_services ())
+ grub_fatal ("cannot exit boot services");
+#endif
+
grub_multiboot_real_boot (entry, mbi_dest);
/* Not reached. */
@@ -114,14 +128,24 @@ grub_get_multiboot_mmap_len (void)
static void
grub_fill_multiboot_mmap (struct grub_multiboot_mmap_entry *first_entry)
{
- struct grub_multiboot_mmap_entry *mmap_entry = (struct grub_multiboot_mmap_entry *) first_entry;
+ struct grub_multiboot_mmap_entry *mmap_entry
+ = (struct grub_multiboot_mmap_entry *) first_entry;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
mmap_entry->addr = addr;
mmap_entry->len = size;
- mmap_entry->type = type;
+ switch (type)
+ {
+ case GRUB_MACHINE_MEMORY_AVAILABLE:
+ mmap_entry->type = GRUB_MULTIBOOT_MEMORY_AVAILABLE;
+ break;
+
+ default:
+ mmap_entry->type = GRUB_MULTIBOOT_MEMORY_RESERVED;
+ break;
+ }
mmap_entry->size = sizeof (struct grub_multiboot_mmap_entry) - sizeof (mmap_entry->size);
mmap_entry++;
@@ -371,7 +395,7 @@ grub_multiboot (int argc, char *argv[])
if (grub_multiboot_get_bootdev (&mbi->boot_device))
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
- grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
+ grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c
index 986ee0b..7701ce0 100644
--- a/loader/multiboot_loader.c
+++ b/loader/multiboot_loader.c
@@ -140,7 +140,7 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
/* XXX Find a better way to identify this.
This is for i386-pc */
#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_COREBOOT) || \
- defined(GRUB_MACHINE_QEMU)
+ defined(GRUB_MACHINE_QEMU) || (defined(GRUB_MACHINE_EFI) && !defined (__x86_64__))
if (header_multi_ver_found == 1)
{
grub_dprintf ("multiboot_loader",
@@ -149,6 +149,7 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
module_version_status = 1;
}
#endif
+#if !defined(GRUB_MACHINE_EFI)
if (header_multi_ver_found == 0 || header_multi_ver_found == 2)
{
grub_dprintf ("multiboot_loader",
@@ -156,6 +157,7 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
grub_multiboot2 (argc, argv);
module_version_status = 2;
}
+#endif
return grub_errno;
@@ -174,7 +176,7 @@ grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
{
#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_COREBOOT) || \
- defined(GRUB_MACHINE_QEMU)
+ defined(GRUB_MACHINE_QEMU) || (defined(GRUB_MACHINE_EFI) && !defined (__x86_64__))
if (module_version_status == 1)
{
grub_dprintf("multiboot_loader",
@@ -182,13 +184,14 @@ grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
grub_module (argc, argv);
}
#endif
+#if !defined(GRUB_MACHINE_EFI)
if (module_version_status == 2)
{
grub_dprintf("multiboot_loader",
"Launching multiboot 2 grub_module2() function\n");
grub_module2 (argc, argv);
}
-
+#endif
return grub_errno;
}