EFI requests support for newreloc

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-04-20 18:08:26 +02:00
parent dae84898b2
commit 91b58e6b74
12 changed files with 399 additions and 86 deletions

View file

@ -22,10 +22,17 @@ relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \
lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c \ lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c \
lib/ieee1275/relocator.c lib/ieee1275/relocator.c
else else
ifeq ($(platform), efi)
relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \
lib/i386/relocator64.S lib/i386/relocator16.S \
lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c \
lib/efi/relocator.c
else
relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \ relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \
lib/i386/relocator64.S lib/i386/relocator16.S \ lib/i386/relocator64.S lib/i386/relocator16.S \
lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c
endif endif
endif
relocator_mod_CFLAGS = $(COMMON_CFLAGS) relocator_mod_CFLAGS = $(COMMON_CFLAGS)
relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) relocator_mod_ASFLAGS = $(COMMON_ASFLAGS)
relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) relocator_mod_LDFLAGS = $(COMMON_LDFLAGS)

View file

@ -53,8 +53,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
grub_efi_device_path_t * grub_efi_device_path_t *
EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle); EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
int EXPORT_FUNC(grub_efi_exit_boot_services) (grub_efi_uintn_t map_key); grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_size_t *outbuf_size, void *outbuf,
int EXPORT_FUNC (grub_efi_finish_boot_services) (void); grub_efi_uintn_t *map_key,
grub_efi_uintn_t *efi_desc_size,
grub_efi_uint32_t *efi_desc_version);
grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memory_map_size, grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memory_map_size,
grub_efi_uintn_t descriptor_size, grub_efi_uintn_t descriptor_size,
grub_efi_uint32_t descriptor_version, grub_efi_uint32_t descriptor_version,
@ -70,4 +72,6 @@ void grub_efi_set_prefix (void);
extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table);
extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);
extern int EXPORT_VAR(grub_efi_is_finished);
#endif /* ! GRUB_EFI_EFI_HEADER */ #endif /* ! GRUB_EFI_EFI_HEADER */

View file

@ -41,10 +41,18 @@ void grub_cpu_relocator_jumper (void *rels, grub_addr_t addr);
#ifdef GRUB_MACHINE_IEEE1275 #ifdef GRUB_MACHINE_IEEE1275
#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 1 #define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 1
#define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG 0
#elif defined (GRUB_MACHINE_EFI)
#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 1
#define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG 12
#else #else
#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 0 #define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 0
#endif #endif
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
#define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT (1 << GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG)
#endif
struct grub_relocator_mmap_event struct grub_relocator_mmap_event
{ {
enum { enum {

View file

@ -181,17 +181,6 @@ grub_halt (void)
GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
} }
int
grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
{
grub_efi_boot_services_t *b;
grub_efi_status_t status;
b = grub_efi_system_table->boot_services;
status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, map_key);
return status == GRUB_EFI_SUCCESS;
}
grub_err_t grub_err_t
grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
grub_efi_uintn_t descriptor_size, grub_efi_uintn_t descriptor_size,
@ -758,26 +747,3 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
dp = (grub_efi_device_path_t *) ((char *) dp + len); dp = (grub_efi_device_path_t *) ((char *) dp + len);
} }
} }
int
grub_efi_finish_boot_services (void)
{
grub_efi_uintn_t mmap_size = 0;
grub_efi_uintn_t map_key;
grub_efi_uintn_t desc_size;
grub_efi_uint32_t desc_version;
void *mmap_buf = 0;
if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
&desc_size, &desc_version) < 0)
return 0;
mmap_buf = grub_malloc (mmap_size);
if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
&desc_size, &desc_version) <= 0)
return 0;
return grub_efi_exit_boot_services (map_key);
}

View file

@ -49,6 +49,12 @@ static struct allocated_page *allocated_pages = 0;
#define MIN_HEAP_SIZE 0x100000 #define MIN_HEAP_SIZE 0x100000
#define MAX_HEAP_SIZE (1600 * 0x100000) #define MAX_HEAP_SIZE (1600 * 0x100000)
static void *finish_mmap_buf = 0;
static grub_efi_uintn_t finish_mmap_size = 0;
static grub_efi_uintn_t finish_key = 0;
static grub_efi_uintn_t finish_desc_size;
static grub_efi_uint32_t finish_desc_version;
int grub_efi_is_finished = 0;
/* Allocate pages. Return the pointer to the first of allocated pages. */ /* Allocate pages. Return the pointer to the first of allocated pages. */
void * void *
@ -140,6 +146,51 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
efi_call_2 (b->free_pages, address, pages); efi_call_2 (b->free_pages, address, pages);
} }
grub_err_t
grub_efi_finish_boot_services (grub_size_t *outbuf_size, void *outbuf,
grub_efi_uintn_t *map_key,
grub_efi_uintn_t *efi_desc_size,
grub_efi_uint32_t *efi_desc_version)
{
grub_efi_boot_services_t *b;
grub_efi_status_t status;
if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
&finish_desc_size, &finish_desc_version) < 0)
return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
if (outbuf && *outbuf_size < finish_mmap_size)
return grub_error (GRUB_ERR_IO, "memory map buffer is too small");
finish_mmap_buf = grub_malloc (finish_mmap_size);
if (!finish_mmap_buf)
return grub_errno;
if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
&finish_desc_size, &finish_desc_version) <= 0)
return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
b = grub_efi_system_table->boot_services;
status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle,
finish_key);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services");
grub_efi_is_finished = 1;
if (outbuf_size)
*outbuf_size = finish_mmap_size;
if (outbuf)
grub_memcpy (outbuf, finish_mmap_buf, finish_mmap_size);
if (map_key)
*map_key = finish_key;
if (efi_desc_size)
*efi_desc_size = finish_desc_size;
if (efi_desc_version)
*efi_desc_version = finish_desc_version;
return GRUB_ERR_NONE;
}
/* Get the memory map as defined in the EFI spec. Return 1 if successful, /* Get the memory map as defined in the EFI spec. Return 1 if successful,
return 0 if partial, or return -1 if an error occurs. */ return 0 if partial, or return -1 if an error occurs. */
int int
@ -154,6 +205,29 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
grub_efi_uintn_t key; grub_efi_uintn_t key;
grub_efi_uint32_t version; grub_efi_uint32_t version;
if (grub_efi_is_finished)
{
int ret = 1;
if (*memory_map_size < finish_mmap_size)
{
grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size);
ret = 0;
}
else
{
grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size);
ret = 1;
}
*memory_map_size = finish_mmap_size;
if (map_key)
*map_key = finish_key;
if (descriptor_size)
*descriptor_size = finish_desc_size;
if (descriptor_version)
*descriptor_version = finish_desc_version;
return ret;
}
/* Allow some parameters to be missing. */ /* Allow some parameters to be missing. */
if (! map_key) if (! map_key)
map_key = &key; map_key = &key;

104
lib/efi/relocator.c Normal file
View file

@ -0,0 +1,104 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 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/relocator.h>
#include <grub/relocator_private.h>
#include <grub/memory.h>
#include <grub/efi/efi.h>
#include <grub/efi/api.h>
#include <grub/term.h>
#define NEXT_MEMORY_DESCRIPTOR(desc, size) \
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
unsigned
grub_relocator_firmware_get_max_events (void)
{
grub_efi_uintn_t mmapsize = 0, descriptor_size = 0;
grub_efi_uint32_t descriptor_version = 0;
grub_efi_uintn_t key;
grub_efi_get_memory_map (&mmapsize, NULL, &key, &descriptor_size,
&descriptor_version);
/* Since grub_relocator_firmware_fill_events uses malloc
we need some reserve. Hence +10. */
return 2 * (mmapsize / descriptor_size + 10);
}
unsigned
grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events)
{
grub_efi_uintn_t mmapsize = 0, desc_size = 0;
grub_efi_uint32_t descriptor_version = 0;
grub_efi_memory_descriptor_t *descs = NULL;
grub_efi_uintn_t key;
int counter = 0;
grub_efi_memory_descriptor_t *desc;
grub_efi_get_memory_map (&mmapsize, NULL, &key, &desc_size,
&descriptor_version);
descs = grub_malloc (mmapsize);
if (!descs)
return 0;
grub_efi_get_memory_map (&mmapsize, descs, &key, &desc_size,
&descriptor_version);
for (desc = descs;
(char *) desc < ((char *) descs + mmapsize);
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{
if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
continue;
events[counter].type = REG_FIRMWARE_START;
events[counter].pos = desc->physical_start;
counter++;
events[counter].type = REG_FIRMWARE_END;
events[counter].pos = desc->physical_start + (desc->num_pages << 12);
counter++;
}
return counter;
}
int
grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size)
{
grub_efi_boot_services_t *b;
grub_efi_physical_address_t address = start;
grub_efi_status_t status;
if (grub_efi_is_finished)
return 1;
b = grub_efi_system_table->boot_services;
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS,
GRUB_EFI_LOADER_DATA, size >> 12, &address);
return (status == GRUB_EFI_SUCCESS);
}
void
grub_relocator_firmware_free_region (grub_addr_t start, grub_size_t size)
{
grub_efi_boot_services_t *b;
if (grub_efi_is_finished)
return;
b = grub_efi_system_table->boot_services;
efi_call_2 (b->free_pages, start, size >> 12);
}

