EFI requests support for newreloc
This commit is contained in:
parent
dae84898b2
commit
91b58e6b74
12 changed files with 399 additions and 86 deletions
|
@ -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/ieee1275/relocator.c
|
||||
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 \
|
||||
lib/i386/relocator64.S lib/i386/relocator16.S \
|
||||
lib/$(target_cpu)/relocator_asm.S lib/i386/relocator.c
|
||||
endif
|
||||
endif
|
||||
relocator_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
relocator_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||
relocator_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
|
|
@ -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);
|
||||
grub_efi_device_path_t *
|
||||
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);
|
||||
int EXPORT_FUNC (grub_efi_finish_boot_services) (void);
|
||||
grub_err_t EXPORT_FUNC (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_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_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_handle_t EXPORT_VAR(grub_efi_image_handle);
|
||||
|
||||
extern int EXPORT_VAR(grub_efi_is_finished);
|
||||
|
||||
#endif /* ! GRUB_EFI_EFI_HEADER */
|
||||
|
|
|
@ -41,10 +41,18 @@ void grub_cpu_relocator_jumper (void *rels, grub_addr_t addr);
|
|||
|
||||
#ifdef GRUB_MACHINE_IEEE1275
|
||||
#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
|
||||
#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 0
|
||||
#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
|
||||
{
|
||||
enum {
|
||||
|
|
|
@ -181,17 +181,6 @@ grub_halt (void)
|
|||
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_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,12 @@ static struct allocated_page *allocated_pages = 0;
|
|||
#define MIN_HEAP_SIZE 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. */
|
||||
void *
|
||||
|
@ -140,6 +146,51 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
|
|||
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,
|
||||
return 0 if partial, or return -1 if an error occurs. */
|
||||
int
|
||||
|
@ -154,6 +205,29 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
|
|||
grub_efi_uintn_t key;
|
||||
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. */
|
||||
if (! map_key)
|
||||
map_key = &key;
|
||||
|
|
104
lib/efi/relocator.c
Normal file
104
lib/efi/relocator.c
Normal 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);
|
||||
}
|
174
lib/relocator.c
174
lib/relocator.c
|
@ -42,6 +42,7 @@ struct grub_relocator_subchunk
|
|||
grub_addr_t start;
|
||||
grub_size_t size;
|
||||
struct grub_relocator_extra_block *extra;
|
||||
struct grub_relocator_fw_leftover *pre, *post;
|
||||
};
|
||||
|
||||
struct grub_relocator_chunk
|
||||
|
@ -62,6 +63,15 @@ struct grub_relocator_extra_block
|
|||
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 *
|
||||
|
@ -159,7 +169,6 @@ allocate_regstart (grub_addr_t addr, grub_size_t size, grub_mm_region_t rb,
|
|||
while (h != newreg->first);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
case CHUNK_TYPE_FIRMWARE:
|
||||
grub_relocator_firmware_free_region (subchu->start, subchu->size);
|
||||
*curschu->extra->prev = curschu->extra->next;
|
||||
grub_free (curschu->extra);
|
||||
{
|
||||
grub_addr_t fstart, fend;
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
@ -406,7 +454,7 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
|
||||
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 + 1) + r->size);
|
||||
events[N].type = FIRMWARE_BLOCK_START;
|
||||
|
@ -420,7 +468,7 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
struct grub_relocator_extra_block *cur;
|
||||
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);
|
||||
events[N].type = FIRMWARE_BLOCK_START;
|
||||
events[N].pos = cur->start;
|
||||
|
@ -432,6 +480,10 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
|
||||
N += grub_relocator_firmware_fill_events (events + N);
|
||||
#endif
|
||||
|
||||
/* No malloc from this point. */
|
||||
base_saved = grub_mm_base;
|
||||
grub_mm_base = NULL;
|
||||
|
@ -475,10 +527,6 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
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. */
|
||||
{
|
||||
int st = 0, e = N / 2;
|
||||
|
@ -654,17 +702,26 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
break;
|
||||
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
|
||||
case CHUNK_TYPE_FIRMWARE:
|
||||
/* The failure here can be very expensive. */
|
||||
if (!grub_relocator_firmware_alloc_region (alloc_start,
|
||||
alloc_end - alloc_start))
|
||||
{
|
||||
if (from_low_priv)
|
||||
start = alloc_end;
|
||||
else
|
||||
end = alloc_start;
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
{
|
||||
grub_addr_t fstart, fend;
|
||||
fstart
|
||||
= ALIGN_DOWN (alloc_start,
|
||||
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
|
||||
fend
|
||||
= ALIGN_UP (alloc_end,
|
||||
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
|
||||
/* The failure here can be very expensive. */
|
||||
if (!grub_relocator_firmware_alloc_region (fstart,
|
||||
fend - fstart))
|
||||
{
|
||||
if (from_low_priv)
|
||||
start = fend;
|
||||
else
|
||||
end = fstart;
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
nallocs++;
|
||||
|
@ -736,7 +793,6 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
/* Malloc is available again. */
|
||||
grub_mm_base = base_saved;
|
||||
|
||||
|
||||
{
|
||||
int last_start = 0;
|
||||
int inreg = 0, regbeg = 0, ncol = 0;
|
||||
|
@ -784,8 +840,6 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
curschu->start = alloc_start;
|
||||
curschu->size = alloc_end - alloc_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
|
||||
|| typepre == CHUNK_TYPE_FIRMWARE))
|
||||
{
|
||||
|
@ -807,6 +861,76 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
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
|
||||
if (!oom)
|
||||
cural++;
|
||||
|
@ -814,7 +938,7 @@ malloc_in_range (struct grub_relocator *rel,
|
|||
free_subchunk (&tofree);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (events[j].type)
|
||||
{
|
||||
case REG_BEG_START:
|
||||
|
|
|
@ -692,8 +692,9 @@ grub_freebsd_boot (void)
|
|||
return err;
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
if (! grub_efi_finish_boot_services ())
|
||||
grub_fatal ("cannot exit boot services");
|
||||
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
#endif
|
||||
|
||||
pagetable = p;
|
||||
|
@ -723,8 +724,9 @@ grub_freebsd_boot (void)
|
|||
return err;
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
if (! grub_efi_finish_boot_services ())
|
||||
grub_fatal ("cannot exit boot services");
|
||||
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
#endif
|
||||
|
||||
grub_memcpy (&stack[9], &bi, sizeof (bi));
|
||||
|
@ -804,8 +806,9 @@ grub_openbsd_boot (void)
|
|||
grub_video_set_mode ("text", 0, 0);
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
if (! grub_efi_finish_boot_services ())
|
||||
grub_fatal ("cannot exit boot services");
|
||||
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
#endif
|
||||
|
||||
state.eip = entry;
|
||||
|
@ -1009,8 +1012,9 @@ grub_netbsd_boot (void)
|
|||
return err;
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
if (! grub_efi_finish_boot_services ())
|
||||
grub_fatal ("cannot exit boot services");
|
||||
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
#endif
|
||||
|
||||
state.eip = entry;
|
||||
|
|
|
@ -681,15 +681,13 @@ grub_linux_boot (void)
|
|||
|
||||
#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;
|
||||
if (grub_efi_get_memory_map (&efi_mmap_size, efi_mmap_buf, &efi_map_key,
|
||||
&efi_desc_size, &efi_desc_version) <= 0)
|
||||
grub_fatal ("cannot get memory map");
|
||||
err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
|
||||
&efi_desc_size, &efi_desc_version);
|
||||
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. */
|
||||
|
||||
/* Pass EFI parameters. */
|
||||
|
|
|
@ -1038,10 +1038,11 @@ grub_xnu_boot (void)
|
|||
bootparams->devtree = devtree_target;
|
||||
bootparams->devtreelen = devtreelen;
|
||||
|
||||
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
|
||||
&map_key, &descriptor_size,
|
||||
&descriptor_version) <= 0)
|
||||
return grub_errno;
|
||||
err = grub_efi_finish_boot_services (&memory_map_size, memory_map,
|
||||
&map_key, &descriptor_size,
|
||||
&descriptor_version);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
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;
|
||||
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,
|
||||
descriptor_version,memory_map);
|
||||
|
||||
|
|
|
@ -126,8 +126,9 @@ grub_multiboot_boot (void)
|
|||
return err;
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
if (! grub_efi_finish_boot_services ())
|
||||
grub_fatal ("cannot exit boot services");
|
||||
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
#endif
|
||||
|
||||
grub_relocator32_boot (grub_multiboot_relocator, state);
|
||||
|
|
|
@ -90,6 +90,9 @@ grub_console_putchar (grub_uint32_t c)
|
|||
grub_efi_char16_t str[2];
|
||||
grub_efi_simple_text_output_interface_t *o;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return;
|
||||
|
||||
o = grub_efi_system_table->con_out;
|
||||
|
||||
/* 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_status_t status;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
if (read_key >= 0)
|
||||
return 1;
|
||||
|
||||
|
@ -217,6 +223,9 @@ grub_console_getkey (void)
|
|||
grub_efi_status_t status;
|
||||
int key;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
if (read_key >= 0)
|
||||
{
|
||||
key = read_key;
|
||||
|
@ -249,7 +258,8 @@ grub_console_getwh (void)
|
|||
grub_efi_uintn_t columns, rows;
|
||||
|
||||
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? */
|
||||
columns = 80;
|
||||
|
@ -264,6 +274,9 @@ grub_console_getxy (void)
|
|||
{
|
||||
grub_efi_simple_text_output_interface_t *o;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return 0;
|
||||
|
||||
o = grub_efi_system_table->con_out;
|
||||
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;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return;
|
||||
|
||||
o = grub_efi_system_table->con_out;
|
||||
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_int32_t orig_attr;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return;
|
||||
|
||||
o = grub_efi_system_table->con_out;
|
||||
orig_attr = o->mode->attribute;
|
||||
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;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return;
|
||||
|
||||
o = grub_efi_system_table->con_out;
|
||||
|
||||
switch (state) {
|
||||
|
@ -331,6 +353,9 @@ grub_console_setcursor (int on)
|
|||
{
|
||||
grub_efi_simple_text_output_interface_t *o;
|
||||
|
||||
if (grub_efi_is_finished)
|
||||
return;
|
||||
|
||||
o = grub_efi_system_table->con_out;
|
||||
efi_call_2 (o->enable_cursor, o, on);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue