Pass-through unknown E820 types. It required reorganisation of mmap
module.
This commit is contained in:
parent
f8f3f15559
commit
6de9ee86bf
8 changed files with 111 additions and 139 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)++;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue