grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: multiboot module in grub2 --with-platform=efi --target=i386


From: Drew Rosen
Subject: Re: multiboot module in grub2 --with-platform=efi --target=i386
Date: Wed, 15 Apr 2009 06:58:37 -0700

We're interested, I've got 30 Xserves that will be paper weights pretty soon if we don't get a 64 bit linux OS on them... rendering for 3d fx in movies.

I'll try to start a http://grub.enbug.org/TestingOnXserve page shortly to combine all the info we've gathered so far.

Thanks.


On Apr 14, 2009, at 2:12 AM, phcoder wrote:

I did the patch for it, however it seems nobody is interested to test it. With it I'm able to boot grub invaders on qemu-tianocore. And I have no xserve. For convenience I resend the patch. If it works I'll split it into components as required for review. Also have a look at http://grub.enbug.org/TestingOnMacbook for some relevant fixes (in linux section).
Drew Rosen wrote:
Hi Uzer Cheg.
Any progress on the Xserve?
On Mar 18, 2009, at 6:22 AM, uzer cheg wrote:
Dear all,

I'm trying to run Xen Dom0 kernel on my Xserve.
As I see I need Grub's entry like this:

menuentry "Xen 3.3 unstable -i386
{
 search --set /boot/xen-3.3.gz
 multiboot /boot/xen-3.3.gz
 module /boot/vmlinuz-2.6.29-rc8-tip root=LABEL=/ ro console=tty0
 module /boot/initrd-2.6.29-rc8-tip.img
}

I just downloaded from svn latest grub2 (revision 2032) and tried to build it.
# cd grub2
# ./configure --with-platform=efi --target=i386
# make
# ./grub-mkimage -d . -o grub.efi apple appleldr boot cat chain
configfile cpio date ext2 echo fat gpt help hexdump hfs hfsplus
iso9660 linux ls normal pc reboot reiserfs scsi search sleep xfs
multiboot module

I got error message
# grub-mkimage: error: cannot stat ./multiboot.mod

I think that make did not build multiboot.mod for efi.
Help me please.
Tell me please how to enable multiboot and module support in efi grub2?

Thank you in advance.


_______________________________________________
Grub-devel mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/grub-devel
_______________________________________________
Grub-devel mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/grub-devel


--

Regards
Vladimir 'phcoder' Serbinenko
diff --git a/conf/common.rmk b/conf/common.rmk
index b0a78b0..fb36edb 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -525,3 +525,10 @@ gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
bufio_mod_SOURCES = io/bufio.c
bufio_mod_CFLAGS = $(COMMON_CFLAGS)
bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += lsmmap.mod
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 41c45db..1cd7484 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -101,8 +101,7 @@ grub_install_SOURCES = util/i386/pc/grub- install.in
pkglib_MODULES = linux.mod normal.mod multiboot.mod     \
        aout.mod play.mod serial.mod ata.mod            \
        memdisk.mod pci.mod lspci.mod reboot.mod        \
-       halt.mod datetime.mod date.mod datehook.mod     \
-       lsmmap.mod
+       halt.mod datetime.mod date.mod datehook.mod     

# For linux.mod.
linux_mod_SOURCES = loader/i386/linux.c
@@ -200,10 +199,5 @@ datehook_mod_SOURCES = hook/datehook.c
datehook_mod_CFLAGS = $(COMMON_CFLAGS)
datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)

-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
include $(srcdir)/conf/i386.mk
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 399376f..e185337 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -81,7 +81,17 @@ grub_install_SOURCES = util/i386/efi/grub- install.in
# Modules.
pkglib_MODULES = kernel.mod normal.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
+       datetime.mod date.mod datehook.mod loadbios.mod \
+       fixvideo.mod multiboot.mod
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/i386/multiboot.c \
+                        loader/i386/multiboot_helper.S \
+                         loader/multiboot2.c \
+                         loader/efi/multiboot2.c \
+                         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
@@ -91,14 +101,14 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
        kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
        kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
        term/efi/console.c disk/efi/efidisk.c \
- kern/time.c kern/list.c kern/handler.c kern/command.c kern/ corecmd.c \ + kern/efi/mmap.c kern/time.c kern/list.c kern/handler.c kern/ command.c kern/corecmd.c \
        kern/i386/tsc.c kern/i386/pit.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c
kernel_mod_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
        partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
-       efi/efi.h efi/time.h efi/disk.h list.h handler.h command.h
+ efi/efi.h efi/time.h efi/disk.h efi/memory.h list.h handler.h command.h
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 96d9c10..df8c062 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -103,7 +103,7 @@ grub_install_SOURCES = util/ieee1275/grub- install.in
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod             \
        multiboot.mod aout.mod serial.mod linux.mod     \
        nand.mod memdisk.mod pci.mod lspci.mod datetime.mod     \
-       date.mod datehook.mod lsmmap.mod
+       date.mod datehook.mod

#
# Only arch dependant part of normal.mod will be here. Common part for
@@ -128,6 +128,7 @@ normal_mod_LDFLAGS = $(COMMON_LDFLAGS)

# For multiboot.mod.
multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
+                       loader/i386/multiboot.c \
                        loader/i386/multiboot_helper.S \
                         loader/multiboot2.c \
                         loader/multiboot_loader.c
@@ -200,10 +201,5 @@ datehook_mod_SOURCES = hook/datehook.c
datehook_mod_CFLAGS = $(COMMON_CFLAGS)
datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)

-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
include $(srcdir)/conf/i386.mk
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 7dfb854..82ede6e 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -289,16 +289,6 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)

-# For aout.mod
-aout_mod_SOURCES = loader/aout.c
-aout_mod_CFLAGS = $(COMMON_CFLAGS)
-aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
-# For bsd.mod
-bsd_mod_SOURCES = loader/i386/bsd.c
-bsd_mod_CFLAGS = $(COMMON_CFLAGS)
-bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For usb.mod
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
usb_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -354,11 +344,6 @@ datehook_mod_SOURCES = hook/datehook.c
datehook_mod_CFLAGS = $(COMMON_CFLAGS)
datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)

-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For ata_pthru.mod.
ata_pthru_mod_SOURCES = disk/ata_pthru.c
ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS)
diff --git a/conf/i386.rmk b/conf/i386.rmk
index 93f84ce..ddf7118 100644
--- a/conf/i386.rmk
+++ b/conf/i386.rmk
@@ -14,3 +14,21 @@ pkglib_MODULES += vga_text.mod
vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c
vga_text_mod_CFLAGS = $(COMMON_CFLAGS)
vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += uppermem.mod
+uppermem_mod_SOURCES = lib/i386/uppermem.c
+uppermem_mod_CFLAGS = $(COMMON_CFLAGS)
+uppermem_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += aout.mod bsd.mod
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd_helper.S
+bsd_mod_CFLAGS = $(COMMON_CFLAGS) -Werror
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+bsd_mod_ASFLAGS = $(COMMON_ASFLAGS)
+
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index 361fb85..c084370 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -111,8 +111,7 @@ pkglib_MODULES = halt.mod \
        reboot.mod \
        suspend.mod \
        multiboot.mod \
-       memdisk.mod \
-       lsmmap.mod
+       memdisk.mod

# For linux.mod.
linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
@@ -167,10 +166,5 @@ memdisk_mod_SOURCES = disk/memdisk.c
memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)

