grub-devel
[Top][All Lists]
Advanced

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

multiboot on EFI


From: phcoder
Subject: multiboot on EFI
Date: Mon, 23 Mar 2009 13:29:55 +0100
User-agent: Thunderbird 2.0.0.21 (X11/20090318)

Hello. Here is an initial version of patch for booting multiboot kernels on i386-efi. No Changelog yet because it's not for inclusion yet.
--

Regards
Vladimir 'phcoder' Serbinenko
diff --git a/conf/common.rmk b/conf/common.rmk
index 100fae7..e64a1a4 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -507,3 +507,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 6f4e8f3..1304eb3 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -102,8 +102,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod    \
        _multiboot.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
@@ -211,10 +210,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 a2454d9..4303b1c 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -80,7 +80,20 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
 # Modules.
 pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
        _linux.mod linux.mod halt.mod reboot.mod pci.mod lspci.mod \
-       datetime.mod date.mod datehook.mod
+       datetime.mod date.mod datehook.mod _multiboot.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 multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -90,14 +103,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/efi/mmap.c kern/time.c kern/list.c kern/handler.c \
        kern/i386/tsc.c kern/i386/pit.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c
 kernel_mod_HEADERS = arg.h 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
+       efi/efi.h efi/time.h efi/disk.h efi/memory.h list.h handler.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 305b31d..460dfdd 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -102,7 +102,7 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
 pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod            \
        multiboot.mod _multiboot.mod aout.mod serial.mod linux.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
@@ -209,10 +209,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 e1ed9aa..0be2729 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -178,8 +178,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod 
linux.mod normal.mod \
        _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
        vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod     \
        ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
-       aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
-       datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
+       pxe.mod pxecmd.mod datetime.mod date.mod \
+       datehook.mod ata_pthru.mod hdparm.mod \
        usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \
        efiemu.mod efiemu_acpi.mod efiemu_pnvram.mod
 
@@ -318,21 +318,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 bsd.mod
-bsd_mod_SOURCES = loader/i386/bsd_normal.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)
@@ -388,11 +373,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 4e86ed8..5338457 100644
--- a/conf/i386.rmk
+++ b/conf/i386.rmk
@@ -19,3 +19,21 @@ 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 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)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd_normal.c
+bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index 66d1d58..c9e185a 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -112,8 +112,7 @@ pkglib_MODULES = halt.mod \
        suspend.mod \
         _multiboot.mod \
         multiboot.mod \
-       memdisk.mod \
-       lsmmap.mod
+       memdisk.mod 
 
 # For _linux.mod.
 _linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
@@ -178,10 +177,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 00296c9..e8bed00 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;
 };
 
@@ -229,4 +231,7 @@ void grub_rescue_cmd_netbsd (int argc, char *argv[]);
 void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
 void grub_rescue_cmd_freebsd_module (int argc, char *argv[]);
 
+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 f858c0a..cb2f918 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -32,9 +32,6 @@ extern grub_size_t EXPORT_VAR(grub_os_area_size);
 
 grub_err_t EXPORT_FUNC(grub_linux_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[]);
diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h
index ea68640..85405dc 100644
--- a/include/grub/i386/multiboot.h
+++ b/include/grub/i386/multiboot.h
@@ -22,7 +22,7 @@
 /* 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));
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/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..11fbc72
--- /dev/null
+++ b/kern/efi/mmap.c
@@ -0,0 +1,158 @@
+/*
+ *  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>
+
+#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;
+}
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index fc27b86..f1b6c18 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -117,27 +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)
-        call    EXT_C(grub_stop_floppy)
-
-       /* 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/bsd.c b/loader/i386/bsd.c
index 25d0f59..712b013 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/rescue.h>
@@ -31,6 +31,11 @@
 #include <grub/misc.h>
 #include <grub/gzio.h>
 #include <grub/aout.h>
+#include <grub/i386/uppermem.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,10 +510,10 @@ 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)
+  /*  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);
+    paddr);*/
 
   if ((!kern_start) || (paddr < kern_start))
     kern_start = paddr;
@@ -577,7 +626,7 @@ grub_rescue_cmd_freebsd (int argc, char *argv[])
          (grub_freebsd_add_meta_module (1, argc, argv, kern_start,
                                         kern_end - kern_start)))
        return;
-      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0);
     }
 }
 
@@ -589,7 +638,7 @@ grub_rescue_cmd_openbsd (int argc, char *argv[])
               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);
 }
 
 void
@@ -600,7 +649,7 @@ grub_rescue_cmd_netbsd (int argc, char *argv[])
               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);
 }
 
 void
@@ -718,11 +767,11 @@ grub_rescue_cmd_freebsd_module (int argc, char *argv[])
   if ((!file) || (!file->size))
     goto fail;
 
-  if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
+  /*  if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
     {
       grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module");
       goto fail;
-    }
+      }*/
 
   grub_file_read (file, (char *) kern_end, file->size);
   if ((!grub_errno) &&
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/multiboot.c b/loader/i386/multiboot.c
index ff758d1..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,7 +61,12 @@ static grub_size_t code_size;
 static grub_err_t
 grub_multiboot_boot (void)
 {
-  grub_stop_floppy ();
+  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);
 
@@ -111,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++;
 
@@ -201,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 ();
@@ -288,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;
 
@@ -343,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);
@@ -372,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/multiboot_helper.S b/loader/i386/multiboot_helper.S
index 1e71120..cd07246 100644
--- a/loader/i386/multiboot_helper.S
+++ b/loader/i386/multiboot_helper.S
@@ -52,7 +52,7 @@ VARIABLE(grub_multiboot_forward_relocator)
        cld
        rep
        movsb
-
+       
        jmp     *%edx
 VARIABLE(grub_multiboot_forward_relocator_end)
 
@@ -91,7 +91,7 @@ FUNCTION(grub_multiboot_real_boot)
 
        /* Move the magic value into eax.  */
        movl    $MULTIBOOT_MAGIC2, %eax
-                               
+
        /* Jump to the relocator.  */
        popl    %ebp
        jmp     *%ebp
diff --git a/loader/i386/xnu_helper.S b/loader/i386/xnu_helper.S
index 901be68..a83bd9a 100644
--- a/loader/i386/xnu_helper.S
+++ b/loader/i386/xnu_helper.S
@@ -15,6 +15,9 @@ FUNCTION(grub_xnu_launch)
        jmp cont1
 cont1:
        lgdt gdtdesc
+
+       jmp cont2
+cont2:
        
        .code32
        
@@ -28,8 +31,8 @@ cont1:
        and $0xffffffef, %eax
        wrmsr
 
-       jmp cont2
-cont2: 
+       jmp cont3
+cont3: 
 #endif
 
        .code32
diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c
index abcad9b..8abce88 100644
--- a/loader/multiboot_loader.c
+++ b/loader/multiboot_loader.c
@@ -140,7 +140,7 @@ grub_rescue_cmd_multiboot_loader (int argc, char *argv[])
 
    /* XXX Find a better way to identify this. 
       This is for i386-pc */
-#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS) || defined 
(GRUB_MACHINE_EFI)
   if (header_multi_ver_found == 1)
     {
       grub_dprintf ("multiboot_loader",
@@ -153,7 +153,9 @@ grub_rescue_cmd_multiboot_loader (int argc, char *argv[])
     {
       grub_dprintf ("multiboot_loader",
            "Launching multiboot 2 grub_multiboot2() function\n");
+#ifndef GRUB_MACHINE_EFI
       grub_multiboot2 (argc, argv);
+#endif
       module_version_status = 2;
     }
 
@@ -170,7 +172,7 @@ void
 grub_rescue_cmd_module_loader (int argc, char *argv[])
 {
 
-#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS) || 
defined(GRUB_MACHINE_EFI)
   if (module_version_status == 1)
     {
       grub_dprintf("multiboot_loader",
@@ -182,7 +184,9 @@ grub_rescue_cmd_module_loader (int argc, char *argv[])
     {
       grub_dprintf("multiboot_loader",
           "Launching multiboot 2 grub_module2() function\n");
+#ifndef GRUB_MACHINE_EFI
       grub_module2 (argc, argv);
+#endif
     }
 }
 
diff --git a/conf/i386.rmk b/conf/i386.rmk
index 93f84ce..5338457 100644
--- a/conf/i386.rmk
+++ b/conf/i386.rmk
@@ -14,3 +14,8 @@ 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)
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;
+}

reply via email to

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