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/$(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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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
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);
|
||||||
|
}
|
158
lib/relocator.c
158
lib/relocator.c
|
@ -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:
|
||||||
|
{
|
||||||
|
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. */
|
/* The failure here can be very expensive. */
|
||||||
if (!grub_relocator_firmware_alloc_region (alloc_start,
|
if (!grub_relocator_firmware_alloc_region (fstart,
|
||||||
alloc_end - alloc_start))
|
fend - fstart))
|
||||||
{
|
{
|
||||||
if (from_low_priv)
|
if (from_low_priv)
|
||||||
start = alloc_end;
|
start = fend;
|
||||||
else
|
else
|
||||||
end = alloc_start;
|
end = fstart;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
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++;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -681,14 +681,12 @@ 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. */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue