2 * runtime-wrappers.c - Runtime Services function call wrappers
4 * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
6 * Split off from arch/x86/platform/efi/efi.c
8 * Copyright (C) 1999 VA Linux Systems
9 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
10 * Copyright (C) 1999-2002 Hewlett-Packard Co.
11 * Copyright (C) 2005-2008 Intel Co.
12 * Copyright (C) 2013 SuSE Labs
14 * This file is released under the GPLv2.
17 #include <linux/bug.h>
18 #include <linux/efi.h>
19 #include <linux/mutex.h>
20 #include <linux/spinlock.h>
24 * According to section 7.1 of the UEFI spec, Runtime Services are not fully
25 * reentrant, and there are particular combinations of calls that need to be
26 * serialized. (source: UEFI Specification v2.4A)
28 * Table 31. Rules for Reentry Into Runtime Services
29 * +------------------------------------+-------------------------------+
30 * | If previous call is busy in | Forbidden to call |
31 * +------------------------------------+-------------------------------+
32 * | Any | SetVirtualAddressMap() |
33 * +------------------------------------+-------------------------------+
34 * | ConvertPointer() | ConvertPointer() |
35 * +------------------------------------+-------------------------------+
36 * | SetVariable() | ResetSystem() |
37 * | UpdateCapsule() | |
39 * | SetWakeupTime() | |
40 * | GetNextHighMonotonicCount() | |
41 * +------------------------------------+-------------------------------+
42 * | GetVariable() | GetVariable() |
43 * | GetNextVariableName() | GetNextVariableName() |
44 * | SetVariable() | SetVariable() |
45 * | QueryVariableInfo() | QueryVariableInfo() |
46 * | UpdateCapsule() | UpdateCapsule() |
47 * | QueryCapsuleCapabilities() | QueryCapsuleCapabilities() |
48 * | GetNextHighMonotonicCount() | GetNextHighMonotonicCount() |
49 * +------------------------------------+-------------------------------+
50 * | GetTime() | GetTime() |
51 * | SetTime() | SetTime() |
52 * | GetWakeupTime() | GetWakeupTime() |
53 * | SetWakeupTime() | SetWakeupTime() |
54 * +------------------------------------+-------------------------------+
56 * Due to the fact that the EFI pstore may write to the variable store in
57 * interrupt context, we need to use a spinlock for at least the groups that
58 * contain SetVariable() and QueryVariableInfo(). That leaves little else, as
59 * none of the remaining functions are actually ever called at runtime.
60 * So let's just use a single spinlock to serialize all Runtime Services calls.
62 static DEFINE_SPINLOCK(efi_runtime_lock
);
64 static efi_status_t
virt_efi_get_time(efi_time_t
*tm
, efi_time_cap_t
*tc
)
68 spin_lock(&efi_runtime_lock
);
69 status
= efi_call_virt(get_time
, tm
, tc
);
70 spin_unlock(&efi_runtime_lock
);
74 static efi_status_t
virt_efi_set_time(efi_time_t
*tm
)
78 spin_lock(&efi_runtime_lock
);
79 status
= efi_call_virt(set_time
, tm
);
80 spin_unlock(&efi_runtime_lock
);
84 static efi_status_t
virt_efi_get_wakeup_time(efi_bool_t
*enabled
,
90 spin_lock(&efi_runtime_lock
);
91 status
= efi_call_virt(get_wakeup_time
, enabled
, pending
, tm
);
92 spin_unlock(&efi_runtime_lock
);
96 static efi_status_t
virt_efi_set_wakeup_time(efi_bool_t enabled
, efi_time_t
*tm
)
100 spin_lock(&efi_runtime_lock
);
101 status
= efi_call_virt(set_wakeup_time
, enabled
, tm
);
102 spin_unlock(&efi_runtime_lock
);
106 static efi_status_t
virt_efi_get_variable(efi_char16_t
*name
,
109 unsigned long *data_size
,
114 spin_lock(&efi_runtime_lock
);
115 status
= efi_call_virt(get_variable
, name
, vendor
, attr
, data_size
,
117 spin_unlock(&efi_runtime_lock
);
121 static efi_status_t
virt_efi_get_next_variable(unsigned long *name_size
,
127 spin_lock(&efi_runtime_lock
);
128 status
= efi_call_virt(get_next_variable
, name_size
, name
, vendor
);
129 spin_unlock(&efi_runtime_lock
);
133 static efi_status_t
virt_efi_set_variable(efi_char16_t
*name
,
136 unsigned long data_size
,
141 spin_lock(&efi_runtime_lock
);
142 status
= efi_call_virt(set_variable
, name
, vendor
, attr
, data_size
,
144 spin_unlock(&efi_runtime_lock
);
149 virt_efi_set_variable_nonblocking(efi_char16_t
*name
, efi_guid_t
*vendor
,
150 u32 attr
, unsigned long data_size
,
155 if (!spin_trylock(&efi_runtime_lock
))
156 return EFI_NOT_READY
;
158 status
= efi_call_virt(set_variable
, name
, vendor
, attr
, data_size
,
160 spin_unlock(&efi_runtime_lock
);
165 static efi_status_t
virt_efi_query_variable_info(u32 attr
,
167 u64
*remaining_space
,
168 u64
*max_variable_size
)
172 if (efi
.runtime_version
< EFI_2_00_SYSTEM_TABLE_REVISION
)
173 return EFI_UNSUPPORTED
;
175 spin_lock(&efi_runtime_lock
);
176 status
= efi_call_virt(query_variable_info
, attr
, storage_space
,
177 remaining_space
, max_variable_size
);
178 spin_unlock(&efi_runtime_lock
);
183 virt_efi_query_variable_info_nonblocking(u32 attr
,
185 u64
*remaining_space
,
186 u64
*max_variable_size
)
190 if (efi
.runtime_version
< EFI_2_00_SYSTEM_TABLE_REVISION
)
191 return EFI_UNSUPPORTED
;
193 if (!spin_trylock(&efi_runtime_lock
))
194 return EFI_NOT_READY
;
196 status
= efi_call_virt(query_variable_info
, attr
, storage_space
,
197 remaining_space
, max_variable_size
);
198 spin_unlock(&efi_runtime_lock
);
202 static efi_status_t
virt_efi_get_next_high_mono_count(u32
*count
)
206 spin_lock(&efi_runtime_lock
);
207 status
= efi_call_virt(get_next_high_mono_count
, count
);
208 spin_unlock(&efi_runtime_lock
);
212 static void virt_efi_reset_system(int reset_type
,
214 unsigned long data_size
,
217 spin_lock(&efi_runtime_lock
);
218 __efi_call_virt(reset_system
, reset_type
, status
, data_size
, data
);
219 spin_unlock(&efi_runtime_lock
);
222 static efi_status_t
virt_efi_update_capsule(efi_capsule_header_t
**capsules
,
224 unsigned long sg_list
)
228 if (efi
.runtime_version
< EFI_2_00_SYSTEM_TABLE_REVISION
)
229 return EFI_UNSUPPORTED
;
231 spin_lock(&efi_runtime_lock
);
232 status
= efi_call_virt(update_capsule
, capsules
, count
, sg_list
);
233 spin_unlock(&efi_runtime_lock
);
237 static efi_status_t
virt_efi_query_capsule_caps(efi_capsule_header_t
**capsules
,
244 if (efi
.runtime_version
< EFI_2_00_SYSTEM_TABLE_REVISION
)
245 return EFI_UNSUPPORTED
;
247 spin_lock(&efi_runtime_lock
);
248 status
= efi_call_virt(query_capsule_caps
, capsules
, count
, max_size
,
250 spin_unlock(&efi_runtime_lock
);
254 void efi_native_runtime_setup(void)
256 efi
.get_time
= virt_efi_get_time
;
257 efi
.set_time
= virt_efi_set_time
;
258 efi
.get_wakeup_time
= virt_efi_get_wakeup_time
;
259 efi
.set_wakeup_time
= virt_efi_set_wakeup_time
;
260 efi
.get_variable
= virt_efi_get_variable
;
261 efi
.get_next_variable
= virt_efi_get_next_variable
;
262 efi
.set_variable
= virt_efi_set_variable
;
263 efi
.set_variable_nonblocking
= virt_efi_set_variable_nonblocking
;
264 efi
.get_next_high_mono_count
= virt_efi_get_next_high_mono_count
;
265 efi
.reset_system
= virt_efi_reset_system
;
266 efi
.query_variable_info
= virt_efi_query_variable_info
;
267 efi
.query_variable_info_nonblocking
= virt_efi_query_variable_info_nonblocking
;
268 efi
.update_capsule
= virt_efi_update_capsule
;
269 efi
.query_capsule_caps
= virt_efi_query_capsule_caps
;