View file

@ -42,6 +42,7 @@ struct grub_relocator_subchunk
grub_addr_t start; grub_addr_t start;
grub_size_t size; grub_size_t size;
struct grub_relocator_extra_block *extra; struct grub_relocator_extra_block *extra;
struct grub_relocator_fw_leftover *pre, *post;
}; };
struct grub_relocator_chunk struct grub_relocator_chunk
@ -62,6 +63,15 @@ struct grub_relocator_extra_block
grub_addr_t end; grub_addr_t end;
}; };
struct grub_relocator_fw_leftover
{
struct grub_relocator_fw_leftover *next;
struct grub_relocator_fw_leftover **prev;
grub_addr_t quantstart;
grub_uint8_t freebytes[GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT / 8];
};
struct grub_relocator_fw_leftover *leftovers;
struct grub_relocator_extra_block *extra_blocks; struct grub_relocator_extra_block *extra_blocks;
struct grub_relocator * struct grub_relocator *
@ -159,7 +169,6 @@ allocate_regstart (grub_addr_t addr, grub_size_t size, grub_mm_region_t rb,
while (h != newreg->first); while (h != newreg->first);
} }
} }
} }
static void static void
@ -211,6 +220,20 @@ allocate_inreg (grub_addr_t addr, grub_size_t size,
} }
} }
static void
check_leftover (struct grub_relocator_fw_leftover *lo)
{
unsigned i;
for (i = 0; i < sizeof (lo->freebytes); i++)
if (lo->freebytes[i] != 0xff)
return;
grub_relocator_firmware_free_region (lo->quantstart,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
*lo->prev = lo->next;
if (lo->next)
lo->next->prev = lo->prev;
}
static void static void
free_subchunk (const struct grub_relocator_subchunk *subchu) free_subchunk (const struct grub_relocator_subchunk *subchu)
{ {
@ -311,9 +334,34 @@ free_subchunk (const struct grub_relocator_subchunk *subchu)
} }
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
case CHUNK_TYPE_FIRMWARE: case CHUNK_TYPE_FIRMWARE:
grub_relocator_firmware_free_region (subchu->start, subchu->size); {
*curschu->extra->prev = curschu->extra->next; grub_addr_t fstart, fend;
grub_free (curschu->extra); fstart = ALIGN_UP (subchu->start,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
fend = ALIGN_DOWN (subchu->start + subchu->size,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
if (fstart < fend)
grub_relocator_firmware_free_region (fstart, fend - fstart);
if (subchu->pre)
{
int off = subchu->start - fstart
- GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT;
grub_memset (subchu->pre->freebytes + off / 8 + 1,
0xff, sizeof (subchu->pre->freebytes) - off / 8 - 1);
subchu->pre->freebytes[off / 8] |= ~((1 << (off % 8)) - 1);
check_leftover (subchu->pre);
}
if (subchu->post)
{
int off = subchu->start + subchu->size - fend;
grub_memset (subchu->pre->freebytes,
0xff, sizeof (subchu->pre->freebytes) - off / 8);
subchu->pre->freebytes[off / 8] |= ((1 << (8 - (off % 8))) - 1);
check_leftover (subchu->post);
}
*subchu->extra->prev = subchu->extra->next;
grub_free (subchu->extra);
}
break; break;
#endif #endif
} }
@ -406,7 +454,7 @@ malloc_in_range (struct grub_relocator *rel,
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
for (r = grub_mm_base; r; r = r->next) for (r = grub_mm_base; r; r = r->next)
{ {
grub_dprintf ("relocator", "Blocking at 0x%x-0x%x\n", grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n",
(grub_addr_t) r - r->pre_size, (grub_addr_t) r - r->pre_size,
(grub_addr_t) (r + 1) + r->size); (grub_addr_t) (r + 1) + r->size);
events[N].type = FIRMWARE_BLOCK_START; events[N].type = FIRMWARE_BLOCK_START;
@ -420,7 +468,7 @@ malloc_in_range (struct grub_relocator *rel,
struct grub_relocator_extra_block *cur; struct grub_relocator_extra_block *cur;
for (cur = extra_blocks; cur; cur = cur->next) for (cur = extra_blocks; cur; cur = cur->next)
{ {
grub_dprintf ("relocator", "Blocking at 0x%x-0x%x\n", grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n",
cur->start, cur->end); cur->start, cur->end);
events[N].type = FIRMWARE_BLOCK_START; events[N].type = FIRMWARE_BLOCK_START;
events[N].pos = cur->start; events[N].pos = cur->start;
@ -432,6 +480,10 @@ malloc_in_range (struct grub_relocator *rel,
} }
#endif #endif
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
N += grub_relocator_firmware_fill_events (events + N);
#endif
/* No malloc from this point. */ /* No malloc from this point. */
base_saved = grub_mm_base; base_saved = grub_mm_base;
grub_mm_base = NULL; grub_mm_base = NULL;
@ -475,10 +527,6 @@ malloc_in_range (struct grub_relocator *rel,
while (pa != r->first); while (pa != r->first);
} }
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
N += grub_relocator_firmware_fill_events (events + N);
#endif
/* Put ending events after starting events. */ /* Put ending events after starting events. */
{ {
int st = 0, e = N / 2; int st = 0, e = N / 2;
@ -654,17 +702,26 @@ malloc_in_range (struct grub_relocator *rel,
break; break;
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
case CHUNK_TYPE_FIRMWARE: case CHUNK_TYPE_FIRMWARE:
/* The failure here can be very expensive. */ {
if (!grub_relocator_firmware_alloc_region (alloc_start, grub_addr_t fstart, fend;
alloc_end - alloc_start)) fstart
{ = ALIGN_DOWN (alloc_start,
if (from_low_priv) GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
start = alloc_end; fend
else = ALIGN_UP (alloc_end,
end = alloc_start; GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
goto retry; /* The failure here can be very expensive. */
} if (!grub_relocator_firmware_alloc_region (fstart,
break; fend - fstart))
{
if (from_low_priv)
start = fend;
else
end = fstart;
goto retry;
}
break;
}
#endif #endif
} }
nallocs++; nallocs++;
@ -736,7 +793,6 @@ malloc_in_range (struct grub_relocator *rel,
/* Malloc is available again. */ /* Malloc is available again. */
grub_mm_base = base_saved; grub_mm_base = base_saved;
{ {
int last_start = 0; int last_start = 0;
int inreg = 0, regbeg = 0, ncol = 0; int inreg = 0, regbeg = 0, ncol = 0;
@ -784,8 +840,6 @@ malloc_in_range (struct grub_relocator *rel,
curschu->start = alloc_start; curschu->start = alloc_start;
curschu->size = alloc_end - alloc_start; curschu->size = alloc_end - alloc_start;
if (typepre == CHUNK_TYPE_REGION_START) if (typepre == CHUNK_TYPE_REGION_START)
curschu->host_start = (grub_addr_t) events[last_start].reg;
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
if (!oom && (typepre == CHUNK_TYPE_REGION_START if (!oom && (typepre == CHUNK_TYPE_REGION_START
|| typepre == CHUNK_TYPE_FIRMWARE)) || typepre == CHUNK_TYPE_FIRMWARE))
{ {
@ -807,6 +861,76 @@ malloc_in_range (struct grub_relocator *rel,
curschu->extra = ne; curschu->extra = ne;
} }
} }
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
if (!oom && typepre == CHUNK_TYPE_FIRMWARE)
{
grub_addr_t fstart, fend;
struct grub_relocator_fw_leftover *lo1 = NULL;
struct grub_relocator_fw_leftover *lo2 = NULL;
fstart
= ALIGN_DOWN (alloc_start,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
fend
= ALIGN_UP (alloc_end,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
if (fstart != alloc_start)
lo1 = grub_malloc (sizeof (*lo1));
if (fend != alloc_end)
lo2 = grub_malloc (sizeof (*lo2));
if ((!lo1 && fstart != alloc_start)
|| (!lo2 && fend != alloc_end))
{
struct grub_relocator_extra_block *ne;
grub_free (lo1);
grub_free (lo2);
lo1 = NULL;
lo2 = NULL;
oom = 1;
grub_memcpy (&tofree, curschu, sizeof (tofree));
ne = extra_blocks;
extra_blocks = extra_blocks->next;
grub_free (ne);
}
if (lo1)
{
lo1->quantstart = fstart;
grub_memset (lo1->freebytes, 0xff,
(alloc_start - fstart) / 8);
lo1->freebytes[(alloc_start - fstart) / 8]
= (1 << ((alloc_start - fstart) % 8)) - 1;
grub_memset (lo1->freebytes
+ ((alloc_start - fstart) / 8) + 1, 0,
sizeof (lo1->freebytes)
- (alloc_start - fstart) / 8 - 1);
lo1->next = leftovers;
lo1->prev = &leftovers;
if (leftovers)
leftovers->prev = &lo1->next;
leftovers = lo1;
}
if (lo2)
{
lo2->quantstart
= fend - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT;
grub_memset (lo2->freebytes, 0,
(alloc_end - lo2->quantstart) / 8);
lo2->freebytes[(alloc_end - lo2->quantstart) / 8]
= ~((1 << ((alloc_end - lo2->quantstart) % 8)) - 1);
grub_memset (lo2->freebytes
+ ((alloc_end - lo2->quantstart) / 8)
+ 1, 0, sizeof (lo2->freebytes)
- (alloc_end - lo2->quantstart) / 8 - 1);
lo2->prev = &leftovers;
if (leftovers)
leftovers->prev = &lo2->next;
lo2->next = leftovers;
leftovers = lo2;
}
curschu->pre = lo1;
curschu->post = lo2;
}
#endif #endif
if (!oom) if (!oom)
cural++; cural++;
@ -814,7 +938,7 @@ malloc_in_range (struct grub_relocator *rel,
free_subchunk (&tofree); free_subchunk (&tofree);
} }
} }
switch (events[j].type) switch (events[j].type)
{ {
case REG_BEG_START: case REG_BEG_START:

View file

@ -692,8 +692,9 @@ grub_freebsd_boot (void)
return err; return err;
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ()) err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
grub_fatal ("cannot exit boot services"); if (err)
return err;
#endif #endif
pagetable = p; pagetable = p;
@ -723,8 +724,9 @@ grub_freebsd_boot (void)
return err; return err;
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ()) err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
grub_fatal ("cannot exit boot services"); if (err)
return err;
#endif #endif
grub_memcpy (&stack[9], &bi, sizeof (bi)); grub_memcpy (&stack[9], &bi, sizeof (bi));
@ -804,8 +806,9 @@ grub_openbsd_boot (void)
grub_video_set_mode ("text", 0, 0); grub_video_set_mode ("text", 0, 0);
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ()) err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
grub_fatal ("cannot exit boot services"); if (err)
return err;
#endif #endif
state.eip = entry; state.eip = entry;
@ -1009,8 +1012,9 @@ grub_netbsd_boot (void)
return err; return err;
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ()) err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
grub_fatal ("cannot exit boot services"); if (err)
return err;
#endif #endif
state.eip = entry; state.eip = entry;

View file

@ -681,15 +681,13 @@ grub_linux_boot (void)
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
{ {
grub_efi_uintn_t efi_map_key, efi_desc_size; grub_efi_uintn_t efi_desc_size;
grub_efi_uint32_t efi_desc_version; grub_efi_uint32_t efi_desc_version;
if (grub_efi_get_memory_map (&efi_mmap_size, efi_mmap_buf, &efi_map_key, err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
&efi_desc_size, &efi_desc_version) <= 0) &efi_desc_size, &efi_desc_version);
grub_fatal ("cannot get memory map"); if (err)
return err;
if (! grub_efi_exit_boot_services (efi_map_key))
grub_fatal ("cannot exit boot services");
/* Note that no boot services are available from here. */ /* Note that no boot services are available from here. */
/* Pass EFI parameters. */ /* Pass EFI parameters. */

View file

@ -1038,10 +1038,11 @@ grub_xnu_boot (void)
bootparams->devtree = devtree_target; bootparams->devtree = devtree_target;
bootparams->devtreelen = devtreelen; bootparams->devtreelen = devtreelen;
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map, err = grub_efi_finish_boot_services (&memory_map_size, memory_map,
&map_key, &descriptor_size, &map_key, &descriptor_size,
&descriptor_version) <= 0) &descriptor_version);
return grub_errno; if (err)
return err;
bootparams->efi_system_table = PTR_TO_UINT32 (grub_autoefi_system_table); bootparams->efi_system_table = PTR_TO_UINT32 (grub_autoefi_system_table);
@ -1096,9 +1097,6 @@ grub_xnu_boot (void)
+ bootparams->heap_size + GRUB_XNU_PAGESIZE; + bootparams->heap_size + GRUB_XNU_PAGESIZE;
grub_xnu_arg1 = bootparams_target; grub_xnu_arg1 = bootparams_target;
if (! grub_autoefi_exit_boot_services (map_key))
return grub_error (GRUB_ERR_IO, "can't exit boot services");
grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size, grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size,
descriptor_version,memory_map); descriptor_version,memory_map);

View file

@ -126,8 +126,9 @@ grub_multiboot_boot (void)
return err; return err;
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ()) err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
grub_fatal ("cannot exit boot services"); if (err)
return err;
#endif #endif
grub_relocator32_boot (grub_multiboot_relocator, state); grub_relocator32_boot (grub_multiboot_relocator, state);

View file

@ -90,6 +90,9 @@ grub_console_putchar (grub_uint32_t c)
grub_efi_char16_t str[2]; grub_efi_char16_t str[2];
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
if (grub_efi_is_finished)
return;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
/* For now, do not try to use a surrogate pair. */ /* For now, do not try to use a surrogate pair. */
@ -120,6 +123,9 @@ grub_console_checkkey (void)
grub_efi_input_key_t key; grub_efi_input_key_t key;
grub_efi_status_t status; grub_efi_status_t status;
if (grub_efi_is_finished)
return 0;
if (read_key >= 0) if (read_key >= 0)
return 1; return 1;
@ -217,6 +223,9 @@ grub_console_getkey (void)
grub_efi_status_t status; grub_efi_status_t status;
int key; int key;
if (grub_efi_is_finished)
return 0;
if (read_key >= 0) if (read_key >= 0)
{ {
key = read_key; key = read_key;
@ -249,7 +258,8 @@ grub_console_getwh (void)
grub_efi_uintn_t columns, rows; grub_efi_uintn_t columns, rows;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
if (efi_call_4 (o->query_mode, o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS) if (grub_efi_is_finished || efi_call_4 (o->query_mode, o, o->mode->mode,
&columns, &rows) != GRUB_EFI_SUCCESS)
{ {
/* Why does this fail? */ /* Why does this fail? */
columns = 80; columns = 80;
@ -264,6 +274,9 @@ grub_console_getxy (void)
{ {
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
if (grub_efi_is_finished)
return 0;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
return ((o->mode->cursor_column << 8) | o->mode->cursor_row); return ((o->mode->cursor_column << 8) | o->mode->cursor_row);
} }
@ -273,6 +286,9 @@ grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y)
{ {
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
if (grub_efi_is_finished)
return;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
efi_call_3 (o->set_cursor_position, o, x, y); efi_call_3 (o->set_cursor_position, o, x, y);
} }
@ -283,6 +299,9 @@ grub_console_cls (void)
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
grub_efi_int32_t orig_attr; grub_efi_int32_t orig_attr;
if (grub_efi_is_finished)
return;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
orig_attr = o->mode->attribute; orig_attr = o->mode->attribute;
efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK); efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK);
@ -295,6 +314,9 @@ grub_console_setcolorstate (grub_term_color_state state)
{ {
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
if (grub_efi_is_finished)
return;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
switch (state) { switch (state) {
@ -331,6 +353,9 @@ grub_console_setcursor (int on)
{ {
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
if (grub_efi_is_finished)
return;
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
efi_call_2 (o->enable_cursor, o, on); efi_call_2 (o->enable_cursor, o, on);
} }