Lift up core size limits on some platforms. Fix potential memory
corruption with big core on small memory systems. Document remaining limits.
This commit is contained in:
parent
f6b58fe538
commit
774683685f
9 changed files with 210 additions and 32 deletions
|
@ -54,7 +54,8 @@ grub_exit (void)
|
|||
#ifdef GRUB_MACHINE_QEMU
|
||||
grub_addr_t grub_modbase;
|
||||
#else
|
||||
grub_addr_t grub_modbase = ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
|
||||
grub_addr_t grub_modbase = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
|
||||
static grub_uint64_t modend;
|
||||
#endif
|
||||
|
||||
/* Helper for grub_machine_init. */
|
||||
|
@ -62,30 +63,32 @@ static int
|
|||
heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
|
||||
void *data __attribute__ ((unused)))
|
||||
{
|
||||
grub_uint64_t begin = addr, end = addr + size;
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
||||
/* Restrict ourselves to 32-bit memory space. */
|
||||
if (addr > GRUB_ULONG_MAX)
|
||||
if (begin > GRUB_ULONG_MAX)
|
||||
return 0;
|
||||
if (addr + size > GRUB_ULONG_MAX)
|
||||
size = GRUB_ULONG_MAX - addr;
|
||||
if (end > GRUB_ULONG_MAX)
|
||||
end = GRUB_ULONG_MAX;
|
||||
#endif
|
||||
|
||||
if (type != GRUB_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
|
||||
/* Avoid the lower memory. */
|
||||
if (addr < GRUB_MEMORY_MACHINE_LOWER_SIZE)
|
||||
{
|
||||
if (addr + size <= GRUB_MEMORY_MACHINE_LOWER_SIZE)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
size -= GRUB_MEMORY_MACHINE_LOWER_SIZE - addr;
|
||||
addr = GRUB_MEMORY_MACHINE_LOWER_SIZE;
|
||||
}
|
||||
}
|
||||
if (begin < GRUB_MEMORY_MACHINE_LOWER_SIZE)
|
||||
begin = GRUB_MEMORY_MACHINE_LOWER_SIZE;
|
||||
|
||||
grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size);
|
||||
#ifndef GRUB_MACHINE_QEMU
|
||||
if (modend && begin < modend)
|
||||
begin = modend;
|
||||
#endif
|
||||
|
||||
if (end <= begin)
|
||||
return 0;
|
||||
|
||||
grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -97,6 +100,9 @@ grub_machine_init (void)
|
|||
grub_modbase = grub_core_entry_addr + (_edata - _start);
|
||||
|
||||
grub_qemu_init_cirrus ();
|
||||
#endif
|
||||
#ifndef GRUB_MACHINE_QEMU
|
||||
modend = grub_modules_get_end ();
|
||||
#endif
|
||||
/* Initialize the console as early as possible. */
|
||||
grub_vga_text_init ();
|
||||
|
|
|
@ -191,6 +191,7 @@ grub_machine_init (void)
|
|||
#if 0
|
||||
int grub_lower_mem;
|
||||
#endif
|
||||
grub_addr_t modend;
|
||||
|
||||
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
|
||||
|
||||
|
@ -222,8 +223,17 @@ grub_machine_init (void)
|
|||
|
||||
compact_mem_regions ();
|
||||
|
||||
modend = grub_modules_get_end ();
|
||||
for (i = 0; i < num_regions; i++)
|
||||
grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
|
||||
{
|
||||
grub_addr_t beg = mem_regions[i].addr;
|
||||
grub_addr_t fin = mem_regions[i].addr + mem_regions[i].size;
|
||||
if (modend && beg < modend)
|
||||
beg = modend;
|
||||
if (beg >= fin)
|
||||
continue;
|
||||
grub_mm_init_region ((void *) beg, fin - beg);
|
||||
}
|
||||
|
||||
grub_tsc_init ();
|
||||
}
|
||||
|
|
|
@ -30,8 +30,10 @@
|
|||
#include <grub/reader.h>
|
||||
#include <grub/parser.h>
|
||||
|
||||
/* This is actualy platform-independant but used only on loongson and sparc. */
|
||||
#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64)
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
#include <grub/machine/memory.h>
|
||||
#endif
|
||||
|
||||
grub_addr_t
|
||||
grub_modules_get_end (void)
|
||||
{
|
||||
|
@ -45,7 +47,6 @@ grub_modules_get_end (void)
|
|||
|
||||
return grub_modbase + modinfo->size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Load all modules in core. */
|
||||
static void
|
||||
|
@ -67,6 +68,8 @@ grub_load_modules (void)
|
|||
}
|
||||
}
|
||||
|
||||
static char *load_config;
|
||||
|
||||
static void
|
||||
grub_load_config (void)
|
||||
{
|
||||
|
@ -76,9 +79,17 @@ grub_load_config (void)
|
|||
/* Not an embedded config, skip. */
|
||||
if (header->type != OBJ_TYPE_CONFIG)
|
||||
continue;
|
||||
|
||||
grub_parser_execute ((char *) header +
|
||||
sizeof (struct grub_module_header));
|
||||
|
||||
load_config = grub_malloc (header->size - sizeof (struct grub_module_header) + 1);
|
||||
if (!load_config)
|
||||
{
|
||||
grub_print_error ();
|
||||
break;
|
||||
}
|
||||
grub_memcpy (load_config, (char *) header +
|
||||
sizeof (struct grub_module_header),
|
||||
header->size - sizeof (struct grub_module_header));
|
||||
load_config[header->size - sizeof (struct grub_module_header)] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -212,6 +223,30 @@ grub_load_normal_mode (void)
|
|||
grub_command_execute ("normal", 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
reclaim_module_space (void)
|
||||
{
|
||||
grub_addr_t modstart, modend;
|
||||
|
||||
if (!grub_modbase)
|
||||
return;
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
modstart = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR;
|
||||
#else
|
||||
modstart = grub_modbase;
|
||||
#endif
|
||||
modend = grub_modules_get_end ();
|
||||
grub_modbase = 0;
|
||||
|
||||
#if GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
|
||||
grub_mm_init_region ((void *) modstart, modend - modstart);
|
||||
#else
|
||||
(void) modstart;
|
||||
(void) modend;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The main routine. */
|
||||
void __attribute__ ((noreturn))
|
||||
grub_main (void)
|
||||
|
@ -224,6 +259,8 @@ grub_main (void)
|
|||
grub_printf ("Welcome to GRUB!\n\n");
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
|
||||
grub_load_config ();
|
||||
|
||||
/* Load pre-loaded modules and free the space. */
|
||||
grub_register_exported_symbols ();
|
||||
#ifdef GRUB_LINKER_HAVE_INIT
|
||||
|
@ -237,9 +274,14 @@ grub_main (void)
|
|||
grub_env_export ("root");
|
||||
grub_env_export ("prefix");
|
||||
|
||||
/* Reclaim space used for modules. */
|
||||
reclaim_module_space ();
|
||||
|
||||
grub_register_core_commands ();
|
||||
|
||||
grub_load_config ();
|
||||
if (load_config)
|
||||
grub_parser_execute (load_config);
|
||||
|
||||
grub_load_normal_mode ();
|
||||
grub_rescue_run ();
|
||||
}
|
||||
|
|
|
@ -117,6 +117,27 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
|||
grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size);
|
||||
#endif
|
||||
|
||||
for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p)
|
||||
if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
|
||||
{
|
||||
r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
*r = *q;
|
||||
r->pre_size += size;
|
||||
|
||||
if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
|
||||
{
|
||||
h = (grub_mm_header_t) (r + 1);
|
||||
h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
|
||||
h->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
r->size += h->size << GRUB_MM_ALIGN_LOG2;
|
||||
r->pre_size &= (GRUB_MM_ALIGN - 1);
|
||||
*p = r;
|
||||
grub_free (h + 1);
|
||||
}
|
||||
*p = r;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate a region from the head. */
|
||||
r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
size -= (char *) r - (char *) addr + sizeof (*r);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue