[2159] 2009-05-02 Vladimir Serbinenko <[email protected]>

Vladimir Serbinenko <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 2159
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2159
Author:   phcoder
Date:     2009-05-02 21:46:34 +0000 (Sat, 02 May 2009)
Log Message:
-----------
2009-05-02  Vladimir Serbinenko <[email protected]>

	Mmap services

	* loader/i386/efi/linux.c (grub_linux_boot): use grub_mmap_iterate
	* loader/i386/linux.c (find_mmap_size): likewise
	(allocate_pages): likewise
	* loader/i386/multiboot.c (grub_get_multiboot_mmap_len): likewise
	(grub_fill_multiboot_mmap): likewise
	(grub_multiboot): use grub_mmap_get_lower and grub_mmap_get_upper
	* loader/i386/pc/linux.c (grub_cmd_linux): use grub_mmap_get_lower
	* include/grub/i386/bsd.h (OPENBSD_MMAP_AVAILABLE): new definition
	(OPENBSD_MMAP_RESERVED): likewise
	* include/grub/i386/pc/memory.h: include grub/memory.h
	(grub_lower_mem): removed
	(grub_upper_mem): likewise
	(GRUB_MACHINE_MEMORY_ACPI): new definition
	(GRUB_MACHINE_MEMORY_NVS): likewise
	(GRUB_MACHINE_MEMORY_MAX_TYPE): likewise
	(GRUB_MACHINE_MEMORY_HOLE): likewise
	(grub_machine_mmap_register): likewise
	(grub_machine_mmap_unregister): likewise
	(grub_machine_get_upper): likewise
	(grub_machine_get_lower): likewise
	(grub_machine_get_post64): likewise
	* include/grub/i386/efi/memory.h: new file
	* include/grub/x86_64/efi/memory.h: likewise
	* include/grub/efi/memory.h: likewise
	* conf/i386-pc.rmk (pkglib_MODULES): added mmap.mod
	(mmap_mod_SOURCES): new variable
	(mmap_mod_LDFLAGS): likewise
	(mmap_mod_ASFLAGS): likewise
	* conf/i386-coreboot.rmk: likewise
	* conf/i386-ieee1275.rmk: likewise
	* conf/i386-efi.rmk: likewise
	* conf/x86_64-efi.rmk: likewise
	* include/grub/types.h (UINT_TO_PTR): new macro
	(PTR_TO_UINT32): likewise
	(PTR_TO_UINT64): likewise
	* include/grub/memory.h: new file
	* mmap/i386/pc/mmap.c: likewise
	* mmap/i386/pc/mmap_helper.S: likewise
	* mmap/i386/uppermem.c: likewise
	* mmap/mmap.c: likewise
	* mmap/efi/mmap.c: likewise
	* kern/i386/coreboot/init.c (grub_machine_init): don't use 
	grub_upper_mem
	* kern/i386/pc/init.c (grub_lower_mem): removed variable
	(grub_upper_mem): likewise
	(grub_machine_init): don't use grub_upper_mem,
	make grub_lower_mem local
	* loader/i386/bsd.c (grub_openbsd_boot): use grub_mmap_get_lower,
	grub_mmap_iterate and grub_mmap_get_upper
	(grub_netbsd_boot): use grub_mmap_get_lower and grub_mmap_get_upper

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/conf/i386-coreboot.rmk
    trunk/grub2/conf/i386-efi.rmk
    trunk/grub2/conf/i386-ieee1275.rmk
    trunk/grub2/conf/i386-pc.rmk
    trunk/grub2/conf/x86_64-efi.rmk
    trunk/grub2/include/grub/i386/bsd.h
    trunk/grub2/include/grub/i386/pc/memory.h
    trunk/grub2/include/grub/types.h
    trunk/grub2/kern/i386/coreboot/init.c
    trunk/grub2/kern/i386/pc/init.c
    trunk/grub2/loader/i386/bsd.c
    trunk/grub2/loader/i386/efi/linux.c
    trunk/grub2/loader/i386/ieee1275/linux.c
    trunk/grub2/loader/i386/linux.c
    trunk/grub2/loader/i386/multiboot.c
    trunk/grub2/loader/i386/pc/linux.c

Added Paths:
-----------
    trunk/grub2/include/grub/efi/memory.h
    trunk/grub2/include/grub/i386/efi/memory.h
    trunk/grub2/include/grub/memory.h
    trunk/grub2/include/grub/x86_64/efi/memory.h
    trunk/grub2/mmap/
    trunk/grub2/mmap/efi/
    trunk/grub2/mmap/efi/mmap.c
    trunk/grub2/mmap/i386/
    trunk/grub2/mmap/i386/mmap.c
    trunk/grub2/mmap/i386/pc/
    trunk/grub2/mmap/i386/pc/mmap.c
    trunk/grub2/mmap/i386/pc/mmap_helper.S
    trunk/grub2/mmap/i386/uppermem.c
    trunk/grub2/mmap/mmap.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/ChangeLog	2009-05-02 21:46:34 UTC (rev 2159)
@@ -1,3 +1,58 @@
+2009-05-02  Vladimir Serbinenko <[email protected]>
+
+	Mmap services
+
+	* loader/i386/efi/linux.c (grub_linux_boot): use grub_mmap_iterate
+	* loader/i386/linux.c (find_mmap_size): likewise
+	(allocate_pages): likewise
+	* loader/i386/multiboot.c (grub_get_multiboot_mmap_len): likewise
+	(grub_fill_multiboot_mmap): likewise
+	(grub_multiboot): use grub_mmap_get_lower and grub_mmap_get_upper
+	* loader/i386/pc/linux.c (grub_cmd_linux): use grub_mmap_get_lower
+	* include/grub/i386/bsd.h (OPENBSD_MMAP_AVAILABLE): new definition
+	(OPENBSD_MMAP_RESERVED): likewise
+	* include/grub/i386/pc/memory.h: include grub/memory.h
+	(grub_lower_mem): removed
+	(grub_upper_mem): likewise
+	(GRUB_MACHINE_MEMORY_ACPI): new definition
+	(GRUB_MACHINE_MEMORY_NVS): likewise
+	(GRUB_MACHINE_MEMORY_MAX_TYPE): likewise
+	(GRUB_MACHINE_MEMORY_HOLE): likewise
+	(grub_machine_mmap_register): likewise
+	(grub_machine_mmap_unregister): likewise
+	(grub_machine_get_upper): likewise
+	(grub_machine_get_lower): likewise
+	(grub_machine_get_post64): likewise
+	* include/grub/i386/efi/memory.h: new file
+	* include/grub/x86_64/efi/memory.h: likewise
+	* include/grub/efi/memory.h: likewise
+	* conf/i386-pc.rmk (pkglib_MODULES): added mmap.mod
+	(mmap_mod_SOURCES): new variable
+	(mmap_mod_LDFLAGS): likewise
+	(mmap_mod_ASFLAGS): likewise
+	* conf/i386-coreboot.rmk: likewise
+	* conf/i386-ieee1275.rmk: likewise
+	* conf/i386-efi.rmk: likewise
+	* conf/x86_64-efi.rmk: likewise
+	* include/grub/types.h (UINT_TO_PTR): new macro
+	(PTR_TO_UINT32): likewise
+	(PTR_TO_UINT64): likewise
+	* include/grub/memory.h: new file
+	* mmap/i386/pc/mmap.c: likewise
+	* mmap/i386/pc/mmap_helper.S: likewise
+	* mmap/i386/uppermem.c: likewise
+	* mmap/mmap.c: likewise
+	* mmap/efi/mmap.c: likewise
+	* kern/i386/coreboot/init.c (grub_machine_init): don't use 
+	grub_upper_mem
+	* kern/i386/pc/init.c (grub_lower_mem): removed variable
+	(grub_upper_mem): likewise
+	(grub_machine_init): don't use grub_upper_mem,
+	make grub_lower_mem local
+	* loader/i386/bsd.c (grub_openbsd_boot): use grub_mmap_get_lower,
+	grub_mmap_iterate and grub_mmap_get_upper
+	(grub_netbsd_boot): use grub_mmap_get_lower and grub_mmap_get_upper
+
 2009-05-02  Bean  <[email protected]>
 
 	* conf/common.rmk (grub_script.tab.c): Change normal/parser.y to

Modified: trunk/grub2/conf/i386-coreboot.rmk
===================================================================
--- trunk/grub2/conf/i386-coreboot.rmk	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/conf/i386-coreboot.rmk	2009-05-02 21:46:34 UTC (rev 2159)
@@ -105,8 +105,14 @@
 	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
+	lsmmap.mod mmap.mod
 
+# For mmap.mod.
+mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c
+mmap_mod_CFLAGS = $(COMMON_CFLAGS)
+mmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+mmap_mod_ASFLAGS = $(COMMON_ASFLAGS)
+
 # For linux.mod.
 linux_mod_SOURCES = loader/i386/linux.c
 linux_mod_CFLAGS = $(COMMON_CFLAGS)

Modified: trunk/grub2/conf/i386-efi.rmk
===================================================================
--- trunk/grub2/conf/i386-efi.rmk	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/conf/i386-efi.rmk	2009-05-02 21:46:34 UTC (rev 2159)
@@ -82,7 +82,7 @@
 # Modules.
 pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
 	linux.mod halt.mod reboot.mod pci.mod lspci.mod \
-	datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod
+	datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod mmap.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -115,6 +115,12 @@
 kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
 	/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
 
+# For mmap.mod.
+mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \
+		   mmap/efi/mmap.c
+mmap_mod_CFLAGS = $(COMMON_CFLAGS)
+mmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For chain.mod.
 chain_mod_SOURCES = loader/efi/chainloader.c
 chain_mod_CFLAGS = $(COMMON_CFLAGS)

Modified: trunk/grub2/conf/i386-ieee1275.rmk
===================================================================
--- trunk/grub2/conf/i386-ieee1275.rmk	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/conf/i386-ieee1275.rmk	2009-05-02 21:46:34 UTC (rev 2159)
@@ -105,8 +105,14 @@
 pkglib_MODULES = 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 lsmmap.mod mmap.mod
 
+# For mmap.mod.
+mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c
+mmap_mod_CFLAGS = $(COMMON_CFLAGS)
+mmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+mmap_mod_ASFLAGS = $(COMMON_ASFLAGS)
+
 # For multiboot.mod.
 multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
 			loader/i386/multiboot_helper.S \

Modified: trunk/grub2/conf/i386-pc.rmk
===================================================================
--- trunk/grub2/conf/i386-pc.rmk	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/conf/i386-pc.rmk	2009-05-02 21:46:34 UTC (rev 2159)
@@ -184,8 +184,16 @@
 	ata.mod vga.mod memdisk.mod pci.mod lspci.mod	\
 	aout.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
 	datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
-	usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod
+	usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \
+	mmap.mod
 
+# For mmap.mod.
+mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \
+		   mmap/i386/pc/mmap.c mmap/i386/pc/mmap_helper.S
+mmap_mod_CFLAGS = $(COMMON_CFLAGS)
+mmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+mmap_mod_ASFLAGS = $(COMMON_ASFLAGS)
+
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
 biosdisk_mod_CFLAGS = $(COMMON_CFLAGS)

Modified: trunk/grub2/conf/x86_64-efi.rmk
===================================================================
--- trunk/grub2/conf/x86_64-efi.rmk	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/conf/x86_64-efi.rmk	2009-05-02 21:46:34 UTC (rev 2159)
@@ -80,7 +80,7 @@
 # Modules.
 pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
 	halt.mod reboot.mod linux.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 mmap.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -114,6 +114,12 @@
 kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
 	/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
 
+# For mmap.mod.
+mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \
+		   mmap/efi/mmap.c
+mmap_mod_CFLAGS = $(COMMON_CFLAGS)
+mmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For chain.mod.
 chain_mod_SOURCES = loader/efi/chainloader.c
 chain_mod_CFLAGS = $(COMMON_CFLAGS)

Added: trunk/grub2/include/grub/efi/memory.h
===================================================================
--- trunk/grub2/include/grub/efi/memory.h	                        (rev 0)
+++ trunk/grub2/include/grub/efi/memory.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,48 @@
+/*
+ *  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 GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER	1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+#define GRUB_MMAP_REGISTER_BY_FIRMWARE  1
+
+#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
+#define GRUB_MACHINE_MEMORY_MAX_TYPE 	5
+  /* This one is special: it's used internally but is never reported 
+     by firmware. */
+#define GRUB_MACHINE_MEMORY_HOLE 	6
+
+
+grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) 
+(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, 
+				       int type, int handle);
+grub_err_t grub_machine_mmap_unregister (int handle);
+
+grub_uint64_t grub_mmap_get_post64 (void);
+grub_uint64_t grub_mmap_get_upper (void);
+grub_uint64_t grub_mmap_get_lower (void);
+
+#endif /* ! GRUB_MEMORY_MACHINE_HEADER */

Modified: trunk/grub2/include/grub/i386/bsd.h
===================================================================
--- trunk/grub2/include/grub/i386/bsd.h	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/include/grub/i386/bsd.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -148,6 +148,8 @@
 {
   grub_uint64_t addr;
   grub_uint64_t len;
+#define	OPENBSD_MMAP_AVAILABLE	1
+#define	OPENBSD_MMAP_RESERVED 2
   grub_uint32_t type;
 };
 

Added: trunk/grub2/include/grub/i386/efi/memory.h
===================================================================
--- trunk/grub2/include/grub/i386/efi/memory.h	                        (rev 0)
+++ trunk/grub2/include/grub/i386/efi/memory.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>

Modified: trunk/grub2/include/grub/i386/pc/memory.h
===================================================================
--- trunk/grub2/include/grub/i386/pc/memory.h	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/include/grub/i386/pc/memory.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -25,6 +25,7 @@
 #ifndef ASM_FILE
 #include <grub/types.h>
 #include <grub/err.h>
+#include <grub/memory.h>
 #endif
 
 /* The scratch buffer used in real mode code.  */
@@ -79,12 +80,6 @@
 
 #ifndef ASM_FILE
 
