All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] decouple mmap parsing by using grub_available_iterate()
@ 2008-08-11 15:22 Robert Millan
  2008-08-11 15:39 ` Vesa Jääskeläinen
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-11 15:22 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 766 bytes --]


Hi,

This patch decouples memory map parsing into a separate grub_available_iterate()
function, for i386-pc and i386-coreboot.  It is mostly intended as a cleanup.
Makes the code more modular so that, for example, the multiboot loader can
construct a memory map without having specific knowledge of the platform,
allows to recombine various init.c & mmap.c in different ways, etc.

Maybe it will be possible to recombine pc/init.c with coreboot/init.c in a
single file later on, although I'm not sure if that might be overkill.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."

[-- Attachment #2: memory_available.diff --]
[-- Type: text/x-diff, Size: 9417 bytes --]

2008-08-11  Robert Millan  <rmh@aybabtu.com>

	* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.

	* include/grub/i386/pc/init.h (GRUB_MACHINE_MEMORY_AVAILABLE): New
	macro.
	(grub_available_iterate): New function declaration.
	* kern/i386/pc/init.c (grub_machine_init): Move e820 parsing from
	here ...
	* kern/i386/pc/mmap.c: New file.
	(grub_available_iterate): ... to here.  Replace hardcoded region type
	check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.

	* include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
	(GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
	(GRUB_MACHINE_MEMORY_AVAILABLE): ... this.
	(grub_available_iterate): Redeclare to return `void', and redeclare
	its hook to use grub_uint64_t as addr and size parameters.

	* kern/i386/coreboot/init.c (grub_machine_init): Adjust heap_init()
	parameters to match with new grub_available_iterate() declaration.
	Move region type check from here ...
	* kern/i386/coreboot/mmap.c (grub_available_iterate): ... to here.

Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk	(revision 1800)
+++ conf/i386-pc.rmk	(working copy)
@@ -43,7 +43,8 @@
 	kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
 	kern/time.c \
-	kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \
+	kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+	kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
 	kern/generic/millisleep.c \
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c	(revision 1800)
+++ kern/i386/pc/init.c	(working copy)
@@ -132,9 +132,6 @@
 void
 grub_machine_init (void)
 {
-  grub_uint32_t cont;
-  struct grub_machine_mmap_entry *entry
-    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
   int i;
   
   /* Initialize the console as early as possible.  */
@@ -156,55 +153,35 @@
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
 		    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
   
-  /* Check if grub_get_mmap_entry works.  */
-  cont = grub_get_mmap_entry (entry, 0);
-
-  if (entry->size)
-    do
-      {
-	/* Avoid the lower memory.  */
-	if (entry->addr < 0x100000)
-	  {
-	    if (entry->len <= 0x100000 - entry->addr)
-	      goto next;
-
-	    entry->len -= 0x100000 - entry->addr;
-	    entry->addr = 0x100000;
-	  }
-	
-	/* Ignore >4GB.  */
-	if (entry->addr <= 0xFFFFFFFF && entry->type == 1)
-	  {
-	    grub_addr_t addr;
-	    grub_size_t len;
-
-	    addr = (grub_addr_t) entry->addr;
-	    len = ((addr + entry->len > 0xFFFFFFFF)
-		   ? 0xFFFFFFFF - addr
-		   : (grub_size_t) entry->len);
-	    add_mem_region (addr, len);
-	  }
-	
-      next:
-	if (! cont)
-	  break;
-	
-	cont = grub_get_mmap_entry (entry, cont);
-      }
-    while (entry->size);
-  else
+  auto int hook (grub_uint64_t, grub_uint64_t);
+  int hook (grub_uint64_t addr, grub_uint64_t size)
     {
-      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
-
-      if (eisa_mmap)
+      /* Avoid the lower memory.  */
+      if (addr < 0x100000)
 	{
-	  add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
-	  add_mem_region (0x1000000, eisa_mmap & ~0xFFFF);
+	  if (size <= 0x100000 - addr)
+	    return 0;
+	  
+	  size -= 0x100000 - addr;
+	  addr = 0x100000;
 	}
-      else
-	add_mem_region (0x100000, grub_get_memsize (1) << 10);
+	
+      /* Ignore >4GB.  */
+      if (addr <= 0xFFFFFFFF)
+	{
+	  grub_size_t len;
+	  
+	  len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
+		 ? 0xFFFFFFFF - addr
+		 : size);
+	  add_mem_region (addr, len);
+	}
+
+      return 0;
     }
 
+  grub_available_iterate (hook);
+  
   compact_mem_regions ();
 
   /* Add the memory regions to free memory, except for the region starting
Index: kern/i386/pc/mmap.c
===================================================================
--- kern/i386/pc/mmap.c	(revision 0)
+++ kern/i386/pc/mmap.c	(revision 0)
@@ -0,0 +1,61 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/types.h>
+
+void
+grub_available_iterate (int (*hook) (grub_uint64_t, grub_uint64_t))
+{
+  grub_uint32_t cont;
+  struct grub_machine_mmap_entry *entry
+    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* Check if grub_get_mmap_entry works.  */
+  cont = grub_get_mmap_entry (entry, 0);
+
+  if (entry->size)
+    do
+      {
+	if (entry->type != GRUB_MACHINE_MEMORY_AVAILABLE)
+	  goto next;
+
+	if (hook (entry->addr, entry->len))
+	  break;
+	
+      next:
+	if (! cont)
+	  break;
+
+	cont = grub_get_mmap_entry (entry, cont);
+      }
+    while (entry->size);
+  else
+    {
+      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
+
+      if (eisa_mmap)
+	{
+	  if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10) == 0)
+	    hook (0x1000000, eisa_mmap & ~0xFFFF);
+	}
+      else
+	hook (0x100000, grub_get_memsize (1) << 10);
+    }
+}
Index: kern/i386/coreboot/init.c
===================================================================
--- kern/i386/coreboot/init.c	(revision 1800)
+++ kern/i386/coreboot/init.c	(working copy)
@@ -82,12 +82,9 @@
   grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
   grub_upper_mem = 0;
 
-  auto int heap_init (mem_region_t);
-  int heap_init (mem_region_t mem_region)
+  auto int heap_init (grub_uint64_t, grub_uint64_t);
+  int heap_init (grub_uint64_t addr, grub_uint64_t size)
   {
-    grub_uint64_t addr = mem_region->addr;
-    grub_uint64_t size = mem_region->size;
-
 #if GRUB_CPU_SIZEOF_VOID_P == 4
     /* Restrict ourselves to 32-bit memory space.  */
     if (addr > ULONG_MAX)
@@ -101,9 +98,6 @@
 
     grub_upper_mem = grub_max (grub_upper_mem, addr + size);
 
-    if (mem_region->type != GRUB_LINUXBIOS_MEMORY_AVAILABLE)
-      return 0;
-
     /* Avoid the lower memory.  */
     if (addr < GRUB_MEMORY_MACHINE_LOWER_SIZE)
       {
Index: kern/i386/coreboot/mmap.c
===================================================================
--- kern/i386/coreboot/mmap.c	(revision 1800)
+++ kern/i386/coreboot/mmap.c	(working copy)
@@ -64,7 +64,7 @@
 }
 
 grub_err_t
-grub_available_iterate (int (*hook) (mem_region_t))
+grub_available_iterate (int (*hook) (grub_uint64_t, grub_uint64_t))
 {
   mem_region_t mem_region;
 
@@ -79,8 +79,13 @@
 				 sizeof (struct grub_linuxbios_table_item));
     for (; (long) mem_region < (long) table_item + (long) table_item->size;
 	 mem_region++)
-      if (hook (mem_region))
-	return 1;
+      {
+	if (mem_region->type != GRUB_MACHINE_MEMORY_AVAILABLE)
+	  continue;
+	
+	if (hook (mem_region->addr, mem_region->size))
+	  return 1;
+      }
 
     return 0;
   }
Index: include/grub/i386/pc/init.h
===================================================================
--- include/grub/i386/pc/init.h	(revision 1800)
+++ include/grub/i386/pc/init.h	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2004,2005,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
@@ -35,6 +35,7 @@
   grub_uint32_t size;
   grub_uint64_t addr;
   grub_uint64_t len;
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
   grub_uint32_t type;
 } __attribute__((packed));
 
@@ -43,6 +44,9 @@
 grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
 				   grub_uint32_t cont);
 
+void EXPORT_FUNC(grub_available_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t));
+
 /* Turn on/off Gate A20.  */
 void grub_gate_a20 (int on);
 
Index: include/grub/i386/coreboot/memory.h
===================================================================
--- include/grub/i386/coreboot/memory.h	(revision 1800)
+++ include/grub/i386/coreboot/memory.h	(working copy)
@@ -25,7 +25,6 @@
 
 #ifndef ASM_FILE
 #include <grub/types.h>
-#include <grub/err.h>
 #endif
 
 #define GRUB_MEMORY_MACHINE_LOWER_USABLE		0x9fc00		/* 640 kiB - 1 kiB */
@@ -55,13 +54,13 @@
 {
   grub_uint64_t addr;
   grub_uint64_t size;
-#define GRUB_LINUXBIOS_MEMORY_AVAILABLE	1
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
   grub_uint32_t type;
 };
 typedef struct grub_linuxbios_mem_region *mem_region_t;
 
-grub_err_t EXPORT_FUNC(grub_available_iterate)
-     (int (*hook) (mem_region_t));
+void EXPORT_FUNC(grub_available_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t));
 
 #endif
 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing by using grub_available_iterate()
  2008-08-11 15:22 [PATCH] decouple mmap parsing by using grub_available_iterate() Robert Millan
@ 2008-08-11 15:39 ` Vesa Jääskeläinen
  2008-08-11 21:24   ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Vesa Jääskeläinen @ 2008-08-11 15:39 UTC (permalink / raw)
  To: The development of GRUB 2

Robert Millan wrote:
> Hi,
> 
> This patch decouples memory map parsing into a separate grub_available_iterate()
> function, for i386-pc and i386-coreboot.  It is mostly intended as a cleanup.
> Makes the code more modular so that, for example, the multiboot loader can
> construct a memory map without having specific knowledge of the platform,
> allows to recombine various init.c & mmap.c in different ways, etc.

Why not use grub_mmap prefix ?



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing by using grub_available_iterate()
  2008-08-11 15:39 ` Vesa Jääskeläinen
@ 2008-08-11 21:24   ` Robert Millan
  2008-08-11 22:07     ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-11 21:24 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Aug 11, 2008 at 06:39:17PM +0300, Vesa Jääskeläinen wrote:
> Robert Millan wrote:
> >Hi,
> >
> >This patch decouples memory map parsing into a separate 
> >grub_available_iterate()
> >function, for i386-pc and i386-coreboot.  It is mostly intended as a 
> >cleanup.
> >Makes the code more modular so that, for example, the multiboot loader can
> >construct a memory map without having specific knowledge of the platform,
> >allows to recombine various init.c & mmap.c in different ways, etc.
> 
> Why not use grub_mmap prefix ?

You mean like grub_mmap_iterate ?  Seems fine (since the change is trivial,
I'll skip sending a new patch).

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing by using grub_available_iterate()
  2008-08-11 21:24   ` Robert Millan
@ 2008-08-11 22:07     ` Robert Millan
  2008-08-12 13:25       ` [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-11 22:07 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Aug 11, 2008 at 11:24:18PM +0200, Robert Millan wrote:
> On Mon, Aug 11, 2008 at 06:39:17PM +0300, Vesa Jääskeläinen wrote:
> > Robert Millan wrote:
> > >Hi,
> > >
> > >This patch decouples memory map parsing into a separate 
> > >grub_available_iterate()
> > >function, for i386-pc and i386-coreboot.  It is mostly intended as a 
> > >cleanup.
> > >Makes the code more modular so that, for example, the multiboot loader can
> > >construct a memory map without having specific knowledge of the platform,
> > >allows to recombine various init.c & mmap.c in different ways, etc.
> > 
> > Why not use grub_mmap prefix ?
> 
> You mean like grub_mmap_iterate ?  Seems fine (since the change is trivial,
> I'll skip sending a new patch).

Now that I think, grub_mmap_iterate() would be misleading, as we're only
iterating through the parts of mmap that are marked as available, not through
the whole thing.  How about grub_mmap_available_iterate?

But this reminds me;  with this interface, it's not possible to gather
information about regions other than the ones that are marked as available.
However, AFAICS, there's no purpose for marking a region as reserved, since
the OS is only going to use regions marked as available anyway.

Therefore, if we implement support for Multiboot mmaps in our loader (as
defined in the spec), we wouldn't be able to include non-available regions in
our map.

Does anyone see a problem in this?  If so, then I think we'd need a function
that can for example handle a third argument, for example `type', for this
purpose.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-11 22:07     ` Robert Millan
@ 2008-08-12 13:25       ` Robert Millan
  2008-08-12 16:29         ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-12 13:25 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 724 bytes --]

On Tue, Aug 12, 2008 at 12:07:23AM +0200, Robert Millan wrote:
> 
> Does anyone see a problem in this?  If so, then I think we'd need a function
> that can for example handle a third argument, for example `type', for this
> purpose.

Actually, adding that third argument was trivial, so I've done that.

Here's a new patch.  This one additionally takes advantage of the new
framework to implement Multiboot mmap in the loader (you can test it using
docs/kernel.c in GRUB Legacy source).

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."

[-- Attachment #2: mmap.diff --]
[-- Type: text/x-diff, Size: 16274 bytes --]

2008-08-12  Robert Millan  <rmh@aybabtu.com>

	* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.

	* include/grub/i386/pc/init.h: Include `<grub/multiboot.h>'.
	(GRUB_MACHINE_MEMORY_AVAILABLE, GRUB_MACHINE_MEMORY_RESERVED): New
	macros.
	(grub_mmap_iterate): New function declaration.
	(struct grub_machine_mmap_entry): Move from here ...
	* include/grub/multiboot.h (struct grub_mmap_entry): ... to here.
	Update all users.
	(GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New
	macros.

	* kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region
	type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.
	Move e820 parsing from here ...
	* kern/i386/pc/mmap.c: New file.
	(grub_mmap_iterate): ... to here.

	* include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
	(GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
	(GRUB_MACHINE_MEMORY_AVAILABLE): ... this.  Update all users.
	(grub_available_iterate): Redeclare to return `void', and redeclare
	its hook to use grub_uint64_t as addr and size parameters, and rename
	to ...
	(grub_mmap_iterate): ... this.  Update all users.

	* kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop
	to make it more readable.

	* loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables.
	(grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions.
	(grub_multiboot_load_elf32): Allocate an extra region after the payload,
	and put the Multiboot memory map there.
	(grub_multiboot): If the loader we're using supports Multiboot memory
	map, refer to it in the Multiboot Information Structure.

Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk	(revision 1800)
+++ conf/i386-pc.rmk	(working copy)
@@ -43,7 +43,8 @@
 	kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
 	kern/time.c \
-	kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \
+	kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+	kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
 	kern/generic/millisleep.c \
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c	(revision 1800)
+++ kern/i386/pc/init.c	(working copy)
@@ -132,9 +132,6 @@
 void
 grub_machine_init (void)
 {
-  grub_uint32_t cont;
-  struct grub_machine_mmap_entry *entry
-    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
   int i;
   
   /* Initialize the console as early as possible.  */
@@ -156,55 +153,35 @@
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
 		    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
   
-  /* Check if grub_get_mmap_entry works.  */
-  cont = grub_get_mmap_entry (entry, 0);
-
-  if (entry->size)
-    do
-      {
-	/* Avoid the lower memory.  */
-	if (entry->addr < 0x100000)
-	  {
-	    if (entry->len <= 0x100000 - entry->addr)
-	      goto next;
-
-	    entry->len -= 0x100000 - entry->addr;
-	    entry->addr = 0x100000;
-	  }
-	
-	/* Ignore >4GB.  */
-	if (entry->addr <= 0xFFFFFFFF && entry->type == 1)
-	  {
-	    grub_addr_t addr;
-	    grub_size_t len;
-
-	    addr = (grub_addr_t) entry->addr;
-	    len = ((addr + entry->len > 0xFFFFFFFF)
-		   ? 0xFFFFFFFF - addr
-		   : (grub_size_t) entry->len);
-	    add_mem_region (addr, len);
-	  }
-	
-      next:
-	if (! cont)
-	  break;
-	
-	cont = grub_get_mmap_entry (entry, cont);
-      }
-    while (entry->size);
-  else
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
     {
-      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
-
-      if (eisa_mmap)
+      /* Avoid the lower memory.  */
+      if (addr < 0x100000)
 	{
-	  add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
-	  add_mem_region (0x1000000, eisa_mmap & ~0xFFFF);
+	  if (size <= 0x100000 - addr)
+	    return 0;
+	  
+	  size -= 0x100000 - addr;
+	  addr = 0x100000;
 	}
-      else
-	add_mem_region (0x100000, grub_get_memsize (1) << 10);
+	
+      /* Ignore >4GB.  */
+      if (addr <= 0xFFFFFFFF && type == GRUB_MMAP_MEMORY_AVAILABLE)
+	{
+	  grub_size_t len;
+	  
+	  len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
+		 ? 0xFFFFFFFF - addr
+		 : size);
+	  add_mem_region (addr, len);
+	}
+
+      return 0;
     }
 
+  grub_mmap_iterate (hook);
+  
   compact_mem_regions ();
 
   /* Add the memory regions to free memory, except for the region starting
Index: kern/i386/pc/mmap.c
===================================================================
--- kern/i386/pc/mmap.c	(revision 0)
+++ kern/i386/pc/mmap.c	(revision 0)
@@ -0,0 +1,60 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/types.h>
+
+void
+grub_mmap_iterate (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  grub_uint32_t cont;
+  struct grub_mmap_entry *entry
+    = (struct grub_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* Check if grub_get_mmap_entry works.  */
+  cont = grub_get_mmap_entry (entry, 0);
+
+  if (entry->size)
+    do
+      {
+	if (hook (entry->addr, entry->len,
+		  /* Multiboot mmaps have been defined to match with the E820 definition.
+		     Therefore, we can just pass type through.  */
+		  entry->type))
+	  break;
+
+	if (! cont)
+	  break;
+
+	cont = grub_get_mmap_entry (entry, cont);
+      }
+    while (entry->size);
+  else
+    {
+      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
+
+      if (eisa_mmap)
+	{
+	  if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MMAP_MEMORY_AVAILABLE) == 0)
+	    hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MMAP_MEMORY_AVAILABLE);
+	}
+      else
+	hook (0x100000, grub_get_memsize (1) << 10, GRUB_MMAP_MEMORY_AVAILABLE);
+    }
+}
Index: kern/i386/coreboot/init.c
===================================================================
--- kern/i386/coreboot/init.c	(revision 1800)
+++ kern/i386/coreboot/init.c	(working copy)
@@ -82,12 +82,9 @@
   grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
   grub_upper_mem = 0;
 
-  auto int heap_init (mem_region_t);
-  int heap_init (mem_region_t mem_region)
+  auto int heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
   {
-    grub_uint64_t addr = mem_region->addr;
-    grub_uint64_t size = mem_region->size;
-
 #if GRUB_CPU_SIZEOF_VOID_P == 4
     /* Restrict ourselves to 32-bit memory space.  */
     if (addr > ULONG_MAX)
@@ -101,7 +98,7 @@
 
     grub_upper_mem = grub_max (grub_upper_mem, addr + size);
 
-    if (mem_region->type != GRUB_LINUXBIOS_MEMORY_AVAILABLE)
+    if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
       return 0;
 
     /* Avoid the lower memory.  */
@@ -134,7 +131,7 @@
     return 0;
   }
 
-  grub_available_iterate (heap_init);
+  grub_mmap_iterate (heap_init);
 
   /* This variable indicates size, not offset.  */
   grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
Index: kern/i386/coreboot/mmap.c
===================================================================
--- kern/i386/coreboot/mmap.c	(revision 1800)
+++ kern/i386/coreboot/mmap.c	(working copy)
@@ -63,8 +63,8 @@
   return 0;
 }
 
-grub_err_t
-grub_available_iterate (int (*hook) (mem_region_t))
+void
+grub_mmap_iterate (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
 {
   mem_region_t mem_region;
 
@@ -77,11 +77,17 @@
     mem_region =
       (mem_region_t) ((long) table_item +
 				 sizeof (struct grub_linuxbios_table_item));
-    for (; (long) mem_region < (long) table_item + (long) table_item->size;
-	 mem_region++)
-      if (hook (mem_region))
-	return 1;
+    while ((long) mem_region < (long) table_item + (long) table_item->size)
+      {
+	if (hook (mem_region->addr, mem_region->size,
+		  /* Multiboot mmaps match with the coreboot mmap definition.
+		     Therefore, we can just pass type through.  */
+		  mem_region->type))
+	  return 1;
 
+	mem_region++;
+      }
+
     return 0;
   }
 
Index: include/grub/i386/pc/init.h
===================================================================
--- include/grub/i386/pc/init.h	(revision 1800)
+++ include/grub/i386/pc/init.h	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2004,2005,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
@@ -21,6 +21,8 @@
 
 #include <grub/types.h>
 #include <grub/symbol.h>
+#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
+				   needed by Multiboot.  */
 
 /* Get the memory size in KB. If EXTENDED is zero, return conventional
    memory, otherwise return extended memory.  */
@@ -30,19 +32,18 @@
    in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
 grub_uint32_t grub_get_eisa_mmap (void);
 
-struct grub_machine_mmap_entry
-{
-  grub_uint32_t size;
-  grub_uint64_t addr;
-  grub_uint64_t len;
-  grub_uint32_t type;
-} __attribute__((packed));
+/* Multiboot mmaps have been defined to match with the E820 definition.  */
+#define GRUB_MACHINE_MEMORY_AVAILABLE	GRUB_MMAP_MEMORY_AVAILABLE
+#define GRUB_MACHINE_MEMORY_RESERVED	GRUB_MMAP_MEMORY_RESERVED
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_mmap_entry *entry,
 				   grub_uint32_t cont);
 
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+
 /* Turn on/off Gate A20.  */
 void grub_gate_a20 (int on);
 
Index: include/grub/i386/coreboot/memory.h
===================================================================
--- include/grub/i386/coreboot/memory.h	(revision 1800)
+++ include/grub/i386/coreboot/memory.h	(working copy)
@@ -25,7 +25,6 @@
 
 #ifndef ASM_FILE
 #include <grub/types.h>
-#include <grub/err.h>
 #endif
 
 #define GRUB_MEMORY_MACHINE_LOWER_USABLE		0x9fc00		/* 640 kiB - 1 kiB */
@@ -55,13 +54,13 @@
 {
   grub_uint64_t addr;
   grub_uint64_t size;
-#define GRUB_LINUXBIOS_MEMORY_AVAILABLE	1
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
   grub_uint32_t type;
 };
 typedef struct grub_linuxbios_mem_region *mem_region_t;
 
-grub_err_t EXPORT_FUNC(grub_available_iterate)
-     (int (*hook) (mem_region_t));
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
 
 #endif
 
Index: include/grub/multiboot.h
===================================================================
--- include/grub/multiboot.h	(revision 1800)
+++ include/grub/multiboot.h	(working copy)
@@ -1,7 +1,7 @@
 /* multiboot.h - multiboot header file with grub definitions. */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,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
@@ -101,6 +101,16 @@
   grub_uint16_t vbe_interface_len;
 };
 
+struct grub_mmap_entry
+{
+  grub_uint32_t size;
+  grub_uint64_t addr;
+  grub_uint64_t len;
+#define GRUB_MMAP_MEMORY_AVAILABLE	1
+#define GRUB_MMAP_MEMORY_RESERVED	2
+  grub_uint32_t type;
+} __attribute__((packed));
+
 struct grub_mod_list
 {
   /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
Index: loader/i386/pc/multiboot.c
===================================================================
--- loader/i386/pc/multiboot.c	(revision 1800)
+++ loader/i386/pc/multiboot.c	(working copy)
@@ -103,14 +103,60 @@
       grub_free ((void *) mbi->cmdline);
       grub_free (mbi);
     }
-
-
+  
   mbi = 0;
   grub_dl_unref (my_mod);
 
   return GRUB_ERR_NONE;
 }
 
+/* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
+   by the spec.  Is there something we can do about it?  */
+static grub_uint32_t mmap_addr = 0;
+static grub_uint32_t mmap_length;
+
+/* Return the length of the Multiboot mmap that will be needed to allocate
+   our platform's map.  */
+static grub_uint32_t
+grub_get_multiboot_mmap_len ()
+{
+  grub_size_t count = 0;
+
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int hook (grub_uint64_t addr __attribute__ ((unused)),
+	    grub_uint64_t size __attribute__ ((unused)),
+	    grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+  
+  grub_mmap_iterate (hook);
+  
+  return count * sizeof (struct grub_mmap_entry);
+}
+
+/* Fill previously allocated Multiboot mmap.  */
+static void
+grub_fill_multiboot_mmap (struct grub_mmap_entry *first_entry)
+{
+  struct grub_mmap_entry *mmap_entry = (struct grub_mmap_entry *) first_entry;
+
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int 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;
+      mmap_entry->size = sizeof (struct grub_mmap_entry) - sizeof (mmap_entry->size);
+      mmap_entry++;
+
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+}
+
 /* Check if BUFFER contains ELF32.  */
 static int
 grub_multiboot_is_elf32 (void *buffer)
@@ -152,7 +198,11 @@
 	if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
 	  highest_segment = i;
       }
-  grub_multiboot_payload_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
+
+  mmap_length = grub_get_multiboot_mmap_len ();
+
+  grub_multiboot_payload_size = ((phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr
+				 + mmap_length);
   grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
 
   if (playground)
@@ -196,6 +246,12 @@
 
 #undef phdr
 
+  grub_fill_multiboot_mmap ((struct grub_mmap_entry *) (grub_multiboot_payload_orig
+							+ grub_multiboot_payload_size
+							- mmap_length));
+
+  mmap_addr = grub_multiboot_payload_dest + grub_multiboot_payload_size - mmap_length;
+
   if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
     entry = (grub_addr_t) playground;
   else
@@ -437,12 +493,18 @@
 
   grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
 
-  mbi->flags = MULTIBOOT_INFO_MEMORY;
-
   /* Convert from bytes to kilobytes.  */
   mbi->mem_lower = grub_lower_mem / 1024;
   mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->flags |= MULTIBOOT_INFO_MEMORY;
 
+  if (mmap_addr)
+    {
+      mbi->mmap_addr = mmap_addr;
+      mbi->mmap_length = mmap_length;
+      mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
+    }
+
   for (i = 0, len = 0; i < argc; i++)
     len += grub_strlen (argv[i]) + 1;
 
Index: loader/i386/bsd.c
===================================================================
--- loader/i386/bsd.c	(revision 1800)
+++ loader/i386/bsd.c	(working copy)
@@ -313,7 +313,7 @@
 grub_openbsd_boot (void)
 {
   char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
-  struct grub_machine_mmap_entry mmap;
+  struct grub_mmap_entry mmap;
   struct grub_openbsd_bios_mmap *pm;
   struct grub_openbsd_bootargs *pa;
   grub_uint32_t bootdev, biosdev, unit, slice, part, cont;

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-12 13:25       ` [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader Robert Millan
@ 2008-08-12 16:29         ` Robert Millan
  2008-08-12 22:38           ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-12 16:29 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 313 bytes --]


My last commit just broke my own patch (sigh).

Here's an updated version.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."

[-- Attachment #2: mmap.diff --]
[-- Type: text/x-diff, Size: 17121 bytes --]

2008-08-12  Robert Millan  <rmh@aybabtu.com>

	* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.

	* include/grub/i386/pc/init.h: Include `<grub/multiboot.h>'.
	(GRUB_MACHINE_MEMORY_AVAILABLE, GRUB_MACHINE_MEMORY_RESERVED): New
	macros.
	(grub_mmap_iterate): New function declaration.
	(struct grub_machine_mmap_entry): Move from here ...
	* include/grub/multiboot.h (struct grub_mmap_entry): ... to here.
	Update all users.
	(GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New
	macros.

	* kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region
	type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.
	Move e820 parsing from here ...
	* kern/i386/pc/mmap.c: New file.
	(grub_mmap_iterate): ... to here.

	* include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
	(GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
	(GRUB_MACHINE_MEMORY_AVAILABLE): ... this.  Update all users.
	(grub_available_iterate): Redeclare to return `void', and redeclare
	its hook to use grub_uint64_t as addr and size parameters, and rename
	to ...
	(grub_mmap_iterate): ... this.  Update all users.

	* kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop
	to make it more readable.

	* loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables.
	(grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions.
	(grub_multiboot): Allocate an extra region after the payload, and fill
	it with a Multiboot memory map.  Adjust a.out loader to calculate size
	with the extra space.
	(grub_multiboot_load_elf32): Adjust elf32 loader to calculate size
	with the extra space.

Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk	(revision 1802)
+++ conf/i386-pc.rmk	(working copy)
@@ -43,7 +43,8 @@
 	kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
 	kern/time.c \
-	kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \
+	kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+	kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
 	kern/generic/millisleep.c \
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c	(revision 1802)
+++ kern/i386/pc/init.c	(working copy)
@@ -132,9 +132,6 @@
 void
 grub_machine_init (void)
 {
-  grub_uint32_t cont;
-  struct grub_machine_mmap_entry *entry
-    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
   int i;
   
   /* Initialize the console as early as possible.  */
@@ -156,55 +153,35 @@
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
 		    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
   
-  /* Check if grub_get_mmap_entry works.  */
-  cont = grub_get_mmap_entry (entry, 0);
-
-  if (entry->size)
-    do
-      {
-	/* Avoid the lower memory.  */
-	if (entry->addr < 0x100000)
-	  {
-	    if (entry->len <= 0x100000 - entry->addr)
-	      goto next;
-
-	    entry->len -= 0x100000 - entry->addr;
-	    entry->addr = 0x100000;
-	  }
-	
-	/* Ignore >4GB.  */
-	if (entry->addr <= 0xFFFFFFFF && entry->type == 1)
-	  {
-	    grub_addr_t addr;
-	    grub_size_t len;
-
-	    addr = (grub_addr_t) entry->addr;
-	    len = ((addr + entry->len > 0xFFFFFFFF)
-		   ? 0xFFFFFFFF - addr
-		   : (grub_size_t) entry->len);
-	    add_mem_region (addr, len);
-	  }
-	
-      next:
-	if (! cont)
-	  break;
-	
-	cont = grub_get_mmap_entry (entry, cont);
-      }
-    while (entry->size);
-  else
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
     {
-      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
-
-      if (eisa_mmap)
+      /* Avoid the lower memory.  */
+      if (addr < 0x100000)
 	{
-	  add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
-	  add_mem_region (0x1000000, eisa_mmap & ~0xFFFF);
+	  if (size <= 0x100000 - addr)
+	    return 0;
+	  
+	  size -= 0x100000 - addr;
+	  addr = 0x100000;
 	}
-      else
-	add_mem_region (0x100000, grub_get_memsize (1) << 10);
+	
+      /* Ignore >4GB.  */
+      if (addr <= 0xFFFFFFFF && type == GRUB_MMAP_MEMORY_AVAILABLE)
+	{
+	  grub_size_t len;
+	  
+	  len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
+		 ? 0xFFFFFFFF - addr
+		 : size);
+	  add_mem_region (addr, len);
+	}
+
+      return 0;
     }
 
+  grub_mmap_iterate (hook);
+  
   compact_mem_regions ();
 
   /* Add the memory regions to free memory, except for the region starting
Index: kern/i386/pc/mmap.c
===================================================================
--- kern/i386/pc/mmap.c	(revision 0)
+++ kern/i386/pc/mmap.c	(revision 0)
@@ -0,0 +1,60 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/types.h>
+
+void
+grub_mmap_iterate (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  grub_uint32_t cont;
+  struct grub_mmap_entry *entry
+    = (struct grub_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* Check if grub_get_mmap_entry works.  */
+  cont = grub_get_mmap_entry (entry, 0);
+
+  if (entry->size)
+    do
+      {
+	if (hook (entry->addr, entry->len,
+		  /* Multiboot mmaps have been defined to match with the E820 definition.
+		     Therefore, we can just pass type through.  */
+		  entry->type))
+	  break;
+
+	if (! cont)
+	  break;
+
+	cont = grub_get_mmap_entry (entry, cont);
+      }
+    while (entry->size);
+  else
+    {
+      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
+
+      if (eisa_mmap)
+	{
+	  if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MMAP_MEMORY_AVAILABLE) == 0)
+	    hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MMAP_MEMORY_AVAILABLE);
+	}
+      else
+	hook (0x100000, grub_get_memsize (1) << 10, GRUB_MMAP_MEMORY_AVAILABLE);
+    }
+}
Index: kern/i386/coreboot/init.c
===================================================================
--- kern/i386/coreboot/init.c	(revision 1802)
+++ kern/i386/coreboot/init.c	(working copy)
@@ -82,12 +82,9 @@
   grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
   grub_upper_mem = 0;
 
-  auto int heap_init (mem_region_t);
-  int heap_init (mem_region_t mem_region)
+  auto int heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
   {
-    grub_uint64_t addr = mem_region->addr;
-    grub_uint64_t size = mem_region->size;
-
 #if GRUB_CPU_SIZEOF_VOID_P == 4
     /* Restrict ourselves to 32-bit memory space.  */
     if (addr > ULONG_MAX)
@@ -101,7 +98,7 @@
 
     grub_upper_mem = grub_max (grub_upper_mem, addr + size);
 
-    if (mem_region->type != GRUB_LINUXBIOS_MEMORY_AVAILABLE)
+    if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
       return 0;
 
     /* Avoid the lower memory.  */
@@ -134,7 +131,7 @@
     return 0;
   }
 
-  grub_available_iterate (heap_init);
+  grub_mmap_iterate (heap_init);
 
   /* This variable indicates size, not offset.  */
   grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
Index: kern/i386/coreboot/mmap.c
===================================================================
--- kern/i386/coreboot/mmap.c	(revision 1802)
+++ kern/i386/coreboot/mmap.c	(working copy)
@@ -63,8 +63,8 @@
   return 0;
 }
 
-grub_err_t
-grub_available_iterate (int (*hook) (mem_region_t))
+void
+grub_mmap_iterate (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
 {
   mem_region_t mem_region;
 
@@ -77,11 +77,17 @@
     mem_region =
       (mem_region_t) ((long) table_item +
 				 sizeof (struct grub_linuxbios_table_item));
-    for (; (long) mem_region < (long) table_item + (long) table_item->size;
-	 mem_region++)
-      if (hook (mem_region))
-	return 1;
+    while ((long) mem_region < (long) table_item + (long) table_item->size)
+      {
+	if (hook (mem_region->addr, mem_region->size,
+		  /* Multiboot mmaps match with the coreboot mmap definition.
+		     Therefore, we can just pass type through.  */
+		  mem_region->type))
+	  return 1;
 
+	mem_region++;
+      }
+
     return 0;
   }
 
Index: include/grub/i386/pc/init.h
===================================================================
--- include/grub/i386/pc/init.h	(revision 1802)
+++ include/grub/i386/pc/init.h	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2004,2005,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
@@ -21,6 +21,8 @@
 
 #include <grub/types.h>
 #include <grub/symbol.h>
+#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
+				   needed by Multiboot.  */
 
 /* Get the memory size in KB. If EXTENDED is zero, return conventional
    memory, otherwise return extended memory.  */
@@ -30,19 +32,18 @@
    in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
 grub_uint32_t grub_get_eisa_mmap (void);
 
-struct grub_machine_mmap_entry
-{
-  grub_uint32_t size;
-  grub_uint64_t addr;
-  grub_uint64_t len;
-  grub_uint32_t type;
-} __attribute__((packed));
+/* Multiboot mmaps have been defined to match with the E820 definition.  */
+#define GRUB_MACHINE_MEMORY_AVAILABLE	GRUB_MMAP_MEMORY_AVAILABLE
+#define GRUB_MACHINE_MEMORY_RESERVED	GRUB_MMAP_MEMORY_RESERVED
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_mmap_entry *entry,
 				   grub_uint32_t cont);
 
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+
 /* Turn on/off Gate A20.  */
 void grub_gate_a20 (int on);
 
Index: include/grub/i386/coreboot/memory.h
===================================================================
--- include/grub/i386/coreboot/memory.h	(revision 1802)
+++ include/grub/i386/coreboot/memory.h	(working copy)
@@ -25,7 +25,6 @@
 
 #ifndef ASM_FILE
 #include <grub/types.h>
-#include <grub/err.h>
 #endif
 
 #define GRUB_MEMORY_MACHINE_LOWER_USABLE		0x9fc00		/* 640 kiB - 1 kiB */
@@ -55,13 +54,13 @@
 {
   grub_uint64_t addr;
   grub_uint64_t size;
-#define GRUB_LINUXBIOS_MEMORY_AVAILABLE	1
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
   grub_uint32_t type;
 };
 typedef struct grub_linuxbios_mem_region *mem_region_t;
 
-grub_err_t EXPORT_FUNC(grub_available_iterate)
-     (int (*hook) (mem_region_t));
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
 
 #endif
 
Index: include/grub/multiboot.h
===================================================================
--- include/grub/multiboot.h	(revision 1802)
+++ include/grub/multiboot.h	(working copy)
@@ -1,7 +1,7 @@
 /* multiboot.h - multiboot header file with grub definitions. */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,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
@@ -101,6 +101,16 @@
   grub_uint16_t vbe_interface_len;
 };
 
+struct grub_mmap_entry
+{
+  grub_uint32_t size;
+  grub_uint64_t addr;
+  grub_uint64_t len;
+#define GRUB_MMAP_MEMORY_AVAILABLE	1
+#define GRUB_MMAP_MEMORY_RESERVED	2
+  grub_uint32_t type;
+} __attribute__((packed));
+
 struct grub_mod_list
 {
   /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
Index: loader/i386/pc/multiboot.c
===================================================================
--- loader/i386/pc/multiboot.c	(revision 1802)
+++ loader/i386/pc/multiboot.c	(working copy)
@@ -78,14 +78,60 @@
       grub_free ((void *) mbi->cmdline);
       grub_free (mbi);
     }
-
-
+  
   mbi = 0;
   grub_dl_unref (my_mod);
 
   return GRUB_ERR_NONE;
 }
 
+/* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
+   by the spec.  Is there something we can do about it?  */
+static grub_uint32_t mmap_addr = 0;
+static grub_uint32_t mmap_length;
+
+/* Return the length of the Multiboot mmap that will be needed to allocate
+   our platform's map.  */
+static grub_uint32_t
+grub_get_multiboot_mmap_len ()
+{
+  grub_size_t count = 0;
+
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int hook (grub_uint64_t addr __attribute__ ((unused)),
+	    grub_uint64_t size __attribute__ ((unused)),
+	    grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+  
+  grub_mmap_iterate (hook);
+  
+  return count * sizeof (struct grub_mmap_entry);
+}
+
+/* Fill previously allocated Multiboot mmap.  */
+static void
+grub_fill_multiboot_mmap (struct grub_mmap_entry *first_entry)
+{
+  struct grub_mmap_entry *mmap_entry = (struct grub_mmap_entry *) first_entry;
+
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int 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;
+      mmap_entry->size = sizeof (struct grub_mmap_entry) - sizeof (mmap_entry->size);
+      mmap_entry++;
+
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+}
+
 /* Check if BUFFER contains ELF32.  */
 static int
 grub_multiboot_is_elf32 (void *buffer)
@@ -127,7 +173,7 @@
 	if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
 	  highest_segment = i;
       }
-  grub_multiboot_payload_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
+  grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
   grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
 
   playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@@ -379,6 +425,9 @@
       playground = NULL;
     }
 
