14
14
* This file is released under the GPLv2.
15
15
*/
16
16
17
+ #define pr_fmt (fmt ) "efi: " fmt
18
+
17
19
#include <linux/bug.h>
18
20
#include <linux/efi.h>
19
21
#include <linux/irqflags.h>
20
22
#include <linux/mutex.h>
21
- #include <linux/spinlock .h>
23
+ #include <linux/semaphore .h>
22
24
#include <linux/stringify.h>
23
25
#include <asm/efi.h>
24
26
@@ -81,30 +83,32 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
81
83
* +------------------------------------+-------------------------------+
82
84
*
83
85
* Due to the fact that the EFI pstore may write to the variable store in
84
- * interrupt context, we need to use a spinlock for at least the groups that
86
+ * interrupt context, we need to use a lock for at least the groups that
85
87
* contain SetVariable() and QueryVariableInfo(). That leaves little else, as
86
88
* none of the remaining functions are actually ever called at runtime.
87
- * So let's just use a single spinlock to serialize all Runtime Services calls.
89
+ * So let's just use a single lock to serialize all Runtime Services calls.
88
90
*/
89
- static DEFINE_SPINLOCK (efi_runtime_lock );
91
+ static DEFINE_SEMAPHORE (efi_runtime_lock );
90
92
91
93
static efi_status_t virt_efi_get_time (efi_time_t * tm , efi_time_cap_t * tc )
92
94
{
93
95
efi_status_t status ;
94
96
95
- spin_lock (& efi_runtime_lock );
97
+ if (down_interruptible (& efi_runtime_lock ))
98
+ return EFI_ABORTED ;
96
99
status = efi_call_virt (get_time , tm , tc );
97
- spin_unlock (& efi_runtime_lock );
100
+ up (& efi_runtime_lock );
98
101
return status ;
99
102
}
100
103
101
104
static efi_status_t virt_efi_set_time (efi_time_t * tm )
102
105
{
103
106
efi_status_t status ;
104
107
105
- spin_lock (& efi_runtime_lock );
108
+ if (down_interruptible (& efi_runtime_lock ))
109
+ return EFI_ABORTED ;
106
110
status = efi_call_virt (set_time , tm );
107
- spin_unlock (& efi_runtime_lock );
111
+ up (& efi_runtime_lock );
108
112
return status ;
109
113
}
110
114
@@ -114,19 +118,21 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
114
118
{
115
119
efi_status_t status ;
116
120
117
- spin_lock (& efi_runtime_lock );
121
+ if (down_interruptible (& efi_runtime_lock ))
122
+ return EFI_ABORTED ;
118
123
status = efi_call_virt (get_wakeup_time , enabled , pending , tm );
119
- spin_unlock (& efi_runtime_lock );
124
+ up (& efi_runtime_lock );
120
125
return status ;
121
126
}
122
127
123
128
static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled , efi_time_t * tm )
124
129
{
125
130
efi_status_t status ;
126
131
127
- spin_lock (& efi_runtime_lock );
132
+ if (down_interruptible (& efi_runtime_lock ))
133
+ return EFI_ABORTED ;
128
134
status = efi_call_virt (set_wakeup_time , enabled , tm );
129
- spin_unlock (& efi_runtime_lock );
135
+ up (& efi_runtime_lock );
130
136
return status ;
131
137
}
132
138
@@ -138,10 +144,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
138
144
{
139
145
efi_status_t status ;
140
146
141
- spin_lock (& efi_runtime_lock );
147
+ if (down_interruptible (& efi_runtime_lock ))
148
+ return EFI_ABORTED ;
142
149
status = efi_call_virt (get_variable , name , vendor , attr , data_size ,
143
150
data );
144
- spin_unlock (& efi_runtime_lock );
151
+ up (& efi_runtime_lock );
145
152
return status ;
146
153
}
147
154
@@ -151,9 +158,10 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
151
158
{
152
159
efi_status_t status ;
153
160
154
- spin_lock (& efi_runtime_lock );
161
+ if (down_interruptible (& efi_runtime_lock ))
162
+ return EFI_ABORTED ;
155
163
status = efi_call_virt (get_next_variable , name_size , name , vendor );
156
- spin_unlock (& efi_runtime_lock );
164
+ up (& efi_runtime_lock );
157
165
return status ;
158
166
}
159
167
@@ -165,10 +173,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
165
173
{
166
174
efi_status_t status ;
167
175
168
- spin_lock (& efi_runtime_lock );
176
+ if (down_interruptible (& efi_runtime_lock ))
177
+ return EFI_ABORTED ;
169
178
status = efi_call_virt (set_variable , name , vendor , attr , data_size ,
170
179
data );
171
- spin_unlock (& efi_runtime_lock );
180
+ up (& efi_runtime_lock );
172
181
return status ;
173
182
}
174
183
@@ -179,12 +188,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
179
188
{
180
189
efi_status_t status ;
181
190
182
- if (! spin_trylock (& efi_runtime_lock ))
191
+ if (down_trylock (& efi_runtime_lock ))
183
192
return EFI_NOT_READY ;
184
193
185
194
status = efi_call_virt (set_variable , name , vendor , attr , data_size ,
186
195
data );
187
- spin_unlock (& efi_runtime_lock );
196
+ up (& efi_runtime_lock );
188
197
return status ;
189
198
}
190
199
@@ -199,10 +208,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
199
208
if (efi .runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION )
200
209
return EFI_UNSUPPORTED ;
201
210
202
- spin_lock (& efi_runtime_lock );
211
+ if (down_interruptible (& efi_runtime_lock ))
212
+ return EFI_ABORTED ;
203
213
status = efi_call_virt (query_variable_info , attr , storage_space ,
204
214
remaining_space , max_variable_size );
205
- spin_unlock (& efi_runtime_lock );
215
+ up (& efi_runtime_lock );
206
216
return status ;
207
217
}
208
218
@@ -217,22 +227,23 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
217
227
if (efi .runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION )
218
228
return EFI_UNSUPPORTED ;
219
229
220
- if (! spin_trylock (& efi_runtime_lock ))
230
+ if (down_trylock (& efi_runtime_lock ))
221
231
return EFI_NOT_READY ;
222
232
223
233
status = efi_call_virt (query_variable_info , attr , storage_space ,
224
234
remaining_space , max_variable_size );
225
- spin_unlock (& efi_runtime_lock );
235
+ up (& efi_runtime_lock );
226
236
return status ;
227
237
}
228
238
229
239
static efi_status_t virt_efi_get_next_high_mono_count (u32 * count )
230
240
{
231
241
efi_status_t status ;
232
242
233
- spin_lock (& efi_runtime_lock );
243
+ if (down_interruptible (& efi_runtime_lock ))
244
+ return EFI_ABORTED ;
234
245
status = efi_call_virt (get_next_high_mono_count , count );
235
- spin_unlock (& efi_runtime_lock );
246
+ up (& efi_runtime_lock );
236
247
return status ;
237
248
}
238
249
@@ -241,9 +252,13 @@ static void virt_efi_reset_system(int reset_type,
241
252
unsigned long data_size ,
242
253
efi_char16_t * data )
243
254
{
244
- spin_lock (& efi_runtime_lock );
255
+ if (down_interruptible (& efi_runtime_lock )) {
256
+ pr_warn ("failed to invoke the reset_system() runtime service:\n"
257
+ "could not get exclusive access to the firmware\n" );
258
+ return ;
259
+ }
245
260
__efi_call_virt (reset_system , reset_type , status , data_size , data );
246
- spin_unlock (& efi_runtime_lock );
261
+ up (& efi_runtime_lock );
247
262
}
248
263
249
264
static efi_status_t virt_efi_update_capsule (efi_capsule_header_t * * capsules ,
@@ -255,9 +270,10 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
255
270
if (efi .runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION )
256
271
return EFI_UNSUPPORTED ;
257
272
258
- spin_lock (& efi_runtime_lock );
273
+ if (down_interruptible (& efi_runtime_lock ))
274
+ return EFI_ABORTED ;
259
275
status = efi_call_virt (update_capsule , capsules , count , sg_list );
260
- spin_unlock (& efi_runtime_lock );
276
+ up (& efi_runtime_lock );
261
277
return status ;
262
278
}
263
279
@@ -271,10 +287,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
271
287
if (efi .runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION )
272
288
return EFI_UNSUPPORTED ;
273
289
274
- spin_lock (& efi_runtime_lock );
290
+ if (down_interruptible (& efi_runtime_lock ))
291
+ return EFI_ABORTED ;
275
292
status = efi_call_virt (query_capsule_caps , capsules , count , max_size ,
276
293
reset_type );
277
- spin_unlock (& efi_runtime_lock );
294
+ up (& efi_runtime_lock );
278
295
return status ;
279
296
}
280
297
0 commit comments