-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
include $(srcdir)/conf/common.mk

diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 8c277c0..137a437 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -54,6 +54,8 @@ char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
grub_efi_device_path_t *
EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
int EXPORT_FUNC(grub_efi_exit_boot_services) (grub_efi_uintn_t map_key);
+int EXPORT_FUNC(grub_efi_finish_boot_services) (void);
+
void EXPORT_FUNC (grub_reboot) (void);
void EXPORT_FUNC (grub_halt) (void);

diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h
new file mode 100644
index 0000000..9000642
--- /dev/null
+++ b/include/grub/efi/memory.h
@@ -0,0 +1,15 @@
+#ifndef GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER     1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+#define GRUB_MACHINE_MEMORY_AVAILABLE  1
+#define GRUB_MACHINE_MEMORY_RESERVED   2
+#define GRUB_MACHINE_MEMORY_ACPI       3
+#define GRUB_MACHINE_MEMORY_NVS         4
+#define GRUB_MACHINE_MEMORY_CODE         5
+
+grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
+(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+#endif /* ! GRUB_MEMORY_MACHINE_HEADER */
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
index f50f18e..723dff5 100644
--- a/include/grub/i386/bsd.h
+++ b/include/grub/i386/bsd.h
@@ -148,6 +148,8 @@ struct grub_openbsd_bios_mmap
{
  grub_uint64_t addr;
  grub_uint64_t len;
+#define        OPENBSD_MMAP_AVAILABLE  1
+#define        OPENBSD_MMAP_RESERVED 2
  grub_uint32_t type;
};

@@ -222,4 +224,7 @@ struct grub_netbsd_btinfo_bootdisk
  int partition;
};

+void grub_unix_real_boot (grub_addr_t entry, ...)
+  __attribute__ ((cdecl,noreturn));
+
#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/ memory.h
new file mode 100644
index 0000000..c9a61bb
--- /dev/null
+++ b/include/grub/i386/efi/memory.h
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index afd3eb9..685c2e0 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -27,12 +27,14 @@ 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_int32_t EXPORT_VAR(grub_linux_is_bzimage);
-extern grub_addr_t EXPORT_VAR(grub_os_area_addr);
-extern grub_size_t EXPORT_VAR(grub_os_area_size);

grub_err_t EXPORT_FUNC(grub_linux16_boot) (void);

-void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
-     __attribute__ ((cdecl,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 EXPORT_FUNC(grub_stop_floppy) (void);

#endif /* ! GRUB_LOADER_CPU_HEADER */
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/include/grub/i386/pc/memory.h b/include/grub/i386/pc/ memory.h
index 08e92a9..e69ff77 100644
--- a/include/grub/i386/pc/memory.h
+++ b/include/grub/i386/pc/memory.h
@@ -92,6 +92,8 @@ struct grub_machine_mmap_entry
  grub_uint64_t len;
#define GRUB_MACHINE_MEMORY_AVAILABLE   1
#define GRUB_MACHINE_MEMORY_RESERVED    2
+#define GRUB_MACHINE_MEMORY_ACPI       3
+#define GRUB_MACHINE_MEMORY_NVS        4
  grub_uint32_t type;
} __attribute__((packed));

diff --git a/include/grub/i386/uppermem.h b/include/grub/i386/ uppermem.h
new file mode 100644
index 0000000..bceed3e
--- /dev/null
+++ b/include/grub/i386/uppermem.h
@@ -0,0 +1,7 @@
+#ifndef GRUB_UPPERMEM_HEADER
+#define GRUB_UPPERMEM_HEADER
+
+grub_err_t
+grub_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper);
+
+#endif
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ ieee1275/ieee1275.h
index 3b5139e..48bc3f2 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -169,7 +169,6 @@ grub_err_t EXPORT_FUNC(grub_children_iterate) (char *devpath,
     int (*hook) (struct grub_ieee1275_devalias *alias));
grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
-int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);

char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path);
char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
diff --git a/include/grub/loader.h b/include/grub/loader.h
index 1ae5fdd..544b2f5 100644
--- a/include/grub/loader.h
+++ b/include/grub/loader.h
@@ -41,4 +41,8 @@ void EXPORT_FUNC(grub_loader_unset) (void);
   depending on the setting by grub_loader_set.  */
grub_err_t EXPORT_FUNC(grub_loader_boot) (void);

+int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
+
+void EXPORT_FUNC(grub_declaimmap) (grub_addr_t addr, grub_size_t size);
+
#endif /* ! GRUB_LOADER_HEADER */
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index bfbffcc..1e6701e 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -39,12 +39,6 @@ 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
diff --git a/include/grub/types.h b/include/grub/types.h
index 8d51b66..faf2257 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -100,6 +100,16 @@ typedef grub_int32_t       grub_ssize_t;
# define LONG_MAX 2147483647UL
#endif

+#if GRUB_CPU_SIZEOF_VOID_P == 4
+#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(x))
+#else
+#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x))
+#endif
+
/* The type for representing a file offset.  */
typedef grub_uint64_t   grub_off_t;

diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/ efi/memory.h
new file mode 100644
index 0000000..c9a61bb
--- /dev/null
+++ b/include/grub/x86_64/efi/memory.h
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>
diff --git a/kern/efi/efi.c b/kern/efi/efi.c
index 9c9a400..754f82c 100644
--- a/kern/efi/efi.c
+++ b/kern/efi/efi.c
@@ -187,6 +187,28 @@ grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
  return status == GRUB_EFI_SUCCESS;
}

+int
+grub_efi_finish_boot_services (void)
+{
+  grub_efi_uintn_t mmap_size = 0;
+  grub_efi_uintn_t map_key;
+  grub_efi_uintn_t desc_size;
+  grub_efi_uint32_t desc_version;
+  void *mmap_buf;
+
+  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+                              &desc_size, &desc_version) < 0)
+    return 0;
+
+  mmap_buf = grub_malloc (mmap_size);
+
+  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+                              &desc_size, &desc_version) <= 0)
+    return 0;
+
+  return  grub_efi_exit_boot_services (map_key);
+}
+
grub_uint32_t
grub_get_rtc (void)
{
diff --git a/kern/efi/mm.c b/kern/efi/mm.c
index 35b12ab..4635776 100644
--- a/kern/efi/mm.c
+++ b/kern/efi/mm.c
@@ -47,7 +47,7 @@ static struct allocated_page *allocated_pages = 0;

/* The minimum and maximum heap size for GRUB itself.  */
#define MIN_HEAP_SIZE   0x100000
-#define MAX_HEAP_SIZE  (16 * 0x100000)
+#define MAX_HEAP_SIZE  (1600 * 0x100000)


/* Allocate pages. Return the pointer to the first of allocated pages. */
diff --git a/kern/efi/mmap.c b/kern/efi/mmap.c
new file mode 100644
index 0000000..3f795cb
--- /dev/null
+++ b/kern/efi/mmap.c
@@ -0,0 +1,177 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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/machine/memory.h>
+#include <grub/err.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+
+#define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
+  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+struct region
+{
+  grub_uint64_t start;
+  grub_uint64_t len;
+  grub_uint32_t type;
+};
+
+grub_err_t
+grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  grub_efi_uintn_t mmap_size = 0;
+  grub_efi_memory_descriptor_t *map_buf;
+  grub_efi_uintn_t map_key = 0;
+  grub_efi_uintn_t desc_size = 0;
+  grub_efi_uint32_t desc_version = 0;
+  grub_uint64_t curstart, curend;
+  grub_uint32_t curtype;
+  grub_efi_memory_descriptor_t *desc;
+  struct region *regions;
+  struct region t;
+  int i, count, done = 1;
+
+  if (grub_efi_get_memory_map (&mmap_size, map_buf,
+                              &map_key, &desc_size,
+                              &desc_version) < 0)
+    return grub_errno;
+
+  map_buf = grub_malloc (mmap_size);
+  if (!map_buf)
+    return grub_errno;
+
+  if (grub_efi_get_memory_map (&mmap_size, map_buf,
+                              &map_key, &desc_size,
+                              &desc_version) <= 0)
+    {
+      grub_free (map_buf);
+      return grub_errno;
+    }
+
+  count = mmap_size / desc_size;
+  if (! count)
+    {
+      grub_free (map_buf);
+      return grub_error (GRUB_ERR_IO, "couldn't get EFI memory map");
+    }
+ regions = (struct region *) grub_malloc (count * sizeof (struct region));
+
+  for (desc = map_buf, i = 0;
+       desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)
+    {
+ grub_dprintf ("efi_mmap", "EFI memory region 0x%llx-0x%llx: %d \n",
+                   desc->physical_start, desc->physical_start
+                   + desc->num_pages * 4096, desc->type);
+      switch (desc->type)
+       {
+       case GRUB_EFI_RUNTIME_SERVICES_CODE:
+         regions[i].start = desc->physical_start;
+         regions[i].len = desc->num_pages * 4096;
+         regions[i].type = GRUB_MACHINE_MEMORY_CODE;
+         break;
+
+       case GRUB_EFI_RESERVED_MEMORY_TYPE:
+       case GRUB_EFI_RUNTIME_SERVICES_DATA:
+       case GRUB_EFI_UNUSABLE_MEMORY:
+       case GRUB_EFI_MEMORY_MAPPED_IO:
+       case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+       case GRUB_EFI_PAL_CODE:
+       case GRUB_EFI_MAX_MEMORY_TYPE:
+         regions[i].start = desc->physical_start;
+         regions[i].len = desc->num_pages * 4096;
+         regions[i].type = GRUB_MACHINE_MEMORY_RESERVED;
+         break;
+
+       case GRUB_EFI_LOADER_CODE:
+       case GRUB_EFI_LOADER_DATA:
+       case GRUB_EFI_BOOT_SERVICES_CODE:
+       case GRUB_EFI_BOOT_SERVICES_DATA:
+       case GRUB_EFI_CONVENTIONAL_MEMORY:
+         regions[i].start = desc->physical_start;
+         regions[i].len = desc->num_pages * 4096;
+         regions[i].type = GRUB_MACHINE_MEMORY_AVAILABLE;
+         break;
+
+       case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+         regions[i].start = desc->physical_start;
+         regions[i].len = desc->num_pages * 4096;
+         regions[i].type = GRUB_MACHINE_MEMORY_ACPI;
+         break;
+
+       case GRUB_EFI_ACPI_MEMORY_NVS:
+         regions[i].start = desc->physical_start;
+         regions[i].len = desc->num_pages * 4096;
+         regions[i].type = GRUB_MACHINE_MEMORY_NVS;
+         break;
+       }
+    }
+
+  /* Bubble-sort the memory map */
+  while (done)
+    {
+      done = 0;
+      for (i = 0; i < count - 1; i++)
+       if (regions[i].start > regions[i + 1].start)
+         {
+           done = 1;
+           t = regions[i];
+           regions[i] = regions[i + 1];
+           regions[i + 1] = t;
+         }
+    }
+
+  curstart = regions[0].start;
+  curend = regions[0].start + regions[0].len;
+  curtype = regions[0].type;
+  for (i = 1; i < count; i++)
+    {
+      if (curend != regions[i].start || curtype != regions[i].type)
+       {
+         hook (curstart, curend - curstart, curtype);
+         curstart = regions[i].start;
+         curtype = regions[i].type;    
+       }
+      curend = regions[i].start + regions[i].len;      
+    }
+
+  hook (curstart, curend - curstart, curtype);
+
+  return GRUB_ERR_NONE;
+}
+
+/* XXX: Manage subpage allocations */
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+  void *ret;
+  ret = grub_efi_allocate_pages (addr  & (~0xfff),
+                                (size + (addr & 0xfff) + 0xfff) >> 12);
+  return (! ret) ? -1 : 0;
+}
+
+/* XXX: Manage subpage allocations */
+void
+grub_declaimmap (grub_addr_t addr, grub_size_t size)
+{
+  grub_efi_free_pages (addr  & (~0xfff),
+                      (size + (addr & 0xfff) + 0xfff) >> 12);
+}
diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c
index 1348488..9c1aee0 100644
--- a/kern/i386/coreboot/init.c
+++ b/kern/i386/coreboot/init.c
@@ -155,3 +155,18 @@ grub_arch_modules_addr (void)
{
  return ALIGN_UP((grub_addr_t) _end, GRUB_MOD_ALIGN);
}
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+  if ((addr < grub_os_area_addr)
+      || (addr + size > grub_os_area_addr + grub_os_area_size))
+    return -1;
+  return 0;
+}
+
+void
+grub_declaimmap (grub_addr_t addr __attribute__ ((unused)),
+                grub_size_t size  __attribute__ ((unused)))
+{
+}
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index bbd2187..d9b37bf 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -117,26 +117,3 @@ bzimage:
linux_setup_seg:
        .word   0
        .code32
-
-/*
- * Use cdecl calling convention for *BSD kernels.
- */
-
-FUNCTION(grub_unix_real_boot)
-
-        call    EXT_C(grub_dl_unload_all)
-
-       /* Interrupts should be disabled.  */
-        cli
-
-       /* Discard `grub_unix_real_boot' return address.  */
-        popl    %eax
-
-        /* Fetch `entry' address ...  */
-        popl   %eax
-
-        /*
- * ... and put our return address in its place. The kernel will
-         * ignore it, but it expects %esp to point to it.
-         */
-        call   *%eax
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 6191412..17d5343 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -43,8 +43,8 @@ struct mem_region
static struct mem_region mem_regions[MAX_REGIONS];
static int num_regions;

-grub_addr_t grub_os_area_addr;
-grub_size_t grub_os_area_size;
+static grub_addr_t grub_os_area_addr;
+static grub_size_t grub_os_area_size;
grub_size_t grub_lower_mem, grub_upper_mem;

void
@@ -233,3 +233,18 @@ grub_arch_modules_addr (void)
  return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
    + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
}
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+  if ((addr < grub_os_area_addr)
+      || (addr + size > grub_os_area_addr + grub_os_area_size))
+    return -1;
+  return 0;
+}
+
+void
+grub_declaimmap (grub_addr_t addr __attribute__ ((unused)),
+                grub_size_t size  __attribute__ ((unused)))
+{
+}
diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c
index d70c3ba..c713d4c 100644
--- a/kern/ieee1275/openfw.c
+++ b/kern/ieee1275/openfw.c
@@ -194,6 +194,13 @@ grub_claimmap (grub_addr_t addr, grub_size_t size)
  return 0;
}

+/* XXX Could someone with better OFW knowledge that me fill this? */
+void
+grub_declaimmap (grub_addr_t addr __attribute__ ((unused)),
+                grub_size_t size  __attribute__ ((unused)))
+{
+}
+
/* Get the device arguments of the Open Firmware node name `path'.  */
static char *
grub_ieee1275_get_devargs (const char *path)
diff --git a/lib/i386/uppermem.c b/lib/i386/uppermem.c
new file mode 100644
index 0000000..623535f
--- /dev/null
+++ b/lib/i386/uppermem.c
@@ -0,0 +1,127 @@
+/* Compute amount of lower and upper memory till the first hole */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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 EFIEMU
+#include <grub/machine/memory.h>
+#include <grub/i386/uppermem.h>
+#endif
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+struct region
+{
+  grub_uint64_t start;
+  grub_uint64_t end;
+};
+
+#ifdef EFIEMU
+grub_err_t
+grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper)
+#else
+grub_err_t
+grub_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper)
+#endif
+{
+  grub_size_t count = 0;
+  struct region *regions = 0;
+  int done = 1;
+  unsigned i;
+  struct region t;
+  grub_uint64_t last_addr;
+
+ 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)
+    {
+#ifdef EFIEMU
+      if (type != GRUB_EFIEMU_MEMORY_AVAILABLE)
+#else
+      if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
+#endif
+       return 0;
+      regions = (struct region *)
+       grub_realloc (regions, (count + 1) * sizeof (struct region));
+      regions[count].start = addr;
+      regions[count].end = addr + size;
+      count++;
+      return 0;
+    }
+
+#ifdef EFIEMU
+  grub_efiemu_mmap_iterate (hook);
+#else
+  grub_machine_mmap_iterate (hook);
+#endif
+
+  /* Bubble-sort the memory map */
+  while (done)
+    {
+      done = 0;
+      for (i = 0; i < count - 1; i++)
+       if (regions[i].start > regions[i + 1].start)
+         {
+           done = 1;
+           t = regions[i];
+           regions[i] = regions[i + 1];
+           regions[i + 1] = t;
+         }
+    }
+
+  /* Set mem_upper and mem_lower */
+  last_addr = 0;
+  for (i = 0; i < count; i++)
+    {
+      grub_uint64_t end = regions[i].end;
+      /* Don't use memory after 0xa0000*/
+      if (end > 0xa0000)
+       end = 0xa0000;
+
+      /* low memory is finished */
+      if (regions[i].start > end)
+       break;
+
+      /* A hole */
+      if (regions[i].start > last_addr)
+       break;
+
+      last_addr = end;
+    }
+
+  *lower = last_addr;
+
+  /* Skip low memory */
+  for (i = 0; i < count && regions[i].end <= 0x100000;
+       i++);
+
+  last_addr = 0x100000;
+  for (; i < count; i++)
+    {
+      /* A hole */
+      if (regions[i].start > last_addr)
+       break;
+
+      last_addr = regions[i].end;
+    }
+
+  *upper = (last_addr - 0x100000);
+  grub_free (regions);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/efi/multiboot2.c b/loader/efi/multiboot2.c
new file mode 100644
index 0000000..44bb542
--- /dev/null
+++ b/loader/efi/multiboot2.c
@@ -0,0 +1,75 @@
+/* multiboot2.c - boot a multiboot 2 OS image. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008  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_module_alloc (grub_size_t size, grub_addr_t *addr)
+{
+  grub_addr_t modaddr;
+
+  modaddr = (grub_addr_t) 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 system table et al. */
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c
index 355cb3f..4023566 100644
--- a/loader/i386/bsd.c
+++ b/loader/i386/bsd.c
@@ -19,8 +19,8 @@
#include <grub/loader.h>
#include <grub/cpu/loader.h>
#include <grub/cpu/bsd.h>
-#include <grub/machine/init.h>
#include <grub/machine/memory.h>
+#include <grub/machine/machine.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
@@ -30,8 +30,13 @@
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/aout.h>
+#include <grub/i386/uppermem.h>
#include <grub/command.h>

+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+
#define ALIGN_DWORD(a)  ALIGN_UP (a, 4)
#define ALIGN_PAGE(a)   ALIGN_UP (a, 4096)

@@ -302,6 +307,15 @@ grub_freebsd_boot (void)

  bi.bi_kernend = kern_end;

+#ifdef GRUB_MACHINE_PCBIOS
+  grub_stop_floppy ();
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+  if (! grub_efi_finish_boot_services ())
+     grub_fatal ("cannot exit boot services");
+#endif
+
grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
                       0, 0, 0, &bi, bi.bi_modulep, kern_end);

@@ -313,30 +327,39 @@ static grub_err_t
grub_openbsd_boot (void)
{
  char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
-  struct grub_machine_mmap_entry mmap;
  struct grub_openbsd_bios_mmap *pm;
  struct grub_openbsd_bootargs *pa;
-  grub_uint32_t bootdev, biosdev, unit, slice, part, cont;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+  grub_uint64_t lower, upper;
+  grub_err_t err;
+
+ 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)
+    {
+      pm->addr = addr;
+      pm->len = size;
+
+      switch (type)
+        {
+        case GRUB_MACHINE_MEMORY_AVAILABLE:
+         pm->type = OPENBSD_MMAP_AVAILABLE;
+         break;
+       
+       default:
+         pm->type = OPENBSD_MMAP_RESERVED;
+         break;
+       }
+      pm++;
+
+      return 0;
+    }

  pa = (struct grub_openbsd_bootargs *) buf;

  pa->ba_type = OPENBSD_BOOTARG_MMAP;
  pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
-  cont = grub_get_mmap_entry (&mmap, 0);
-  if (mmap.size)
-    do
-      {
-       pm->addr = mmap.addr;
-       pm->len = mmap.len;
-       pm->type = mmap.type;
-       pm++;

-       if (!cont)
-         break;
-
-       cont = grub_get_mmap_entry (&mmap, cont);
-      }
-    while (mmap.size);
+  grub_machine_mmap_iterate (hook);

  pa->ba_size = (char *) pm - (char *) pa;
  pa->ba_next = (struct grub_openbsd_bootargs *) pm;
@@ -348,8 +371,20 @@ grub_openbsd_boot (void)
  bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
             (part << OPENBSD_B_PARTSHIFT));

+  if ((err = grub_get_lower_upper_memory (&lower, &upper)))
+    return err;
+
+#ifdef GRUB_MACHINE_PCBIOS
+  grub_stop_floppy ();
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+  if (! grub_efi_finish_boot_services ())
+     grub_fatal ("cannot exit boot services");
+#endif
+
grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
-                      0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+                      0, upper >> 10, lower >> 10,
                       (char *) pa - buf, buf);

  /* Not reached.  */
@@ -362,6 +397,8 @@ grub_netbsd_boot (void)
  struct grub_netbsd_btinfo_rootdevice *rootdev;
  struct grub_netbsd_bootinfo *bootinfo;
  grub_uint32_t biosdev, unit, slice, part;
+  grub_uint64_t lower, upper;
+  grub_err_t err;

  grub_bsd_get_device (&biosdev, &unit, &slice, &part);

@@ -376,8 +413,20 @@ grub_netbsd_boot (void)
  bootinfo->bi_count = 1;
  bootinfo->bi_data[0] = rootdev;

+  if ((err = grub_get_lower_upper_memory (&lower, &upper)))
+    return err;
+
+#ifdef GRUB_MACHINE_PCBIOS
+  grub_stop_floppy ();
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+  if (! grub_efi_finish_boot_services ())
+     grub_fatal ("cannot exit boot services");
+#endif
+
  grub_unix_real_boot (entry, bootflags, 0, bootinfo,
-                      0, grub_upper_mem >> 10, grub_lower_mem >> 10);
+                      0, upper >> 10, lower >> 10);

  /* Not reached.  */
  return GRUB_ERR_NONE;
@@ -461,8 +510,7 @@ grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr)
  phdr->p_paddr &= 0xFFFFFF;
  paddr = phdr->p_paddr;

-  if ((paddr < grub_os_area_addr)
- || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+  if (grub_claimmap (paddr, phdr->p_memsz) < 0)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
                       paddr);

@@ -578,7 +626,7 @@ grub_cmd_freebsd (grub_command_t cmd __attribute__ ((unused)),
          (grub_freebsd_add_meta_module (1, argc, argv, kern_start,
                                         kern_end - kern_start)))
        return grub_errno;
-      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0);
    }

  return grub_errno;
@@ -593,7 +641,7 @@ grub_cmd_openbsd (grub_command_t cmd __attribute__ ((unused)),
               grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));

  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
-    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 0);

  return grub_errno;
}
@@ -607,7 +655,7 @@ grub_cmd_netbsd (grub_command_t cmd __attribute__ ((unused)),
               grub_bsd_parse_flags (argv[1], netbsd_opts, netbsd_flags));

  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
-    grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
+    grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);

  return grub_errno;
}
@@ -725,7 +773,7 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
  if ((!file) || (!file->size))
    goto fail;

-  if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
+  if (grub_claimmap (kern_end, file->size) < 0)
    {
grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module");
      goto fail;
diff --git a/loader/i386/bsd_helper.S b/loader/i386/bsd_helper.S
new file mode 100644
index 0000000..9cdea0c
--- /dev/null
+++ b/loader/i386/bsd_helper.S
@@ -0,0 +1,65 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 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/>.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ *       Be careful of that you must not modify some registers. Quote
+ *       from gcc-2.95.2/gcc/config/i386/i386.h:
+
+   1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like.
+
+  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
+ */
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ * So the first three arguments are passed in %eax, %edx, and %ecx, + * respectively, and if a function has a fixed number of arguments + * and the number if greater than three, the function must return + * with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+#include <grub/symbol.h>
+
+/*
+ * Use cdecl calling convention for *BSD kernels.
+ */
+
+FUNCTION(grub_unix_real_boot)
+
+       /* Interrupts should be disabled.  */
+        cli
+
+       /* Discard `grub_unix_real_boot' return address.  */
+        popl    %eax
+
+        /* Fetch `entry' address ...  */
+        popl   %eax
+
+        /*
+ * ... and put our return address in its place. The kernel will
+         * ignore it, but it expects %esp to point to it.
+         */
+        call   *%eax
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index 100b268..e729a8e 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -18,6 +18,7 @@

#include <grub/loader.h>
#include <grub/machine/loader.h>
+#include <grub/machine/memory.h>
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/err.h>
@@ -46,9 +47,10 @@ static int loaded;
static void *real_mode_mem;
static void *prot_mode_mem;
static void *initrd_mem;
-static grub_efi_uintn_t real_mode_pages;
-static grub_efi_uintn_t prot_mode_pages;
-static grub_efi_uintn_t initrd_pages;
+static grub_size_t real_size;
+static grub_size_t mmap_size;
+static grub_size_t prot_size;
+static grub_size_t initrd_size;
static void *mmap_buf;

static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
@@ -95,26 +97,26 @@ page_align (grub_size_t size)

/* Find the optimal number of pages for the memory map. Is it better to
   move this code to efi/mm.c?  */
-static grub_efi_uintn_t
+static grub_size_t
find_mmap_size (void)
{
-  static grub_efi_uintn_t mmap_size = 0;
+  static grub_efi_uintn_t cache_mmap_size = 0;

-  if (mmap_size != 0)
-    return mmap_size;
+  if (cache_mmap_size != 0)
+    return cache_mmap_size;

-  mmap_size = (1 << 12);
+  cache_mmap_size = (1 << 12);
  while (1)
    {
      int ret;
      grub_efi_memory_descriptor_t *mmap;
      grub_efi_uintn_t desc_size;

-      mmap = grub_malloc (mmap_size);
+      mmap = grub_malloc (cache_mmap_size);
      if (! mmap)
        return 0;

- ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); + ret = grub_efi_get_memory_map (&cache_mmap_size, mmap, 0, &desc_size, 0);
      grub_free (mmap);

      if (ret < 0)
@@ -122,14 +124,14 @@ find_mmap_size (void)
      else if (ret > 0)
        break;

-      mmap_size += (1 << 12);
+      cache_mmap_size += (1 << 12);
    }

/* Increase the size a bit for safety, because GRUB allocates more on
     later, and EFI itself may allocate more.  */
-  mmap_size += (1 << 12);
+  cache_mmap_size += (1 << 12);

-  return page_align (mmap_size);
+  return page_align (cache_mmap_size);
}

static void
@@ -137,19 +139,19 @@ free_pages (void)
{
  if (real_mode_mem)
    {
- grub_efi_free_pages ((grub_addr_t) real_mode_mem, real_mode_pages); + grub_declaimmap ((grub_addr_t) real_mode_mem, real_size + mmap_size);
      real_mode_mem = 0;
    }

  if (prot_mode_mem)
    {
- grub_efi_free_pages ((grub_addr_t) prot_mode_mem, prot_mode_pages);
+      grub_declaimmap ((grub_addr_t) prot_mode_mem, prot_size);
      prot_mode_mem = 0;
    }

  if (initrd_mem)
    {
-      grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+      grub_declaimmap ((grub_addr_t) initrd_mem, initrd_size);
      initrd_mem = 0;
    }
}
@@ -161,9 +163,8 @@ allocate_pages (grub_size_t prot_size)
{
  grub_efi_uintn_t desc_size;
  grub_efi_memory_descriptor_t *mmap, *mmap_end;
-  grub_efi_uintn_t mmap_size, tmp_mmap_size;
+  grub_efi_uintn_t tmp_mmap_size;
  grub_efi_memory_descriptor_t *desc;
-  grub_size_t real_size;

  /* Make sure that each size is aligned to a page boundary.  */
  real_size = GRUB_LINUX_CL_END_OFFSET;
@@ -173,11 +174,6 @@ allocate_pages (grub_size_t prot_size)
grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
                (unsigned) real_size, (unsigned) prot_size, (unsigned) 
mmap_size);

-  /* Calculate the number of pages; Combine the real mode code with
-     the memory map buffer for simplicity.  */
-  real_mode_pages = ((real_size + mmap_size) >> 12);
-  prot_mode_pages = (prot_size >> 12);
-
  /* Initialize the memory pointers with NULL for convenience.  */
  real_mode_mem = 0;
  prot_mode_mem = 0;
@@ -192,44 +188,40 @@ allocate_pages (grub_size_t prot_size)
    grub_fatal ("cannot get memory map");

  mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
-
-  /* First, find free pages for the real mode code
-     and the memory map buffer.  */
-  for (desc = mmap;
-       desc < mmap_end;
-       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+
+ /* FIXME: Should request low memory from the heap when this feature is
+     implemented.  */
+
+ 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)
    {
- /* Probably it is better to put the real mode code in the traditional
-        space for safety.  */
-      if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-         && desc->physical_start <= 0x90000
-         && desc->num_pages >= real_mode_pages)
+      /* We must put real mode code in the traditional space.  */
+
+      if (type == GRUB_MACHINE_MEMORY_AVAILABLE
+         && addr <= 0x90000)
        {
-         grub_efi_physical_address_t physical_end;
-         grub_efi_physical_address_t addr;
-       
-         physical_end = desc->physical_start + (desc->num_pages << 12);
-         if (physical_end > 0x90000)
-           physical_end = 0x90000;
-
-         grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
-                       (unsigned) desc->physical_start,
-                       (unsigned) physical_end);
-         addr = physical_end - real_size - mmap_size;
          if (addr < 0x10000)
-           continue;
+           {
+             size += addr - 0x10000;
+             addr = 0x10000;
+           }

-         grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
-                       (unsigned) real_mode_pages, (unsigned long) addr);
-         real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
-         if (! real_mode_mem)
-           grub_fatal ("cannot allocate pages");
-       
-         desc->num_pages -= real_mode_pages;
-         break;
+         if (addr + size > 0x90000)
+           size = 0x90000 - addr;
+
+         if (real_size + mmap_size > size)
+           return 0;
+
+ real_mode_mem = (void *) ((addr + size) - (real_size + mmap_size));
+         if (grub_claimmap ((grub_addr_t) real_mode_mem,
+                            real_size + mmap_size) < 0)
+           return 0;
+         return 1;
        }
-    }

+      return 0;
+    }
+  grub_machine_mmap_iterate (hook);
  if (! real_mode_mem)
    {
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
@@ -238,20 +230,20 @@ allocate_pages (grub_size_t prot_size)

  mmap_buf = (void *) ((char *) real_mode_mem + real_size);
        
+  prot_mode_mem = (void *) 0x100000;
  /* Next, find free pages for the protected mode code.  */
  /* XXX what happens if anything is using this address?  */
- prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages);
-  if (! prot_mode_mem)
+  if (grub_claimmap (0x100000, prot_size) < 0)
    {
      grub_error (GRUB_ERR_OUT_OF_MEMORY,
                  "cannot allocate protected mode pages");
      goto fail;
    }

- grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
-               "prot_mode_mem = %lx, prot_mode_pages = %x\n",
-               (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
-               (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+  grub_dprintf ("linux", "real_mode_mem = %lx, real_size = %x, "
+                "prot_mode_mem = %lx, prot_size = %x\n",
+                (unsigned long) real_mode_mem, (unsigned) real_size,
+                (unsigned long) prot_mode_mem, (unsigned) prot_size);

  grub_free (mmap);
  return 1;
@@ -300,7 +292,6 @@ grub_linux_boot (void)
  grub_efi_uintn_t map_key;
  grub_efi_uintn_t desc_size;
  grub_efi_uint32_t desc_version;
-  grub_efi_memory_descriptor_t *desc;
  int e820_num;

  params = real_mode_mem;
@@ -318,77 +309,46 @@ grub_linux_boot (void)
                               &desc_size, &desc_version) <= 0)
    grub_fatal ("cannot get memory map");

-  e820_num = 0;
-  for (desc = mmap_buf;
-       desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
-       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+ 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)
    {
-      switch (desc->type)
-       {
-       case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+      switch (type)
+        {
+        case GRUB_MACHINE_MEMORY_AVAILABLE:
          grub_e820_add_region (params->e820_map, &e820_num,
-                               desc->physical_start,
-                               desc->num_pages << 12,
-                               GRUB_E820_ACPI);
+                               addr, size, GRUB_E820_RAM);
          break;

-       case GRUB_EFI_ACPI_MEMORY_NVS:
+#ifdef GRUB_MACHINE_MEMORY_ACPI
+        case GRUB_MACHINE_MEMORY_ACPI:
          grub_e820_add_region (params->e820_map, &e820_num,
-                               desc->physical_start,
-                               desc->num_pages << 12,
-                               GRUB_E820_NVS);
+                               addr, size, GRUB_E820_ACPI);
          break;
+#endif

-       case GRUB_EFI_RUNTIME_SERVICES_CODE:
+#ifdef GRUB_MACHINE_MEMORY_NVS
+        case GRUB_MACHINE_MEMORY_NVS:
          grub_e820_add_region (params->e820_map, &e820_num,
-                               desc->physical_start,
-                               desc->num_pages << 12,
-                               GRUB_E820_EXEC_CODE);
+                               addr, size, GRUB_E820_NVS);
          break;
+#endif

-       case GRUB_EFI_LOADER_CODE:
-       case GRUB_EFI_LOADER_DATA:
-       case GRUB_EFI_BOOT_SERVICES_CODE:
-       case GRUB_EFI_BOOT_SERVICES_DATA:
-       case GRUB_EFI_CONVENTIONAL_MEMORY:
-         {
-           grub_uint64_t start, size, end;
-
-           start = desc->physical_start;
-           size = desc->num_pages << 12;
-           end = start + size;
-
-           /* Skip A0000 - 100000 region.  */
-           if ((start < 0x100000ULL) && (end > 0xA0000ULL))
-             {
-               if (start < 0xA0000ULL)
-                 {
-                   grub_e820_add_region (params->e820_map, &e820_num,
-                                         start,
-                                         0xA0000ULL - start,
-                                         GRUB_E820_RAM);
-                 }
-
-               if (end <= 0x100000ULL)
-                 continue;
-
-               start = 0x100000ULL;
-               size = end - start;
-             }
-
-           grub_e820_add_region (params->e820_map, &e820_num,
-                                 start, size, GRUB_E820_RAM);
-           break;
-         }
-
-       default:
+#ifdef GRUB_MACHINE_MEMORY_CODE
+        case GRUB_MACHINE_MEMORY_CODE:
          grub_e820_add_region (params->e820_map, &e820_num,
-                               desc->physical_start,
-                               desc->num_pages << 12,
-                               GRUB_E820_RESERVED);
-       }
+                               addr, size, GRUB_E820_EXEC_CODE);
+         break;
+#endif
+
+        default:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                addr, size, GRUB_E820_RESERVED);
+        }
+      return 0;
    }

+  e820_num = 0;
+  grub_machine_mmap_iterate (hook);
  params->mmap_size = e820_num;

  if (! grub_efi_exit_boot_services (map_key))
@@ -633,7 +593,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
  struct linux_kernel_header lh;
  struct linux_kernel_params *params;
  grub_uint8_t setup_sects;
-  grub_size_t real_size, prot_size;
  grub_ssize_t len;
  int i;
  char *dest;
@@ -916,9 +875,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
  grub_ssize_t size;
  grub_addr_t addr_min, addr_max;
  grub_addr_t addr;
-  grub_efi_uintn_t mmap_size;
-  grub_efi_memory_descriptor_t *desc;
-  grub_efi_uintn_t desc_size;
  struct linux_kernel_header *lh;

  if (argc == 0)
@@ -938,11 +894,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
    goto fail;

  size = grub_file_size (file);
-  initrd_pages = (page_align (size) >> 12);
+  initrd_size = page_align (size);

  lh = (struct linux_kernel_header *) real_mode_mem;
+
+  /* Get the highest address available for the initrd.  */
+  if (grub_le_to_cpu16 (lh->version) >= 0x0203)
+    {
+      addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
+
+      /* XXX in reality, Linux specifies a bogus value, so
+        it is necessary to make sure that ADDR_MAX does not exceed
+        0x3fffffff.  */
+      if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
+       addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+    }
+  else
+    addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;

-  addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
  if (linux_mem_size != 0 && linux_mem_size < addr_max)
    addr_max = linux_mem_size;

@@ -953,49 +922,21 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
  addr_max -= 0x10000;

  /* Usually, the compression ratio is about 50%.  */
- addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
-            + page_align (size);
+  addr_min = (grub_addr_t) prot_mode_mem + prot_size * 3
+             + page_align (size);

-  /* Find the highest address to put the initrd.  */
-  mmap_size = find_mmap_size ();
- if (grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0)
-    grub_fatal ("cannot get memory map");
-
-  addr = 0;
-  for (desc = mmap_buf;
-       desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
-       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
-    {
-      if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-         && desc->num_pages >= initrd_pages)
-       {
-         grub_efi_physical_address_t physical_end;
-       
-         physical_end = desc->physical_start + (desc->num_pages << 12);
-         if (physical_end > addr_max)
-           physical_end = addr_max;
-
-         if (physical_end < page_align (size))
-           continue;
-
-         physical_end -= page_align (size);
-
-         if ((physical_end >= addr_min) &&
-             (physical_end >= desc->physical_start) &&
-             (physical_end > addr))
-           addr = physical_end;
-       }
-    }
+  /* Put the initrd as high as possible, 4KiB aligned.  */
+  addr = (addr_max - size) & ~0xFFF;
+  while (addr >= addr_min && grub_claimmap (addr, initrd_size) < 0)
+    addr -= 0x1000;

-  if (addr == 0)
+  if (addr < addr_min)
    {
-      grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free pages available");
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "The initrd is too big");
      goto fail;
    }

-  initrd_mem = grub_efi_allocate_pages (addr, initrd_pages);
-  if (! initrd_mem)
-    grub_fatal ("cannot allocate pages");
+  initrd_mem = (void *) addr;

  if (grub_file_read (file, initrd_mem, size) != size)
    {
diff --git a/loader/i386/linux.c b/loader/i386/linux.c
index 01d10d5..4811f1a 100644
--- a/loader/i386/linux.c
+++ b/loader/i386/linux.c
@@ -45,9 +45,10 @@ static int loaded;
static void *real_mode_mem;
static void *prot_mode_mem;
static void *initrd_mem;
-static grub_uint32_t real_mode_pages;
-static grub_uint32_t prot_mode_pages;
-static grub_uint32_t initrd_pages;
+static grub_size_t real_size;
+static grub_size_t mmap_size;
+static grub_size_t prot_size;
+static grub_size_t initrd_size;

static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
  {
@@ -182,7 +183,24 @@ find_mmap_size (void)
static void
free_pages (void)
{
-  real_mode_mem = prot_mode_mem = initrd_mem = 0;
+  if (real_mode_mem)
+    {
+      grub_declaimmap ((grub_addr_t) real_mode_mem, real_size
+                              + mmap_size);
+      real_mode_mem = 0;
+    }
+
+  if (prot_mode_mem)
+    {
+      grub_declaimmap ((grub_addr_t) prot_mode_mem, prot_size);
+      prot_mode_mem = 0;
+    }
+
+  if (initrd_mem)
+    {
+      grub_declaimmap ((grub_addr_t) initrd_mem, initrd_size);
+      initrd_mem = 0;
+    }
}

/* Allocate pages for the real mode code and the protected mode code
@@ -190,8 +208,6 @@ free_pages (void)
static int
allocate_pages (grub_size_t prot_size)
{
-  grub_size_t real_size, mmap_size;
-
  /* Make sure that each size is aligned to a page boundary.  */
  real_size = GRUB_LINUX_CL_END_OFFSET;
  prot_size = page_align (prot_size);
@@ -200,11 +216,6 @@ allocate_pages (grub_size_t prot_size)
grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
                (unsigned) real_size, (unsigned) prot_size, (unsigned) 
mmap_size);

-  /* Calculate the number of pages; Combine the real mode code with
-     the memory map buffer for simplicity.  */
-  real_mode_pages = ((real_size + mmap_size) >> 12);
-  prot_mode_pages = (prot_size >> 12);
-
  /* Initialize the memory pointers with NULL for convenience.  */
  free_pages ();

@@ -232,6 +243,8 @@ allocate_pages (grub_size_t prot_size)
            return 0;

          real_mode_mem = (void *) ((addr + size) - (real_size + mmap_size));
+         if (grub_claimmap (real_mode_mem, real_size + mmap_size) < 0)
+           return 0;
          return 1;
        }

@@ -245,6 +258,14 @@ allocate_pages (grub_size_t prot_size)
    }

  prot_mode_mem = (void *) 0x100000;
+  /* Next, find free pages for the protected mode code.  */
+  /* XXX what happens if anything is using this address?  */
+  if (grub_claimmap (0x100000, prot_size) < 0)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                 "cannot allocate protected mode pages");
+      goto fail;
+    }

  grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
                "prot_mode_mem = %lx, prot_mode_pages = %x\n",
@@ -396,6 +417,27 @@ grub_linux_boot (void)
                                addr, size, GRUB_E820_RAM);
          break;

+#ifdef GRUB_MACHINE_MEMORY_ACPI
+        case GRUB_MACHINE_MEMORY_ACPI:
+         grub_e820_add_region (params->e820_map, &e820_num,
+                               addr, size, GRUB_E820_ACPI);
+         break;
+#endif
+
+#ifdef GRUB_MACHINE_MEMORY_NVS
+        case GRUB_MACHINE_MEMORY_NVS:
+         grub_e820_add_region (params->e820_map, &e820_num,
+                               addr, size, GRUB_E820_NVS);
+         break;
+#endif
+
+#ifdef GRUB_MACHINE_MEMORY_CODE
+        case GRUB_MACHINE_MEMORY_CODE:
+         grub_e820_add_region (params->e820_map, &e820_num,
+                               addr, size, GRUB_E820_EXEC_CODE);
+         break;
+#endif
+
        default:
          grub_e820_add_region (params->e820_map, &e820_num,
                                addr, size, GRUB_E820_RESERVED);
@@ -457,7 +499,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
  struct linux_kernel_header lh;
  struct linux_kernel_params *params;
  grub_uint8_t setup_sects;
-  grub_size_t real_size, prot_size;
  grub_ssize_t len;
  int i;
  char *dest;
@@ -693,7 +734,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
    goto fail;

  size = grub_file_size (file);
-  initrd_pages = (page_align (size) >> 12);
+  initrd_size = page_align (size);

  lh = (struct linux_kernel_header *) real_mode_mem;

@@ -724,11 +765,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
             + page_align (size);

-  if (addr_max > grub_os_area_addr + grub_os_area_size)
-    addr_max = grub_os_area_addr + grub_os_area_size;
-
  /* Put the initrd as high as possible, 4KiB aligned.  */
  addr = (addr_max - size) & ~0xFFF;
