mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 16:53:54 +08:00
Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fixes from Ingo Molnar: "This contains a Xen fix, an arm64 fix and a race condition / robustization set of fixes related to ExitBootServices() usage and boundary conditions" * 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/efi: Use efi_exit_boot_services() efi/libstub: Use efi_exit_boot_services() in FDT efi/libstub: Introduce ExitBootServices helper efi/libstub: Allocate headspace in efi_get_memory_map() efi: Fix handling error value in fdt_find_uefi_params efi: Make for_each_efi_memory_desc_in_map() cope with running on Xen
This commit is contained in:
commit
7c2c114416
@ -1004,79 +1004,87 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
|
||||
return status;
|
||||
}
|
||||
|
||||
struct exit_boot_struct {
|
||||
struct boot_params *boot_params;
|
||||
struct efi_info *efi;
|
||||
struct setup_data *e820ext;
|
||||
__u32 e820ext_size;
|
||||
bool is64;
|
||||
};
|
||||
|
||||
static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
|
||||
struct efi_boot_memmap *map,
|
||||
void *priv)
|
||||
{
|
||||
static bool first = true;
|
||||
const char *signature;
|
||||
__u32 nr_desc;
|
||||
efi_status_t status;
|
||||
struct exit_boot_struct *p = priv;
|
||||
|
||||
if (first) {
|
||||
nr_desc = *map->buff_size / *map->desc_size;
|
||||
if (nr_desc > ARRAY_SIZE(p->boot_params->e820_map)) {
|
||||
u32 nr_e820ext = nr_desc -
|
||||
ARRAY_SIZE(p->boot_params->e820_map);
|
||||
|
||||
status = alloc_e820ext(nr_e820ext, &p->e820ext,
|
||||
&p->e820ext_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
signature = p->is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
|
||||
memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
|
||||
|
||||
p->efi->efi_systab = (unsigned long)sys_table_arg;
|
||||
p->efi->efi_memdesc_size = *map->desc_size;
|
||||
p->efi->efi_memdesc_version = *map->desc_ver;
|
||||
p->efi->efi_memmap = (unsigned long)*map->map;
|
||||
p->efi->efi_memmap_size = *map->map_size;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
p->efi->efi_systab_hi = (unsigned long)sys_table_arg >> 32;
|
||||
p->efi->efi_memmap_hi = (unsigned long)*map->map >> 32;
|
||||
#endif
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static efi_status_t exit_boot(struct boot_params *boot_params,
|
||||
void *handle, bool is64)
|
||||
{
|
||||
struct efi_info *efi = &boot_params->efi_info;
|
||||
unsigned long map_sz, key, desc_size;
|
||||
unsigned long map_sz, key, desc_size, buff_size;
|
||||
efi_memory_desc_t *mem_map;
|
||||
struct setup_data *e820ext;
|
||||
const char *signature;
|
||||
__u32 e820ext_size;
|
||||
__u32 nr_desc, prev_nr_desc;
|
||||
efi_status_t status;
|
||||
__u32 desc_version;
|
||||
bool called_exit = false;
|
||||
u8 nr_entries;
|
||||
int i;
|
||||
struct efi_boot_memmap map;
|
||||
struct exit_boot_struct priv;
|
||||
|
||||
nr_desc = 0;
|
||||
e820ext = NULL;
|
||||
e820ext_size = 0;
|
||||
|
||||
get_map:
|
||||
status = efi_get_memory_map(sys_table, &mem_map, &map_sz, &desc_size,
|
||||
&desc_version, &key);
|
||||
map.map = &mem_map;
|
||||
map.map_size = &map_sz;
|
||||
map.desc_size = &desc_size;
|
||||
map.desc_ver = &desc_version;
|
||||
map.key_ptr = &key;
|
||||
map.buff_size = &buff_size;
|
||||
priv.boot_params = boot_params;
|
||||
priv.efi = &boot_params->efi_info;
|
||||
priv.e820ext = NULL;
|
||||
priv.e820ext_size = 0;
|
||||
priv.is64 = is64;
|
||||
|
||||
/* Might as well exit boot services now */
|
||||
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
||||
exit_boot_func);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
prev_nr_desc = nr_desc;
|
||||
nr_desc = map_sz / desc_size;
|
||||
if (nr_desc > prev_nr_desc &&
|
||||
nr_desc > ARRAY_SIZE(boot_params->e820_map)) {
|
||||
u32 nr_e820ext = nr_desc - ARRAY_SIZE(boot_params->e820_map);
|
||||
|
||||
status = alloc_e820ext(nr_e820ext, &e820ext, &e820ext_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_mem_map;
|
||||
|
||||
efi_call_early(free_pool, mem_map);
|
||||
goto get_map; /* Allocated memory, get map again */
|
||||
}
|
||||
|
||||
signature = is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
|
||||
memcpy(&efi->efi_loader_signature, signature, sizeof(__u32));
|
||||
|
||||
efi->efi_systab = (unsigned long)sys_table;
|
||||
efi->efi_memdesc_size = desc_size;
|
||||
efi->efi_memdesc_version = desc_version;
|
||||
efi->efi_memmap = (unsigned long)mem_map;
|
||||
efi->efi_memmap_size = map_sz;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
efi->efi_systab_hi = (unsigned long)sys_table >> 32;
|
||||
efi->efi_memmap_hi = (unsigned long)mem_map >> 32;
|
||||
#endif
|
||||
|
||||
/* Might as well exit boot services now */
|
||||
status = efi_call_early(exit_boot_services, handle, key);
|
||||
if (status != EFI_SUCCESS) {
|
||||
/*
|
||||
* ExitBootServices() will fail if any of the event
|
||||
* handlers change the memory map. In which case, we
|
||||
* must be prepared to retry, but only once so that
|
||||
* we're guaranteed to exit on repeated failures instead
|
||||
* of spinning forever.
|
||||
*/
|
||||
if (called_exit)
|
||||
goto free_mem_map;
|
||||
|
||||
called_exit = true;
|
||||
efi_call_early(free_pool, mem_map);
|
||||
goto get_map;
|
||||
}
|
||||
|
||||
e820ext = priv.e820ext;
|
||||
e820ext_size = priv.e820ext_size;
|
||||
/* Historic? */
|
||||
boot_params->alt_mem_k = 32 * 1024;
|
||||
|
||||
@ -1085,10 +1093,6 @@ get_map:
|
||||
return status;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
free_mem_map:
|
||||
efi_call_early(free_pool, mem_map);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -657,9 +657,12 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
|
||||
}
|
||||
|
||||
if (subnode) {
|
||||
node = of_get_flat_dt_subnode_by_name(node, subnode);
|
||||
if (node < 0)
|
||||
int err = of_get_flat_dt_subnode_by_name(node, subnode);
|
||||
|
||||
if (err < 0)
|
||||
return 0;
|
||||
|
||||
node = err;
|
||||
}
|
||||
|
||||
return __find_uefi_params(node, info, dt_params[i].params);
|
||||
|
@ -41,6 +41,8 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
|
||||
#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
|
||||
#endif
|
||||
|
||||
#define EFI_MMAP_NR_SLACK_SLOTS 8
|
||||
|
||||
struct file_info {
|
||||
efi_file_handle_t *handle;
|
||||
u64 size;
|
||||
@ -63,49 +65,62 @@ void efi_printk(efi_system_table_t *sys_table_arg, char *str)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool mmap_has_headroom(unsigned long buff_size,
|
||||
unsigned long map_size,
|
||||
unsigned long desc_size)
|
||||
{
|
||||
unsigned long slack = buff_size - map_size;
|
||||
|
||||
return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
|
||||
}
|
||||
|
||||
efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
|
||||
efi_memory_desc_t **map,
|
||||
unsigned long *map_size,
|
||||
unsigned long *desc_size,
|
||||
u32 *desc_ver,
|
||||
unsigned long *key_ptr)
|
||||
struct efi_boot_memmap *map)
|
||||
{
|
||||
efi_memory_desc_t *m = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long key;
|
||||
u32 desc_version;
|
||||
|
||||
*map_size = sizeof(*m) * 32;
|
||||
*map->desc_size = sizeof(*m);
|
||||
*map->map_size = *map->desc_size * 32;
|
||||
*map->buff_size = *map->map_size;
|
||||
again:
|
||||
/*
|
||||
* Add an additional efi_memory_desc_t because we're doing an
|
||||
* allocation which may be in a new descriptor region.
|
||||
*/
|
||||
*map_size += sizeof(*m);
|
||||
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
|
||||
*map_size, (void **)&m);
|
||||
*map->map_size, (void **)&m);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
*desc_size = 0;
|
||||
*map->desc_size = 0;
|
||||
key = 0;
|
||||
status = efi_call_early(get_memory_map, map_size, m,
|
||||
&key, desc_size, &desc_version);
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
status = efi_call_early(get_memory_map, map->map_size, m,
|
||||
&key, map->desc_size, &desc_version);
|
||||
if (status == EFI_BUFFER_TOO_SMALL ||
|
||||
!mmap_has_headroom(*map->buff_size, *map->map_size,
|
||||
*map->desc_size)) {
|
||||
efi_call_early(free_pool, m);
|
||||
/*
|
||||
* Make sure there is some entries of headroom so that the
|
||||
* buffer can be reused for a new map after allocations are
|
||||
* no longer permitted. Its unlikely that the map will grow to
|
||||
* exceed this headroom once we are ready to trigger
|
||||
* ExitBootServices()
|
||||
*/
|
||||
*map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS;
|
||||
*map->buff_size = *map->map_size;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_call_early(free_pool, m);
|
||||
|
||||
if (key_ptr && status == EFI_SUCCESS)
|
||||
*key_ptr = key;
|
||||
if (desc_ver && status == EFI_SUCCESS)
|
||||
*desc_ver = desc_version;
|
||||
if (map->key_ptr && status == EFI_SUCCESS)
|
||||
*map->key_ptr = key;
|
||||
if (map->desc_ver && status == EFI_SUCCESS)
|
||||
*map->desc_ver = desc_version;
|
||||
|
||||
fail:
|
||||
*map = m;
|
||||
*map->map = m;
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -113,13 +128,20 @@ fail:
|
||||
unsigned long get_dram_base(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
efi_status_t status;
|
||||
unsigned long map_size;
|
||||
unsigned long map_size, buff_size;
|
||||
unsigned long membase = EFI_ERROR;
|
||||
struct efi_memory_map map;
|
||||
efi_memory_desc_t *md;
|
||||
struct efi_boot_memmap boot_map;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, (efi_memory_desc_t **)&map.map,
|
||||
&map_size, &map.desc_size, NULL, NULL);
|
||||
boot_map.map = (efi_memory_desc_t **)&map.map;
|
||||
boot_map.map_size = &map_size;
|
||||
boot_map.desc_size = &map.desc_size;
|
||||
boot_map.desc_ver = NULL;
|
||||
boot_map.key_ptr = NULL;
|
||||
boot_map.buff_size = &buff_size;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &boot_map);
|
||||
if (status != EFI_SUCCESS)
|
||||
return membase;
|
||||
|
||||
@ -144,15 +166,22 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
|
||||
unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long max)
|
||||
{
|
||||
unsigned long map_size, desc_size;
|
||||
unsigned long map_size, desc_size, buff_size;
|
||||
efi_memory_desc_t *map;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
u64 max_addr = 0;
|
||||
int i;
|
||||
struct efi_boot_memmap boot_map;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
|
||||
NULL, NULL);
|
||||
boot_map.map = ↦
|
||||
boot_map.map_size = &map_size;
|
||||
boot_map.desc_size = &desc_size;
|
||||
boot_map.desc_ver = NULL;
|
||||
boot_map.key_ptr = NULL;
|
||||
boot_map.buff_size = &buff_size;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &boot_map);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
@ -230,14 +259,21 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
|
||||
unsigned long size, unsigned long align,
|
||||
unsigned long *addr)
|
||||
{
|
||||
unsigned long map_size, desc_size;
|
||||
unsigned long map_size, desc_size, buff_size;
|
||||
efi_memory_desc_t *map;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
int i;
|
||||
struct efi_boot_memmap boot_map;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
|
||||
NULL, NULL);
|
||||
boot_map.map = ↦
|
||||
boot_map.map_size = &map_size;
|
||||
boot_map.desc_size = &desc_size;
|
||||
boot_map.desc_ver = NULL;
|
||||
boot_map.key_ptr = NULL;
|
||||
boot_map.buff_size = &buff_size;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &boot_map);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
@ -704,3 +740,76 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
|
||||
*cmd_line_len = options_bytes;
|
||||
return (char *)cmdline_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle calling ExitBootServices according to the requirements set out by the
|
||||
* spec. Obtains the current memory map, and returns that info after calling
|
||||
* ExitBootServices. The client must specify a function to perform any
|
||||
* processing of the memory map data prior to ExitBootServices. A client
|
||||
* specific structure may be passed to the function via priv. The client
|
||||
* function may be called multiple times.
|
||||
*/
|
||||
efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
|
||||
void *handle,
|
||||
struct efi_boot_memmap *map,
|
||||
void *priv,
|
||||
efi_exit_boot_map_processing priv_func)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, map);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
status = priv_func(sys_table_arg, map, priv);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_map;
|
||||
|
||||
status = efi_call_early(exit_boot_services, handle, *map->key_ptr);
|
||||
|
||||
if (status == EFI_INVALID_PARAMETER) {
|
||||
/*
|
||||
* The memory map changed between efi_get_memory_map() and
|
||||
* exit_boot_services(). Per the UEFI Spec v2.6, Section 6.4:
|
||||
* EFI_BOOT_SERVICES.ExitBootServices we need to get the
|
||||
* updated map, and try again. The spec implies one retry
|
||||
* should be sufficent, which is confirmed against the EDK2
|
||||
* implementation. Per the spec, we can only invoke
|
||||
* get_memory_map() and exit_boot_services() - we cannot alloc
|
||||
* so efi_get_memory_map() cannot be used, and we must reuse
|
||||
* the buffer. For all practical purposes, the headroom in the
|
||||
* buffer should account for any changes in the map so the call
|
||||
* to get_memory_map() is expected to succeed here.
|
||||
*/
|
||||
*map->map_size = *map->buff_size;
|
||||
status = efi_call_early(get_memory_map,
|
||||
map->map_size,
|
||||
*map->map,
|
||||
map->key_ptr,
|
||||
map->desc_size,
|
||||
map->desc_ver);
|
||||
|
||||
/* exit_boot_services() was called, thus cannot free */
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
status = priv_func(sys_table_arg, map, priv);
|
||||
/* exit_boot_services() was called, thus cannot free */
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
status = efi_call_early(exit_boot_services, handle, *map->key_ptr);
|
||||
}
|
||||
|
||||
/* exit_boot_services() was called, thus cannot free */
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
free_map:
|
||||
efi_call_early(free_pool, *map->map);
|
||||
fail:
|
||||
return status;
|
||||
}
|
||||
|
@ -152,6 +152,27 @@ fdt_set_fail:
|
||||
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
||||
#endif
|
||||
|
||||
struct exit_boot_struct {
|
||||
efi_memory_desc_t *runtime_map;
|
||||
int *runtime_entry_count;
|
||||
};
|
||||
|
||||
static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
|
||||
struct efi_boot_memmap *map,
|
||||
void *priv)
|
||||
{
|
||||
struct exit_boot_struct *p = priv;
|
||||
/*
|
||||
* Update the memory map with virtual addresses. The function will also
|
||||
* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
|
||||
* entries so that we can pass it straight to SetVirtualAddressMap()
|
||||
*/
|
||||
efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
|
||||
p->runtime_map, p->runtime_entry_count);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory for a new FDT, then add EFI, commandline, and
|
||||
* initrd related fields to the FDT. This routine increases the
|
||||
@ -175,13 +196,22 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||
unsigned long fdt_addr,
|
||||
unsigned long fdt_size)
|
||||
{
|
||||
unsigned long map_size, desc_size;
|
||||
unsigned long map_size, desc_size, buff_size;
|
||||
u32 desc_ver;
|
||||
unsigned long mmap_key;
|
||||
efi_memory_desc_t *memory_map, *runtime_map;
|
||||
unsigned long new_fdt_size;
|
||||
efi_status_t status;
|
||||
int runtime_entry_count = 0;
|
||||
struct efi_boot_memmap map;
|
||||
struct exit_boot_struct priv;
|
||||
|
||||
map.map = &runtime_map;
|
||||
map.map_size = &map_size;
|
||||
map.desc_size = &desc_size;
|
||||
map.desc_ver = &desc_ver;
|
||||
map.key_ptr = &mmap_key;
|
||||
map.buff_size = &buff_size;
|
||||
|
||||
/*
|
||||
* Get a copy of the current memory map that we will use to prepare
|
||||
@ -189,8 +219,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||
* subsequent allocations adding entries, since they could not affect
|
||||
* the number of EFI_MEMORY_RUNTIME regions.
|
||||
*/
|
||||
status = efi_get_memory_map(sys_table, &runtime_map, &map_size,
|
||||
&desc_size, &desc_ver, &mmap_key);
|
||||
status = efi_get_memory_map(sys_table, &map);
|
||||
if (status != EFI_SUCCESS) {
|
||||
pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n");
|
||||
return status;
|
||||
@ -199,6 +228,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||
pr_efi(sys_table,
|
||||
"Exiting boot services and installing virtual address map...\n");
|
||||
|
||||
map.map = &memory_map;
|
||||
/*
|
||||
* Estimate size of new FDT, and allocate memory for it. We
|
||||
* will allocate a bigger buffer if this ends up being too
|
||||
@ -218,8 +248,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||
* we can get the memory map key needed for
|
||||
* exit_boot_services().
|
||||
*/
|
||||
status = efi_get_memory_map(sys_table, &memory_map, &map_size,
|
||||
&desc_size, &desc_ver, &mmap_key);
|
||||
status = efi_get_memory_map(sys_table, &map);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail_free_new_fdt;
|
||||
|
||||
@ -250,16 +279,11 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the memory map with virtual addresses. The function will also
|
||||
* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
|
||||
* entries so that we can pass it straight into SetVirtualAddressMap()
|
||||
*/
|
||||
efi_get_virtmap(memory_map, map_size, desc_size, runtime_map,
|
||||
&runtime_entry_count);
|
||||
|
||||
/* Now we are ready to exit_boot_services.*/
|
||||
status = sys_table->boottime->exit_boot_services(handle, mmap_key);
|
||||
sys_table->boottime->free_pool(memory_map);
|
||||
priv.runtime_map = runtime_map;
|
||||
priv.runtime_entry_count = &runtime_entry_count;
|
||||
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
||||
exit_boot_func);
|
||||
|
||||
if (status == EFI_SUCCESS) {
|
||||
efi_set_virtual_address_map_t *svam;
|
||||
|
@ -73,12 +73,20 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
|
||||
unsigned long random_seed)
|
||||
{
|
||||
unsigned long map_size, desc_size, total_slots = 0, target_slot;
|
||||
unsigned long buff_size;
|
||||
efi_status_t status;
|
||||
efi_memory_desc_t *memory_map;
|
||||
int map_offset;
|
||||
struct efi_boot_memmap map;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &memory_map, &map_size,
|
||||
&desc_size, NULL, NULL);
|
||||
map.map = &memory_map;
|
||||
map.map_size = &map_size;
|
||||
map.desc_size = &desc_size;
|
||||
map.desc_ver = NULL;
|
||||
map.key_ptr = NULL;
|
||||
map.buff_size = &buff_size;
|
||||
|
||||
status = efi_get_memory_map(sys_table_arg, &map);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
|
@ -118,6 +118,15 @@ typedef struct {
|
||||
u32 imagesize;
|
||||
} efi_capsule_header_t;
|
||||
|
||||
struct efi_boot_memmap {
|
||||
efi_memory_desc_t **map;
|
||||
unsigned long *map_size;
|
||||
unsigned long *desc_size;
|
||||
u32 *desc_ver;
|
||||
unsigned long *key_ptr;
|
||||
unsigned long *buff_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* EFI capsule flags
|
||||
*/
|
||||
@ -946,7 +955,7 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
|
||||
/* Iterate through an efi_memory_map */
|
||||
#define for_each_efi_memory_desc_in_map(m, md) \
|
||||
for ((md) = (m)->map; \
|
||||
((void *)(md) + (m)->desc_size) <= (m)->map_end; \
|
||||
(md) && ((void *)(md) + (m)->desc_size) <= (m)->map_end; \
|
||||
(md) = (void *)(md) + (m)->desc_size)
|
||||
|
||||
/**
|
||||
@ -1371,11 +1380,7 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
|
||||
efi_loaded_image_t *image, int *cmd_line_len);
|
||||
|
||||
efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
|
||||
efi_memory_desc_t **map,
|
||||
unsigned long *map_size,
|
||||
unsigned long *desc_size,
|
||||
u32 *desc_ver,
|
||||
unsigned long *key_ptr);
|
||||
struct efi_boot_memmap *map);
|
||||
|
||||
efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
|
||||
unsigned long size, unsigned long align,
|
||||
@ -1457,4 +1462,14 @@ extern void efi_call_virt_check_flags(unsigned long flags, const char *call);
|
||||
arch_efi_call_virt_teardown(); \
|
||||
})
|
||||
|
||||
typedef efi_status_t (*efi_exit_boot_map_processing)(
|
||||
efi_system_table_t *sys_table_arg,
|
||||
struct efi_boot_memmap *map,
|
||||
void *priv);
|
||||
|
||||
efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
|
||||
void *handle,
|
||||
struct efi_boot_memmap *map,
|
||||
void *priv,
|
||||
efi_exit_boot_map_processing priv_func);
|
||||
#endif /* _LINUX_EFI_H */
|
||||
|
Loading…
Reference in New Issue
Block a user