Skip to content

Commit

Permalink
efi/x86: Move UEFI Runtime Services wrappers to generic code
Browse files Browse the repository at this point in the history
In order for other archs (such as arm64) to be able to reuse the virtual
mode function call wrappers, move them to drivers/firmware/efi/runtime-wrappers.c.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
  • Loading branch information
Ard Biesheuvel authored and Matt Fleming committed Jul 7, 2014
1 parent f49182e commit 022ee6c
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 142 deletions.
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,7 @@ config EFI
bool "EFI runtime service support"
depends on ACPI
select UCS2_STRING
select EFI_RUNTIME_WRAPPERS
---help---
This enables the kernel to use EFI runtime services that are
available (such as the EFI variable services).
Expand Down
144 changes: 2 additions & 142 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,130 +88,6 @@ static int __init setup_add_efi_memmap(char *arg)
}
early_param("add_efi_memmap", setup_add_efi_memmap);

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);
status = efi_call_virt(get_time, tm, tc);
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);
status = efi_call_virt(set_time, tm);
spin_unlock_irqrestore(&rtc_lock, flags);
return status;
}

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);
status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
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);
status = efi_call_virt(set_wakeup_time, enabled, tm);
spin_unlock_irqrestore(&rtc_lock, flags);
return status;
}

static efi_status_t virt_efi_get_variable(efi_char16_t *name,
efi_guid_t *vendor,
u32 *attr,
unsigned long *data_size,
void *data)
{
return efi_call_virt(get_variable,
name, vendor, attr,
data_size, data);
}

static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
efi_char16_t *name,
efi_guid_t *vendor)
{
return efi_call_virt(get_next_variable,
name_size, name, vendor);
}

static efi_status_t virt_efi_set_variable(efi_char16_t *name,
efi_guid_t *vendor,
u32 attr,
unsigned long data_size,
void *data)
{
return efi_call_virt(set_variable,
name, vendor, attr,
data_size, data);
}

static efi_status_t virt_efi_query_variable_info(u32 attr,
u64 *storage_space,
u64 *remaining_space,
u64 *max_variable_size)
{
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

return efi_call_virt(query_variable_info, attr, storage_space,
remaining_space, max_variable_size);
}

static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
{
return efi_call_virt(get_next_high_mono_count, count);
}

static void virt_efi_reset_system(int reset_type,
efi_status_t status,
unsigned long data_size,
efi_char16_t *data)
{
__efi_call_virt(reset_system, reset_type, status,
data_size, data);
}

static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
unsigned long count,
unsigned long sg_list)
{
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

return efi_call_virt(update_capsule, capsules, count, sg_list);
}

static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
unsigned long count,
u64 *max_size,
int *reset_type)
{
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

return efi_call_virt(query_capsule_caps, capsules, count, max_size,
reset_type);
}

static efi_status_t __init phys_efi_set_virtual_address_map(
unsigned long memory_map_size,
unsigned long descriptor_size,
Expand Down Expand Up @@ -721,22 +597,6 @@ void __init old_map_region(efi_memory_desc_t *md)
(unsigned long long)md->phys_addr);
}

static void native_runtime_setup(void)
{
efi.get_time = virt_efi_get_time;
efi.set_time = virt_efi_set_time;
efi.get_wakeup_time = virt_efi_get_wakeup_time;
efi.set_wakeup_time = virt_efi_set_wakeup_time;
efi.get_variable = virt_efi_get_variable;
efi.get_next_variable = virt_efi_get_next_variable;
efi.set_variable = virt_efi_set_variable;
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.update_capsule = virt_efi_update_capsule;
efi.query_capsule_caps = virt_efi_query_capsule_caps;
}