+  while (addr >= addr_min && grub_claimmap (addr, initrd_size) < 0)
+    addr -= 0x1000;

  if (addr < addr_min)
    {
diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c
index 27042a5..055b1cf 100644
--- a/loader/i386/multiboot.c
+++ b/loader/i386/multiboot.c
@@ -30,7 +30,7 @@
#include <grub/loader.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
-#include <grub/machine/init.h>
+#include <grub/machine/machine.h>
#include <grub/machine/memory.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
@@ -43,6 +43,13 @@
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
+#include <grub/cpu/loader.h>
+#include <grub/cpu/multiboot.h>
+#include <grub/i386/uppermem.h>
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif

extern grub_dl_t my_mod;
static struct grub_multiboot_info *mbi, *mbi_dest;
@@ -54,6 +61,13 @@ static grub_size_t code_size;
static grub_err_t
grub_multiboot_boot (void)
{
+  grub_printf ("Boot\n");
+
+#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.  */
@@ -109,14 +123,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++;

@@ -199,6 +223,7 @@ grub_multiboot (int argc, char *argv[])
  struct grub_multiboot_header *header;
  grub_ssize_t len, cmdline_length, boot_loader_name_length;
  grub_uint32_t mmap_length;
+  grub_uint64_t lower, upper;
  int i;

  grub_loader_unset ();
@@ -286,7 +311,9 @@ grub_multiboot (int argc, char *argv[])
      grub_multiboot_payload_dest = header->load_addr;

      grub_multiboot_payload_size += code_size;
- playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+      playground = grub_malloc (RELOCATOR_SIZEOF(forward)
+                               + grub_multiboot_payload_size
+                               + RELOCATOR_SIZEOF(backward));
      if (! playground)
        goto fail;

@@ -341,9 +368,12 @@ grub_multiboot (int argc, char *argv[])
                grub_multiboot_payload_size,
                grub_multiboot_payload_entry_offset);

+  if (grub_get_lower_upper_memory (&lower, &upper))
+    goto fail;
+
  /* Convert from bytes to kilobytes.  */
-  mbi->mem_lower = grub_lower_mem / 1024;
-  mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->mem_lower = lower / 1024;
+  mbi->mem_upper = upper / 1024;
  mbi->flags |= MULTIBOOT_INFO_MEMORY;

  cmdline = p = cmdline_addr (grub_multiboot_payload_orig);
@@ -370,7 +400,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/i386/pc/linux.c b/loader/i386/pc/linux.c
index 8ff97f4..4823ddc 100644
--- a/loader/i386/pc/linux.c
+++ b/loader/i386/pc/linux.c
@@ -71,11 +71,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
  if (! file)
    goto fail;

-  if ((grub_size_t) grub_file_size (file) > grub_os_area_size)
+ if (grub_claimmap (GRUB_LINUX_BZIMAGE_ADDR, grub_file_size (file)) < 0)
    {
- grub_error (GRUB_ERR_OUT_OF_RANGE, "too big kernel (0x%x > 0x %x)",
-                 (grub_size_t) grub_file_size (file),
-                 grub_os_area_size);
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "too big kernel (0x%x)",
+                 (grub_size_t) grub_file_size (file));
      goto fail;
    }

@@ -340,9 +339,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
     worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
  addr_max -= 0x10000;

-  if (addr_max > grub_os_area_addr + grub_os_area_size)
-    addr_max = grub_os_area_addr + grub_os_area_size;
-
addr_min = (grub_addr_t) grub_linux_tmp_addr + GRUB_LINUX_CL_END_OFFSET;

  file = grub_file_open (argv[0]);
@@ -353,6 +349,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),

  /* Put the initrd as high as possible, 4KiB aligned.  */
  addr = (addr_max - size) & ~0xFFF;
+  while (addr >= addr_min && grub_claimmap (addr, size) < 0)
+    addr -= 0x1000;

  if (addr < addr_min)
    {
diff --git a/loader/i386/pc/multiboot2.c b/loader/i386/pc/multiboot2.c
index d5fe8e3..b065fa7 100644
--- a/loader/i386/pc/multiboot2.c
+++ b/loader/i386/pc/multiboot2.c
@@ -25,32 +25,6 @@
#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_error (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;
@@ -73,6 +47,7 @@ grub_mb2_arch_module_free (grub_addr_t addr, UNUSED grub_size_t size)
void
grub_mb2_arch_boot (grub_addr_t entry, void *tags)
{
+  grub_stop_floppy ();
  grub_multiboot2_real_boot (entry, tags);
}

diff --git a/loader/ieee1275/multiboot2.c b/loader/ieee1275/ multiboot2.c
index c253fc9..462135b 100644
--- a/loader/ieee1275/multiboot2.c
+++ b/loader/ieee1275/multiboot2.c
@@ -31,41 +31,6 @@
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)
{
diff --git a/loader/multiboot2.c b/loader/multiboot2.c
index 2fb56bf..a6cee06 100644
--- a/loader/multiboot2.c
+++ b/loader/multiboot2.c
@@ -38,6 +38,42 @@ static char *grub_mb2_tags_pos;
static grub_size_t grub_mb2_tags_len;
static int grub_mb2_tags_count;

+/* Claim the memory occupied by the multiboot kernel.  */
+static grub_err_t
+grub_mb2_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.  */
+static grub_err_t
+grub_mb2_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;
+}
+
+
static void
grub_mb2_tags_free (void)
{
@@ -279,13 +315,13 @@ grub_mb2_load_elf (grub_elf_t elf, int argc, char *argv[])
  if (grub_elf_is_elf32 (elf))
    {
      entry = elf->ehdr.ehdr32.e_entry;
- err = grub_elf32_load (elf, grub_mb2_arch_elf32_hook, &kern_base,
+      err = grub_elf32_load (elf, grub_mb2_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,
+      err = grub_elf64_load (elf, grub_mb2_elf64_hook, &kern_base,
                             &kern_size);
    }
  else
diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c
index f4a3933..6c30d5a 100644
--- a/loader/multiboot_loader.c
+++ b/loader/multiboot_loader.c
@@ -137,9 +137,7 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),

   /* Launch multi boot with header */

-   /* XXX Find a better way to identify this.
-      This is for i386-pc */
-#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+#if defined(__i386__)
  if (header_multi_ver_found == 1)
    {
      grub_dprintf ("multiboot_loader",
@@ -152,7 +150,9 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
    {
      grub_dprintf ("multiboot_loader",
           "Launching multiboot 2 grub_multiboot2() function\n");
+#ifndef GRUB_MACHINE_EFI
      grub_multiboot2 (argc, argv);
+#endif
      module_version_status = 2;
    }

@@ -172,7 +172,7 @@ grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
                        int argc, char *argv[])
{

-#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+#if defined(__i386__)
  if (module_version_status == 1)
    {
      grub_dprintf("multiboot_loader",
@@ -184,7 +184,9 @@ grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
    {
      grub_dprintf("multiboot_loader",
          "Launching multiboot 2 grub_module2() function\n");
+#ifndef GRUB_MACHINE_EFI
      grub_module2 (argc, argv);
+#endif
    }

  return grub_errno;
_______________________________________________
Grub-devel mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/grub-devel





reply via email to

[Prev in Thread] Current Thread [Next in Thread]