-#ifndef GRUB_MACHINE_IEEE1275
-extern grub_size_t EXPORT_VAR(grub_lower_mem);
-#endif
-
-extern grub_size_t EXPORT_VAR(grub_upper_mem);
-
 struct grub_machine_mmap_entry
 {
   grub_uint32_t size;
@@ -92,12 +87,45 @@
   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
+#define GRUB_MACHINE_MEMORY_MAX_TYPE 	4
+  /* This one is special: it's used internally but is never reported 
+     by firmware. */
+#define GRUB_MACHINE_MEMORY_HOLE 	5
+
   grub_uint32_t type;
 } __attribute__((packed));
 
 grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
      (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
 
+grub_uint64_t grub_mmap_get_post64 (void);
+grub_uint64_t grub_mmap_get_upper (void);
+grub_uint64_t grub_mmap_get_lower (void);
+
+#define GRUB_MMAP_MALLOC_LOW 1
+
+#ifdef GRUB_MACHINE_PCBIOS
+grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, 
+				       int type, int handle);
+grub_err_t grub_machine_mmap_unregister (int handle);
+#else
+static inline grub_err_t 
+grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), 
+			    grub_uint64_t size __attribute__ ((unused)), 
+			    int type __attribute__ ((unused)), 
+			    int handle __attribute__ ((unused)))
+{
+  return GRUB_ERR_NONE;
+}
+static inline grub_err_t 
+grub_machine_mmap_unregister (int handle  __attribute__ ((unused)))
+{
+  return GRUB_ERR_NONE;
+}
 #endif
 
+#endif
+
 #endif /* ! GRUB_MEMORY_MACHINE_HEADER */

Added: trunk/grub2/include/grub/memory.h
===================================================================
--- trunk/grub2/include/grub/memory.h	                        (rev 0)
+++ trunk/grub2/include/grub/memory.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,52 @@
+/* memory.h - describe the memory map */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#ifndef GRUB_MEMORY_HEADER
+#define GRUB_MEMORY_HEADER	1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/machine/memory.h>
+
+grub_err_t grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 
+							    grub_uint64_t, 
+							    grub_uint32_t));
+int grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type);
+grub_err_t grub_mmap_unregister (int handle);
+
+char *grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size,
+				     int *handle, int type, int flags);
+
+void grub_mmap_free_and_unregister (int handle);
+
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
+
+struct grub_mmap_region
+{
+  struct grub_mmap_region *next;
+  grub_uint64_t start;
+  grub_uint64_t end;
+  int type;
+  int handle;
+};
+
+extern struct grub_mmap_region *grub_mmap_overlays;
+#endif
+
+#endif /* ! GRUB_MEMORY_HEADER */

Modified: trunk/grub2/include/grub/types.h
===================================================================
--- trunk/grub2/include/grub/types.h	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/include/grub/types.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -102,6 +102,16 @@
 # define GRUB_LONG_MIN -2147483648UL
 #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;
 

Added: trunk/grub2/include/grub/x86_64/efi/memory.h
===================================================================
--- trunk/grub2/include/grub/x86_64/efi/memory.h	                        (rev 0)
+++ trunk/grub2/include/grub/x86_64/efi/memory.h	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>

Modified: trunk/grub2/kern/i386/coreboot/init.c
===================================================================
--- trunk/grub2/kern/i386/coreboot/init.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/kern/i386/coreboot/init.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -82,16 +82,11 @@
 #if GRUB_CPU_SIZEOF_VOID_P == 4
     /* Restrict ourselves to 32-bit memory space.  */
     if (addr > GRUB_ULONG_MAX)
-      {
-	grub_upper_mem = GRUB_ULONG_MAX;
-	return 0;
-      }
+      return 0;
     if (addr + size > GRUB_ULONG_MAX)
       size = GRUB_ULONG_MAX - addr;
 #endif
 
-    grub_upper_mem = grub_max (grub_upper_mem, addr + size);
-
     if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
       return 0;
 
@@ -128,9 +123,6 @@
   grub_machine_mmap_init ();
   grub_machine_mmap_iterate (heap_init);
 
-  /* This variable indicates size, not offset.  */
-  grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
-
   grub_tsc_init ();
 }
 

Modified: trunk/grub2/kern/i386/pc/init.c
===================================================================
--- trunk/grub2/kern/i386/pc/init.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/kern/i386/pc/init.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -45,7 +45,6 @@
 
 grub_addr_t grub_os_area_addr;
 grub_size_t grub_os_area_size;
-grub_size_t grub_lower_mem, grub_upper_mem;
 
 void 
 grub_arch_sync_caches (void *address __attribute__ ((unused)),
@@ -133,6 +132,7 @@
 grub_machine_init (void)
 {
   int i;
+  int grub_lower_mem;
   
   /* Initialize the console as early as possible.  */
   grub_console_init ();
@@ -197,7 +197,6 @@
       {
 	grub_size_t quarter = mem_regions[i].size >> 2;
 
-	grub_upper_mem = mem_regions[i].size;
 	grub_os_area_addr = mem_regions[i].addr;
 	grub_os_area_size = mem_regions[i].size - quarter;
 	grub_mm_init_region ((void *) (grub_os_area_addr + grub_os_area_size),

Modified: trunk/grub2/loader/i386/bsd.c
===================================================================
--- trunk/grub2/loader/i386/bsd.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/loader/i386/bsd.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -313,31 +313,37 @@
 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;
 
+  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++;
+  grub_mmap_iterate (hook);
 
-	if (!cont)
-	  break;
-
-	cont = grub_get_mmap_entry (&mmap, cont);
-      }
-    while (mmap.size);
-
   pa->ba_size = (char *) pm - (char *) pa;
   pa->ba_next = (struct grub_openbsd_bootargs *) pm;
   pa = pa->ba_next;
@@ -349,7 +355,8 @@
 	     (part << OPENBSD_B_PARTSHIFT));
 
   grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
-		       0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+		       0, grub_mmap_get_upper () >> 10, 
+		       grub_mmap_get_lower () >> 10,
 		       (char *) pa - buf, buf);
 
   /* Not reached.  */
@@ -377,7 +384,8 @@
   bootinfo->bi_data[0] = rootdev;
 
   grub_unix_real_boot (entry, bootflags, 0, bootinfo,
-		       0, grub_upper_mem >> 10, grub_lower_mem >> 10);
+		       0, grub_mmap_get_upper () >> 10, 
+		       grub_mmap_get_lower () >> 10);
 
   /* Not reached.  */
   return GRUB_ERR_NONE;

Modified: trunk/grub2/loader/i386/efi/linux.c
===================================================================
--- trunk/grub2/loader/i386/efi/linux.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/loader/i386/efi/linux.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -32,6 +32,7 @@
 #include <grub/efi/uga_draw.h>
 #include <grub/pci.h>
 #include <grub/command.h>
+#include <grub/memory.h>
 
 #define GRUB_LINUX_CL_OFFSET		0x1000
 #define GRUB_LINUX_CL_END_OFFSET	0x2000
@@ -300,7 +301,6 @@
   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;
@@ -313,84 +313,53 @@
 		(unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
 		(unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
 
-  mmap_size = find_mmap_size ();
-  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
-			       &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_mmap_iterate (hook);
   params->mmap_size = e820_num;
 
+  mmap_size = find_mmap_size ();
+  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+			       &desc_size, &desc_version) <= 0)
+    grub_fatal ("cannot get memory map");
+
   if (! grub_efi_exit_boot_services (map_key))
      grub_fatal ("cannot exit boot services");
 

Modified: trunk/grub2/loader/i386/ieee1275/linux.c
===================================================================
--- trunk/grub2/loader/i386/ieee1275/linux.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/loader/i386/ieee1275/linux.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -100,7 +100,7 @@
 
   grub_memset ((char *) params, 0, GRUB_OFW_LINUX_CL_OFFSET);
 
-  params->alt_mem = grub_upper_mem >> 10;
+  params->alt_mem = grub_mmap_get_upper () >> 10;
   params->ext_mem = params->alt_mem;
 
   lh->cmd_line_ptr = (char *)

