diff options
Diffstat (limited to 'drivers/firmware/efi')
| -rw-r--r-- | drivers/firmware/efi/arm-runtime.c | 5 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 13 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi.c | 180 | ||||
| -rw-r--r-- | drivers/firmware/efi/efibc.c | 4 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c | 169 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/fdt.c | 54 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/random.c | 12 | ||||
| -rw-r--r-- | drivers/firmware/efi/runtime-wrappers.c | 53 |
8 files changed, 382 insertions, 108 deletions
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 17ccf0a87..c394b81fe 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -107,6 +107,11 @@ static int __init arm_enable_runtime_services(void) return 0; } + if (efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_info("EFI runtime services access via paravirt.\n"); + return 0; + } + pr_info("Remapping and enabling EFI services.\n"); mapsize = efi.memmap.map_end - efi.memmap.map; diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index eac76a79a..30a24d09e 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -34,6 +34,7 @@ struct pstore_read_data { int *count; struct timespec *timespec; bool *compressed; + ssize_t *ecc_notice_size; char **buf; }; @@ -69,6 +70,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) *cb_data->compressed = true; else *cb_data->compressed = false; + *cb_data->ecc_notice_size = 0; } else if (sscanf(name, "dump-type%u-%u-%d-%lu", cb_data->type, &part, &cnt, &time) == 4) { *cb_data->id = generic_id(time, part, cnt); @@ -76,6 +78,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) cb_data->timespec->tv_sec = time; cb_data->timespec->tv_nsec = 0; *cb_data->compressed = false; + *cb_data->ecc_notice_size = 0; } else if (sscanf(name, "dump-type%u-%u-%lu", cb_data->type, &part, &time) == 3) { /* @@ -88,6 +91,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) cb_data->timespec->tv_sec = time; cb_data->timespec->tv_nsec = 0; *cb_data->compressed = false; + *cb_data->ecc_notice_size = 0; } else return 0; @@ -210,6 +214,7 @@ static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos) static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *timespec, char **buf, bool *compressed, + ssize_t *ecc_notice_size, struct pstore_info *psi) { struct pstore_read_data data; @@ -220,6 +225,7 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, data.count = count; data.timespec = timespec; data.compressed = compressed; + data.ecc_notice_size = ecc_notice_size; data.buf = buf; *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); @@ -393,6 +399,13 @@ static __init int efivars_pstore_init(void) static __exit void efivars_pstore_exit(void) { + if (!efi_pstore_info.bufsize) + return; + + pstore_unregister(&efi_pstore_info); + kfree(efi_pstore_info.buf); + efi_pstore_info.buf = NULL; + efi_pstore_info.bufsize = 0; } module_init(efivars_pstore_init); diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 05509f3aa..7dd2e2d37 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -24,6 +24,9 @@ #include <linux/of_fdt.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/acpi.h> +#include <linux/ucs2_string.h> #include <asm/early_ioremap.h> @@ -195,6 +198,96 @@ static void generic_ops_unregister(void) efivars_unregister(&generic_efivars); } +#if IS_ENABLED(CONFIG_ACPI) +#define EFIVAR_SSDT_NAME_MAX 16 +static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata; +static int __init efivar_ssdt_setup(char *str) +{ + if (strlen(str) < sizeof(efivar_ssdt)) + memcpy(efivar_ssdt, str, strlen(str)); + else + pr_warn("efivar_ssdt: name too long: %s\n", str); + return 0; +} +__setup("efivar_ssdt=", efivar_ssdt_setup); + +static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor, + unsigned long name_size, void *data) +{ + struct efivar_entry *entry; + struct list_head *list = data; + char utf8_name[EFIVAR_SSDT_NAME_MAX]; + int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size); + + ucs2_as_utf8(utf8_name, name, limit - 1); + if (strncmp(utf8_name, efivar_ssdt, limit) != 0) + return 0; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return 0; + + memcpy(entry->var.VariableName, name, name_size); + memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t)); + + efivar_entry_add(entry, list); + + return 0; +} + +static __init int efivar_ssdt_load(void) +{ + LIST_HEAD(entries); + struct efivar_entry *entry, *aux; + unsigned long size; + void *data; + int ret; + + ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries); + + list_for_each_entry_safe(entry, aux, &entries, list) { + pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt, + &entry->var.VendorGuid); + + list_del(&entry->list); + + ret = efivar_entry_size(entry, &size); + if (ret) { + pr_err("failed to get var size\n"); + goto free_entry; + } + + data = kmalloc(size, GFP_KERNEL); + if (!data) + goto free_entry; + + ret = efivar_entry_get(entry, NULL, &size, data); + if (ret) { + pr_err("failed to get var data\n"); + goto free_data; + } + + ret = acpi_load_table(data); + if (ret) { + pr_err("failed to load table: %d\n", ret); + goto free_data; + } + + goto free_entry; + +free_data: + kfree(data); + +free_entry: + kfree(entry); + } + + return ret; +} +#else +static inline int efivar_ssdt_load(void) { return 0; } +#endif + /* * We register the efi subsystem with the firmware subsystem and the * efivars subsystem with the efi subsystem, if the system was booted with @@ -218,6 +311,9 @@ static int __init efisubsys_init(void) if (error) goto err_put; + if (efi_enabled(EFI_RUNTIME_SERVICES)) + efivar_ssdt_load(); + error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); if (error) { pr_err("efi: Sysfs attribute export failed with error %d.\n", @@ -472,12 +568,14 @@ device_initcall(efi_load_efivars); FIELD_SIZEOF(struct efi_fdt_params, field) \ } -static __initdata struct { +struct params { const char name[32]; const char propname[32]; int offset; int size; -} dt_params[] = { +}; + +static __initdata struct params fdt_params[] = { UEFI_PARAM("System Table", "linux,uefi-system-table", system_table), UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap), UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size), @@ -485,44 +583,94 @@ static __initdata struct { UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver) }; +static __initdata struct params xen_fdt_params[] = { + UEFI_PARAM("System Table", "xen,uefi-system-table", system_table), + UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap), + UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size), + UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size), + UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver) +}; + +#define EFI_FDT_PARAMS_SIZE ARRAY_SIZE(fdt_params) + +static __initdata struct { + const char *uname; + const char *subnode; + struct params *params; +} dt_params[] = { + { "hypervisor", "uefi", xen_fdt_params }, + { "chosen", NULL, fdt_params }, +}; + struct param_info { int found; void *params; + const char *missing; }; -static int __init fdt_find_uefi_params(unsigned long node, const char *uname, - int depth, void *data) +static int __init __find_uefi_params(unsigned long node, + struct param_info *info, + struct params *params) { - struct param_info *info = data; const void *prop; void *dest; u64 val; int i, len; - if (depth != 1 || strcmp(uname, "chosen") != 0) - return 0; - - for (i = 0; i < ARRAY_SIZE(dt_params); i++) { - prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len); - if (!prop) + for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) { + prop = of_get_flat_dt_prop(node, params[i].propname, &len); + if (!prop) { + info->missing = params[i].name; return 0; - dest = info->params + dt_params[i].offset; + } + + dest = info->params + params[i].offset; info->found++; val = of_read_number(prop, len / sizeof(u32)); - if (dt_params[i].size == sizeof(u32)) + if (params[i].size == sizeof(u32)) *(u32 *)dest = val; else *(u64 *)dest = val; if (efi_enabled(EFI_DBG)) - pr_info(" %s: 0x%0*llx\n", dt_params[i].name, - dt_params[i].size * 2, val); + pr_info(" %s: 0x%0*llx\n", params[i].name, + params[i].size * 2, val); } + return 1; } +static int __init fdt_find_uefi_params(unsigned long node, const char *uname, + int depth, void *data) +{ + struct param_info *info = data; + int i; + + for (i = 0; i < ARRAY_SIZE(dt_params); i++) { + const char *subnode = dt_params[i].subnode; + + if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) { + info->missing = dt_params[i].params[0].name; + continue; + } + + if (subnode) { + 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); + } + + return 0; +} + int __init efi_get_fdt_params(struct efi_fdt_params *params) { struct param_info info; @@ -538,7 +686,7 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params) pr_info("UEFI not found.\n"); else if (!ret) pr_err("Can't find '%s' in device tree!\n", - dt_params[info.found].name); + info.missing); return ret; } diff --git a/drivers/firmware/efi/efibc.c b/drivers/firmware/efi/efibc.c index 8dd0c7085..503bbe2a9 100644 --- a/drivers/firmware/efi/efibc.c +++ b/drivers/firmware/efi/efibc.c @@ -37,13 +37,13 @@ static int efibc_set_variable(const char *name, const char *value) size_t size = (strlen(value) + 1) * sizeof(efi_char16_t); if (size > sizeof(entry->var.Data)) { - pr_err("value is too large"); + pr_err("value is too large (%zu bytes) for '%s' EFI variable\n", size, name); return -EINVAL; } entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) { - pr_err("failed to allocate efivar entry"); + pr_err("failed to allocate efivar entry for '%s' EFI variable\n", name); return -ENOMEM; } diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 3bd127f95..aded10662 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -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; + + 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, &map, &map_size, &desc_size, - NULL, NULL); + 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; +} diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index e58abfa95..a6a93116a 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -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; diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c index 53f6d3fe6..0c9f58c5b 100644 --- a/drivers/firmware/efi/libstub/random.c +++ b/drivers/firmware/efi/libstub/random.c @@ -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; diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 23bef6bb7..41958774c 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -22,7 +22,16 @@ #include <linux/stringify.h> #include <asm/efi.h> -static void efi_call_virt_check_flags(unsigned long flags, const char *call) +/* + * Wrap around the new efi_call_virt_generic() macros so that the + * code doesn't get too cluttered: + */ +#define efi_call_virt(f, args...) \ + efi_call_virt_pointer(efi.systab->runtime, f, args) +#define __efi_call_virt(f, args...) \ + __efi_call_virt_pointer(efi.systab->runtime, f, args) + +void efi_call_virt_check_flags(unsigned long flags, const char *call) { unsigned long cur_flags, mismatch; @@ -39,48 +48,6 @@ static void efi_call_virt_check_flags(unsigned long flags, const char *call) } /* - * Arch code can implement the following three template macros, avoiding - * reptition for the void/non-void return cases of {__,}efi_call_virt: - * - * * arch_efi_call_virt_setup - * - * Sets up the environment for the call (e.g. switching page tables, - * allowing kernel-mode use of floating point, if required). - * - * * arch_efi_call_virt - * - * Performs the call. The last expression in the macro must be the call - * itself, allowing the logic to be shared by the void and non-void - * cases. - * - * * arch_efi_call_virt_teardown - * - * Restores the usual kernel environment once the call has returned. - */ - -#define efi_call_virt(f, args...) \ -({ \ - efi_status_t __s; \ - unsigned long flags; \ - arch_efi_call_virt_setup(); \ - local_save_flags(flags); \ - __s = arch_efi_call_virt(f, args); \ - efi_call_virt_check_flags(flags, __stringify(f)); \ - arch_efi_call_virt_teardown(); \ - __s; \ -}) - -#define __efi_call_virt(f, args...) \ -({ \ - unsigned long flags; \ - arch_efi_call_virt_setup(); \ - local_save_flags(flags); \ - arch_efi_call_virt(f, args); \ - efi_call_virt_check_flags(flags, __stringify(f)); \ - arch_efi_call_virt_teardown(); \ -}) - -/* * According to section 7.1 of the UEFI spec, Runtime Services are not fully * reentrant, and there are particular combinations of calls that need to be * serialized. (source: UEFI Specification v2.4A) |