+  mmap_length = grub_get_multiboot_mmap_len ();
+  grub_multiboot_payload_size = mmap_length;
+
   if (header->flags & MULTIBOOT_AOUT_KLUDGE)
     {
       int offset = ((char *) header - buffer -
@@ -387,9 +436,9 @@
 		       header->load_end_addr - header->load_addr);
 
       if (header->bss_end_addr)
-	grub_multiboot_payload_size = (header->bss_end_addr - header->load_addr);
+	grub_multiboot_payload_size += (header->bss_end_addr - header->load_addr);
       else
-	grub_multiboot_payload_size = load_size;
+	grub_multiboot_payload_size += load_size;
       grub_multiboot_payload_dest = header->load_addr;
 
       playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@@ -416,6 +465,12 @@
     goto fail;
 
       
+  grub_fill_multiboot_mmap ((struct grub_mmap_entry *) (grub_multiboot_payload_orig
+							+ grub_multiboot_payload_size
+							- mmap_length));
+
+  mmap_addr = grub_multiboot_payload_dest + grub_multiboot_payload_size - mmap_length;
+
   if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
     {
       grub_memmove (playground, &grub_multiboot_forward_relocator, RELOCATOR_SIZEOF(forward));
@@ -439,12 +494,15 @@
 
   grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
 
-  mbi->flags = MULTIBOOT_INFO_MEMORY;
-
   /* Convert from bytes to kilobytes.  */
   mbi->mem_lower = grub_lower_mem / 1024;
   mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->flags |= MULTIBOOT_INFO_MEMORY;
 
+  mbi->mmap_addr = mmap_addr;
+  mbi->mmap_length = mmap_length;
+  mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
+
   for (i = 0, len = 0; i < argc; i++)
     len += grub_strlen (argv[i]) + 1;
 
Index: loader/i386/bsd.c
===================================================================
--- loader/i386/bsd.c	(revision 1802)
+++ loader/i386/bsd.c	(working copy)
@@ -313,7 +313,7 @@
 grub_openbsd_boot (void)
 {
   char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
-  struct grub_machine_mmap_entry mmap;
+  struct grub_mmap_entry mmap;
   struct grub_openbsd_bios_mmap *pm;
   struct grub_openbsd_bootargs *pa;
   grub_uint32_t bootdev, biosdev, unit, slice, part, cont;

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-12 16:29         ` Robert Millan
@ 2008-08-12 22:38           ` Robert Millan
  2008-08-12 23:44             ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-12 22:38 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 341 bytes --]


And here's a new one, using NESTED_FUNC_ATTR to prevent %ecx being trashed
as Bean pointed out on IRC.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."

[-- Attachment #2: mmap.diff --]
[-- Type: text/x-diff, Size: 15242 bytes --]

2008-08-12  Robert Millan  <rmh@aybabtu.com>

	* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.

	* include/grub/i386/pc/init.h: Include `<grub/multiboot.h>'.
	(GRUB_MACHINE_MEMORY_AVAILABLE, GRUB_MACHINE_MEMORY_RESERVED): New
	macros.
	(grub_mmap_iterate): New function declaration.
	(struct grub_machine_mmap_entry): Move from here ...
	* include/grub/multiboot.h (struct grub_mmap_entry): ... to here.
	Update all users.
	(GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New
	macros.

	* kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region
	type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.
	Move e820 parsing from here ...
	* kern/i386/pc/mmap.c: New file.
	(grub_mmap_iterate): ... to here.

	* include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
	(GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
	(GRUB_MACHINE_MEMORY_AVAILABLE): ... this.  Update all users.
	(grub_available_iterate): Redeclare to return `void', and redeclare
	its hook to use grub_uint64_t as addr and size parameters, and rename
	to ...
	(grub_mmap_iterate): ... this.  Update all users.

	* kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop
	to make it more readable.

	* loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables.
	(grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions.
	(grub_multiboot): Allocate an extra region after the payload, and fill
	it with a Multiboot memory map.  Adjust a.out loader to calculate size
	with the extra space.
	(grub_multiboot_load_elf32): Adjust elf32 loader to calculate size
	with the extra space.

Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk	(revision 1802)
+++ conf/i386-pc.rmk	(working copy)
@@ -43,7 +43,8 @@
 	kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
 	kern/time.c \
-	kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \
+	kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+	kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
 	kern/generic/millisleep.c \
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c	(revision 1802)
+++ kern/i386/pc/init.c	(working copy)
@@ -132,9 +132,6 @@
 void
 grub_machine_init (void)
 {
-  grub_uint32_t cont;
-  struct grub_machine_mmap_entry *entry
-    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
   int i;
   
   /* Initialize the console as early as possible.  */
@@ -156,55 +153,35 @@
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
 		    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
   
-  /* Check if grub_get_mmap_entry works.  */
-  cont = grub_get_mmap_entry (entry, 0);
-
-  if (entry->size)
-    do
-      {
-	/* Avoid the lower memory.  */
-	if (entry->addr < 0x100000)
-	  {
-	    if (entry->len <= 0x100000 - entry->addr)
-	      goto next;
-
-	    entry->len -= 0x100000 - entry->addr;
-	    entry->addr = 0x100000;
-	  }
-	
-	/* Ignore >4GB.  */
-	if (entry->addr <= 0xFFFFFFFF && entry->type == 1)
-	  {
-	    grub_addr_t addr;
-	    grub_size_t len;
-
-	    addr = (grub_addr_t) entry->addr;
-	    len = ((addr + entry->len > 0xFFFFFFFF)
-		   ? 0xFFFFFFFF - addr
-		   : (grub_size_t) entry->len);
-	    add_mem_region (addr, len);
-	  }
-	
-      next:
-	if (! cont)
-	  break;
-	
-	cont = grub_get_mmap_entry (entry, cont);
-      }
-    while (entry->size);
-  else
+  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)
     {
-      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
-
-      if (eisa_mmap)
+      /* Avoid the lower memory.  */
+      if (addr < 0x100000)
 	{
-	  add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
-	  add_mem_region (0x1000000, eisa_mmap & ~0xFFFF);
+	  if (size <= 0x100000 - addr)
+	    return 0;
+	  
+	  size -= 0x100000 - addr;
+	  addr = 0x100000;
 	}
-      else
-	add_mem_region (0x100000, grub_get_memsize (1) << 10);
+	
+      /* Ignore >4GB.  */
+      if (addr <= 0xFFFFFFFF && type == GRUB_MMAP_MEMORY_AVAILABLE)
+	{
+	  grub_size_t len;
+	  
+	  len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
+		 ? 0xFFFFFFFF - addr
+		 : size);
+	  add_mem_region (addr, len);
+	}
+
+      return 0;
     }
 
+  grub_mmap_iterate (hook);
+  
   compact_mem_regions ();
 
   /* Add the memory regions to free memory, except for the region starting
Index: kern/i386/coreboot/init.c
===================================================================
--- kern/i386/coreboot/init.c	(revision 1802)
+++ kern/i386/coreboot/init.c	(working copy)
@@ -82,12 +82,9 @@
   grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
   grub_upper_mem = 0;
 
-  auto int heap_init (mem_region_t);
-  int heap_init (mem_region_t mem_region)
+  auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
   {
-    grub_uint64_t addr = mem_region->addr;
-    grub_uint64_t size = mem_region->size;
-
 #if GRUB_CPU_SIZEOF_VOID_P == 4
     /* Restrict ourselves to 32-bit memory space.  */
     if (addr > ULONG_MAX)
@@ -101,7 +98,7 @@
 
     grub_upper_mem = grub_max (grub_upper_mem, addr + size);
 
-    if (mem_region->type != GRUB_LINUXBIOS_MEMORY_AVAILABLE)
+    if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
       return 0;
 
     /* Avoid the lower memory.  */
@@ -134,7 +131,7 @@
     return 0;
   }
 
-  grub_available_iterate (heap_init);
+  grub_mmap_iterate (heap_init);
 
   /* This variable indicates size, not offset.  */
   grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
Index: kern/i386/coreboot/mmap.c
===================================================================
--- kern/i386/coreboot/mmap.c	(revision 1802)
+++ kern/i386/coreboot/mmap.c	(working copy)
@@ -63,8 +63,8 @@
   return 0;
 }
 
-grub_err_t
-grub_available_iterate (int (*hook) (mem_region_t))
+void
+grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
 {
   mem_region_t mem_region;
 
@@ -77,11 +77,17 @@
     mem_region =
       (mem_region_t) ((long) table_item +
 				 sizeof (struct grub_linuxbios_table_item));
-    for (; (long) mem_region < (long) table_item + (long) table_item->size;
-	 mem_region++)
-      if (hook (mem_region))
-	return 1;
+    while ((long) mem_region < (long) table_item + (long) table_item->size)
+      {
+	if (hook (mem_region->addr, mem_region->size,
+		  /* Multiboot mmaps match with the coreboot mmap definition.
+		     Therefore, we can just pass type through.  */
+		  mem_region->type))
+	  return 1;
 
+	mem_region++;
+      }
+
     return 0;
   }
 
Index: include/grub/i386/pc/init.h
===================================================================
--- include/grub/i386/pc/init.h	(revision 1802)
+++ include/grub/i386/pc/init.h	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2004,2005,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
@@ -21,6 +21,8 @@
 
 #include <grub/types.h>
 #include <grub/symbol.h>
+#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
+				   needed by Multiboot.  */
 
 /* Get the memory size in KB. If EXTENDED is zero, return conventional
    memory, otherwise return extended memory.  */
@@ -30,19 +32,18 @@
    in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
 grub_uint32_t grub_get_eisa_mmap (void);
 
-struct grub_machine_mmap_entry
-{
-  grub_uint32_t size;
-  grub_uint64_t addr;
-  grub_uint64_t len;
-  grub_uint32_t type;
-} __attribute__((packed));
+/* Multiboot mmaps have been defined to match with the E820 definition.  */
+#define GRUB_MACHINE_MEMORY_AVAILABLE	GRUB_MMAP_MEMORY_AVAILABLE
+#define GRUB_MACHINE_MEMORY_RESERVED	GRUB_MMAP_MEMORY_RESERVED
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_mmap_entry *entry,
 				   grub_uint32_t cont);
 
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+
 /* Turn on/off Gate A20.  */
 void grub_gate_a20 (int on);
 
Index: include/grub/i386/coreboot/memory.h
===================================================================
--- include/grub/i386/coreboot/memory.h	(revision 1802)
+++ include/grub/i386/coreboot/memory.h	(working copy)
@@ -25,7 +25,6 @@
 
 #ifndef ASM_FILE
 #include <grub/types.h>
-#include <grub/err.h>
 #endif
 
 #define GRUB_MEMORY_MACHINE_LOWER_USABLE		0x9fc00		/* 640 kiB - 1 kiB */
@@ -55,13 +54,13 @@
 {
   grub_uint64_t addr;
   grub_uint64_t size;
-#define GRUB_LINUXBIOS_MEMORY_AVAILABLE	1
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
   grub_uint32_t type;
 };
 typedef struct grub_linuxbios_mem_region *mem_region_t;
 
-grub_err_t EXPORT_FUNC(grub_available_iterate)
-     (int (*hook) (mem_region_t));
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
 
 #endif
 
Index: include/grub/multiboot.h
===================================================================
--- include/grub/multiboot.h	(revision 1802)
+++ include/grub/multiboot.h	(working copy)
@@ -1,7 +1,7 @@
 /* multiboot.h - multiboot header file with grub definitions. */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,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
@@ -101,6 +101,16 @@
   grub_uint16_t vbe_interface_len;
 };
 
+struct grub_mmap_entry
+{
+  grub_uint32_t size;
+  grub_uint64_t addr;
+  grub_uint64_t len;
+#define GRUB_MMAP_MEMORY_AVAILABLE	1
+#define GRUB_MMAP_MEMORY_RESERVED	2
+  grub_uint32_t type;
+} __attribute__((packed));
+
 struct grub_mod_list
 {
   /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
Index: loader/i386/pc/multiboot.c
===================================================================
--- loader/i386/pc/multiboot.c	(revision 1802)
+++ loader/i386/pc/multiboot.c	(working copy)
@@ -78,14 +78,60 @@
       grub_free ((void *) mbi->cmdline);
       grub_free (mbi);
     }
-
-
+  
   mbi = 0;
   grub_dl_unref (my_mod);
 
   return GRUB_ERR_NONE;
 }
 
+/* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
+   by the spec.  Is there something we can do about it?  */
+static grub_uint32_t mmap_addr = 0;
+static grub_uint32_t mmap_length;
+
+/* Return the length of the Multiboot mmap that will be needed to allocate
+   our platform's map.  */
+static grub_uint32_t
+grub_get_multiboot_mmap_len ()
+{
+  grub_size_t count = 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 __attribute__ ((unused)),
+			     grub_uint64_t size __attribute__ ((unused)),
+			     grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+  
+  grub_mmap_iterate (hook);
+  
+  return count * sizeof (struct grub_mmap_entry);
+}
+
+/* Fill previously allocated Multiboot mmap.  */
+static void
+grub_fill_multiboot_mmap (struct grub_mmap_entry *first_entry)
+{
+  struct grub_mmap_entry *mmap_entry = (struct grub_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;
+      mmap_entry->size = sizeof (struct grub_mmap_entry) - sizeof (mmap_entry->size);
+      mmap_entry++;
+
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+}
+
 /* Check if BUFFER contains ELF32.  */
 static int
 grub_multiboot_is_elf32 (void *buffer)
@@ -127,7 +173,7 @@
 	if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
 	  highest_segment = i;
       }
-  grub_multiboot_payload_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
+  grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
   grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
 
   playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@@ -379,6 +425,9 @@
       playground = NULL;
     }
 
+  mmap_length = grub_get_multiboot_mmap_len ();
+  grub_multiboot_payload_size = mmap_length;
+
   if (header->flags & MULTIBOOT_AOUT_KLUDGE)
     {
       int offset = ((char *) header - buffer -
@@ -387,9 +436,9 @@
 		       header->load_end_addr - header->load_addr);
 
       if (header->bss_end_addr)
-	grub_multiboot_payload_size = (header->bss_end_addr - header->load_addr);
+	grub_multiboot_payload_size += (header->bss_end_addr - header->load_addr);
       else
-	grub_multiboot_payload_size = load_size;
+	grub_multiboot_payload_size += load_size;
       grub_multiboot_payload_dest = header->load_addr;
 
       playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@@ -416,6 +465,12 @@
     goto fail;
 
       
+  grub_fill_multiboot_mmap ((struct grub_mmap_entry *) (grub_multiboot_payload_orig
+							+ grub_multiboot_payload_size
+							- mmap_length));
+
+  mmap_addr = grub_multiboot_payload_dest + grub_multiboot_payload_size - mmap_length;
+
   if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
     {
       grub_memmove (playground, &grub_multiboot_forward_relocator, RELOCATOR_SIZEOF(forward));
@@ -439,12 +494,15 @@
 
   grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
 
-  mbi->flags = MULTIBOOT_INFO_MEMORY;
-
   /* Convert from bytes to kilobytes.  */
   mbi->mem_lower = grub_lower_mem / 1024;
   mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->flags |= MULTIBOOT_INFO_MEMORY;
 
+  mbi->mmap_addr = mmap_addr;
+  mbi->mmap_length = mmap_length;
+  mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
+
   for (i = 0, len = 0; i < argc; i++)
     len += grub_strlen (argv[i]) + 1;
 
Index: loader/i386/bsd.c
===================================================================
--- loader/i386/bsd.c	(revision 1802)
+++ loader/i386/bsd.c	(working copy)
@@ -313,7 +313,7 @@
 grub_openbsd_boot (void)
 {
   char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
-  struct grub_machine_mmap_entry mmap;
+  struct grub_mmap_entry mmap;
   struct grub_openbsd_bios_mmap *pm;
   struct grub_openbsd_bootargs *pa;
   grub_uint32_t bootdev, biosdev, unit, slice, part, cont;

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-12 22:38           ` Robert Millan
@ 2008-08-12 23:44             ` Robert Millan
  2008-08-13 17:52               ` Marco Gerards
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-12 23:44 UTC (permalink / raw)
  To: The development of GRUB 2; +Cc: Jonathan A. Kollasch

[-- Attachment #1: Type: text/plain, Size: 322 bytes --]


And here we go *AGAIN*, this time not forgetting to include all files in the
patch.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."

[-- Attachment #2: mmap.diff --]
[-- Type: text/x-diff, Size: 17138 bytes --]

2008-08-12  Robert Millan  <rmh@aybabtu.com>

	* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.

	* include/grub/i386/pc/init.h: Include `<grub/multiboot.h>'.
	(GRUB_MACHINE_MEMORY_AVAILABLE, GRUB_MACHINE_MEMORY_RESERVED): New
	macros.
	(grub_mmap_iterate): New function declaration.
	(struct grub_machine_mmap_entry): Move from here ...
	* include/grub/multiboot.h (struct grub_mmap_entry): ... to here.
	Update all users.
	(GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New
	macros.

	* kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region
	type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.
	Move e820 parsing from here ...
	* kern/i386/pc/mmap.c: New file.
	(grub_mmap_iterate): ... to here.

	* include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
	(GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
	(GRUB_MACHINE_MEMORY_AVAILABLE): ... this.  Update all users.
	(grub_available_iterate): Redeclare to return `void', and redeclare
	its hook to use grub_uint64_t as addr and size parameters, and rename
	to ...
	(grub_mmap_iterate): ... this.  Update all users.

	* kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop
	to make it more readable.

	* loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables.
	(grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions.
	(grub_multiboot): Allocate an extra region after the payload, and fill
	it with a Multiboot memory map.  Adjust a.out loader to calculate size
	with the extra space.
	(grub_multiboot_load_elf32): Adjust elf32 loader to calculate size
	with the extra space.

Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk	(revision 1802)
+++ conf/i386-pc.rmk	(working copy)
@@ -43,7 +43,8 @@
 	kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
 	kern/time.c \
-	kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \
+	kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+	kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
 	kern/generic/millisleep.c \
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c	(revision 1802)
+++ kern/i386/pc/init.c	(working copy)
@@ -132,9 +132,6 @@
 void
 grub_machine_init (void)
 {
-  grub_uint32_t cont;
-  struct grub_machine_mmap_entry *entry
-    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
   int i;
   
   /* Initialize the console as early as possible.  */
@@ -156,55 +153,35 @@
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
 		    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
   
-  /* Check if grub_get_mmap_entry works.  */
-  cont = grub_get_mmap_entry (entry, 0);
-
-  if (entry->size)
-    do
-      {
-	/* Avoid the lower memory.  */
-	if (entry->addr < 0x100000)
-	  {
-	    if (entry->len <= 0x100000 - entry->addr)
-	      goto next;
-
-	    entry->len -= 0x100000 - entry->addr;
-	    entry->addr = 0x100000;
-	  }
-	
-	/* Ignore >4GB.  */
-	if (entry->addr <= 0xFFFFFFFF && entry->type == 1)
-	  {
-	    grub_addr_t addr;
-	    grub_size_t len;
-
-	    addr = (grub_addr_t) entry->addr;
-	    len = ((addr + entry->len > 0xFFFFFFFF)
-		   ? 0xFFFFFFFF - addr
-		   : (grub_size_t) entry->len);
-	    add_mem_region (addr, len);
-	  }
-	
-      next:
-	if (! cont)
-	  break;
-	
-	cont = grub_get_mmap_entry (entry, cont);
-      }
-    while (entry->size);
-  else
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
     {
-      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
-
-      if (eisa_mmap)
+      /* Avoid the lower memory.  */
+      if (addr < 0x100000)
 	{
-	  add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
-	  add_mem_region (0x1000000, eisa_mmap & ~0xFFFF);
+	  if (size <= 0x100000 - addr)
+	    return 0;
+	  
+	  size -= 0x100000 - addr;
+	  addr = 0x100000;
 	}
-      else
-	add_mem_region (0x100000, grub_get_memsize (1) << 10);
+	
+      /* Ignore >4GB.  */
+      if (addr <= 0xFFFFFFFF && type == GRUB_MMAP_MEMORY_AVAILABLE)
+	{
+	  grub_size_t len;
+	  
+	  len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
+		 ? 0xFFFFFFFF - addr
+		 : size);
+	  add_mem_region (addr, len);
+	}
+
+      return 0;
     }
 
+  grub_mmap_iterate (hook);
+  
   compact_mem_regions ();
 
   /* Add the memory regions to free memory, except for the region starting
Index: kern/i386/pc/mmap.c
===================================================================
--- kern/i386/pc/mmap.c	(revision 0)
+++ kern/i386/pc/mmap.c	(revision 0)
@@ -0,0 +1,60 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/types.h>
+
+void
+grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  grub_uint32_t cont;
+  struct grub_mmap_entry *entry
+    = (struct grub_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* Check if grub_get_mmap_entry works.  */
+  cont = grub_get_mmap_entry (entry, 0);
+
+  if (entry->size)
+    do
+      {
+	if (hook (entry->addr, entry->len,
+		  /* Multiboot mmaps have been defined to match with the E820 definition.
+		     Therefore, we can just pass type through.  */
+		  entry->type))
+	  break;
+
+	if (! cont)
+	  break;
+
+	cont = grub_get_mmap_entry (entry, cont);
+      }
+    while (entry->size);
+  else
+    {
+      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
+
+      if (eisa_mmap)
+	{
+	  if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MMAP_MEMORY_AVAILABLE) == 0)
+	    hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MMAP_MEMORY_AVAILABLE);
+	}
+      else
+	hook (0x100000, grub_get_memsize (1) << 10, GRUB_MMAP_MEMORY_AVAILABLE);
+    }
+}
Index: kern/i386/coreboot/init.c
===================================================================
--- kern/i386/coreboot/init.c	(revision 1802)
+++ kern/i386/coreboot/init.c	(working copy)
@@ -82,12 +82,9 @@
   grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
   grub_upper_mem = 0;
 
-  auto int heap_init (mem_region_t);
-  int heap_init (mem_region_t mem_region)
+  auto int heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
   {
-    grub_uint64_t addr = mem_region->addr;
-    grub_uint64_t size = mem_region->size;
-
 #if GRUB_CPU_SIZEOF_VOID_P == 4
     /* Restrict ourselves to 32-bit memory space.  */
     if (addr > ULONG_MAX)
@@ -101,7 +98,7 @@
 
     grub_upper_mem = grub_max (grub_upper_mem, addr + size);
 
-    if (mem_region->type != GRUB_LINUXBIOS_MEMORY_AVAILABLE)
+    if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
       return 0;
 
     /* Avoid the lower memory.  */
@@ -134,7 +131,7 @@
     return 0;
   }
 
-  grub_available_iterate (heap_init);
+  grub_mmap_iterate (heap_init);
 
   /* This variable indicates size, not offset.  */
   grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
Index: kern/i386/coreboot/mmap.c
===================================================================
--- kern/i386/coreboot/mmap.c	(revision 1802)
+++ kern/i386/coreboot/mmap.c	(working copy)
@@ -63,8 +63,8 @@
   return 0;
 }
 
-grub_err_t
-grub_available_iterate (int (*hook) (mem_region_t))
+void
+grub_mmap_iterate (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
 {
   mem_region_t mem_region;
 
@@ -77,11 +77,17 @@
     mem_region =
       (mem_region_t) ((long) table_item +
 				 sizeof (struct grub_linuxbios_table_item));
-    for (; (long) mem_region < (long) table_item + (long) table_item->size;
-	 mem_region++)
-      if (hook (mem_region))
-	return 1;
+    while ((long) mem_region < (long) table_item + (long) table_item->size)
+      {
+	if (hook (mem_region->addr, mem_region->size,
+		  /* Multiboot mmaps match with the coreboot mmap definition.
+		     Therefore, we can just pass type through.  */
+		  mem_region->type))
+	  return 1;
 
+	mem_region++;
+      }
+
     return 0;
   }
 
Index: include/grub/i386/pc/init.h
===================================================================
--- include/grub/i386/pc/init.h	(revision 1802)
+++ include/grub/i386/pc/init.h	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2004,2005,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
@@ -21,6 +21,8 @@
 
 #include <grub/types.h>
 #include <grub/symbol.h>
+#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
+				   needed by Multiboot.  */
 
 /* Get the memory size in KB. If EXTENDED is zero, return conventional
    memory, otherwise return extended memory.  */
@@ -30,19 +32,18 @@
    in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
 grub_uint32_t grub_get_eisa_mmap (void);
 
-struct grub_machine_mmap_entry
-{
-  grub_uint32_t size;
-  grub_uint64_t addr;
-  grub_uint64_t len;
-  grub_uint32_t type;
-} __attribute__((packed));
+/* Multiboot mmaps have been defined to match with the E820 definition.  */
+#define GRUB_MACHINE_MEMORY_AVAILABLE	GRUB_MMAP_MEMORY_AVAILABLE
+#define GRUB_MACHINE_MEMORY_RESERVED	GRUB_MMAP_MEMORY_RESERVED
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_mmap_entry *entry,
 				   grub_uint32_t cont);
 
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+
 /* Turn on/off Gate A20.  */
 void grub_gate_a20 (int on);
 
Index: include/grub/i386/coreboot/memory.h
===================================================================
--- include/grub/i386/coreboot/memory.h	(revision 1802)
+++ include/grub/i386/coreboot/memory.h	(working copy)
@@ -25,7 +25,6 @@
 
 #ifndef ASM_FILE
 #include <grub/types.h>
-#include <grub/err.h>
 #endif
 
 #define GRUB_MEMORY_MACHINE_LOWER_USABLE		0x9fc00		/* 640 kiB - 1 kiB */
@@ -55,13 +54,13 @@
 {
   grub_uint64_t addr;
   grub_uint64_t size;
-#define GRUB_LINUXBIOS_MEMORY_AVAILABLE	1
+#define GRUB_MACHINE_MEMORY_AVAILABLE		1
   grub_uint32_t type;
 };
 typedef struct grub_linuxbios_mem_region *mem_region_t;
 
-grub_err_t EXPORT_FUNC(grub_available_iterate)
-     (int (*hook) (mem_region_t));
+void EXPORT_FUNC(grub_mmap_iterate)
+     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
 
 #endif
 
Index: include/grub/multiboot.h
===================================================================
--- include/grub/multiboot.h	(revision 1802)
+++ include/grub/multiboot.h	(working copy)
@@ -1,7 +1,7 @@
 /* multiboot.h - multiboot header file with grub definitions. */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,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
@@ -101,6 +101,16 @@
   grub_uint16_t vbe_interface_len;
 };
 
+struct grub_mmap_entry
+{
+  grub_uint32_t size;
+  grub_uint64_t addr;
+  grub_uint64_t len;
+#define GRUB_MMAP_MEMORY_AVAILABLE	1
+#define GRUB_MMAP_MEMORY_RESERVED	2
+  grub_uint32_t type;
+} __attribute__((packed));
+
 struct grub_mod_list
 {
   /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
Index: loader/i386/pc/multiboot.c
===================================================================
--- loader/i386/pc/multiboot.c	(revision 1802)
+++ loader/i386/pc/multiboot.c	(working copy)
@@ -78,14 +78,60 @@
       grub_free ((void *) mbi->cmdline);
       grub_free (mbi);
     }
-
-
+  
   mbi = 0;
   grub_dl_unref (my_mod);
 
   return GRUB_ERR_NONE;
 }
 
+/* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
+   by the spec.  Is there something we can do about it?  */
+static grub_uint32_t mmap_addr = 0;
+static grub_uint32_t mmap_length;
+
+/* Return the length of the Multiboot mmap that will be needed to allocate
+   our platform's map.  */
+static grub_uint32_t
+grub_get_multiboot_mmap_len ()
+{
+  grub_size_t count = 0;
+
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int hook (grub_uint64_t addr __attribute__ ((unused)),
+	    grub_uint64_t size __attribute__ ((unused)),
+	    grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+  
+  grub_mmap_iterate (hook);
+  
+  return count * sizeof (struct grub_mmap_entry);
+}
+
+/* Fill previously allocated Multiboot mmap.  */
+static void
+grub_fill_multiboot_mmap (struct grub_mmap_entry *first_entry)
+{
+  struct grub_mmap_entry *mmap_entry = (struct grub_mmap_entry *) first_entry;
+
+  auto int hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int 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;
+      mmap_entry->size = sizeof (struct grub_mmap_entry) - sizeof (mmap_entry->size);
+      mmap_entry++;
+
+      return 0;
+    }
+
+  grub_mmap_iterate (hook);
+}
+
 /* Check if BUFFER contains ELF32.  */
 static int
 grub_multiboot_is_elf32 (void *buffer)
@@ -127,7 +173,7 @@
 	if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
 	  highest_segment = i;
       }
-  grub_multiboot_payload_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
+  grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
   grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
 
   playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@@ -379,6 +425,9 @@
       playground = NULL;
     }
 
+  mmap_length = grub_get_multiboot_mmap_len ();
+  grub_multiboot_payload_size = mmap_length;
+
   if (header->flags & MULTIBOOT_AOUT_KLUDGE)
     {
       int offset = ((char *) header - buffer -
@@ -387,9 +436,9 @@
 		       header->load_end_addr - header->load_addr);
 
       if (header->bss_end_addr)
-	grub_multiboot_payload_size = (header->bss_end_addr - header->load_addr);
+	grub_multiboot_payload_size += (header->bss_end_addr - header->load_addr);
       else
-	grub_multiboot_payload_size = load_size;
+	grub_multiboot_payload_size += load_size;
       grub_multiboot_payload_dest = header->load_addr;
 
       playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@@ -416,6 +465,12 @@
     goto fail;
 
       
+  grub_fill_multiboot_mmap ((struct grub_mmap_entry *) (grub_multiboot_payload_orig
+							+ grub_multiboot_payload_size
+							- mmap_length));
+
+  mmap_addr = grub_multiboot_payload_dest + grub_multiboot_payload_size - mmap_length;
+
   if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
     {
       grub_memmove (playground, &grub_multiboot_forward_relocator, RELOCATOR_SIZEOF(forward));
@@ -439,12 +494,15 @@
 
   grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
 
-  mbi->flags = MULTIBOOT_INFO_MEMORY;
-
   /* Convert from bytes to kilobytes.  */
   mbi->mem_lower = grub_lower_mem / 1024;
   mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->flags |= MULTIBOOT_INFO_MEMORY;
 
+  mbi->mmap_addr = mmap_addr;
+  mbi->mmap_length = mmap_length;
+  mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
+
   for (i = 0, len = 0; i < argc; i++)
     len += grub_strlen (argv[i]) + 1;
 
Index: loader/i386/bsd.c
===================================================================
--- loader/i386/bsd.c	(revision 1802)
+++ loader/i386/bsd.c	(working copy)
@@ -313,7 +313,7 @@
 grub_openbsd_boot (void)
 {
   char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
-  struct grub_machine_mmap_entry mmap;
+  struct grub_mmap_entry mmap;
   struct grub_openbsd_bios_mmap *pm;
   struct grub_openbsd_bootargs *pa;
   grub_uint32_t bootdev, biosdev, unit, slice, part, cont;

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-12 23:44             ` Robert Millan
@ 2008-08-13 17:52               ` Marco Gerards
  2008-08-13 19:51                 ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Marco Gerards @ 2008-08-13 17:52 UTC (permalink / raw)
  To: The development of GRUB 2; +Cc: Jonathan A. Kollasch

Hi,

Robert Millan <rmh@aybabtu.com> writes:

> And here we go *AGAIN*, this time not forgetting to include all files in the
> patch.

[...]

> Index: include/grub/i386/pc/init.h
> ===================================================================
> --- include/grub/i386/pc/init.h	(revision 1802)
> +++ include/grub/i386/pc/init.h	(working copy)
> @@ -1,6 +1,6 @@
>  /*
>   *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
> + *  Copyright (C) 2002,2004,2005,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
> @@ -21,6 +21,8 @@
>  
>  #include <grub/types.h>
>  #include <grub/symbol.h>
> +#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
> +				   needed by Multiboot.  */

Isn't it better to split the header file?  This seems like a hack.
  
>  /* Get the memory size in KB. If EXTENDED is zero, return conventional
>     memory, otherwise return extended memory.  */
> @@ -30,19 +32,18 @@
>     in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
>  grub_uint32_t grub_get_eisa_mmap (void);
>  
> -struct grub_machine_mmap_entry
> -{
> -  grub_uint32_t size;
> -  grub_uint64_t addr;
> -  grub_uint64_t len;
> -  grub_uint32_t type;
> -} __attribute__((packed));
> +/* Multiboot mmaps have been defined to match with the E820 definition.  */
> +#define GRUB_MACHINE_MEMORY_AVAILABLE	GRUB_MMAP_MEMORY_AVAILABLE
> +#define GRUB_MACHINE_MEMORY_RESERVED	GRUB_MMAP_MEMORY_RESERVED
>  
>  /* Get a memory map entry. Return next continuation value. Zero means
>     the end.  */
> -grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
> +grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_mmap_entry *entry,
>  				   grub_uint32_t cont);
>  
> +void EXPORT_FUNC(grub_mmap_iterate)
> +     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
> +
>  /* Turn on/off Gate A20.  */
>  void grub_gate_a20 (int on);
>  
> Index: include/grub/i386/coreboot/memory.h
> ===================================================================
> --- include/grub/i386/coreboot/memory.h	(revision 1802)
> +++ include/grub/i386/coreboot/memory.h	(working copy)
> @@ -25,7 +25,6 @@
>  
>  #ifndef ASM_FILE
>  #include <grub/types.h>
> -#include <grub/err.h>
>  #endif
>  
>  #define GRUB_MEMORY_MACHINE_LOWER_USABLE		0x9fc00		/* 640 kiB - 1 kiB */
> @@ -55,13 +54,13 @@
>  {
>    grub_uint64_t addr;
>    grub_uint64_t size;
> -#define GRUB_LINUXBIOS_MEMORY_AVAILABLE	1
> +#define GRUB_MACHINE_MEMORY_AVAILABLE		1
>    grub_uint32_t type;
>  };
>  typedef struct grub_linuxbios_mem_region *mem_region_t;
>  
> -grub_err_t EXPORT_FUNC(grub_available_iterate)
> -     (int (*hook) (mem_region_t));
> +void EXPORT_FUNC(grub_mmap_iterate)
> +     (int (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
>  
>  #endif
>  
> Index: include/grub/multiboot.h
> ===================================================================
> --- include/grub/multiboot.h	(revision 1802)
> +++ include/grub/multiboot.h	(working copy)
> @@ -1,7 +1,7 @@
>  /* multiboot.h - multiboot header file with grub definitions. */
>  /*
>   *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
> + *  Copyright (C) 2003,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
> @@ -101,6 +101,16 @@
>    grub_uint16_t vbe_interface_len;
>  };
>  
> +struct grub_mmap_entry
> +{
> +  grub_uint32_t size;
> +  grub_uint64_t addr;
> +  grub_uint64_t len;
> +#define GRUB_MMAP_MEMORY_AVAILABLE	1
> +#define GRUB_MMAP_MEMORY_RESERVED	2
> +  grub_uint32_t type;
> +} __attribute__((packed));
> +
>  struct grub_mod_list
>  {
>    /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
> Index: loader/i386/pc/multiboot.c
> ===================================================================
> --- loader/i386/pc/multiboot.c	(revision 1802)
> +++ loader/i386/pc/multiboot.c	(working copy)
> @@ -78,14 +78,60 @@
>        grub_free ((void *) mbi->cmdline);
>        grub_free (mbi);
>      }
> -
> -
> +  

Hm? :-)

--
Marco




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-13 17:52               ` Marco Gerards
@ 2008-08-13 19:51                 ` Robert Millan
  2008-08-16 14:50                   ` Marco Gerards
  0 siblings, 1 reply; 12+ messages in thread
From: Robert Millan @ 2008-08-13 19:51 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Aug 13, 2008 at 07:52:59PM +0200, Marco Gerards wrote:
> >  #include <grub/types.h>
> >  #include <grub/symbol.h>
> > +#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
> > +				   needed by Multiboot.  */
> 
> Isn't it better to split the header file?  This seems like a hack.

The definition is part of the Multiboot spec, so it really needs to be present
in multiboot.h.

We could also define it separately as grub_mmap_entry in multiboot.h and keep
the grub_machine_mmap_entry definition in pc/init.h.  Then other arches could
have their own grub_machine_mmap_entry variant which _does_ differ from
grub_mmap_entry (like coreboot).

What do you think?
  
> > Index: loader/i386/pc/multiboot.c
> > ===================================================================
> > --- loader/i386/pc/multiboot.c	(revision 1802)
> > +++ loader/i386/pc/multiboot.c	(working copy)
> > @@ -78,14 +78,60 @@
> >        grub_free ((void *) mbi->cmdline);
> >        grub_free (mbi);
> >      }
> > -
> > -
> > +  
> 
> Hm? :-)

Some minor janitor work ;-)

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-13 19:51                 ` Robert Millan
@ 2008-08-16 14:50                   ` Marco Gerards
  2008-08-17 16:31                     ` Robert Millan
  0 siblings, 1 reply; 12+ messages in thread
From: Marco Gerards @ 2008-08-16 14:50 UTC (permalink / raw)
  To: The development of GRUB 2

Robert Millan <rmh@aybabtu.com> writes:

> On Wed, Aug 13, 2008 at 07:52:59PM +0200, Marco Gerards wrote:
>> >  #include <grub/types.h>
>> >  #include <grub/symbol.h>
>> > +#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
>> > +				   needed by Multiboot.  */
>> 
>> Isn't it better to split the header file?  This seems like a hack.
>
> The definition is part of the Multiboot spec, so it really needs to be present
> in multiboot.h.
>
> We could also define it separately as grub_mmap_entry in multiboot.h and keep
> the grub_machine_mmap_entry definition in pc/init.h.  Then other arches could
> have their own grub_machine_mmap_entry variant which _does_ differ from
> grub_mmap_entry (like coreboot).
>
> What do you think?

This sounds fine to me.
   
>> > Index: loader/i386/pc/multiboot.c
>> > ===================================================================
>> > --- loader/i386/pc/multiboot.c	(revision 1802)
>> > +++ loader/i386/pc/multiboot.c	(working copy)
>> > @@ -78,14 +78,60 @@
>> >        grub_free ((void *) mbi->cmdline);
>> >        grub_free (mbi);
>> >      }
>> > -
>> > -
>> > +  
>> 
>> Hm? :-)
>
> Some minor janitor work ;-)

:-)

--
Marco




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader
  2008-08-16 14:50                   ` Marco Gerards
@ 2008-08-17 16:31                     ` Robert Millan
  0 siblings, 0 replies; 12+ messages in thread
From: Robert Millan @ 2008-08-17 16:31 UTC (permalink / raw)
  To: The development of GRUB 2


Committed.

On Sat, Aug 16, 2008 at 04:50:17PM +0200, Marco Gerards wrote:
> Robert Millan <rmh@aybabtu.com> writes:
> 
> > On Wed, Aug 13, 2008 at 07:52:59PM +0200, Marco Gerards wrote:
> >> >  #include <grub/types.h>
> >> >  #include <grub/symbol.h>
> >> > +#include <grub/multiboot.h>	/* For struct grub_mmap_entry, which is also
> >> > +				   needed by Multiboot.  */
> >> 
> >> Isn't it better to split the header file?  This seems like a hack.
> >
> > The definition is part of the Multiboot spec, so it really needs to be present
> > in multiboot.h.
> >
> > We could also define it separately as grub_mmap_entry in multiboot.h and keep
> > the grub_machine_mmap_entry definition in pc/init.h.  Then other arches could
> > have their own grub_machine_mmap_entry variant which _does_ differ from
> > grub_mmap_entry (like coreboot).
> >
> > What do you think?
> 
> This sounds fine to me.
>    
> >> > Index: loader/i386/pc/multiboot.c
> >> > ===================================================================
> >> > --- loader/i386/pc/multiboot.c	(revision 1802)
> >> > +++ loader/i386/pc/multiboot.c	(working copy)
> >> > @@ -78,14 +78,60 @@
> >> >        grub_free ((void *) mbi->cmdline);
> >> >        grub_free (mbi);
> >> >      }
> >> > -
> >> > -
> >> > +  
> >> 
> >> Hm? :-)
> >
> > Some minor janitor work ;-)
> 
> :-)
> 
> --
> Marco
> 
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
> 

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-08-17 16:33 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-11 15:22 [PATCH] decouple mmap parsing by using grub_available_iterate() Robert Millan
2008-08-11 15:39 ` Vesa Jääskeläinen
2008-08-11 21:24   ` Robert Millan
2008-08-11 22:07     ` Robert Millan
2008-08-12 13:25       ` [PATCH] decouple mmap parsing and implement Multiboot mmap in the loader Robert Millan
2008-08-12 16:29         ` Robert Millan
2008-08-12 22:38           ` Robert Millan
2008-08-12 23:44             ` Robert Millan
2008-08-13 17:52               ` Marco Gerards
2008-08-13 19:51                 ` Robert Millan
2008-08-16 14:50                   ` Marco Gerards
2008-08-17 16:31                     ` Robert Millan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.