From patchwork Thu Jan 25 10:31:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 125783 Delivered-To: patch@linaro.org Received: by 10.46.66.141 with SMTP id h13csp1016548ljf; Thu, 25 Jan 2018 02:31:52 -0800 (PST) X-Google-Smtp-Source: AH8x2275dW8Oyqtr/3xfyR5hX4prMRCT10E/oF9UQCrkCWZeOzizc6Jucgw8JiDIlKLP0SXPjG9r X-Received: by 10.99.110.138 with SMTP id j132mr13111944pgc.313.1516876312275; Thu, 25 Jan 2018 02:31:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516876312; cv=none; d=google.com; s=arc-20160816; b=GTxgxn2KPvQZf+ifkdM5FRu6nmkNYYoBN0tSO9D5vgXRbbgerWqyFfuAbv7/GD//q3 YPmCO/te9IlUwli+53fHhkATcwbX9XWFZvaKLJyWsmrWSQqEEYEg4mxmwCwZjLMu3Lwi 2Bbs3CoWim0pHzt5UHq9a23ZL55jz1e/x6e6hzFIEz5ctYtIcXCDyxO07kiS03fkt0s2 iCB1LZG2qmjMWHuSJWewpomad6ykXPkzcE8759GahRGBvVUDq+4zeDP25HBEa2PnVSA9 o23Q1nUvPpiKb2CqZ+68HXNKrDh8jIIYNb5gCUSYJpwXABXIuGTUf/btaKn6KKLNBBLt 1B3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=Uer7t1TLZr0EJieU1YJDWSUtTB70aCLmfgcVSEDWHp0=; b=XhFMFb8fQLK5QCAEuB1lnApE6+RMLpzl8Ynk2sYpJkfYvAhFVKwj18GzjNPLJCDF/j s/CHErO69s83ThuI+BP7lz5p3Gs5yZL7LHBFndZgGdrqphS5V601KAPCp3Ripf2Us07N P0qvJZbbNLzdaxcz5ozs4jPKPak7GKwJPbYBfbIqrAEfSH0BAlv3eAwkltGNkH4eP8uH XZVlw5mti6LBFUfHVOpnlncFzDH+MqVjV60x2A0b11FCYKXKZdvVrD5GCLHfPdW/Rtz5 LyY9MwVlQpKf4FcEIdYMVXJ9cMfZBcASfWWXHOFMSj74qT8dMKSeb7BoOoaPVrIOKxal QLeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=YLyTMV5+; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n188si1088646pga.175.2018.01.25.02.31.52; Thu, 25 Jan 2018 02:31:52 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=YLyTMV5+; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751184AbeAYKbv (ORCPT + 2 others); Thu, 25 Jan 2018 05:31:51 -0500 Received: from mail-wr0-f195.google.com ([209.85.128.195]:40645 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751154AbeAYKbu (ORCPT ); Thu, 25 Jan 2018 05:31:50 -0500 Received: by mail-wr0-f195.google.com with SMTP id 100so7104979wrb.7 for ; Thu, 25 Jan 2018 02:31:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WyBXwDXEDstE0keE/ai7u7i2exQLm/n5/KN2TdM/BEY=; b=YLyTMV5+VOu7CrvnMq+OjoK/FLp5j5wmuafCnwXcSb/YD88Hny8x9pYb3Zd7L840IG 8qXR/0hSgUq9EHfG1VHKhGH2Zy7psWrhBJhnjV3f+kHWIhCQaCKb3i3+XuQQP4Kx/qZK hmCqXEFNVhmc2Hw6oZP1+8c5/OgVZ/rWL06N0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WyBXwDXEDstE0keE/ai7u7i2exQLm/n5/KN2TdM/BEY=; b=P7n3ageHOPr/KXTORDVhjWzBCNiudfOj6GIkt8Nzx/MrAPzWU+9Qh3SIRW7/He50el HiJd+EdgRKDpOOX5lT2P25NBJWANOLf6UsuhszU5MmpyWuzzHSeLC5FZOdJ/TmTpFmLU MxQfDTWYDhgJ58EUeWJXb411o9JLKLHYyqPIa4BJEVDJP8ZTgHq26SRmajMsh1FH/FeZ ufo0E2ZgkCL3z0YzjpW7w2w001QkEeIZQzXxgaDD0rXgMBQgfjQg+ONK0fyByPEbiSMN WVPYaQKZflA7rvHG8Z4DJZaM/Ow8qUMRvj2FhUg8RnInomogU4jPKxY3rbDk701TTh17 oHEA== X-Gm-Message-State: AKwxyte6Gf2O/4mPy/6j8ZEr9l+Zn2ipqLnbp9nhNLOhV6Q0w6sQhXi1 NH5xgMkjuW9aMpkMfAIEXwsJ7yHvLlU= X-Received: by 10.223.163.134 with SMTP id l6mr8105844wrb.220.1516876309098; Thu, 25 Jan 2018 02:31:49 -0800 (PST) Received: from localhost.localdomain ([160.167.127.168]) by smtp.gmail.com with ESMTPSA id j77sm1199964wmf.37.2018.01.25.02.31.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Jan 2018 02:31:48 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com Cc: joakim.bech@linaro.org, leif.lindholm@linaro.org, graeme.gregory@linaro.org, Ard Biesheuvel Subject: [PATCH 3/4] efi/arm64: marshall runtime services arguments via buffer in TTBR0 Date: Thu, 25 Jan 2018 10:31:30 +0000 Message-Id: <20180125103131.19168-4-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180125103131.19168-1-ard.biesheuvel@linaro.org> References: <20180125103131.19168-1-ard.biesheuvel@linaro.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org If we want to unmap the kernel while executing UEFI runtime services, we need to ensure that all arguments passed to those services are valid during that time, and this includes pointer arguments to string buffers and other data. So we have to do the rather tedious job of replacing each generic runtime wrapper with one that takes the above into account. Fortunately, UEFI runtime services are not reentrant, so we can create a static buffer with fields for each runtime service, and a separate buffer for get/set_variable. This does limit variable names to 1024 characters and the variables themselves to 64 KB, but this should not be a limitation in practice. Note that capsule update is omitted for now - this will be addressed in a subsequent patch. Signed-off-by: Ard Biesheuvel --- arch/arm64/Kconfig | 1 - arch/arm64/include/asm/efi.h | 5 + arch/arm64/kernel/efi.c | 475 +++++++++++++++++++- 3 files changed, 479 insertions(+), 2 deletions(-) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index de83b53c7e19..f2224566cc75 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1196,7 +1196,6 @@ config EFI select LIBFDT select UCS2_STRING select EFI_PARAMS_FROM_FDT - select EFI_RUNTIME_WRAPPERS select EFI_STUB select EFI_ARMSTUB default y diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index b9b09a734719..b96bc4836c37 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -165,4 +165,9 @@ int __init efi_allocate_runtime_regions(struct mm_struct *mm); #define EFI_CODE_BASE 0x200000 #define EFI_CODE_SIZE PAGE_SIZE +#define EFI_VARBUFFER_BASE 0x210000 +#define EFI_VARBUFFER_SIZE SZ_64K + +#define EFI_DATA_BASE 0x220000 + #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 68c920b2f4f0..cd23c20fba39 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -11,9 +11,15 @@ * */ +#define pr_fmt(fmt) "efi: " fmt + +#include #include #include - +#include +#include +#include +#include #include /* @@ -136,6 +142,63 @@ bool on_efi_stack(unsigned long sp) return sp >= EFI_STACK_BASE && sp < (EFI_STACK_BASE + EFI_STACK_SIZE); } +#define MAX_CAPSULES 16 +#define MAX_VARNAME_LEN 1024 + +#define EFI_ADDR(arg) (&((typeof(__efi_rt_marshall_data)*)EFI_DATA_BASE)->arg) +#define EFI_DATA(arg) (__efi_rt_marshall_data.arg) + +static union { + struct { + efi_time_t tm; + efi_time_cap_t tc; + } get_time; + + struct { + efi_time_t tm; + } set_time; + + struct { + efi_bool_t enabled; + efi_bool_t pending; + efi_time_t tm; + } get_wakeup_time; + + struct { + efi_char16_t name[MAX_VARNAME_LEN]; + efi_guid_t vendor; + u32 attr; + unsigned long data_size; + void *data; + } get_variable; + + struct { + unsigned long name_size; + efi_char16_t name[MAX_VARNAME_LEN]; + efi_guid_t vendor; + } get_next_variable; + + struct { + u64 storage_space; + u64 remaining_space; + u64 max_variable_size; + } query_variable_info; + + struct { + u32 count; + } get_next_high_mono_count; + + struct { + efi_capsule_header_t capsules[MAX_CAPSULES]; + efi_capsule_header_t *capsule_headers[MAX_CAPSULES]; + u64 max_size; + int reset_type; + } query_capsule_caps; + +} __efi_rt_marshall_data __page_aligned_bss; + +static u8 __efi_rt_varbuffer[EFI_VARBUFFER_SIZE] __page_aligned_bss; + int __init efi_allocate_runtime_regions(struct mm_struct *mm) { static u8 stack[EFI_STACK_SIZE] __page_aligned_bss; @@ -152,5 +215,415 @@ int __init efi_allocate_runtime_regions(struct mm_struct *mm) __pgprot(pgprot_val(PAGE_KERNEL_ROX) | PTE_NG), false); + /* map the marshall data struct */ + create_pgd_mapping(mm, __pa_symbol(&__efi_rt_marshall_data), + EFI_DATA_BASE, sizeof(__efi_rt_marshall_data), + __pgprot(pgprot_val(PAGE_KERNEL) | PTE_NG), + false); + + /* map the varbuffer */ + create_pgd_mapping(mm, __pa_symbol(__efi_rt_varbuffer), + EFI_VARBUFFER_BASE, EFI_VARBUFFER_SIZE, + __pgprot(pgprot_val(PAGE_KERNEL) | PTE_NG), + false); + return 0; } + +/* + * 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; + + local_save_flags(cur_flags); + + mismatch = flags ^ cur_flags; + if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK)) + return; + + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE); + pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n", + flags, cur_flags, call); + local_irq_restore(flags); +} + +static int strlen16(efi_char16_t const *name) +{ + int ret = 0; + + while (*name++) + ret++; + + return ret; +} + +static DEFINE_SEMAPHORE(efi_runtime_lock); + +static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) +{ + efi_status_t status; + + if (!tm) + return EFI_INVALID_PARAMETER; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_call_virt(get_time, + EFI_ADDR(get_time.tm), + tc ? EFI_ADDR(get_time.tc): NULL); + + *tm = EFI_DATA(get_time.tm); + if (tc) + *tc = EFI_DATA(get_time.tc); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_set_time(efi_time_t *tm) +{ + efi_status_t status; + + if (!tm) + return EFI_INVALID_PARAMETER; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + EFI_DATA(set_time.tm) = *tm; + + status = efi_call_virt(set_time, + EFI_ADDR(set_time.tm)); + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, + efi_bool_t *pending, + efi_time_t *tm) +{ + efi_status_t status; + + if (!enabled || !pending || !tm) + return EFI_INVALID_PARAMETER; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_call_virt(get_wakeup_time, + EFI_ADDR(get_wakeup_time.enabled), + EFI_ADDR(get_wakeup_time.pending), + EFI_ADDR(get_wakeup_time.tm)); + + *enabled = EFI_DATA(get_wakeup_time.enabled); + *pending = EFI_DATA(get_wakeup_time.pending); + *tm = EFI_DATA(get_wakeup_time.tm); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + EFI_DATA(set_time.tm) = *tm; + + status = efi_call_virt(set_wakeup_time, enabled, + EFI_ADDR(set_time.tm)); + up(&efi_runtime_lock); + 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) +{ + efi_status_t status; + int l = strlen16(name) + 1; + + if (!name || !vendor || !data_size) + return EFI_INVALID_PARAMETER; + + if (*data_size > EFI_VARBUFFER_SIZE || l > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + memcpy(EFI_DATA(get_variable.name), name, l * sizeof(efi_char16_t)); + EFI_DATA(get_variable.vendor) = *vendor; + EFI_DATA(get_variable.data_size) = *data_size; + + status = efi_call_virt(get_variable, + EFI_ADDR(get_variable.name), + EFI_ADDR(get_variable.vendor), + attr ? EFI_ADDR(get_variable.attr) : NULL, + EFI_ADDR(get_variable.data_size), + data ? (void *)EFI_VARBUFFER_BASE : NULL); + + if (attr) + *attr = EFI_DATA(get_variable.attr); + *data_size = EFI_DATA(get_variable.data_size); + if (data) + memcpy(data, __efi_rt_varbuffer, *data_size); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, + efi_char16_t *name, + efi_guid_t *vendor) +{ + efi_status_t status; + + if (*name_size > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + EFI_DATA(get_next_variable.name_size) = *name_size; + memcpy(EFI_DATA(get_next_variable.name), name, *name_size); + EFI_DATA(get_next_variable.vendor) = *vendor; + + status = efi_call_virt(get_next_variable, + EFI_ADDR(get_next_variable.name_size), + EFI_ADDR(get_next_variable.name), + EFI_ADDR(get_next_variable.vendor)); + + *name_size = EFI_DATA(get_next_variable.name_size); + memcpy(name, EFI_DATA(get_next_variable.name), *name_size); + *vendor = EFI_DATA(get_next_variable.vendor); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_set_variable(efi_char16_t *name, + efi_guid_t *vendor, + u32 attr, + unsigned long data_size, + void *data) +{ + efi_status_t status; + int l = strlen16(name) + 1; + + if (!name || !vendor) + return EFI_INVALID_PARAMETER; + + if (data_size > EFI_VARBUFFER_SIZE || l > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + memcpy(EFI_DATA(get_variable.name), name, l * sizeof(efi_char16_t)); + EFI_DATA(get_variable.vendor) = *vendor; + if (data) + memcpy(__efi_rt_varbuffer, data, data_size); + + status = efi_call_virt(set_variable, + EFI_ADDR(get_variable.name), + EFI_ADDR(get_variable.vendor), + attr, + data_size, + data ? (void *)EFI_VARBUFFER_BASE : NULL); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t +virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, + u32 attr, unsigned long data_size, + void *data) +{ + efi_status_t status; + int l = strlen16(name) + 1; + + if (!name || !vendor) + return EFI_INVALID_PARAMETER; + + if (data_size > EFI_VARBUFFER_SIZE || l > MAX_VARNAME_LEN) + return EFI_NOT_READY; + + if (down_trylock(&efi_runtime_lock)) + return EFI_NOT_READY; + + memcpy(EFI_DATA(get_variable.name), name, l * sizeof(efi_char16_t)); + EFI_DATA(get_variable.vendor) = *vendor; + if (data) + memcpy(__efi_rt_varbuffer, data, data_size); + + status = efi_call_virt(set_variable, + EFI_ADDR(get_variable.name), + EFI_ADDR(get_variable.vendor), + attr, + data_size, + data ? (void *)EFI_VARBUFFER_BASE : NULL); + + up(&efi_runtime_lock); + return status; +} + + +static efi_status_t virt_efi_query_variable_info(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + status = efi_call_virt(query_variable_info, + attr, + EFI_ADDR(query_variable_info.storage_space), + EFI_ADDR(query_variable_info.remaining_space), + EFI_ADDR(query_variable_info.max_variable_size)); + + *storage_space = EFI_DATA(query_variable_info.storage_space); + *remaining_space = EFI_DATA(query_variable_info.remaining_space); + *max_variable_size = EFI_DATA(query_variable_info.max_variable_size); + + up(&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 (down_trylock(&efi_runtime_lock)) + return EFI_NOT_READY; + + status = efi_call_virt(query_variable_info, + attr, + EFI_ADDR(query_variable_info.storage_space), + EFI_ADDR(query_variable_info.remaining_space), + EFI_ADDR(query_variable_info.max_variable_size)); + + *storage_space = EFI_DATA(query_variable_info.storage_space); + *remaining_space = EFI_DATA(query_variable_info.remaining_space); + *max_variable_size = EFI_DATA(query_variable_info.max_variable_size); + + up(&efi_runtime_lock); + return status; +} + +static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_call_virt(get_next_high_mono_count, + EFI_ADDR(get_next_high_mono_count.count)); + + *count = EFI_DATA(get_next_high_mono_count.count); + + up(&efi_runtime_lock); + return status; +} + +static void virt_efi_reset_system(int reset_type, + efi_status_t status, + unsigned long data_size, + efi_char16_t *data) +{ + /* we don't use 'data' in the kernel */ + pr_warn("efi_reset_system: ignoring 'data' argument\n"); + + if (down_interruptible(&efi_runtime_lock)) { + pr_warn("failed to invoke the reset_system() runtime service:\n" + "could not get exclusive access to the firmware\n"); + return; + } + __efi_call_virt(reset_system, reset_type, status, 0, NULL); + up(&efi_runtime_lock); +} + +static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, + unsigned long count, + unsigned long sg_list) +{ +// efi_status_t status; + + return EFI_NOT_READY; + +// if (down_interruptible(&efi_runtime_lock)) +// return EFI_ABORTED; +// status = efi_call_virt(update_capsule, capsules, count, sg_list); +// up(&efi_runtime_lock); +// return status; +} + +static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, + unsigned long count, + u64 *max_size, + int *reset_type) +{ + efi_status_t status; + int i; + + if (count > MAX_CAPSULES) + return EFI_NOT_READY; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + + for (i = 0; i < count; i++) { + EFI_DATA(query_capsule_caps.capsules[i]) = *capsules[i]; + EFI_DATA(query_capsule_caps.capsule_headers[i]) = + EFI_ADDR(query_capsule_caps.capsules[i]); + } + + status = efi_call_virt(query_capsule_caps, + EFI_ADDR(query_capsule_caps.capsule_headers), + count, + EFI_ADDR(query_capsule_caps.max_size), + EFI_ADDR(query_capsule_caps.reset_type)); + + *max_size = EFI_DATA(query_capsule_caps.max_size); + *reset_type = EFI_DATA(query_capsule_caps.reset_type); + + up(&efi_runtime_lock); + return status; +} + +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.set_variable_nonblocking = virt_efi_set_variable_nonblocking; + 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; +}