/* Merge contiguous regions of the same type and attribute */
static void __init efi_merge_regions(void)
{
Expand Down Expand Up @@ -923,7 +783,7 @@ static void __init kexec_enter_virtual_mode(void)
*/
efi.runtime_version = efi_systab.hdr.revision;

native_runtime_setup();
efi_native_runtime_setup();

efi.set_virtual_address_map = NULL;

Expand Down Expand Up @@ -1012,7 +872,7 @@ static void __init __efi_enter_virtual_mode(void)
efi.runtime_version = efi_systab.hdr.revision;

if (efi_is_native())
native_runtime_setup();
efi_native_runtime_setup();
else
efi_thunk_runtime_setup();

Expand Down
3 changes: 3 additions & 0 deletions drivers/firmware/efi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ config EFI_PARAMS_FROM_FDT
the EFI runtime support gets system table address, memory
map address, and other parameters from the device tree.

config EFI_RUNTIME_WRAPPERS
bool

endmenu

config UEFI_CPER
Expand Down
1 change: 1 addition & 0 deletions drivers/firmware/efi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
obj-$(CONFIG_UEFI_CPER) += cper.o
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
161 changes: 161 additions & 0 deletions drivers/firmware/efi/runtime-wrappers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* runtime-wrappers.c - Runtime Services function call wrappers
*
* Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
*
* Split off from arch/x86/platform/efi/efi.c
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 1999-2002 Hewlett-Packard Co.
* Copyright (C) 2005-2008 Intel Co.
* Copyright (C) 2013 SuSE Labs
*
* This file is released under the GPLv2.
*/

#include <linux/efi.h>
#include <linux/spinlock.h> /* spinlock_t */
#include <asm/efi.h>

/*
* 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);
status = efi_call_virt(get_time, tm, tc);
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);
status = efi_call_virt(set_time, tm);
spin_unlock_irqrestore(&rtc_lock, flags);
return status;
}

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);
status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
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);
status = efi_call_virt(set_wakeup_time, enabled, tm);
spin_unlock_irqrestore(&rtc_lock, flags);
return status;
}

static efi_status_t virt_efi_get_variable(efi_char16_t *name,
efi_guid_t *vendor,
u32 *attr,
unsigned long *data_size,
void *data)
{
return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
}

static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
efi_char16_t *name,
efi_guid_t *vendor)
{
return efi_call_virt(get_next_variable, name_size, name, vendor);
}

static efi_status_t virt_efi_set_variable(efi_char16_t *name,
efi_guid_t *vendor,
u32 attr,
unsigned long data_size,
void *data)
{
return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
}

static efi_status_t virt_efi_query_variable_info(u32 attr,
u64 *storage_space,
u64 *remaining_space,
u64 *max_variable_size)
{
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

return efi_call_virt(query_variable_info, attr, storage_space,
remaining_space, max_variable_size);
}

static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
{
return efi_call_virt(get_next_high_mono_count, count);
}

static void virt_efi_reset_system(int reset_type,
efi_status_t status,
unsigned long data_size,
efi_char16_t *data)
{
__efi_call_virt(reset_system, reset_type, status, data_size, data);
}

static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
unsigned long count,
unsigned long sg_list)
{
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

return efi_call_virt(update_capsule, capsules, count, sg_list);
}

static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
unsigned long count,
u64 *max_size,
int *reset_type)
{
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

return efi_call_virt(query_capsule_caps, capsules, count, max_size,
reset_type);
}

void efi_native_runtime_setup(void)
{
efi.get_time = virt_efi_get_time;
efi.set_time = virt_efi_set_time;
efi.get_wakeup_time = virt_efi_get_wakeup_time;
efi.set_wakeup_time = virt_efi_set_wakeup_time;
efi.get_variable = virt_efi_get_variable;
efi.get_next_variable = virt_efi_get_next_variable;
efi.set_variable = virt_efi_set_variable;
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.update_capsule = virt_efi_update_capsule;
efi.query_capsule_caps = virt_efi_query_capsule_caps;
}
2 changes: 2 additions & 0 deletions include/linux/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,8 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
int *reset_type);
typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size);

void efi_native_runtime_setup(void);

/*
* EFI Configuration Table and GUID definitions
*/
Expand Down

0 comments on commit 022ee6c

Please sign in to comment.