diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index e859772ab..75f6eacbe 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -28,6 +28,9 @@ - multiple regions may be used as free space. They may not be contiguous. + - if existing regions are insufficient to satisfy an allocation, a new + region can be requested from firmware. + Regions are managed by a singly linked list, and the meta information is stored in the beginning of each region. Space after the meta information is used to allocate memory. @@ -81,6 +84,7 @@ grub_mm_region_t grub_mm_base; +grub_mm_add_region_func_t grub_mm_add_region_fn; /* Get a header from the pointer PTR, and set *P and *R to a pointer to the header and a pointer to its region, respectively. PTR must @@ -444,6 +448,32 @@ grub_memalign (grub_size_t align, grub_size_t size) count++; goto again; + case 1: + /* Request additional pages, contiguous */ + count++; + + if (grub_mm_add_region_fn != NULL && + grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) + goto again; + + /* fallthrough */ + + case 2: + /* Request additional pages, anything at all */ + count++; + + if (grub_mm_add_region_fn != NULL) + { + /* + * Try again even if this fails, in case it was able to partially + * satisfy the request + */ + grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); + goto again; + } + + /* fallthrough */ + default: break; } diff --git a/include/grub/mm.h b/include/grub/mm.h index 44fde7cb9..f3bf87fa0 100644 --- a/include/grub/mm.h +++ b/include/grub/mm.h @@ -20,6 +20,7 @@ #ifndef GRUB_MM_H #define GRUB_MM_H 1 +#include #include #include #include @@ -28,6 +29,23 @@ # define NULL ((void *) 0) #endif +#define GRUB_MM_ADD_REGION_NONE 0 +#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) + +/* + * Function used to request memory regions of `grub_size_t` bytes. The second + * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. + */ +typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); + +/* + * Set this function pointer to enable adding memory-regions at runtime in case + * a memory allocation cannot be satisfied with existing regions. + */ +#ifndef GRUB_MACHINE_EMU +extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); +#endif + void grub_mm_init_region (void *addr, grub_size_t size); void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size); void *EXPORT_FUNC(grub_malloc) (grub_size_t size);