]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Pass-through unknown E820 types. It required reorganisation of mmap
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 14 Oct 2013 14:33:44 +0000 (16:33 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 14 Oct 2013 14:33:44 +0000 (16:33 +0200)
module.

ChangeLog
grub-core/commands/lsmmap.c
grub-core/loader/i386/bsd.c
grub-core/loader/i386/linux.c
grub-core/loader/i386/multiboot_mbi.c
grub-core/loader/multiboot_mbi2.c
grub-core/mmap/mmap.c
include/grub/memory.h

index 222522e4de88743b53f5d70d8d1f266e7a2ab68c..06e07b7ea50df5aafaf759da8c8d202b5b5540e6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-10-14  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Pass-through unknown E820 types. It required reorganisation of mmap
+       module.
+
 2013-10-14  Andrey Borzenkov <arvidjaar@gmail.com>
 
        * Makefile.util.def: Add osdep/init.c to grub-mount files.
index 0d298559c8cdb303209d89552084e39d503be62e..4b504fd28f8e7428eb7d383b4b3bda15bcb16f39 100644 (file)
@@ -38,8 +38,7 @@ static const char *names[] =
     [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"),
     [GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"),
     [GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"),
-    [GRUB_MEMORY_CODE] = N_("RAM holding firmware code"),
-    [GRUB_MEMORY_HOLE] = N_("Address range not associated with RAM")
+    [GRUB_MEMORY_CODE] = N_("RAM holding firmware code")
   };
 
 /* Helper for grub_cmd_lsmmap.  */
@@ -47,7 +46,7 @@ static int
 lsmmap_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
             void *data __attribute__ ((unused)))
 {
-  if (type < ARRAY_SIZE (names) && names[type])
+  if (type < (int) ARRAY_SIZE (names) && type >= 0 && names[type])
     grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"),
                  (long long) addr, (long long) size, _(names[type]));
   else
index 90877a365a2771a10f04ee2d3f75517c7887c2f6..5143813fec4f3c65f6707b36ab8d9df3718f855d 100644 (file)
@@ -287,34 +287,15 @@ generate_e820_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
 
   ctx->cur.addr = addr;
   ctx->cur.size = size;
-  switch (type)
-    {
-    case GRUB_MEMORY_AVAILABLE:
-      ctx->cur.type = GRUB_E820_RAM;
-      break;
-
-    case GRUB_MEMORY_ACPI:
-      ctx->cur.type = GRUB_E820_ACPI;
-      break;
-
-    case GRUB_MEMORY_NVS:
-      ctx->cur.type = GRUB_E820_NVS;
-      break;
-    case GRUB_MEMORY_COREBOOT_TABLES:
+
+  if (type == GRUB_MEMORY_COREBOOT_TABLES
+      && addr == 0)
       /* Nowadays the tables at 0 don't contain anything important but
        *BSD needs the memory at 0 for own needs.
        */
-      if (addr == 0)
-       ctx->cur.type = GRUB_E820_RAM;
-      else
-       ctx->cur.type = GRUB_E820_COREBOOT_TABLES;
-      break;
-    default:
-    case GRUB_MEMORY_CODE:
-    case GRUB_MEMORY_RESERVED:
-      ctx->cur.type = GRUB_E820_RESERVED;
-      break;
-    }  
+    type = GRUB_E820_RAM;
+
+  ctx->cur.type = type;
 
   /* Merge regions if possible. */
   if (ctx->count && ctx->cur.type == ctx->prev.type
index 4ff61060977fb081135bbdc40e39bb6e6796b45d..4e6a38898f84cd538305998d87658d23f4b3d81c 100644 (file)
@@ -421,36 +421,15 @@ grub_linux_boot_mmap_find (grub_uint64_t addr, grub_uint64_t size,
   return 1;
 }
 
+/* GRUB types conveniently match E820 types.  */
 static int
 grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size,
                           grub_memory_type_t type, void *data)
 {
   struct grub_linux_boot_ctx *ctx = data;
 
-  grub_uint32_t e820_type;
-  switch (type)
-    {
-    case GRUB_MEMORY_AVAILABLE:
-      e820_type = GRUB_E820_RAM;
-      break;
-
-    case GRUB_MEMORY_ACPI:
-      e820_type = GRUB_E820_ACPI;
-      break;
-
-    case GRUB_MEMORY_NVS:
-      e820_type = GRUB_E820_NVS;
-      break;
-
-    case GRUB_MEMORY_BADRAM:
-      e820_type = GRUB_E820_BADRAM;
-      break;
-
-    default:
-      e820_type = GRUB_E820_RESERVED;
-    }
   if (grub_e820_add_region (ctx->params->e820_map, &ctx->e820_num,
-                           addr, size, e820_type))
+                           addr, size, type))
     return 1;
 
   return 0;
index 18fd367eed43e0244102af12b200b49ed8fad6a6..37cf36d7a698240567283b19cba59983f896eb25 100644 (file)
@@ -233,28 +233,7 @@ grub_fill_multiboot_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
 
   (*mmap_entry)->addr = addr;
   (*mmap_entry)->len = size;
-  switch (type)
-    {
-    case GRUB_MEMORY_AVAILABLE:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_AVAILABLE;
-      break;
-
-    case GRUB_MEMORY_ACPI:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
-      break;
-
-    case GRUB_MEMORY_NVS:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_NVS;
-      break;
-
-    case GRUB_MEMORY_BADRAM:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_BADRAM;
-      break;
-      
-    default:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_RESERVED;
-      break;
-    }
+  (*mmap_entry)->type = type;
   (*mmap_entry)->size = sizeof (struct multiboot_mmap_entry) - sizeof ((*mmap_entry)->size);
   (*mmap_entry)++;
 
index ccd32a746ccd7d4fa03658ac1cf317456846857f..561c7915732065f869935c4a2e2af7fd7571c85b 100644 (file)
@@ -331,28 +331,7 @@ grub_fill_multiboot_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
 
   (*mmap_entry)->addr = addr;
   (*mmap_entry)->len = size;
-  switch (type)
-    {
-    case GRUB_MEMORY_AVAILABLE:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_AVAILABLE;
-      break;
-
-    case GRUB_MEMORY_ACPI:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
-      break;
-
-    case GRUB_MEMORY_NVS:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_NVS;
-      break;
-
-    case GRUB_MEMORY_BADRAM:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_BADRAM;
-      break;
-
-    default:
-      (*mmap_entry)->type = MULTIBOOT_MEMORY_RESERVED;
-      break;
-    }
+  (*mmap_entry)->type = type;
   (*mmap_entry)++;
 
   return 0;
index d8bd8d2e691ee79d957ae84430cc4534cdb4261e..6a31cbae325aa95c7003e6f7e28bbfb969b12db5 100644 (file)
@@ -35,23 +35,7 @@ static int curhandle = 1;
 
 #endif
 
-/* If same page is used by multiple types it's resolved
-   according to priority:
-   1 - free memory
-   2 - memory usable by firmware-aware code
-   3 - unusable memory
-   4 - a range deliberately empty
-*/
-static const int priority[] =
-{
-  [GRUB_MEMORY_AVAILABLE] = 1,
-  [GRUB_MEMORY_RESERVED] = 3,
-  [GRUB_MEMORY_ACPI] = 2,
-  [GRUB_MEMORY_COREBOOT_TABLES] = 2,
-  [GRUB_MEMORY_CODE] = 3,
-  [GRUB_MEMORY_NVS] = 3,
-  [GRUB_MEMORY_HOLE] = 4,
-};
+static int current_priority = 1;
 
 /* Scanline events. */
 struct grub_mmap_scan
@@ -61,7 +45,9 @@ struct grub_mmap_scan
   /* 0 = region starts, 1 = region ends. */
   int type;
   /* Which type of memory region? */
-  int memtype;
+  grub_memory_type_t memtype;
+  /* Priority. 0 means coming from firmware.  */
+  int priority;
 };
 
 /* Context for grub_mmap_iterate.  */
@@ -90,27 +76,36 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
 {
   struct grub_mmap_iterate_ctx *ctx = data;
 
-  ctx->scanline_events[ctx->i].pos = addr;
-  ctx->scanline_events[ctx->i].type = 0;
-  if (type < ARRAY_SIZE (priority) && priority[type])
-    ctx->scanline_events[ctx->i].memtype = type;
-  else
+  if (type == GRUB_MEMORY_HOLE)
     {
       grub_dprintf ("mmap", "Unknown memory type %d. Assuming unusable\n",
                    type);
-      ctx->scanline_events[ctx->i].memtype = GRUB_MEMORY_RESERVED;
+      type = GRUB_MEMORY_RESERVED;
     }
+
+  ctx->scanline_events[ctx->i].pos = addr;
+  ctx->scanline_events[ctx->i].type = 0;
+  ctx->scanline_events[ctx->i].memtype = type;
+  ctx->scanline_events[ctx->i].priority = 0;
+
   ctx->i++;
 
   ctx->scanline_events[ctx->i].pos = addr + size;
   ctx->scanline_events[ctx->i].type = 1;
-  ctx->scanline_events[ctx->i].memtype =
-    ctx->scanline_events[ctx->i - 1].memtype;
+  ctx->scanline_events[ctx->i].memtype = type;
+  ctx->scanline_events[ctx->i].priority = 0;
   ctx->i++;
 
   return 0;
 }
 
+struct mm_list
+{
+  struct mm_list *next;
+  grub_memory_type_t val;
+  int present;
+};
+
 grub_err_t
 grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
 {
@@ -127,8 +122,9 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
   int lasttype;
   /* Current scanline event. */
   int curtype;
-  /* How many regions of given type overlap at current location? */
-  int present[ARRAY_SIZE (priority)];
+  /* How many regions of given type/priority overlap at current location? */
+  /* Normally there shouldn't be more than one region per priority but be robust.  */
+  struct mm_list *present;
   /* Number of mmap chunks. */
   int mmap_num;
 
@@ -146,12 +142,17 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
   grub_machine_mmap_iterate (count_hook, &mmap_num);
 
   /* Initialize variables. */
-  grub_memset (present, 0, sizeof (present));
   ctx.scanline_events = (struct grub_mmap_scan *)
     grub_malloc (sizeof (struct grub_mmap_scan) * 2 * mmap_num);
 
-  if (! ctx.scanline_events)
-    return grub_errno;
+  present = grub_zalloc (sizeof (present[0]) * current_priority);
+
+  if (! ctx.scanline_events || !present)
+    {
+      grub_free (ctx.scanline_events);
+      grub_free (present);
+      return grub_errno;
+    }
 
   ctx.i = 0;
 #ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
@@ -160,16 +161,14 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
     {
       ctx.scanline_events[ctx.i].pos = cur->start;
       ctx.scanline_events[ctx.i].type = 0;
-      if (cur->type < ARRAY_SIZE (priority) && priority[cur->type])
-       ctx.scanline_events[ctx.i].memtype = cur->type;
-      else
-       ctx.scanline_events[ctx.i].memtype = GRUB_MEMORY_RESERVED;
+      ctx.scanline_events[ctx.i].memtype = cur->type;
+      ctx.scanline_events[ctx.i].priority = cur->priority;
       ctx.i++;
 
       ctx.scanline_events[ctx.i].pos = cur->end;
       ctx.scanline_events[ctx.i].type = 1;
-      ctx.scanline_events[ctx.i].memtype =
-       ctx.scanline_events[ctx.i - 1].memtype;
+      ctx.scanline_events[ctx.i].memtype = cur->type;
+      ctx.scanline_events[ctx.i].priority = cur->priority;
       ctx.i++;
     }
 #endif /* ! GRUB_MMAP_REGISTER_BY_FIRMWARE */
@@ -200,18 +199,66 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
   lasttype = ctx.scanline_events[0].memtype;
   for (i = 0; i < 2 * mmap_num; i++)
     {
-      unsigned k;
       /* Process event. */
       if (ctx.scanline_events[i].type)
-       present[ctx.scanline_events[i].memtype]--;
+       {
+         if (present[ctx.scanline_events[i].priority].present)
+           {
+             if (present[ctx.scanline_events[i].priority].val == ctx.scanline_events[i].memtype)
+               {
+                 if (present[ctx.scanline_events[i].priority].next)
+                   {
+                     struct mm_list *p = present[ctx.scanline_events[i].priority].next;
+                     present[ctx.scanline_events[i].priority] = *p;
+                     grub_free (p);
+                   }
+                 else
+                   {
+                     present[ctx.scanline_events[i].priority].present = 0;
+                   }
+               }
+             else
+               {
+                 struct mm_list **q = &(present[ctx.scanline_events[i].priority].next), *p;
+                 for (; *q; q = &((*q)->next))
+                   if ((*q)->val == ctx.scanline_events[i].memtype)
+                     {
+                       p = *q;
+                       *q = p->next;
+                       grub_free (p);
+                       break;
+                     }
+               }
+           }
+       }
       else
-       present[ctx.scanline_events[i].memtype]++;
+       {
+         if (!present[ctx.scanline_events[i].priority].present)
+           {
+             present[ctx.scanline_events[i].priority].present = 1;
+             present[ctx.scanline_events[i].priority].val = ctx.scanline_events[i].memtype;
+           }
+         else
+           {
+             struct mm_list *n = grub_malloc (sizeof (*n));
+             n->val = ctx.scanline_events[i].memtype;
+             n->present = 1;
+             n->next = present[ctx.scanline_events[i].priority].next;
+             present[ctx.scanline_events[i].priority].next = n;
+           }
+       }
 
       /* Determine current region type. */
       curtype = -1;
-      for (k = 0; k < ARRAY_SIZE (priority); k++)
-       if (present[k] && (curtype == -1 || priority[k] > priority[curtype]))
-         curtype = k;
+      {
+       int k;
+       for (k = current_priority - 1; k >= 0; k--)
+         if (present[k].present)
+           {
+             curtype = present[k].val;
+             break;
+           }
+      }
 
       /* Announce region to the hook if necessary. */
       if ((curtype == -1 || curtype != lasttype)
@@ -255,6 +302,7 @@ grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type)
   cur->end = start + size;
   cur->type = type;
   cur->handle = curhandle++;
+  cur->priority = current_priority++;
   grub_mmap_overlays = cur;
 
   if (grub_machine_mmap_register (start, size, type, curhandle))
index 0df807424deb52ff703864057bb4e4bff78fb9de..083cfb6802e84d6db6f0e3b9c219ee31967c6b4f 100644 (file)
@@ -33,8 +33,9 @@ typedef enum grub_memory_type
     GRUB_MEMORY_COREBOOT_TABLES = 16,
     GRUB_MEMORY_CODE = 20,
     /* This one is special: it's used internally but is never reported
-       by firmware. */
-    GRUB_MEMORY_HOLE = 21
+       by firmware. Don't use -1 as it's used internally for other purposes. */
+    GRUB_MEMORY_HOLE = -2,
+    GRUB_MEMORY_MAX = 0x10000
   } grub_memory_type_t;
 
 typedef int (*grub_memory_hook_t) (grub_uint64_t,
@@ -75,6 +76,7 @@ struct grub_mmap_region
   grub_uint64_t end;
   grub_memory_type_t type;
   int handle;
+  int priority;
 };
 
 extern struct grub_mmap_region *grub_mmap_overlays;