Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar: "The main changes are: - Use separate EFI page tables when executing EFI firmware code. This isolates the EFI context from the rest of the kernel, which has security and general robustness advantages. (Matt Fleming) - Run regular UEFI firmware with interrupts enabled. This is already the status quo under other OSs. (Ard Biesheuvel) - Various x86 EFI enhancements, such as the use of non-executable attributes for EFI memory mappings. (Sai Praneeth Prakhya) - Various arm64 UEFI enhancements. (Ard Biesheuvel) - ... various fixes and cleanups. The separate EFI page tables feature got delayed twice already, because it's an intrusive change and we didn't feel confident about it - third time's the charm we hope!" * 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (37 commits) x86/mm/pat: Fix boot crash when 1GB pages are not supported by the CPU x86/efi: Only map kernel text for EFI mixed mode x86/efi: Map EFI_MEMORY_{XP,RO} memory region bits to EFI page tables x86/mm/pat: Don't implicitly allow _PAGE_RW in kernel_map_pages_in_pgd() efi/arm*: Perform hardware compatibility check efi/arm64: Check for h/w support before booting a >4 KB granular kernel efi/arm: Check for LPAE support before booting a LPAE kernel efi/arm-init: Use read-only early mappings efi/efistub: Prevent __init annotations from being used arm64/vmlinux.lds.S: Handle .init.rodata.xxx and .init.bss sections efi/arm64: Drop __init annotation from handle_kernel_image() x86/mm/pat: Use _PAGE_GLOBAL bit for EFI page table mappings efi/runtime-wrappers: Run UEFI Runtime Services with interrupts enabled efi: Reformat GUID tables to follow the format in UEFI spec efi: Add Persistent Memory type name efi: Add NV memory attribute x86/efi: Show actual ending addresses in efi_print_memmap x86/efi/bgrt: Don't ignore the BGRT if the 'valid' bit is 0 efivars: Use to_efivar_entry efi: Runtime-wrapper: Get rid of the rtc_lock spinlock ...
This commit is contained in:
@@ -61,8 +61,8 @@ static int __init uefi_init(void)
|
||||
char vendor[100] = "unknown";
|
||||
int i, retval;
|
||||
|
||||
efi.systab = early_memremap(efi_system_table,
|
||||
sizeof(efi_system_table_t));
|
||||
efi.systab = early_memremap_ro(efi_system_table,
|
||||
sizeof(efi_system_table_t));
|
||||
if (efi.systab == NULL) {
|
||||
pr_warn("Unable to map EFI system table.\n");
|
||||
return -ENOMEM;
|
||||
@@ -86,8 +86,8 @@ static int __init uefi_init(void)
|
||||
efi.systab->hdr.revision & 0xffff);
|
||||
|
||||
/* Show what we know for posterity */
|
||||
c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
|
||||
sizeof(vendor) * sizeof(efi_char16_t));
|
||||
c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
|
||||
sizeof(vendor) * sizeof(efi_char16_t));
|
||||
if (c16) {
|
||||
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
|
||||
vendor[i] = c16[i];
|
||||
@@ -100,8 +100,8 @@ static int __init uefi_init(void)
|
||||
efi.systab->hdr.revision & 0xffff, vendor);
|
||||
|
||||
table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
|
||||
config_tables = early_memremap(efi_to_phys(efi.systab->tables),
|
||||
table_size);
|
||||
config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
|
||||
table_size);
|
||||
if (config_tables == NULL) {
|
||||
pr_warn("Unable to map EFI config table array.\n");
|
||||
retval = -ENOMEM;
|
||||
@@ -185,7 +185,7 @@ void __init efi_init(void)
|
||||
efi_system_table = params.system_table;
|
||||
|
||||
memmap.phys_map = params.mmap;
|
||||
memmap.map = early_memremap(params.mmap, params.mmap_size);
|
||||
memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
|
||||
if (memmap.map == NULL) {
|
||||
/*
|
||||
* If we are booting via UEFI, the UEFI memory map is the only
|
||||
|
@@ -182,6 +182,7 @@ static int generic_ops_register(void)
|
||||
{
|
||||
generic_ops.get_variable = efi.get_variable;
|
||||
generic_ops.set_variable = efi.set_variable;
|
||||
generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
|
||||
generic_ops.get_next_variable = efi.get_next_variable;
|
||||
generic_ops.query_variable_store = efi_query_variable_store;
|
||||
|
||||
@@ -326,38 +327,6 @@ u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
|
||||
return end;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't ioremap data in EFI boot services RAM, because we've already mapped
|
||||
* it as RAM. So, look it up in the existing EFI memory map instead. Only
|
||||
* callable after efi_enter_virtual_mode and before efi_free_boot_services.
|
||||
*/
|
||||
void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
|
||||
{
|
||||
struct efi_memory_map *map;
|
||||
void *p;
|
||||
map = efi.memmap;
|
||||
if (!map)
|
||||
return NULL;
|
||||
if (WARN_ON(!map->map))
|
||||
return NULL;
|
||||
for (p = map->map; p < map->map_end; p += map->desc_size) {
|
||||
efi_memory_desc_t *md = p;
|
||||
u64 size = md->num_pages << EFI_PAGE_SHIFT;
|
||||
u64 end = md->phys_addr + size;
|
||||
if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
|
||||
md->type != EFI_BOOT_SERVICES_CODE &&
|
||||
md->type != EFI_BOOT_SERVICES_DATA)
|
||||
continue;
|
||||
if (!md->virt_addr)
|
||||
continue;
|
||||
if (phys_addr >= md->phys_addr && phys_addr < end) {
|
||||
phys_addr += md->virt_addr - md->phys_addr;
|
||||
return (__force void __iomem *)(unsigned long)phys_addr;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __initdata efi_config_table_type_t common_tables[] = {
|
||||
{ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
|
||||
{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
|
||||
@@ -586,7 +555,8 @@ static __initdata char memory_type_name[][20] = {
|
||||
"ACPI Memory NVS",
|
||||
"Memory Mapped I/O",
|
||||
"MMIO Port Space",
|
||||
"PAL Code"
|
||||
"PAL Code",
|
||||
"Persistent Memory",
|
||||
};
|
||||
|
||||
char * __init efi_md_typeattr_format(char *buf, size_t size,
|
||||
@@ -613,13 +583,16 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
|
||||
if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
|
||||
EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
|
||||
EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
|
||||
EFI_MEMORY_NV |
|
||||
EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
|
||||
snprintf(pos, size, "|attr=0x%016llx]",
|
||||
(unsigned long long)attr);
|
||||
else
|
||||
snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
|
||||
snprintf(pos, size,
|
||||
"|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
|
||||
attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
|
||||
attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
|
||||
attr & EFI_MEMORY_NV ? "NV" : "",
|
||||
attr & EFI_MEMORY_XP ? "XP" : "",
|
||||
attr & EFI_MEMORY_RP ? "RP" : "",
|
||||
attr & EFI_MEMORY_WP ? "WP" : "",
|
||||
|
@@ -386,7 +386,7 @@ static const struct sysfs_ops efivar_attr_ops = {
|
||||
|
||||
static void efivar_release(struct kobject *kobj)
|
||||
{
|
||||
struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
|
||||
struct efivar_entry *var = to_efivar_entry(kobj);
|
||||
kfree(var);
|
||||
}
|
||||
|
||||
|
@@ -167,14 +167,11 @@ static struct kset *esrt_kset;
|
||||
static int esre_create_sysfs_entry(void *esre, int entry_num)
|
||||
{
|
||||
struct esre_entry *entry;
|
||||
char name[20];
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(name, "entry%d", entry_num);
|
||||
|
||||
entry->kobj.kset = esrt_kset;
|
||||
|
||||
if (esrt->fw_resource_version == 1) {
|
||||
@@ -182,7 +179,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)
|
||||
|
||||
entry->esre.esre1 = esre;
|
||||
rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
|
||||
"%s", name);
|
||||
"entry%d", entry_num);
|
||||
if (rc) {
|
||||
kfree(entry);
|
||||
return rc;
|
||||
|
@@ -192,6 +192,10 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
||||
|
||||
pr_efi(sys_table, "Booting Linux Kernel...\n");
|
||||
|
||||
status = check_platform_features(sys_table);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Get a handle to the loaded image protocol. This is used to get
|
||||
* information about the running image, such as size and the command
|
||||
|
@@ -9,6 +9,23 @@
|
||||
#include <linux/efi.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
int block;
|
||||
|
||||
/* non-LPAE kernels can run anywhere */
|
||||
if (!IS_ENABLED(CONFIG_ARM_LPAE))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
/* LPAE kernels need compatible hardware */
|
||||
block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
|
||||
if (block < 5) {
|
||||
pr_efi_err(sys_table_arg, "This LPAE kernel is not supported by your CPU\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
|
||||
unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
|
@@ -12,18 +12,38 @@
|
||||
#include <linux/efi.h>
|
||||
#include <asm/efi.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
extern bool __nokaslr;
|
||||
|
||||
efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
|
||||
unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
unsigned long *reserve_addr,
|
||||
unsigned long *reserve_size,
|
||||
unsigned long dram_base,
|
||||
efi_loaded_image_t *image)
|
||||
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
u64 tg;
|
||||
|
||||
/* UEFI mandates support for 4 KB granularity, no need to check */
|
||||
if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
|
||||
if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
|
||||
if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
|
||||
pr_efi_err(sys_table_arg, "This 64 KB granular kernel is not supported by your CPU\n");
|
||||
else
|
||||
pr_efi_err(sys_table_arg, "This 16 KB granular kernel is not supported by your CPU\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
|
||||
unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
unsigned long *reserve_addr,
|
||||
unsigned long *reserve_size,
|
||||
unsigned long dram_base,
|
||||
efi_loaded_image_t *image)
|
||||
{
|
||||
efi_status_t status;
|
||||
unsigned long kernel_size, kernel_memsize = 0;
|
||||
|
@@ -5,6 +5,16 @@
|
||||
/* error code which can't be mistaken for valid address */
|
||||
#define EFI_ERROR (~0UL)
|
||||
|
||||
/*
|
||||
* __init annotations should not be used in the EFI stub, since the code is
|
||||
* either included in the decompressor (x86, ARM) where they have no effect,
|
||||
* or the whole stub is __init annotated at the section level (arm64), by
|
||||
* renaming the sections, in which case the __init annotation will be
|
||||
* redundant, and will result in section names like .init.init.text, and our
|
||||
* linker script does not expect that.
|
||||
*/
|
||||
#undef __init
|
||||
|
||||
void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
|
||||
|
||||
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
|
||||
@@ -50,4 +60,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
|
||||
unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long random_seed);
|
||||
|
||||
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
|
||||
|
||||
#endif
|
||||
|
@@ -61,63 +61,23 @@
|
||||
*/
|
||||
static DEFINE_SPINLOCK(efi_runtime_lock);
|
||||
|
||||
/*
|
||||
* Some runtime services calls can be reentrant under NMI, even if the table
|
||||
* above says they are not. (source: UEFI Specification v2.4A)
|
||||
*
|
||||
* Table 32. Functions that may be called after Machine Check, INIT and NMI
|
||||
* +----------------------------+------------------------------------------+
|
||||
* | Function | Called after Machine Check, INIT and NMI |
|
||||
* +----------------------------+------------------------------------------+
|
||||
* | GetTime() | Yes, even if previously busy. |
|
||||
* | GetVariable() | Yes, even if previously busy |
|
||||
* | GetNextVariableName() | Yes, even if previously busy |
|
||||
* | QueryVariableInfo() | Yes, even if previously busy |
|
||||
* | SetVariable() | Yes, even if previously busy |
|
||||
* | UpdateCapsule() | Yes, even if previously busy |
|
||||
* | QueryCapsuleCapabilities() | Yes, even if previously busy |
|
||||
* | ResetSystem() | Yes, even if previously busy |
|
||||
* +----------------------------+------------------------------------------+
|
||||
*
|
||||
* In order to prevent deadlocks under NMI, the wrappers for these functions
|
||||
* may only grab the efi_runtime_lock or rtc_lock spinlocks if !efi_in_nmi().
|
||||
* However, not all of the services listed are reachable through NMI code paths,
|
||||
* so the the special handling as suggested by the UEFI spec is only implemented
|
||||
* for QueryVariableInfo() and SetVariable(), as these can be reached in NMI
|
||||
* context through efi_pstore_write().
|
||||
*/
|
||||
|
||||
/*
|
||||
* As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
|
||||
* the EFI specification requires that callers of the time related runtime
|
||||
* functions serialize with other CMOS accesses in the kernel, as the EFI time
|
||||
* functions may choose to also use the legacy CMOS RTC.
|
||||
*/
|
||||
__weak DEFINE_SPINLOCK(rtc_lock);
|
||||
|
||||
static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(get_time, tm, tc);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
static efi_status_t virt_efi_set_time(efi_time_t *tm)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(set_time, tm);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -125,27 +85,21 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
|
||||
efi_bool_t *pending,
|
||||
efi_time_t *tm)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(set_wakeup_time, enabled, tm);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -155,13 +109,12 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
|
||||
unsigned long *data_size,
|
||||
void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(get_variable, name, vendor, attr, data_size,
|
||||
data);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -169,12 +122,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
|
||||
efi_char16_t *name,
|
||||
efi_guid_t *vendor)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(get_next_variable, name_size, name, vendor);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -184,13 +136,12 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
|
||||
unsigned long data_size,
|
||||
void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(set_variable, name, vendor, attr, data_size,
|
||||
data);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -199,15 +150,14 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
|
||||
u32 attr, unsigned long data_size,
|
||||
void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
|
||||
if (!spin_trylock(&efi_runtime_lock))
|
||||
return EFI_NOT_READY;
|
||||
|
||||
status = efi_call_virt(set_variable, name, vendor, attr, data_size,
|
||||
data);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -217,27 +167,45 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
|
||||
u64 *remaining_space,
|
||||
u64 *max_variable_size)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(query_variable_info, attr, storage_space,
|
||||
remaining_space, max_variable_size);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static efi_status_t
|
||||
virt_efi_query_variable_info_nonblocking(u32 attr,
|
||||
u64 *storage_space,
|
||||
u64 *remaining_space,
|
||||
u64 *max_variable_size)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
if (!spin_trylock(&efi_runtime_lock))
|
||||
return EFI_NOT_READY;
|
||||
|
||||
status = efi_call_virt(query_variable_info, attr, storage_space,
|
||||
remaining_space, max_variable_size);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(get_next_high_mono_count, count);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -246,26 +214,23 @@ static void virt_efi_reset_system(int reset_type,
|
||||
unsigned long data_size,
|
||||
efi_char16_t *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
__efi_call_virt(reset_system, reset_type, status, data_size, data);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
}
|
||||
|
||||
static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
|
||||
unsigned long count,
|
||||
unsigned long sg_list)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(update_capsule, capsules, count, sg_list);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -274,16 +239,15 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
|
||||
u64 *max_size,
|
||||
int *reset_type)
|
||||
{
|
||||
unsigned long flags;
|
||||
efi_status_t status;
|
||||
|
||||
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||
spin_lock(&efi_runtime_lock);
|
||||
status = efi_call_virt(query_capsule_caps, capsules, count, max_size,
|
||||
reset_type);
|
||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||
spin_unlock(&efi_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -300,6 +264,7 @@ void efi_native_runtime_setup(void)
|
||||
efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
|
||||
efi.reset_system = virt_efi_reset_system;
|
||||
efi.query_variable_info = virt_efi_query_variable_info;
|
||||
efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nonblocking;
|
||||
efi.update_capsule = virt_efi_update_capsule;
|
||||
efi.query_capsule_caps = virt_efi_query_capsule_caps;
|
||||
}
|
||||
|
@@ -300,7 +300,18 @@ check_var_size(u32 attributes, unsigned long size)
|
||||
if (!fops->query_variable_store)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
return fops->query_variable_store(attributes, size);
|
||||
return fops->query_variable_store(attributes, size, false);
|
||||
}
|
||||
|
||||
static efi_status_t
|
||||
check_var_size_nonblocking(u32 attributes, unsigned long size)
|
||||
{
|
||||
const struct efivar_operations *fops = __efivars->ops;
|
||||
|
||||
if (!fops->query_variable_store)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
return fops->query_variable_store(attributes, size, true);
|
||||
}
|
||||
|
||||
static int efi_status_to_err(efi_status_t status)
|
||||
@@ -681,7 +692,8 @@ efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
|
||||
if (!spin_trylock_irqsave(&__efivars->lock, flags))
|
||||
return -EBUSY;
|
||||
|
||||
status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
|
||||
status = check_var_size_nonblocking(attributes,
|
||||
size + ucs2_strsize(name, 1024));
|
||||
if (status != EFI_SUCCESS) {
|
||||
spin_unlock_irqrestore(&__efivars->lock, flags);
|
||||
return -ENOSPC;
|
||||
|
Reference in New Issue
Block a user