Modified: trunk/grub2/loader/i386/linux.c
===================================================================
--- trunk/grub2/loader/i386/linux.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/loader/i386/linux.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -169,7 +169,7 @@
       return 0;
     }
   
-  grub_machine_mmap_iterate (hook);
+  grub_mmap_iterate (hook);
   
   mmap_size = count * sizeof (struct grub_e820_mmap);
 
@@ -238,7 +238,7 @@
 
       return 0;
     }
-  grub_machine_mmap_iterate (hook);
+  grub_mmap_iterate (hook);
   if (! real_mode_mem)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
@@ -397,6 +397,27 @@
 				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);
@@ -405,9 +426,10 @@
     }
 
   e820_num = 0;
-  grub_machine_mmap_iterate (hook);
+  grub_mmap_iterate (hook);
   params->mmap_size = e820_num;
 
+
   /* Hardware interrupts are not safe any longer.  */
   asm volatile ("cli" : : );
   

Modified: trunk/grub2/loader/i386/multiboot.c
===================================================================
--- trunk/grub2/loader/i386/multiboot.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/loader/i386/multiboot.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -99,7 +99,7 @@
       return 0;
     }
   
-  grub_machine_mmap_iterate (hook);
+  grub_mmap_iterate (hook);
   
   return count * sizeof (struct grub_multiboot_mmap_entry);
 }
@@ -122,7 +122,7 @@
       return 0;
     }
 
-  grub_machine_mmap_iterate (hook);
+  grub_mmap_iterate (hook);
 }
 
 #define MULTIBOOT_LOAD_ELF64
@@ -341,8 +341,8 @@
 		grub_multiboot_payload_entry_offset);
 
   /* Convert from bytes to kilobytes.  */
-  mbi->mem_lower = grub_lower_mem / 1024;
-  mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->mem_lower = grub_mmap_get_lower () / 1024;
+  mbi->mem_upper = grub_mmap_get_upper () / 1024;
   mbi->flags |= MULTIBOOT_INFO_MEMORY;
 
   cmdline = p = cmdline_addr (grub_multiboot_payload_orig);

Modified: trunk/grub2/loader/i386/pc/linux.c
===================================================================
--- trunk/grub2/loader/i386/pc/linux.c	2009-05-02 19:49:34 UTC (rev 2158)
+++ trunk/grub2/loader/i386/pc/linux.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -108,8 +108,9 @@
       lh.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
       
       /* Put the real mode part at as a high location as possible.  */
-      grub_linux_real_addr = (char *) (grub_lower_mem
-				       - GRUB_LINUX_SETUP_MOVE_SIZE);
+      grub_linux_real_addr 
+	= (char *) UINT_TO_PTR (grub_mmap_get_lower ()
+				- GRUB_LINUX_SETUP_MOVE_SIZE);
       /* But it must not exceed the traditional area.  */
       if (grub_linux_real_addr > (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR)
 	grub_linux_real_addr = (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR;
@@ -159,12 +160,12 @@
     }
   
   if (grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE
-      > (char *) grub_lower_mem)
+      > (char *) UINT_TO_PTR (grub_mmap_get_lower ()))
     {
       grub_error (GRUB_ERR_OUT_OF_RANGE,
 		 "too small lower memory (0x%x > 0x%x)",
-		 grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE,
-		 (char *) grub_lower_mem);
+		  grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE,
+		  (int) grub_mmap_get_lower ());
       goto fail;
     }
 

Added: trunk/grub2/mmap/efi/mmap.c
===================================================================
--- trunk/grub2/mmap/efi/mmap.c	                        (rev 0)
+++ trunk/grub2/mmap/efi/mmap.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,284 @@
+/* Mmap management. */
+/*
+ *  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/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)))
+
+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 = 0;
+  grub_efi_uintn_t map_key = 0;
+  grub_efi_uintn_t desc_size = 0;
+  grub_efi_uint32_t desc_version = 0;
+  grub_efi_memory_descriptor_t *desc;
+
+  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;
+    }
+
+  for (desc = map_buf;
+       desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      grub_dprintf ("mmap", "EFI memory region 0x%llx-0x%llx: %d\n",
+		    (unsigned long long) desc->physical_start, 
+		    (unsigned long long) desc->physical_start
+		    + desc->num_pages * 4096, desc->type);
+      switch (desc->type)
+	{
+	case GRUB_EFI_RUNTIME_SERVICES_CODE:
+	  hook (desc->physical_start, desc->num_pages * 4096, 
+		GRUB_MACHINE_MEMORY_CODE);
+	  break;
+
+	default:
+	  grub_printf ("Unknown memory type %d, considering reserved\n",
+		       desc->type);
+
+	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:
+	  hook (desc->physical_start, desc->num_pages * 4096, 
+		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:
+	  hook (desc->physical_start, desc->num_pages * 4096, 
+		GRUB_MACHINE_MEMORY_AVAILABLE);
+	  break;
+
+	case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+	  hook (desc->physical_start, desc->num_pages * 4096, 
+		GRUB_MACHINE_MEMORY_ACPI);
+	  break;
+
+	case GRUB_EFI_ACPI_MEMORY_NVS:
+	  hook (desc->physical_start, desc->num_pages * 4096, 
+		GRUB_MACHINE_MEMORY_NVS);
+	  break;
+	}
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static inline grub_efi_memory_type_t 
+make_efi_memtype (int type)
+{
+  switch (type)
+    {
+    case GRUB_MACHINE_MEMORY_CODE:
+      return GRUB_EFI_RUNTIME_SERVICES_CODE;
+
+      /* No way to remove a chunk of memory from EFI mmap. 
+	 So mark it as unusable. */
+    case GRUB_MACHINE_MEMORY_HOLE:
+      
+    default:
+
+    case GRUB_MACHINE_MEMORY_RESERVED:
+      return GRUB_EFI_UNUSABLE_MEMORY;
+
+    case GRUB_MACHINE_MEMORY_AVAILABLE:
+      return GRUB_EFI_CONVENTIONAL_MEMORY;
+
+    case GRUB_MACHINE_MEMORY_ACPI:
+      return GRUB_EFI_ACPI_RECLAIM_MEMORY;
+
+    case GRUB_MACHINE_MEMORY_NVS:
+      return GRUB_EFI_ACPI_RECLAIM_MEMORY;
+      
+    }
+
+}
+
+struct overlay
+{
+  struct overlay *next;
+  grub_efi_physical_address_t address;
+  grub_efi_uintn_t pages;
+  int handle;
+};
+
+static struct overlay *overlays = 0;
+static int curhandle = 1;
+
+int
+grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type)
+{
+  grub_uint64_t end = start + size;
+  grub_efi_physical_address_t address;
+  grub_efi_boot_services_t *b;
+  grub_efi_uintn_t pages;
+  grub_efi_status_t status;
+  struct overlay *curover;
+
+  curover = (struct overlay *) grub_malloc (sizeof (struct overlay));
+  if (! curover)
+    return 0;
+      
+  b = grub_efi_system_table->boot_services;
+  address = start & (~0x3ffULL);
+  pages = (end - address  + 0x3ff) >> 12;
+  status = efi_call_2 (b->free_pages, address, pages);
+  if (status != GRUB_EFI_SUCCESS && status != GRUB_EFI_NOT_FOUND)
+    {
+      grub_free (curover);
+      return 0;
+    }
+  status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS, 
+		       make_efi_memtype (type), pages, &address);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_free (curover);
+      return 0;
+    }
+  curover->next = overlays;
+  curover->handle = curhandle++;
+  curover->address = address;
+  curover->pages = pages;
+  overlays = curover;
+
+  return curover->handle;
+}
+
+grub_err_t 
+grub_machine_mmap_unregister (int handle)
+{
+  struct overlay *curover, *prevover;
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+
+  b = grub_efi_system_table->boot_services;
+
+  
+  for (curover = overlays, prevover = 0; curover; 
+       prevover = curover, curover = curover->next)
+    {
+      if (curover->handle == handle)
+	{
+	  status = efi_call_2 (b->free_pages, curover->address, curover->pages);
+	  if (prevover != 0)
+	    prevover->next = curover->next;
+	  else
+	    overlays = curover->next;
+	  grub_free (curover);
+	  return GRUB_ERR_NONE;
+	}
+    }
+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "handle %d not found", handle);
+}
+
+/* Result is always page-aligned. */
+char *
+grub_mmap_malign_and_register (grub_uint64_t align __attribute__ ((unused)), 
+			       grub_uint64_t size,
+			       int *handle, int type, 
+			       int flags __attribute__ ((unused)))
+{
+  grub_efi_physical_address_t address;
+  grub_efi_boot_services_t *b;
+  grub_efi_uintn_t pages;
+  grub_efi_status_t status;
+  struct overlay *curover;
+  grub_efi_allocate_type_t atype;
+
+  curover = (struct overlay *) grub_malloc (sizeof (struct overlay));
+  if (! curover)
+    return 0;
+      
+  b = grub_efi_system_table->boot_services;
+
+  address = 0xffffffff;
+
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
+  /* Limit the memory access to less than 4GB for 32-bit platforms.  */
+  atype = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
+#else
+  atype = GRUB_EFI_ALLOCATE_ANY_PAGES;
+#endif
+
+  pages = (size + 0x3ff) >> 12;
+  status = efi_call_4 (b->allocate_pages, atype, 
+		       make_efi_memtype (type), pages, &address);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_free (curover);
+      return 0;
+    }
+
+  if (address == 0)
+    {
+      /* Uggh, the address 0 was allocated... This is too annoying,
+	 so reallocate another one.  */
+      address = 0xffffffff;
+      status = efi_call_4 (b->allocate_pages, atype, 
+			   make_efi_memtype (type), pages, &address);
+      grub_efi_free_pages (0, pages);
+      if (status != GRUB_EFI_SUCCESS)
+	return 0;
+    }
+  
+  curover->next = overlays;
+  curover->handle = curhandle++;
+  curover->address = address;
+  curover->pages = pages;
+  overlays = curover;
+  *handle = curover->handle;
+
+  return UINT_TO_PTR (curover->address);
+}
+
+void 
+grub_mmap_free_and_unregister (int handle)
+{
+  grub_machine_mmap_unregister (handle);
+}

Added: trunk/grub2/mmap/i386/mmap.c
===================================================================
--- trunk/grub2/mmap/i386/mmap.c	                        (rev 0)
+++ trunk/grub2/mmap/i386/mmap.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,98 @@
+/* Mmap management. */
+/*
+ *  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/memory.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
+
+char *
+grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size,
+			       int *handle, int type, int flags)
+{
+  grub_uint64_t highestlow = 0;
+
+  auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, 
+				       grub_uint32_t);
+  int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t rangesize, 
+				  grub_uint32_t memtype)
+  {
+    grub_uint64_t end = start + rangesize;
+    if (memtype != GRUB_MACHINE_MEMORY_AVAILABLE)
+      return 0;
+    if (end > 0x100000)
+      end = 0x100000;
+    if (end > start + size
+	&& highestlow < ((end - size) - ((end - size) & (align - 1))))
+      highestlow = (end - size)  - ((end - size) & (align - 1));
+    return 0;
+  }
+
+  char * ret;
+  if (flags & GRUB_MMAP_MALLOC_LOW)
+    {
+      /* FIXME: use low-memory mm allocation once it's available. */
+      grub_mmap_iterate (find_hook);
+      ret = UINT_TO_PTR (highestlow);
+    }
+  else
+    ret = grub_memalign (align, size);
+
+  if (! ret)
+    {
+      *handle = 0;
+      return 0;
+    }
+
+  *handle = grub_mmap_register (PTR_TO_UINT64 (ret), size, type);
+  if (! *handle)
+    {
+      grub_free (ret);
+      return 0;
+    }    
+
+  return ret;
+}
+
+void
+grub_mmap_free_and_unregister (int handle)
+{
+  struct grub_mmap_region *cur;
+  grub_uint64_t addr;
+
+  for (cur = grub_mmap_overlays; cur; cur = cur->next)
+    if (cur->handle == handle)
+      break;
+
+  if (! cur)
+    return;
+
+  addr = cur->start;
+    
+  grub_mmap_unregister (handle);
+
+  if (addr >= 0x100000)
+    grub_free (UINT_TO_PTR (addr));
+}
+
+#endif

Added: trunk/grub2/mmap/i386/pc/mmap.c
===================================================================
--- trunk/grub2/mmap/i386/pc/mmap.c	                        (rev 0)
+++ trunk/grub2/mmap/i386/pc/mmap.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,216 @@
+/* Mmap management. */
+/*
+ *  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/memory.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/loader.h>
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+static void *hooktarget = 0;
+
+extern grub_uint8_t grub_machine_mmaphook_start;
+extern grub_uint8_t grub_machine_mmaphook_end;
+extern grub_uint8_t grub_machine_mmaphook_int12;
+extern grub_uint8_t grub_machine_mmaphook_int15;
+
+static grub_uint16_t grub_machine_mmaphook_int12offset = 0;
+static grub_uint16_t grub_machine_mmaphook_int12segment = 0;
+extern grub_uint16_t grub_machine_mmaphook_int15offset;
+extern grub_uint16_t grub_machine_mmaphook_int15segment;
+
+extern grub_uint16_t grub_machine_mmaphook_mmap_num;
+extern grub_uint16_t grub_machine_mmaphook_kblow;
+extern grub_uint16_t grub_machine_mmaphook_kbin16mb;
+extern grub_uint16_t grub_machine_mmaphook_64kbin4gb;
+
+struct grub_e820_mmap_entry
+{
+  grub_uint64_t addr;
+  grub_uint64_t len;
+  grub_uint32_t type;
+} __attribute__((packed));
+
+
+static grub_err_t 
+preboot (int noreturn __attribute__ ((unused)))
+{
+  struct grub_e820_mmap_entry *hookmmap, *hookmmapcur;
+  auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, 
+				       grub_uint32_t);
+  int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, 
+				  grub_uint32_t type)
+  {
+    grub_dprintf ("mmap", "mmap chunk %llx-%llx:%x\n", addr, addr + size, type);
+    hookmmapcur->addr = addr;
+    hookmmapcur->len = size;
+    hookmmapcur->type = type;
+    hookmmapcur++;
+    return 0;
+  }
+
+  if (! hooktarget)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+		       "no space is allocated for memory hook");
+
+  grub_dprintf ("mmap", "installing preboot handlers\n");
+
+  hookmmapcur = hookmmap = (struct grub_e820_mmap_entry *) 
+    ((grub_uint8_t *) hooktarget + (&grub_machine_mmaphook_end 
+				    - &grub_machine_mmaphook_start));
+
+  grub_mmap_iterate (fill_hook);  
+  grub_machine_mmaphook_mmap_num = hookmmapcur - hookmmap;
+
+  grub_machine_mmaphook_kblow = grub_mmap_get_lower () >> 10;
+  grub_machine_mmaphook_kbin16mb 
+    = min (grub_mmap_get_upper (),0x3f00000ULL) >> 10;
+  grub_machine_mmaphook_64kbin4gb 
+    = min (grub_mmap_get_post64 (), 0xfc000000ULL) >> 16;
+
+  /* Correct BDA. */
+  *((grub_uint16_t *) 0x413) = grub_mmap_get_lower () >> 10;
+
+  /* Save old interrupt handlers. */
+  grub_machine_mmaphook_int12offset = *((grub_uint16_t *) 0x48);
+  grub_machine_mmaphook_int12segment = *((grub_uint16_t *) 0x4a);
+  grub_machine_mmaphook_int15offset = *((grub_uint16_t *) 0x54);
+  grub_machine_mmaphook_int15segment = *((grub_uint16_t *) 0x56);
+
+  grub_dprintf ("mmap", "hooktarget = %p\n", hooktarget);
+
+  /* Install the interrupt handlers. */
+  grub_memcpy (hooktarget, &grub_machine_mmaphook_start,
+	       &grub_machine_mmaphook_end - &grub_machine_mmaphook_start);
+
+  *((grub_uint16_t *) 0x4a) = PTR_TO_UINT32 (hooktarget) >> 4;
+  *((grub_uint16_t *) 0x56) = PTR_TO_UINT32 (hooktarget) >> 4;
+  *((grub_uint16_t *) 0x48) = &grub_machine_mmaphook_int12 
+    - &grub_machine_mmaphook_start;
+  *((grub_uint16_t *) 0x54) = &grub_machine_mmaphook_int15
+    - &grub_machine_mmaphook_start;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+preboot_rest (void)
+{
+  /* Restore old interrupt handlers. */
+  *((grub_uint16_t *) 0x48) = grub_machine_mmaphook_int12offset;
+  *((grub_uint16_t *) 0x4a) = grub_machine_mmaphook_int12segment;
+  *((grub_uint16_t *) 0x54) = grub_machine_mmaphook_int15offset;
+  *((grub_uint16_t *) 0x56) = grub_machine_mmaphook_int15segment;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t 
+malloc_hook (void)
+{
+  static int reentry = 0;
+  static int mmapregion = 0;
+  static int slots_available = 0;
+  int hooksize;
+  int regcount = 0;
+  auto int NESTED_FUNC_ATTR count_hook (grub_uint64_t, grub_uint64_t, 
+					grub_uint32_t);
+  int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), 
+				   grub_uint64_t size __attribute__ ((unused)), 
+				   grub_uint32_t type __attribute__ ((unused)))
+  {
+    regcount++;
+    return 0;
+  }
+
+  if (reentry)
+    return GRUB_ERR_NONE;
+
+  grub_dprintf ("mmap", "registering\n");
+
+  grub_mmap_iterate (count_hook);
+
+  /* Mapping hook itself may introduce up to 2 additional regions. */
+  regcount += 2;
+
+  if (regcount <= slots_available)
+    return GRUB_ERR_NONE;
+
+  if (mmapregion)
+    {
+      grub_mmap_free_and_unregister (mmapregion);
+      mmapregion = 0;
+      hooktarget = 0;
+    }
+
+  hooksize = &grub_machine_mmaphook_end - &grub_machine_mmaphook_start
+    + regcount * sizeof (struct grub_e820_mmap_entry);
+  /* Allocate an integer number of KiB. */
+  hooksize = ((hooksize - 1) | 0x3ff) + 1;
+  slots_available = (hooksize - (&grub_machine_mmaphook_end 
+				 - &grub_machine_mmaphook_start))
+    / sizeof (struct grub_e820_mmap_entry);
+
+  reentry = 1;
+  hooktarget 
+    = grub_mmap_malign_and_register (16, hooksize, &mmapregion, 
+				     GRUB_MACHINE_MEMORY_RESERVED,
+				     GRUB_MMAP_MALLOC_LOW);
+  reentry = 0;
+
+  if (! hooktarget)
+    {
+      slots_available = 0;
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY, "No space for mmap hook");
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), 
+			    grub_uint64_t size __attribute__ ((unused)), 
+			    int type __attribute__ ((unused)),
+			    int handle  __attribute__ ((unused)))
+{
+  grub_err_t err;
+  static void *preb_handle = 0;
+
+  err = malloc_hook ();
+  if (err)
+    return err;
+
+  if (! preb_handle)
+    {
+      grub_dprintf ("mmap", "adding preboot\n");
+      preb_handle 
+	= grub_loader_register_preboot_hook (preboot, preboot_rest, 
+					     GRUB_LOADER_PREBOOT_HOOK_PRIO_MEMORY);
+      if (! preb_handle)
+	return grub_errno;
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_machine_mmap_unregister (int handle __attribute__ ((unused)))
+{
+  return GRUB_ERR_NONE;
+}

Added: trunk/grub2/mmap/i386/pc/mmap_helper.S
===================================================================
--- trunk/grub2/mmap/i386/pc/mmap_helper.S	                        (rev 0)
+++ trunk/grub2/mmap/i386/pc/mmap_helper.S	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,122 @@
+/* Mmap management. */
+/*
+ *  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/symbol.h>
+
+#define DS(x) ((x) - segstart)
+
+segstart:	
+VARIABLE(grub_machine_mmaphook_start)
+	.code16
+VARIABLE(grub_machine_mmaphook_int12)
+	push %ds
+	push %cs
+	pop %ds
+	movw DS (EXT_C (grub_machine_mmaphook_kblow)), %ax
+	pop %ds
+	iret
+
+VARIABLE(grub_machine_mmaphook_int15)
+	pushf
+	cmpw $0xe801, %ax
+	jz e801
+	cmpw $0xe820, %ax
+	jz e820
+	cmpb $0x88, %ah
+	jz h88
+	popf
+	/* ljmp */
+	.byte	0xea
+VARIABLE (grub_machine_mmaphook_int15offset)
+	.word	0
+VARIABLE (grub_machine_mmaphook_int15segment)
+	.word	0
+	
+e801:
+	popf
+	push %ds
+	push %cs
+	pop %ds
+	movw DS (EXT_C (grub_machine_mmaphook_kbin16mb)), %ax
+	movw DS (EXT_C (grub_machine_mmaphook_64kbin4gb)), %bx
+	movw %ax, %cx
+	movw %bx, %dx
+	pop %ds
+	clc
+	iret
+
+h88:
+	popf
+	push %ds
+	push %cs
+	pop %ds
+	movw DS (EXT_C (grub_machine_mmaphook_kbin16mb)), %ax
+	pop %ds
+	clc
+	iret
+
+e820:
+	popf
+	push %ds
+	push %cs
+	pop %ds
+	cmpw $20, %cx
+	jb errexit
+	cmpw DS (EXT_C (grub_machine_mmaphook_mmap_num)), %bx
+	jae errexit
+	cmp $0x534d4150, %edx
+	jne errexit
+	push %si
+	push %di
+	movw $20, %cx
+	movw $(DS(mmaphook_mmap)), %si
+	mov %bx, %ax
+	imul $20, %ax
+	add %ax, %si
+	rep movsb
+	pop %di
+	pop %si
+	movl $20, %ecx
+	inc %bx
+	cmpw DS(EXT_C(grub_machine_mmaphook_mmap_num)), %bx
+	jb noclean
+	xor %bx, %bx	
+noclean:	
+	mov $0x534d4150, %eax
+	pop %ds
+	clc
+	iret
+errexit:
+	mov $0x534d4150, %eax
+	pop %ds
+	stc
+	xor %bx, %bx
+	iret	
+	
+VARIABLE(grub_machine_mmaphook_mmap_num)
+	.word 0
+VARIABLE(grub_machine_mmaphook_kblow)
+	.word 0
+VARIABLE (grub_machine_mmaphook_kbin16mb)
+	.word 0
+VARIABLE (grub_machine_mmaphook_64kbin4gb)
+	.word 0
+mmaphook_mmap:
+	/* Memory map is placed just after the interrupt handlers. */
+VARIABLE(grub_machine_mmaphook_end)

Added: trunk/grub2/mmap/i386/uppermem.c
===================================================================
--- trunk/grub2/mmap/i386/uppermem.c	                        (rev 0)
+++ trunk/grub2/mmap/i386/uppermem.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,85 @@
+/* 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/>.
+ */
+
+#include <grub/memory.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+grub_uint64_t 
+grub_mmap_get_lower (void)
+{
+  grub_uint64_t lower = 0;
+
+  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)
+    {
+      if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
+	return 0;
+      if (addr == 0)
+	lower = size;
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+  if (lower > 0x100000)
+    lower =  0x100000;
+  return lower;
+}
+
+grub_uint64_t 
+grub_mmap_get_upper (void)
+{
+  grub_uint64_t upper = 0;
+
+  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)
+    {
+      if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
+	return 0;
+      if (addr <= 0x100000 && addr + size > 0x100000)
+	upper = addr + size - 0x100000;
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+  return upper;
+}
+
+/* Count the continous bytes after 64 MiB. */
+grub_uint64_t 
+grub_mmap_get_post64 (void)
+{
+  grub_uint64_t post64 = 0;
+
+  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)
+    {
+      if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
+	return 0;
+      if (addr <= 0x4000000 && addr + size > 0x4000000)
+	post64 = addr + size - 0x4000000;
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+  return post64;
+}

Added: trunk/grub2/mmap/mmap.c
===================================================================
--- trunk/grub2/mmap/mmap.c	                        (rev 0)
+++ trunk/grub2/mmap/mmap.c	2009-05-02 21:46:34 UTC (rev 2159)
@@ -0,0 +1,426 @@
+/* Mmap management. */
+/*
+ *  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/memory.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/command.h>
+#include <grub/dl.h>
+
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
+
+struct grub_mmap_region *grub_mmap_overlays = 0;
+static int curhandle = 1;
+
+#endif
+
+grub_err_t
+grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 
+						 grub_uint64_t, grub_uint32_t))
+{
+
+  /* This function resolves overlapping regions and sorts the memory map.
+     It uses scanline (sweeping) algorithm.
+  */
+  /* If same page is used by multiple types it's resolved 
+     according to priority:
+     1 - free memory
+     2 - memory usable by firmware-aware code
+     3 - unusable memory
+     4 - a range deliberately empty
+  */
+  int priority[GRUB_MACHINE_MEMORY_MAX_TYPE + 2] =
+    {
+#ifdef GRUB_MACHINE_MEMORY_AVAILABLE
+      [GRUB_MACHINE_MEMORY_AVAILABLE] = 1,
+#endif
+#ifdef GRUB_MACHINE_MEMORY_RESERVED
+      [GRUB_MACHINE_MEMORY_RESERVED] = 3,
+#endif
+#ifdef GRUB_MACHINE_MEMORY_ACPI
+      [GRUB_MACHINE_MEMORY_ACPI] = 2,
+#endif
+#ifdef GRUB_MACHINE_MEMORY_CODE
+      [GRUB_MACHINE_MEMORY_CODE] = 3,
+#endif
+#ifdef GRUB_MACHINE_MEMORY_NVS
+      [GRUB_MACHINE_MEMORY_NVS] = 3,
+#endif
+      [GRUB_MACHINE_MEMORY_HOLE] = 4,
+    };
+
+  int i, k, done;
+
+  /* Scanline events. */
+  struct grub_mmap_scan
+  {
+    /* At which memory address. */
+    grub_uint64_t pos;
+    /* 0 = region starts, 1 = region ends. */
+    int type;
+    /* Which type of memory region? */
+    int memtype;
+  };
+  struct grub_mmap_scan *scanline_events;
+  struct grub_mmap_scan t;
+
+  /* Previous scanline event. */
+  grub_uint64_t lastaddr;
+  int lasttype;
+  /* Current scanline event. */
+  int curtype;
+  /* How many regions of given type overlap at current location? */
+  int present[GRUB_MACHINE_MEMORY_MAX_TYPE + 2];
+  /* Number of mmap chunks. */
+  int mmap_num;
+
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE     
+  struct grub_mmap_region *cur;
+#endif
+  
+  auto int NESTED_FUNC_ATTR count_hook (grub_uint64_t, grub_uint64_t, 
+					grub_uint32_t);
+  int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)),
+				   grub_uint64_t size __attribute__ ((unused)),
+				   grub_uint32_t type __attribute__ ((unused)))
+  {
+    mmap_num++;
+    return 0;
+  }
+
+  auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, 
+					grub_uint32_t);
+  int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr,
+				  grub_uint64_t size,
+				  grub_uint32_t type)
+  {
+    scanline_events[i].pos = addr;
+    scanline_events[i].type = 0;
+    if (type <= GRUB_MACHINE_MEMORY_MAX_TYPE && priority[type])
+      scanline_events[i].memtype = type;
+    else
+      {
+	grub_dprintf ("mmap", "Unknown memory type %d. Assuming unusable\n",
+		      type);
+	scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED;
+      }
+    i++;
+
+    scanline_events[i].pos = addr + size;
+    scanline_events[i].type = 1;
+    scanline_events[i].memtype = scanline_events[i - 1].memtype;
+    i++;
+
+    return 0;
+  }
+  
+  mmap_num = 0;
+
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE   
+  for (cur = grub_mmap_overlays; cur; cur = cur->next)
+    mmap_num++;
+#endif
+
+  grub_machine_mmap_iterate (count_hook);
+  
+  /* Initialize variables. */
+  grub_memset (present, 0, sizeof (present));
+  scanline_events = (struct grub_mmap_scan *) 
+    grub_malloc (sizeof (struct grub_mmap_scan) * 2 * mmap_num);
+  
+  if (! scanline_events)
+    {
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+			 "couldn't allocate space for new memory map");
+    }
+
+  i = 0;
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE   
+  /* Register scanline events. */
+  for (cur = grub_mmap_overlays; cur; cur = cur->next)
+    {
+      scanline_events[i].pos = cur->start;
+      scanline_events[i].type = 0;
+      if (cur->type == GRUB_MACHINE_MEMORY_HOLE 
+	  || (cur->type >= 0 && cur->type <= GRUB_MACHINE_MEMORY_MAX_TYPE
+	      && priority[cur->type]))
+	scanline_events[i].memtype = cur->type;
+      else
+	scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED;
+      i++;
+
+      scanline_events[i].pos = cur->end;
+      scanline_events[i].type = 1;
+      scanline_events[i].memtype = scanline_events[i - 1].memtype;
+      i++;
+    }
+#endif /* ! GRUB_MMAP_REGISTER_BY_FIRMWARE */
+
+  grub_machine_mmap_iterate (fill_hook);
+
+  /* Primitive bubble sort. It has complexity O(n^2) but since we're 
+     unlikely to have more than 100 chunks it's probably one of the 
+     fastest for one purpose. */
+  done = 1;
+  while (done)
+    {
+      done = 0;
+      for (i = 0; i < 2 * mmap_num - 1; i++)
+	if (scanline_events[i + 1].pos < scanline_events[i].pos
+	    || (scanline_events[i + 1].pos == scanline_events[i].pos
+		&& scanline_events[i + 1].type == 0 
+		&& scanline_events[i].type == 1))
+	  {
+	    t = scanline_events[i + 1];
+	    scanline_events[i + 1] = scanline_events[i];
+	    scanline_events[i] = t;
+	    done = 1;
+	  }
+    }
+
+  lastaddr = scanline_events[0].pos;
+  lasttype = scanline_events[0].memtype;
+  for (i = 0; i < 2 * mmap_num; i++)
+    {
+      /* Process event. */
+      if (scanline_events[i].type)
+	present[scanline_events[i].memtype]--;
+      else
+	present[scanline_events[i].memtype]++;
+
+      /* Determine current region type. */
+      curtype = -1;
+      for (k = 0; k <= GRUB_MACHINE_MEMORY_MAX_TYPE + 1; k++)
+	if (present[k] && (curtype == -1 || priority[k] > priority[curtype]))
+	  curtype = k;
+
+      /* Anounce region to the hook if necessary. */
+      if ((curtype == -1 || curtype != lasttype) 
+	  && lastaddr != scanline_events[i].pos
+	  && lasttype != -1
+	  && lasttype != GRUB_MACHINE_MEMORY_HOLE
+	  && hook (lastaddr, scanline_events[i].pos - lastaddr, lasttype))
+	{
+	  grub_free (scanline_events);
+	  return GRUB_ERR_NONE;
+	}
+
+      /* Update last values if necessary. */
+      if (curtype == -1 || curtype != lasttype) 
+	{
+	  lasttype = curtype;
+	  lastaddr = scanline_events[i].pos;
+	}
+    }
+
+  grub_free (scanline_events);
+  return GRUB_ERR_NONE;
+}
+
+#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE   
+int
+grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type)
+{
+  struct grub_mmap_region *cur;
+
+  grub_dprintf ("mmap", "registering\n");
+
+  cur = (struct grub_mmap_region *) 
+    grub_malloc (sizeof (struct grub_mmap_region));
+  if (! cur)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+		  "couldn't allocate memory map overlay");
+      return 0;
+    }
+
+  cur->next = grub_mmap_overlays;
+  cur->start = start;
+  cur->end = start + size;
+  cur->type = type;
+  cur->handle = curhandle++;
+  grub_mmap_overlays = cur;
+
+  if (grub_machine_mmap_register (start, size, type, curhandle))
+    {
+      grub_mmap_overlays = cur->next;
+      grub_free (cur);
+      return 0;
+    }
+
+  return cur->handle;
+}
+
+grub_err_t
+grub_mmap_unregister (int handle)
+{
+  struct grub_mmap_region *cur, *prev;
+
+  for (cur = grub_mmap_overlays, prev = 0; cur; prev= cur, cur = cur->next)
+    if (handle == cur->handle)
+      {
+	grub_err_t err;
+	if ((err = grub_machine_mmap_unregister (handle)))
+	  return err;
+
+	if (prev)
+	  prev->next = cur->next;
+	else
+	  grub_mmap_overlays = cur->next;
+	grub_free (cur);
+	return GRUB_ERR_NONE;
+      }
+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "mmap overlay not found");
+}
+
+#endif /* ! GRUB_MMAP_REGISTER_BY_FIRMWARE */
+
+#define CHUNK_SIZE	0x400
+
+static inline grub_uint64_t 
+fill_mask (grub_uint64_t addr, grub_uint64_t mask, grub_uint64_t iterator)
+{
+  int i, j;
+  grub_uint64_t ret = (addr & mask);
+
+  /* Find first fixed bit. */
+  for (i = 0; i < 64; i++)
+    if ((mask & (1ULL << i)) != 0)
+      break;
+  j = 0;
+  for (; i < 64; i++)
+    if ((mask & (1ULL << i)) == 0)
+      {
+	if ((iterator & (1ULL << j)) != 0)
+	  ret |= 1ULL << i;
+	j++;
+      }
+  return ret;
+}
+
+static grub_err_t
+grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)),
+		 int argc, char **args)
+{
+  char * str;
+  grub_uint64_t badaddr, badmask;
+
+  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 __attribute__ ((unused)))
+  {
+    grub_uint64_t iterator, low, high, cur;
+    int tail, var;
+    int i;
+    grub_dprintf ("badram", "hook %llx+%llx\n", (unsigned long long) addr, 
+		  (unsigned long long) size); 
+
+    /* How many trailing zeros? */
+    for (tail = 0; ! (badmask & (1ULL << tail)); tail++);
+
+    /* How many zeros in mask? */
+    var = 0;
+    for (i = 0; i < 64; i++)
+      if (! (badmask & (1ULL << i)))
+	var++;
+
+    if (fill_mask (badaddr, badmask, 0) >= addr)
+      iterator = 0;
+    else
+      {
+	low = 0;
+	high = ~0ULL;
+	/* Find starting value. Keep low and high such that 
+	   fill_mask (low) < addr and fill_mask (high) >= addr;
+	*/
+	while (high - low > 1)
+	  {
+	    cur = (low + high) / 2;
+	    if (fill_mask (badaddr, badmask, cur) >= addr)
+	      high = cur;
+	    else
+	      low = cur;
+	  }
+	iterator = high;
+      }
+
+    for (; iterator < (1ULL << (var - tail))
+	   && (cur = fill_mask (badaddr, badmask, iterator)) < addr + size; 
+	 iterator++)
+      {
+	grub_dprintf ("badram", "%llx (size %llx) is a badram range\n", 
+		      (long long) cur, (long long) (1ULL << tail) - 1); 
+	grub_mmap_register (cur, (1ULL << tail) - 1, GRUB_MACHINE_MEMORY_HOLE);
+      }
+    return 0;
+  }
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "badram string required");
+
+  grub_dprintf ("badram", "executing badram\n");
+
+  str = args[0];
+
+  while (1)
+    {
+      /* Parse address and mask.  */
+      badaddr = grub_strtoull (str, &str, 16);
+      if (*str == ',')
+	str++;
+      badmask = grub_strtoull (str, &str, 16);
+      if (*str == ',')
+	str++;
+
+      if (grub_errno == GRUB_ERR_BAD_NUMBER)
+	{
+	  grub_errno = 0;
+	  return GRUB_ERR_NONE;
+	}
+
+      /* When part of a page is tainted, we discard the whole of it.  There's
+	 no point in providing sub-page chunks.  */
+      badmask &= ~(CHUNK_SIZE - 1);
+
+      grub_dprintf ("badram", "badram %llx:%llx\n", 
+		    (unsigned long long) badaddr, (unsigned long long) badmask);
+
+      grub_mmap_iterate (hook);
+    }
+}
+
+static grub_command_t cmd;
+
+
+GRUB_MOD_INIT(mmap)
+{
+  (void) mod;			/* To stop warning. */
+  cmd = grub_register_command ("badram", grub_cmd_badram,
+			       "badram ADDR1,MASK1[,ADDR2,MASK2[,...]]", 
+			       "declare memory regions as badram");
+}
+
+GRUB_MOD_FINI(mmap)
+{
+  grub_unregister_command (cmd);
+}
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.