1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Originally from efivars.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
6*4882a593Smuzhiyun * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/capability.h>
10*4882a593Smuzhiyun #include <linux/types.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/mm.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/string.h>
16*4882a593Smuzhiyun #include <linux/smp.h>
17*4882a593Smuzhiyun #include <linux/efi.h>
18*4882a593Smuzhiyun #include <linux/sysfs.h>
19*4882a593Smuzhiyun #include <linux/device.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/ctype.h>
22*4882a593Smuzhiyun #include <linux/ucs2_string.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /* Private pointer to registered efivars */
25*4882a593Smuzhiyun static struct efivars *__efivars;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun * efivars_lock protects three things:
29*4882a593Smuzhiyun * 1) efivarfs_list and efivars_sysfs_list
30*4882a593Smuzhiyun * 2) ->ops calls
31*4882a593Smuzhiyun * 3) (un)registration of __efivars
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun static DEFINE_SEMAPHORE(efivars_lock);
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static bool
validate_device_path(efi_char16_t * var_name,int match,u8 * buffer,unsigned long len)36*4882a593Smuzhiyun validate_device_path(efi_char16_t *var_name, int match, u8 *buffer,
37*4882a593Smuzhiyun unsigned long len)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun struct efi_generic_dev_path *node;
40*4882a593Smuzhiyun int offset = 0;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun node = (struct efi_generic_dev_path *)buffer;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun if (len < sizeof(*node))
45*4882a593Smuzhiyun return false;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun while (offset <= len - sizeof(*node) &&
48*4882a593Smuzhiyun node->length >= sizeof(*node) &&
49*4882a593Smuzhiyun node->length <= len - offset) {
50*4882a593Smuzhiyun offset += node->length;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if ((node->type == EFI_DEV_END_PATH ||
53*4882a593Smuzhiyun node->type == EFI_DEV_END_PATH2) &&
54*4882a593Smuzhiyun node->sub_type == EFI_DEV_END_ENTIRE)
55*4882a593Smuzhiyun return true;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun node = (struct efi_generic_dev_path *)(buffer + offset);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun * If we're here then either node->length pointed past the end
62*4882a593Smuzhiyun * of the buffer or we reached the end of the buffer without
63*4882a593Smuzhiyun * finding a device path end node.
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun return false;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun static bool
validate_boot_order(efi_char16_t * var_name,int match,u8 * buffer,unsigned long len)69*4882a593Smuzhiyun validate_boot_order(efi_char16_t *var_name, int match, u8 *buffer,
70*4882a593Smuzhiyun unsigned long len)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun /* An array of 16-bit integers */
73*4882a593Smuzhiyun if ((len % 2) != 0)
74*4882a593Smuzhiyun return false;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return true;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun static bool
validate_load_option(efi_char16_t * var_name,int match,u8 * buffer,unsigned long len)80*4882a593Smuzhiyun validate_load_option(efi_char16_t *var_name, int match, u8 *buffer,
81*4882a593Smuzhiyun unsigned long len)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun u16 filepathlength;
84*4882a593Smuzhiyun int i, desclength = 0, namelen;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun namelen = ucs2_strnlen(var_name, EFI_VAR_NAME_LEN);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /* Either "Boot" or "Driver" followed by four digits of hex */
89*4882a593Smuzhiyun for (i = match; i < match+4; i++) {
90*4882a593Smuzhiyun if (var_name[i] > 127 ||
91*4882a593Smuzhiyun hex_to_bin(var_name[i] & 0xff) < 0)
92*4882a593Smuzhiyun return true;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* Reject it if there's 4 digits of hex and then further content */
96*4882a593Smuzhiyun if (namelen > match + 4)
97*4882a593Smuzhiyun return false;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* A valid entry must be at least 8 bytes */
100*4882a593Smuzhiyun if (len < 8)
101*4882a593Smuzhiyun return false;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun filepathlength = buffer[4] | buffer[5] << 8;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /*
106*4882a593Smuzhiyun * There's no stored length for the description, so it has to be
107*4882a593Smuzhiyun * found by hand
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /* Each boot entry must have a descriptor */
112*4882a593Smuzhiyun if (!desclength)
113*4882a593Smuzhiyun return false;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /*
116*4882a593Smuzhiyun * If the sum of the length of the description, the claimed filepath
117*4882a593Smuzhiyun * length and the original header are greater than the length of the
118*4882a593Smuzhiyun * variable, it's malformed
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun if ((desclength + filepathlength + 6) > len)
121*4882a593Smuzhiyun return false;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun * And, finally, check the filepath
125*4882a593Smuzhiyun */
126*4882a593Smuzhiyun return validate_device_path(var_name, match, buffer + desclength + 6,
127*4882a593Smuzhiyun filepathlength);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun static bool
validate_uint16(efi_char16_t * var_name,int match,u8 * buffer,unsigned long len)131*4882a593Smuzhiyun validate_uint16(efi_char16_t *var_name, int match, u8 *buffer,
132*4882a593Smuzhiyun unsigned long len)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun /* A single 16-bit integer */
135*4882a593Smuzhiyun if (len != 2)
136*4882a593Smuzhiyun return false;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun return true;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun static bool
validate_ascii_string(efi_char16_t * var_name,int match,u8 * buffer,unsigned long len)142*4882a593Smuzhiyun validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
143*4882a593Smuzhiyun unsigned long len)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun int i;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun for (i = 0; i < len; i++) {
148*4882a593Smuzhiyun if (buffer[i] > 127)
149*4882a593Smuzhiyun return false;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (buffer[i] == 0)
152*4882a593Smuzhiyun return true;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return false;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun struct variable_validate {
159*4882a593Smuzhiyun efi_guid_t vendor;
160*4882a593Smuzhiyun char *name;
161*4882a593Smuzhiyun bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
162*4882a593Smuzhiyun unsigned long len);
163*4882a593Smuzhiyun };
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /*
166*4882a593Smuzhiyun * This is the list of variables we need to validate, as well as the
167*4882a593Smuzhiyun * whitelist for what we think is safe not to default to immutable.
168*4882a593Smuzhiyun *
169*4882a593Smuzhiyun * If it has a validate() method that's not NULL, it'll go into the
170*4882a593Smuzhiyun * validation routine. If not, it is assumed valid, but still used for
171*4882a593Smuzhiyun * whitelisting.
172*4882a593Smuzhiyun *
173*4882a593Smuzhiyun * Note that it's sorted by {vendor,name}, but globbed names must come after
174*4882a593Smuzhiyun * any other name with the same prefix.
175*4882a593Smuzhiyun */
176*4882a593Smuzhiyun static const struct variable_validate variable_validate[] = {
177*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
178*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
179*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
180*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
181*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
182*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
183*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
184*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
185*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
186*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
187*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
188*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
189*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
190*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
191*4882a593Smuzhiyun { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
192*4882a593Smuzhiyun { LINUX_EFI_CRASH_GUID, "*", NULL },
193*4882a593Smuzhiyun { NULL_GUID, "", NULL },
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /*
197*4882a593Smuzhiyun * Check if @var_name matches the pattern given in @match_name.
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * @var_name: an array of @len non-NUL characters.
200*4882a593Smuzhiyun * @match_name: a NUL-terminated pattern string, optionally ending in "*". A
201*4882a593Smuzhiyun * final "*" character matches any trailing characters @var_name,
202*4882a593Smuzhiyun * including the case when there are none left in @var_name.
203*4882a593Smuzhiyun * @match: on output, the number of non-wildcard characters in @match_name
204*4882a593Smuzhiyun * that @var_name matches, regardless of the return value.
205*4882a593Smuzhiyun * @return: whether @var_name fully matches @match_name.
206*4882a593Smuzhiyun */
207*4882a593Smuzhiyun static bool
variable_matches(const char * var_name,size_t len,const char * match_name,int * match)208*4882a593Smuzhiyun variable_matches(const char *var_name, size_t len, const char *match_name,
209*4882a593Smuzhiyun int *match)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun for (*match = 0; ; (*match)++) {
212*4882a593Smuzhiyun char c = match_name[*match];
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun switch (c) {
215*4882a593Smuzhiyun case '*':
216*4882a593Smuzhiyun /* Wildcard in @match_name means we've matched. */
217*4882a593Smuzhiyun return true;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun case '\0':
220*4882a593Smuzhiyun /* @match_name has ended. Has @var_name too? */
221*4882a593Smuzhiyun return (*match == len);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun default:
224*4882a593Smuzhiyun /*
225*4882a593Smuzhiyun * We've reached a non-wildcard char in @match_name.
226*4882a593Smuzhiyun * Continue only if there's an identical character in
227*4882a593Smuzhiyun * @var_name.
228*4882a593Smuzhiyun */
229*4882a593Smuzhiyun if (*match < len && c == var_name[*match])
230*4882a593Smuzhiyun continue;
231*4882a593Smuzhiyun return false;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun bool
efivar_validate(efi_guid_t vendor,efi_char16_t * var_name,u8 * data,unsigned long data_size)237*4882a593Smuzhiyun efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
238*4882a593Smuzhiyun unsigned long data_size)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun int i;
241*4882a593Smuzhiyun unsigned long utf8_size;
242*4882a593Smuzhiyun u8 *utf8_name;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun utf8_size = ucs2_utf8size(var_name);
245*4882a593Smuzhiyun utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
246*4882a593Smuzhiyun if (!utf8_name)
247*4882a593Smuzhiyun return false;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun ucs2_as_utf8(utf8_name, var_name, utf8_size);
250*4882a593Smuzhiyun utf8_name[utf8_size] = '\0';
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
253*4882a593Smuzhiyun const char *name = variable_validate[i].name;
254*4882a593Smuzhiyun int match = 0;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (efi_guidcmp(vendor, variable_validate[i].vendor))
257*4882a593Smuzhiyun continue;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
260*4882a593Smuzhiyun if (variable_validate[i].validate == NULL)
261*4882a593Smuzhiyun break;
262*4882a593Smuzhiyun kfree(utf8_name);
263*4882a593Smuzhiyun return variable_validate[i].validate(var_name, match,
264*4882a593Smuzhiyun data, data_size);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun kfree(utf8_name);
268*4882a593Smuzhiyun return true;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_validate);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun bool
efivar_variable_is_removable(efi_guid_t vendor,const char * var_name,size_t len)273*4882a593Smuzhiyun efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
274*4882a593Smuzhiyun size_t len)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun int i;
277*4882a593Smuzhiyun bool found = false;
278*4882a593Smuzhiyun int match = 0;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /*
281*4882a593Smuzhiyun * Check if our variable is in the validated variables list
282*4882a593Smuzhiyun */
283*4882a593Smuzhiyun for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
284*4882a593Smuzhiyun if (efi_guidcmp(variable_validate[i].vendor, vendor))
285*4882a593Smuzhiyun continue;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun if (variable_matches(var_name, len,
288*4882a593Smuzhiyun variable_validate[i].name, &match)) {
289*4882a593Smuzhiyun found = true;
290*4882a593Smuzhiyun break;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /*
295*4882a593Smuzhiyun * If it's in our list, it is removable.
296*4882a593Smuzhiyun */
297*4882a593Smuzhiyun return found;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun static efi_status_t
check_var_size(u32 attributes,unsigned long size)302*4882a593Smuzhiyun check_var_size(u32 attributes, unsigned long size)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun const struct efivar_operations *fops;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun if (!__efivars)
307*4882a593Smuzhiyun return EFI_UNSUPPORTED;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun fops = __efivars->ops;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun if (!fops->query_variable_store)
312*4882a593Smuzhiyun return EFI_UNSUPPORTED;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun return fops->query_variable_store(attributes, size, false);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static efi_status_t
check_var_size_nonblocking(u32 attributes,unsigned long size)318*4882a593Smuzhiyun check_var_size_nonblocking(u32 attributes, unsigned long size)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun const struct efivar_operations *fops;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun if (!__efivars)
323*4882a593Smuzhiyun return EFI_UNSUPPORTED;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun fops = __efivars->ops;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun if (!fops->query_variable_store)
328*4882a593Smuzhiyun return EFI_UNSUPPORTED;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun return fops->query_variable_store(attributes, size, true);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
variable_is_present(efi_char16_t * variable_name,efi_guid_t * vendor,struct list_head * head)333*4882a593Smuzhiyun static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
334*4882a593Smuzhiyun struct list_head *head)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun struct efivar_entry *entry, *n;
337*4882a593Smuzhiyun unsigned long strsize1, strsize2;
338*4882a593Smuzhiyun bool found = false;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun strsize1 = ucs2_strsize(variable_name, 1024);
341*4882a593Smuzhiyun list_for_each_entry_safe(entry, n, head, list) {
342*4882a593Smuzhiyun strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
343*4882a593Smuzhiyun if (strsize1 == strsize2 &&
344*4882a593Smuzhiyun !memcmp(variable_name, &(entry->var.VariableName),
345*4882a593Smuzhiyun strsize2) &&
346*4882a593Smuzhiyun !efi_guidcmp(entry->var.VendorGuid,
347*4882a593Smuzhiyun *vendor)) {
348*4882a593Smuzhiyun found = true;
349*4882a593Smuzhiyun break;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun return found;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /*
356*4882a593Smuzhiyun * Returns the size of variable_name, in bytes, including the
357*4882a593Smuzhiyun * terminating NULL character, or variable_name_size if no NULL
358*4882a593Smuzhiyun * character is found among the first variable_name_size bytes.
359*4882a593Smuzhiyun */
var_name_strnsize(efi_char16_t * variable_name,unsigned long variable_name_size)360*4882a593Smuzhiyun static unsigned long var_name_strnsize(efi_char16_t *variable_name,
361*4882a593Smuzhiyun unsigned long variable_name_size)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun unsigned long len;
364*4882a593Smuzhiyun efi_char16_t c;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /*
367*4882a593Smuzhiyun * The variable name is, by definition, a NULL-terminated
368*4882a593Smuzhiyun * string, so make absolutely sure that variable_name_size is
369*4882a593Smuzhiyun * the value we expect it to be. If not, return the real size.
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun for (len = 2; len <= variable_name_size; len += sizeof(c)) {
372*4882a593Smuzhiyun c = variable_name[(len / sizeof(c)) - 1];
373*4882a593Smuzhiyun if (!c)
374*4882a593Smuzhiyun break;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return min(len, variable_name_size);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /*
381*4882a593Smuzhiyun * Print a warning when duplicate EFI variables are encountered and
382*4882a593Smuzhiyun * disable the sysfs workqueue since the firmware is buggy.
383*4882a593Smuzhiyun */
dup_variable_bug(efi_char16_t * str16,efi_guid_t * vendor_guid,unsigned long len16)384*4882a593Smuzhiyun static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
385*4882a593Smuzhiyun unsigned long len16)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun size_t i, len8 = len16 / sizeof(efi_char16_t);
388*4882a593Smuzhiyun char *str8;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun str8 = kzalloc(len8, GFP_KERNEL);
391*4882a593Smuzhiyun if (!str8)
392*4882a593Smuzhiyun return;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun for (i = 0; i < len8; i++)
395*4882a593Smuzhiyun str8[i] = str16[i];
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
398*4882a593Smuzhiyun str8, vendor_guid);
399*4882a593Smuzhiyun kfree(str8);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun /**
403*4882a593Smuzhiyun * efivar_init - build the initial list of EFI variables
404*4882a593Smuzhiyun * @func: callback function to invoke for every variable
405*4882a593Smuzhiyun * @data: function-specific data to pass to @func
406*4882a593Smuzhiyun * @duplicates: error if we encounter duplicates on @head?
407*4882a593Smuzhiyun * @head: initialised head of variable list
408*4882a593Smuzhiyun *
409*4882a593Smuzhiyun * Get every EFI variable from the firmware and invoke @func. @func
410*4882a593Smuzhiyun * should call efivar_entry_add() to build the list of variables.
411*4882a593Smuzhiyun *
412*4882a593Smuzhiyun * Returns 0 on success, or a kernel error code on failure.
413*4882a593Smuzhiyun */
efivar_init(int (* func)(efi_char16_t *,efi_guid_t,unsigned long,void *),void * data,bool duplicates,struct list_head * head)414*4882a593Smuzhiyun int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
415*4882a593Smuzhiyun void *data, bool duplicates, struct list_head *head)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun const struct efivar_operations *ops;
418*4882a593Smuzhiyun unsigned long variable_name_size = 1024;
419*4882a593Smuzhiyun efi_char16_t *variable_name;
420*4882a593Smuzhiyun efi_status_t status;
421*4882a593Smuzhiyun efi_guid_t vendor_guid;
422*4882a593Smuzhiyun int err = 0;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun if (!__efivars)
425*4882a593Smuzhiyun return -EFAULT;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun ops = __efivars->ops;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun variable_name = kzalloc(variable_name_size, GFP_KERNEL);
430*4882a593Smuzhiyun if (!variable_name) {
431*4882a593Smuzhiyun printk(KERN_ERR "efivars: Memory allocation failed.\n");
432*4882a593Smuzhiyun return -ENOMEM;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (down_interruptible(&efivars_lock)) {
436*4882a593Smuzhiyun err = -EINTR;
437*4882a593Smuzhiyun goto free;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /*
441*4882a593Smuzhiyun * Per EFI spec, the maximum storage allocated for both
442*4882a593Smuzhiyun * the variable name and variable data is 1024 bytes.
443*4882a593Smuzhiyun */
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun do {
446*4882a593Smuzhiyun variable_name_size = 1024;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun status = ops->get_next_variable(&variable_name_size,
449*4882a593Smuzhiyun variable_name,
450*4882a593Smuzhiyun &vendor_guid);
451*4882a593Smuzhiyun switch (status) {
452*4882a593Smuzhiyun case EFI_SUCCESS:
453*4882a593Smuzhiyun if (duplicates)
454*4882a593Smuzhiyun up(&efivars_lock);
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun variable_name_size = var_name_strnsize(variable_name,
457*4882a593Smuzhiyun variable_name_size);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /*
460*4882a593Smuzhiyun * Some firmware implementations return the
461*4882a593Smuzhiyun * same variable name on multiple calls to
462*4882a593Smuzhiyun * get_next_variable(). Terminate the loop
463*4882a593Smuzhiyun * immediately as there is no guarantee that
464*4882a593Smuzhiyun * we'll ever see a different variable name,
465*4882a593Smuzhiyun * and may end up looping here forever.
466*4882a593Smuzhiyun */
467*4882a593Smuzhiyun if (duplicates &&
468*4882a593Smuzhiyun variable_is_present(variable_name, &vendor_guid,
469*4882a593Smuzhiyun head)) {
470*4882a593Smuzhiyun dup_variable_bug(variable_name, &vendor_guid,
471*4882a593Smuzhiyun variable_name_size);
472*4882a593Smuzhiyun status = EFI_NOT_FOUND;
473*4882a593Smuzhiyun } else {
474*4882a593Smuzhiyun err = func(variable_name, vendor_guid,
475*4882a593Smuzhiyun variable_name_size, data);
476*4882a593Smuzhiyun if (err)
477*4882a593Smuzhiyun status = EFI_NOT_FOUND;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun if (duplicates) {
481*4882a593Smuzhiyun if (down_interruptible(&efivars_lock)) {
482*4882a593Smuzhiyun err = -EINTR;
483*4882a593Smuzhiyun goto free;
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun break;
488*4882a593Smuzhiyun case EFI_UNSUPPORTED:
489*4882a593Smuzhiyun err = -EOPNOTSUPP;
490*4882a593Smuzhiyun status = EFI_NOT_FOUND;
491*4882a593Smuzhiyun break;
492*4882a593Smuzhiyun case EFI_NOT_FOUND:
493*4882a593Smuzhiyun break;
494*4882a593Smuzhiyun default:
495*4882a593Smuzhiyun printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
496*4882a593Smuzhiyun status);
497*4882a593Smuzhiyun status = EFI_NOT_FOUND;
498*4882a593Smuzhiyun break;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun } while (status != EFI_NOT_FOUND);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun up(&efivars_lock);
504*4882a593Smuzhiyun free:
505*4882a593Smuzhiyun kfree(variable_name);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun return err;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_init);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /**
512*4882a593Smuzhiyun * efivar_entry_add - add entry to variable list
513*4882a593Smuzhiyun * @entry: entry to add to list
514*4882a593Smuzhiyun * @head: list head
515*4882a593Smuzhiyun *
516*4882a593Smuzhiyun * Returns 0 on success, or a kernel error code on failure.
517*4882a593Smuzhiyun */
efivar_entry_add(struct efivar_entry * entry,struct list_head * head)518*4882a593Smuzhiyun int efivar_entry_add(struct efivar_entry *entry, struct list_head *head)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
521*4882a593Smuzhiyun return -EINTR;
522*4882a593Smuzhiyun list_add(&entry->list, head);
523*4882a593Smuzhiyun up(&efivars_lock);
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_add);
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /**
530*4882a593Smuzhiyun * efivar_entry_remove - remove entry from variable list
531*4882a593Smuzhiyun * @entry: entry to remove from list
532*4882a593Smuzhiyun *
533*4882a593Smuzhiyun * Returns 0 on success, or a kernel error code on failure.
534*4882a593Smuzhiyun */
efivar_entry_remove(struct efivar_entry * entry)535*4882a593Smuzhiyun int efivar_entry_remove(struct efivar_entry *entry)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
538*4882a593Smuzhiyun return -EINTR;
539*4882a593Smuzhiyun list_del(&entry->list);
540*4882a593Smuzhiyun up(&efivars_lock);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun return 0;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_remove);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun /*
547*4882a593Smuzhiyun * efivar_entry_list_del_unlock - remove entry from variable list
548*4882a593Smuzhiyun * @entry: entry to remove
549*4882a593Smuzhiyun *
550*4882a593Smuzhiyun * Remove @entry from the variable list and release the list lock.
551*4882a593Smuzhiyun *
552*4882a593Smuzhiyun * NOTE: slightly weird locking semantics here - we expect to be
553*4882a593Smuzhiyun * called with the efivars lock already held, and we release it before
554*4882a593Smuzhiyun * returning. This is because this function is usually called after
555*4882a593Smuzhiyun * set_variable() while the lock is still held.
556*4882a593Smuzhiyun */
efivar_entry_list_del_unlock(struct efivar_entry * entry)557*4882a593Smuzhiyun static void efivar_entry_list_del_unlock(struct efivar_entry *entry)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun list_del(&entry->list);
560*4882a593Smuzhiyun up(&efivars_lock);
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun /**
564*4882a593Smuzhiyun * __efivar_entry_delete - delete an EFI variable
565*4882a593Smuzhiyun * @entry: entry containing EFI variable to delete
566*4882a593Smuzhiyun *
567*4882a593Smuzhiyun * Delete the variable from the firmware but leave @entry on the
568*4882a593Smuzhiyun * variable list.
569*4882a593Smuzhiyun *
570*4882a593Smuzhiyun * This function differs from efivar_entry_delete() because it does
571*4882a593Smuzhiyun * not remove @entry from the variable list. Also, it is safe to be
572*4882a593Smuzhiyun * called from within a efivar_entry_iter_begin() and
573*4882a593Smuzhiyun * efivar_entry_iter_end() region, unlike efivar_entry_delete().
574*4882a593Smuzhiyun *
575*4882a593Smuzhiyun * Returns 0 on success, or a converted EFI status code if
576*4882a593Smuzhiyun * set_variable() fails.
577*4882a593Smuzhiyun */
__efivar_entry_delete(struct efivar_entry * entry)578*4882a593Smuzhiyun int __efivar_entry_delete(struct efivar_entry *entry)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun efi_status_t status;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun if (!__efivars)
583*4882a593Smuzhiyun return -EINVAL;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun status = __efivars->ops->set_variable(entry->var.VariableName,
586*4882a593Smuzhiyun &entry->var.VendorGuid,
587*4882a593Smuzhiyun 0, 0, NULL);
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun return efi_status_to_err(status);
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__efivar_entry_delete);
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun /**
594*4882a593Smuzhiyun * efivar_entry_delete - delete variable and remove entry from list
595*4882a593Smuzhiyun * @entry: entry containing variable to delete
596*4882a593Smuzhiyun *
597*4882a593Smuzhiyun * Delete the variable from the firmware and remove @entry from the
598*4882a593Smuzhiyun * variable list. It is the caller's responsibility to free @entry
599*4882a593Smuzhiyun * once we return.
600*4882a593Smuzhiyun *
601*4882a593Smuzhiyun * Returns 0 on success, -EINTR if we can't grab the semaphore,
602*4882a593Smuzhiyun * converted EFI status code if set_variable() fails.
603*4882a593Smuzhiyun */
efivar_entry_delete(struct efivar_entry * entry)604*4882a593Smuzhiyun int efivar_entry_delete(struct efivar_entry *entry)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun const struct efivar_operations *ops;
607*4882a593Smuzhiyun efi_status_t status;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
610*4882a593Smuzhiyun return -EINTR;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun if (!__efivars) {
613*4882a593Smuzhiyun up(&efivars_lock);
614*4882a593Smuzhiyun return -EINVAL;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun ops = __efivars->ops;
617*4882a593Smuzhiyun status = ops->set_variable(entry->var.VariableName,
618*4882a593Smuzhiyun &entry->var.VendorGuid,
619*4882a593Smuzhiyun 0, 0, NULL);
620*4882a593Smuzhiyun if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND)) {
621*4882a593Smuzhiyun up(&efivars_lock);
622*4882a593Smuzhiyun return efi_status_to_err(status);
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun efivar_entry_list_del_unlock(entry);
626*4882a593Smuzhiyun return 0;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_delete);
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun /**
631*4882a593Smuzhiyun * efivar_entry_set - call set_variable()
632*4882a593Smuzhiyun * @entry: entry containing the EFI variable to write
633*4882a593Smuzhiyun * @attributes: variable attributes
634*4882a593Smuzhiyun * @size: size of @data buffer
635*4882a593Smuzhiyun * @data: buffer containing variable data
636*4882a593Smuzhiyun * @head: head of variable list
637*4882a593Smuzhiyun *
638*4882a593Smuzhiyun * Calls set_variable() for an EFI variable. If creating a new EFI
639*4882a593Smuzhiyun * variable, this function is usually followed by efivar_entry_add().
640*4882a593Smuzhiyun *
641*4882a593Smuzhiyun * Before writing the variable, the remaining EFI variable storage
642*4882a593Smuzhiyun * space is checked to ensure there is enough room available.
643*4882a593Smuzhiyun *
644*4882a593Smuzhiyun * If @head is not NULL a lookup is performed to determine whether
645*4882a593Smuzhiyun * the entry is already on the list.
646*4882a593Smuzhiyun *
647*4882a593Smuzhiyun * Returns 0 on success, -EINTR if we can't grab the semaphore,
648*4882a593Smuzhiyun * -EEXIST if a lookup is performed and the entry already exists on
649*4882a593Smuzhiyun * the list, or a converted EFI status code if set_variable() fails.
650*4882a593Smuzhiyun */
efivar_entry_set(struct efivar_entry * entry,u32 attributes,unsigned long size,void * data,struct list_head * head)651*4882a593Smuzhiyun int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
652*4882a593Smuzhiyun unsigned long size, void *data, struct list_head *head)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun const struct efivar_operations *ops;
655*4882a593Smuzhiyun efi_status_t status;
656*4882a593Smuzhiyun efi_char16_t *name = entry->var.VariableName;
657*4882a593Smuzhiyun efi_guid_t vendor = entry->var.VendorGuid;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
660*4882a593Smuzhiyun return -EINTR;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun if (!__efivars) {
663*4882a593Smuzhiyun up(&efivars_lock);
664*4882a593Smuzhiyun return -EINVAL;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun ops = __efivars->ops;
667*4882a593Smuzhiyun if (head && efivar_entry_find(name, vendor, head, false)) {
668*4882a593Smuzhiyun up(&efivars_lock);
669*4882a593Smuzhiyun return -EEXIST;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
673*4882a593Smuzhiyun if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
674*4882a593Smuzhiyun status = ops->set_variable(name, &vendor,
675*4882a593Smuzhiyun attributes, size, data);
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun up(&efivars_lock);
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun return efi_status_to_err(status);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_set);
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun /*
685*4882a593Smuzhiyun * efivar_entry_set_nonblocking - call set_variable_nonblocking()
686*4882a593Smuzhiyun *
687*4882a593Smuzhiyun * This function is guaranteed to not block and is suitable for calling
688*4882a593Smuzhiyun * from crash/panic handlers.
689*4882a593Smuzhiyun *
690*4882a593Smuzhiyun * Crucially, this function will not block if it cannot acquire
691*4882a593Smuzhiyun * efivars_lock. Instead, it returns -EBUSY.
692*4882a593Smuzhiyun */
693*4882a593Smuzhiyun static int
efivar_entry_set_nonblocking(efi_char16_t * name,efi_guid_t vendor,u32 attributes,unsigned long size,void * data)694*4882a593Smuzhiyun efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
695*4882a593Smuzhiyun u32 attributes, unsigned long size, void *data)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun const struct efivar_operations *ops;
698*4882a593Smuzhiyun efi_status_t status;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (down_trylock(&efivars_lock))
701*4882a593Smuzhiyun return -EBUSY;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun if (!__efivars) {
704*4882a593Smuzhiyun up(&efivars_lock);
705*4882a593Smuzhiyun return -EINVAL;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun status = check_var_size_nonblocking(attributes,
709*4882a593Smuzhiyun size + ucs2_strsize(name, 1024));
710*4882a593Smuzhiyun if (status != EFI_SUCCESS) {
711*4882a593Smuzhiyun up(&efivars_lock);
712*4882a593Smuzhiyun return -ENOSPC;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun ops = __efivars->ops;
716*4882a593Smuzhiyun status = ops->set_variable_nonblocking(name, &vendor, attributes,
717*4882a593Smuzhiyun size, data);
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun up(&efivars_lock);
720*4882a593Smuzhiyun return efi_status_to_err(status);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun /**
724*4882a593Smuzhiyun * efivar_entry_set_safe - call set_variable() if enough space in firmware
725*4882a593Smuzhiyun * @name: buffer containing the variable name
726*4882a593Smuzhiyun * @vendor: variable vendor guid
727*4882a593Smuzhiyun * @attributes: variable attributes
728*4882a593Smuzhiyun * @block: can we block in this context?
729*4882a593Smuzhiyun * @size: size of @data buffer
730*4882a593Smuzhiyun * @data: buffer containing variable data
731*4882a593Smuzhiyun *
732*4882a593Smuzhiyun * Ensures there is enough free storage in the firmware for this variable, and
733*4882a593Smuzhiyun * if so, calls set_variable(). If creating a new EFI variable, this function
734*4882a593Smuzhiyun * is usually followed by efivar_entry_add().
735*4882a593Smuzhiyun *
736*4882a593Smuzhiyun * Returns 0 on success, -ENOSPC if the firmware does not have enough
737*4882a593Smuzhiyun * space for set_variable() to succeed, or a converted EFI status code
738*4882a593Smuzhiyun * if set_variable() fails.
739*4882a593Smuzhiyun */
efivar_entry_set_safe(efi_char16_t * name,efi_guid_t vendor,u32 attributes,bool block,unsigned long size,void * data)740*4882a593Smuzhiyun int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
741*4882a593Smuzhiyun bool block, unsigned long size, void *data)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun const struct efivar_operations *ops;
744*4882a593Smuzhiyun efi_status_t status;
745*4882a593Smuzhiyun unsigned long varsize;
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun if (!__efivars)
748*4882a593Smuzhiyun return -EINVAL;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun ops = __efivars->ops;
751*4882a593Smuzhiyun if (!ops->query_variable_store)
752*4882a593Smuzhiyun return -ENOSYS;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun /*
755*4882a593Smuzhiyun * If the EFI variable backend provides a non-blocking
756*4882a593Smuzhiyun * ->set_variable() operation and we're in a context where we
757*4882a593Smuzhiyun * cannot block, then we need to use it to avoid live-locks,
758*4882a593Smuzhiyun * since the implication is that the regular ->set_variable()
759*4882a593Smuzhiyun * will block.
760*4882a593Smuzhiyun *
761*4882a593Smuzhiyun * If no ->set_variable_nonblocking() is provided then
762*4882a593Smuzhiyun * ->set_variable() is assumed to be non-blocking.
763*4882a593Smuzhiyun */
764*4882a593Smuzhiyun if (!block && ops->set_variable_nonblocking)
765*4882a593Smuzhiyun return efivar_entry_set_nonblocking(name, vendor, attributes,
766*4882a593Smuzhiyun size, data);
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun varsize = size + ucs2_strsize(name, 1024);
769*4882a593Smuzhiyun if (!block) {
770*4882a593Smuzhiyun if (down_trylock(&efivars_lock))
771*4882a593Smuzhiyun return -EBUSY;
772*4882a593Smuzhiyun status = check_var_size_nonblocking(attributes, varsize);
773*4882a593Smuzhiyun } else {
774*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
775*4882a593Smuzhiyun return -EINTR;
776*4882a593Smuzhiyun status = check_var_size(attributes, varsize);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun if (status != EFI_SUCCESS) {
780*4882a593Smuzhiyun up(&efivars_lock);
781*4882a593Smuzhiyun return -ENOSPC;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun status = ops->set_variable(name, &vendor, attributes, size, data);
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun up(&efivars_lock);
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun return efi_status_to_err(status);
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_set_safe);
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun /**
793*4882a593Smuzhiyun * efivar_entry_find - search for an entry
794*4882a593Smuzhiyun * @name: the EFI variable name
795*4882a593Smuzhiyun * @guid: the EFI variable vendor's guid
796*4882a593Smuzhiyun * @head: head of the variable list
797*4882a593Smuzhiyun * @remove: should we remove the entry from the list?
798*4882a593Smuzhiyun *
799*4882a593Smuzhiyun * Search for an entry on the variable list that has the EFI variable
800*4882a593Smuzhiyun * name @name and vendor guid @guid. If an entry is found on the list
801*4882a593Smuzhiyun * and @remove is true, the entry is removed from the list.
802*4882a593Smuzhiyun *
803*4882a593Smuzhiyun * The caller MUST call efivar_entry_iter_begin() and
804*4882a593Smuzhiyun * efivar_entry_iter_end() before and after the invocation of this
805*4882a593Smuzhiyun * function, respectively.
806*4882a593Smuzhiyun *
807*4882a593Smuzhiyun * Returns the entry if found on the list, %NULL otherwise.
808*4882a593Smuzhiyun */
efivar_entry_find(efi_char16_t * name,efi_guid_t guid,struct list_head * head,bool remove)809*4882a593Smuzhiyun struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
810*4882a593Smuzhiyun struct list_head *head, bool remove)
811*4882a593Smuzhiyun {
812*4882a593Smuzhiyun struct efivar_entry *entry, *n;
813*4882a593Smuzhiyun int strsize1, strsize2;
814*4882a593Smuzhiyun bool found = false;
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun list_for_each_entry_safe(entry, n, head, list) {
817*4882a593Smuzhiyun strsize1 = ucs2_strsize(name, 1024);
818*4882a593Smuzhiyun strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
819*4882a593Smuzhiyun if (strsize1 == strsize2 &&
820*4882a593Smuzhiyun !memcmp(name, &(entry->var.VariableName), strsize1) &&
821*4882a593Smuzhiyun !efi_guidcmp(guid, entry->var.VendorGuid)) {
822*4882a593Smuzhiyun found = true;
823*4882a593Smuzhiyun break;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun if (!found)
828*4882a593Smuzhiyun return NULL;
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun if (remove) {
831*4882a593Smuzhiyun if (entry->scanning) {
832*4882a593Smuzhiyun /*
833*4882a593Smuzhiyun * The entry will be deleted
834*4882a593Smuzhiyun * after scanning is completed.
835*4882a593Smuzhiyun */
836*4882a593Smuzhiyun entry->deleting = true;
837*4882a593Smuzhiyun } else
838*4882a593Smuzhiyun list_del(&entry->list);
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun return entry;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_find);
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun /**
846*4882a593Smuzhiyun * efivar_entry_size - obtain the size of a variable
847*4882a593Smuzhiyun * @entry: entry for this variable
848*4882a593Smuzhiyun * @size: location to store the variable's size
849*4882a593Smuzhiyun */
efivar_entry_size(struct efivar_entry * entry,unsigned long * size)850*4882a593Smuzhiyun int efivar_entry_size(struct efivar_entry *entry, unsigned long *size)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun const struct efivar_operations *ops;
853*4882a593Smuzhiyun efi_status_t status;
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun *size = 0;
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
858*4882a593Smuzhiyun return -EINTR;
859*4882a593Smuzhiyun if (!__efivars) {
860*4882a593Smuzhiyun up(&efivars_lock);
861*4882a593Smuzhiyun return -EINVAL;
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun ops = __efivars->ops;
864*4882a593Smuzhiyun status = ops->get_variable(entry->var.VariableName,
865*4882a593Smuzhiyun &entry->var.VendorGuid, NULL, size, NULL);
866*4882a593Smuzhiyun up(&efivars_lock);
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun if (status != EFI_BUFFER_TOO_SMALL)
869*4882a593Smuzhiyun return efi_status_to_err(status);
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun return 0;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_size);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun /**
876*4882a593Smuzhiyun * __efivar_entry_get - call get_variable()
877*4882a593Smuzhiyun * @entry: read data for this variable
878*4882a593Smuzhiyun * @attributes: variable attributes
879*4882a593Smuzhiyun * @size: size of @data buffer
880*4882a593Smuzhiyun * @data: buffer to store variable data
881*4882a593Smuzhiyun *
882*4882a593Smuzhiyun * The caller MUST call efivar_entry_iter_begin() and
883*4882a593Smuzhiyun * efivar_entry_iter_end() before and after the invocation of this
884*4882a593Smuzhiyun * function, respectively.
885*4882a593Smuzhiyun */
__efivar_entry_get(struct efivar_entry * entry,u32 * attributes,unsigned long * size,void * data)886*4882a593Smuzhiyun int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
887*4882a593Smuzhiyun unsigned long *size, void *data)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun efi_status_t status;
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun if (!__efivars)
892*4882a593Smuzhiyun return -EINVAL;
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun status = __efivars->ops->get_variable(entry->var.VariableName,
895*4882a593Smuzhiyun &entry->var.VendorGuid,
896*4882a593Smuzhiyun attributes, size, data);
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun return efi_status_to_err(status);
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__efivar_entry_get);
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun /**
903*4882a593Smuzhiyun * efivar_entry_get - call get_variable()
904*4882a593Smuzhiyun * @entry: read data for this variable
905*4882a593Smuzhiyun * @attributes: variable attributes
906*4882a593Smuzhiyun * @size: size of @data buffer
907*4882a593Smuzhiyun * @data: buffer to store variable data
908*4882a593Smuzhiyun */
efivar_entry_get(struct efivar_entry * entry,u32 * attributes,unsigned long * size,void * data)909*4882a593Smuzhiyun int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
910*4882a593Smuzhiyun unsigned long *size, void *data)
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun efi_status_t status;
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
915*4882a593Smuzhiyun return -EINTR;
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun if (!__efivars) {
918*4882a593Smuzhiyun up(&efivars_lock);
919*4882a593Smuzhiyun return -EINVAL;
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun status = __efivars->ops->get_variable(entry->var.VariableName,
923*4882a593Smuzhiyun &entry->var.VendorGuid,
924*4882a593Smuzhiyun attributes, size, data);
925*4882a593Smuzhiyun up(&efivars_lock);
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun return efi_status_to_err(status);
928*4882a593Smuzhiyun }
929*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_get);
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun /**
932*4882a593Smuzhiyun * efivar_entry_set_get_size - call set_variable() and get new size (atomic)
933*4882a593Smuzhiyun * @entry: entry containing variable to set and get
934*4882a593Smuzhiyun * @attributes: attributes of variable to be written
935*4882a593Smuzhiyun * @size: size of data buffer
936*4882a593Smuzhiyun * @data: buffer containing data to write
937*4882a593Smuzhiyun * @set: did the set_variable() call succeed?
938*4882a593Smuzhiyun *
939*4882a593Smuzhiyun * This is a pretty special (complex) function. See efivarfs_file_write().
940*4882a593Smuzhiyun *
941*4882a593Smuzhiyun * Atomically call set_variable() for @entry and if the call is
942*4882a593Smuzhiyun * successful, return the new size of the variable from get_variable()
943*4882a593Smuzhiyun * in @size. The success of set_variable() is indicated by @set.
944*4882a593Smuzhiyun *
945*4882a593Smuzhiyun * Returns 0 on success, -EINVAL if the variable data is invalid,
946*4882a593Smuzhiyun * -ENOSPC if the firmware does not have enough available space, or a
947*4882a593Smuzhiyun * converted EFI status code if either of set_variable() or
948*4882a593Smuzhiyun * get_variable() fail.
949*4882a593Smuzhiyun *
950*4882a593Smuzhiyun * If the EFI variable does not exist when calling set_variable()
951*4882a593Smuzhiyun * (EFI_NOT_FOUND), @entry is removed from the variable list.
952*4882a593Smuzhiyun */
efivar_entry_set_get_size(struct efivar_entry * entry,u32 attributes,unsigned long * size,void * data,bool * set)953*4882a593Smuzhiyun int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
954*4882a593Smuzhiyun unsigned long *size, void *data, bool *set)
955*4882a593Smuzhiyun {
956*4882a593Smuzhiyun const struct efivar_operations *ops;
957*4882a593Smuzhiyun efi_char16_t *name = entry->var.VariableName;
958*4882a593Smuzhiyun efi_guid_t *vendor = &entry->var.VendorGuid;
959*4882a593Smuzhiyun efi_status_t status;
960*4882a593Smuzhiyun int err;
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun *set = false;
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun if (efivar_validate(*vendor, name, data, *size) == false)
965*4882a593Smuzhiyun return -EINVAL;
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun /*
968*4882a593Smuzhiyun * The lock here protects the get_variable call, the conditional
969*4882a593Smuzhiyun * set_variable call, and removal of the variable from the efivars
970*4882a593Smuzhiyun * list (in the case of an authenticated delete).
971*4882a593Smuzhiyun */
972*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
973*4882a593Smuzhiyun return -EINTR;
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun if (!__efivars) {
976*4882a593Smuzhiyun err = -EINVAL;
977*4882a593Smuzhiyun goto out;
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun /*
981*4882a593Smuzhiyun * Ensure that the available space hasn't shrunk below the safe level
982*4882a593Smuzhiyun */
983*4882a593Smuzhiyun status = check_var_size(attributes, *size + ucs2_strsize(name, 1024));
984*4882a593Smuzhiyun if (status != EFI_SUCCESS) {
985*4882a593Smuzhiyun if (status != EFI_UNSUPPORTED) {
986*4882a593Smuzhiyun err = efi_status_to_err(status);
987*4882a593Smuzhiyun goto out;
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun if (*size > 65536) {
991*4882a593Smuzhiyun err = -ENOSPC;
992*4882a593Smuzhiyun goto out;
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun ops = __efivars->ops;
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun status = ops->set_variable(name, vendor, attributes, *size, data);
999*4882a593Smuzhiyun if (status != EFI_SUCCESS) {
1000*4882a593Smuzhiyun err = efi_status_to_err(status);
1001*4882a593Smuzhiyun goto out;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun *set = true;
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun /*
1007*4882a593Smuzhiyun * Writing to the variable may have caused a change in size (which
1008*4882a593Smuzhiyun * could either be an append or an overwrite), or the variable to be
1009*4882a593Smuzhiyun * deleted. Perform a GetVariable() so we can tell what actually
1010*4882a593Smuzhiyun * happened.
1011*4882a593Smuzhiyun */
1012*4882a593Smuzhiyun *size = 0;
1013*4882a593Smuzhiyun status = ops->get_variable(entry->var.VariableName,
1014*4882a593Smuzhiyun &entry->var.VendorGuid,
1015*4882a593Smuzhiyun NULL, size, NULL);
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun if (status == EFI_NOT_FOUND)
1018*4882a593Smuzhiyun efivar_entry_list_del_unlock(entry);
1019*4882a593Smuzhiyun else
1020*4882a593Smuzhiyun up(&efivars_lock);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun if (status && status != EFI_BUFFER_TOO_SMALL)
1023*4882a593Smuzhiyun return efi_status_to_err(status);
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun return 0;
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun out:
1028*4882a593Smuzhiyun up(&efivars_lock);
1029*4882a593Smuzhiyun return err;
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_set_get_size);
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun /**
1035*4882a593Smuzhiyun * efivar_entry_iter_begin - begin iterating the variable list
1036*4882a593Smuzhiyun *
1037*4882a593Smuzhiyun * Lock the variable list to prevent entry insertion and removal until
1038*4882a593Smuzhiyun * efivar_entry_iter_end() is called. This function is usually used in
1039*4882a593Smuzhiyun * conjunction with __efivar_entry_iter() or efivar_entry_iter().
1040*4882a593Smuzhiyun */
efivar_entry_iter_begin(void)1041*4882a593Smuzhiyun int efivar_entry_iter_begin(void)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun return down_interruptible(&efivars_lock);
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_iter_begin);
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun /**
1048*4882a593Smuzhiyun * efivar_entry_iter_end - finish iterating the variable list
1049*4882a593Smuzhiyun *
1050*4882a593Smuzhiyun * Unlock the variable list and allow modifications to the list again.
1051*4882a593Smuzhiyun */
efivar_entry_iter_end(void)1052*4882a593Smuzhiyun void efivar_entry_iter_end(void)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun up(&efivars_lock);
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_iter_end);
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun /**
1059*4882a593Smuzhiyun * __efivar_entry_iter - iterate over variable list
1060*4882a593Smuzhiyun * @func: callback function
1061*4882a593Smuzhiyun * @head: head of the variable list
1062*4882a593Smuzhiyun * @data: function-specific data to pass to callback
1063*4882a593Smuzhiyun * @prev: entry to begin iterating from
1064*4882a593Smuzhiyun *
1065*4882a593Smuzhiyun * Iterate over the list of EFI variables and call @func with every
1066*4882a593Smuzhiyun * entry on the list. It is safe for @func to remove entries in the
1067*4882a593Smuzhiyun * list via efivar_entry_delete().
1068*4882a593Smuzhiyun *
1069*4882a593Smuzhiyun * You MUST call efivar_entry_iter_begin() before this function, and
1070*4882a593Smuzhiyun * efivar_entry_iter_end() afterwards.
1071*4882a593Smuzhiyun *
1072*4882a593Smuzhiyun * It is possible to begin iteration from an arbitrary entry within
1073*4882a593Smuzhiyun * the list by passing @prev. @prev is updated on return to point to
1074*4882a593Smuzhiyun * the last entry passed to @func. To begin iterating from the
1075*4882a593Smuzhiyun * beginning of the list @prev must be %NULL.
1076*4882a593Smuzhiyun *
1077*4882a593Smuzhiyun * The restrictions for @func are the same as documented for
1078*4882a593Smuzhiyun * efivar_entry_iter().
1079*4882a593Smuzhiyun */
__efivar_entry_iter(int (* func)(struct efivar_entry *,void *),struct list_head * head,void * data,struct efivar_entry ** prev)1080*4882a593Smuzhiyun int __efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
1081*4882a593Smuzhiyun struct list_head *head, void *data,
1082*4882a593Smuzhiyun struct efivar_entry **prev)
1083*4882a593Smuzhiyun {
1084*4882a593Smuzhiyun struct efivar_entry *entry, *n;
1085*4882a593Smuzhiyun int err = 0;
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun if (!prev || !*prev) {
1088*4882a593Smuzhiyun list_for_each_entry_safe(entry, n, head, list) {
1089*4882a593Smuzhiyun err = func(entry, data);
1090*4882a593Smuzhiyun if (err)
1091*4882a593Smuzhiyun break;
1092*4882a593Smuzhiyun }
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun if (prev)
1095*4882a593Smuzhiyun *prev = entry;
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun return err;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun list_for_each_entry_safe_continue((*prev), n, head, list) {
1102*4882a593Smuzhiyun err = func(*prev, data);
1103*4882a593Smuzhiyun if (err)
1104*4882a593Smuzhiyun break;
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun return err;
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__efivar_entry_iter);
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun /**
1112*4882a593Smuzhiyun * efivar_entry_iter - iterate over variable list
1113*4882a593Smuzhiyun * @func: callback function
1114*4882a593Smuzhiyun * @head: head of variable list
1115*4882a593Smuzhiyun * @data: function-specific data to pass to callback
1116*4882a593Smuzhiyun *
1117*4882a593Smuzhiyun * Iterate over the list of EFI variables and call @func with every
1118*4882a593Smuzhiyun * entry on the list. It is safe for @func to remove entries in the
1119*4882a593Smuzhiyun * list via efivar_entry_delete() while iterating.
1120*4882a593Smuzhiyun *
1121*4882a593Smuzhiyun * Some notes for the callback function:
1122*4882a593Smuzhiyun * - a non-zero return value indicates an error and terminates the loop
1123*4882a593Smuzhiyun * - @func is called from atomic context
1124*4882a593Smuzhiyun */
efivar_entry_iter(int (* func)(struct efivar_entry *,void *),struct list_head * head,void * data)1125*4882a593Smuzhiyun int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
1126*4882a593Smuzhiyun struct list_head *head, void *data)
1127*4882a593Smuzhiyun {
1128*4882a593Smuzhiyun int err = 0;
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun err = efivar_entry_iter_begin();
1131*4882a593Smuzhiyun if (err)
1132*4882a593Smuzhiyun return err;
1133*4882a593Smuzhiyun err = __efivar_entry_iter(func, head, data, NULL);
1134*4882a593Smuzhiyun efivar_entry_iter_end();
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun return err;
1137*4882a593Smuzhiyun }
1138*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_entry_iter);
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun /**
1141*4882a593Smuzhiyun * efivars_kobject - get the kobject for the registered efivars
1142*4882a593Smuzhiyun *
1143*4882a593Smuzhiyun * If efivars_register() has not been called we return NULL,
1144*4882a593Smuzhiyun * otherwise return the kobject used at registration time.
1145*4882a593Smuzhiyun */
efivars_kobject(void)1146*4882a593Smuzhiyun struct kobject *efivars_kobject(void)
1147*4882a593Smuzhiyun {
1148*4882a593Smuzhiyun if (!__efivars)
1149*4882a593Smuzhiyun return NULL;
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun return __efivars->kobject;
1152*4882a593Smuzhiyun }
1153*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivars_kobject);
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun /**
1156*4882a593Smuzhiyun * efivars_register - register an efivars
1157*4882a593Smuzhiyun * @efivars: efivars to register
1158*4882a593Smuzhiyun * @ops: efivars operations
1159*4882a593Smuzhiyun * @kobject: @efivars-specific kobject
1160*4882a593Smuzhiyun *
1161*4882a593Smuzhiyun * Only a single efivars can be registered at any time.
1162*4882a593Smuzhiyun */
efivars_register(struct efivars * efivars,const struct efivar_operations * ops,struct kobject * kobject)1163*4882a593Smuzhiyun int efivars_register(struct efivars *efivars,
1164*4882a593Smuzhiyun const struct efivar_operations *ops,
1165*4882a593Smuzhiyun struct kobject *kobject)
1166*4882a593Smuzhiyun {
1167*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
1168*4882a593Smuzhiyun return -EINTR;
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun efivars->ops = ops;
1171*4882a593Smuzhiyun efivars->kobject = kobject;
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun __efivars = efivars;
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun pr_info("Registered efivars operations\n");
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun up(&efivars_lock);
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun return 0;
1180*4882a593Smuzhiyun }
1181*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivars_register);
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun /**
1184*4882a593Smuzhiyun * efivars_unregister - unregister an efivars
1185*4882a593Smuzhiyun * @efivars: efivars to unregister
1186*4882a593Smuzhiyun *
1187*4882a593Smuzhiyun * The caller must have already removed every entry from the list,
1188*4882a593Smuzhiyun * failure to do so is an error.
1189*4882a593Smuzhiyun */
efivars_unregister(struct efivars * efivars)1190*4882a593Smuzhiyun int efivars_unregister(struct efivars *efivars)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun int rv;
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun if (down_interruptible(&efivars_lock))
1195*4882a593Smuzhiyun return -EINTR;
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun if (!__efivars) {
1198*4882a593Smuzhiyun printk(KERN_ERR "efivars not registered\n");
1199*4882a593Smuzhiyun rv = -EINVAL;
1200*4882a593Smuzhiyun goto out;
1201*4882a593Smuzhiyun }
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun if (__efivars != efivars) {
1204*4882a593Smuzhiyun rv = -EINVAL;
1205*4882a593Smuzhiyun goto out;
1206*4882a593Smuzhiyun }
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun pr_info("Unregistered efivars operations\n");
1209*4882a593Smuzhiyun __efivars = NULL;
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun rv = 0;
1212*4882a593Smuzhiyun out:
1213*4882a593Smuzhiyun up(&efivars_lock);
1214*4882a593Smuzhiyun return rv;
1215*4882a593Smuzhiyun }
1216*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivars_unregister);
1217*4882a593Smuzhiyun
efivar_supports_writes(void)1218*4882a593Smuzhiyun int efivar_supports_writes(void)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun return __efivars && __efivars->ops->set_variable;
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(efivar_supports_writes);
1223