]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/firmware/efi/efivars.c
Merge tag 'kvm-ppc-fixes-4.20-1' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / firmware / efi / efivars.c
1 /*
2  * Originally from efivars.c,
3  *
4  * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
5  * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
6  *
7  * This code takes all variables accessible from EFI runtime and
8  *  exports them via sysfs
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * Changelog:
25  *
26  *  17 May 2004 - Matt Domsch <Matt_Domsch@dell.com>
27  *   remove check for efi_enabled in exit
28  *   add MODULE_VERSION
29  *
30  *  26 Apr 2004 - Matt Domsch <Matt_Domsch@dell.com>
31  *   minor bug fixes
32  *
33  *  21 Apr 2004 - Matt Tolentino <matthew.e.tolentino@intel.com)
34  *   converted driver to export variable information via sysfs
35  *   and moved to drivers/firmware directory
36  *   bumped revision number to v0.07 to reflect conversion & move
37  *
38  *  10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
39  *   fix locking per Peter Chubb's findings
40  *
41  *  25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
42  *   move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_to_str()
43  *
44  *  12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
45  *   use list_for_each_safe when deleting vars.
46  *   remove ifdef CONFIG_SMP around include <linux/smp.h>
47  *   v0.04 release to linux-ia64@linuxia64.org
48  *
49  *  20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
50  *   Moved vars from /proc/efi to /proc/efi/vars, and made
51  *   efi.c own the /proc/efi directory.
52  *   v0.03 release to linux-ia64@linuxia64.org
53  *
54  *  26 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
55  *   At the request of Stephane, moved ownership of /proc/efi
56  *   to efi.c, and now efivars lives under /proc/efi/vars.
57  *
58  *  12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
59  *   Feedback received from Stephane Eranian incorporated.
60  *   efivar_write() checks copy_from_user() return value.
61  *   efivar_read/write() returns proper errno.
62  *   v0.02 release to linux-ia64@linuxia64.org
63  *
64  *  26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
65  *   v0.01 release to linux-ia64@linuxia64.org
66  */
67
68 #include <linux/efi.h>
69 #include <linux/module.h>
70 #include <linux/slab.h>
71 #include <linux/ucs2_string.h>
72 #include <linux/compat.h>
73
74 #define EFIVARS_VERSION "0.08"
75 #define EFIVARS_DATE "2004-May-17"
76
77 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
78 MODULE_DESCRIPTION("sysfs interface to EFI Variables");
79 MODULE_LICENSE("GPL");
80 MODULE_VERSION(EFIVARS_VERSION);
81 MODULE_ALIAS("platform:efivars");
82
83 LIST_HEAD(efivar_sysfs_list);
84 EXPORT_SYMBOL_GPL(efivar_sysfs_list);
85
86 static struct kset *efivars_kset;
87
88 static struct bin_attribute *efivars_new_var;
89 static struct bin_attribute *efivars_del_var;
90
91 struct compat_efi_variable {
92         efi_char16_t  VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
93         efi_guid_t    VendorGuid;
94         __u32         DataSize;
95         __u8          Data[1024];
96         __u32         Status;
97         __u32         Attributes;
98 } __packed;
99
100 struct efivar_attribute {
101         struct attribute attr;
102         ssize_t (*show) (struct efivar_entry *entry, char *buf);
103         ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
104 };
105
106 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
107 struct efivar_attribute efivar_attr_##_name = { \
108         .attr = {.name = __stringify(_name), .mode = _mode}, \
109         .show = _show, \
110         .store = _store, \
111 };
112
113 #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
114 #define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
115
116 /*
117  * Prototype for sysfs creation function
118  */
119 static int
120 efivar_create_sysfs_entry(struct efivar_entry *new_var);
121
122 static ssize_t
123 efivar_guid_read(struct efivar_entry *entry, char *buf)
124 {
125         struct efi_variable *var = &entry->var;
126         char *str = buf;
127
128         if (!entry || !buf)
129                 return 0;
130
131         efi_guid_to_str(&var->VendorGuid, str);
132         str += strlen(str);
133         str += sprintf(str, "\n");
134
135         return str - buf;
136 }
137
138 static ssize_t
139 efivar_attr_read(struct efivar_entry *entry, char *buf)
140 {
141         struct efi_variable *var = &entry->var;
142         char *str = buf;
143
144         if (!entry || !buf)
145                 return -EINVAL;
146
147         var->DataSize = 1024;
148         if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
149                 return -EIO;
150
151         if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
152                 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
153         if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
154                 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
155         if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
156                 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
157         if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
158                 str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
159         if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
160                 str += sprintf(str,
161                         "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
162         if (var->Attributes &
163                         EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
164                 str += sprintf(str,
165                         "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
166         if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
167                 str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
168         return str - buf;
169 }
170
171 static ssize_t
172 efivar_size_read(struct efivar_entry *entry, char *buf)
173 {
174         struct efi_variable *var = &entry->var;
175         char *str = buf;
176
177         if (!entry || !buf)
178                 return -EINVAL;
179
180         var->DataSize = 1024;
181         if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
182                 return -EIO;
183
184         str += sprintf(str, "0x%lx\n", var->DataSize);
185         return str - buf;
186 }
187
188 static ssize_t
189 efivar_data_read(struct efivar_entry *entry, char *buf)
190 {
191         struct efi_variable *var = &entry->var;
192
193         if (!entry || !buf)
194                 return -EINVAL;
195
196         var->DataSize = 1024;
197         if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
198                 return -EIO;
199
200         memcpy(buf, var->Data, var->DataSize);
201         return var->DataSize;
202 }
203
204 static inline int
205 sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor,
206              unsigned long size, u32 attributes, u8 *data)
207 {
208         /*
209          * If only updating the variable data, then the name
210          * and guid should remain the same
211          */
212         if (memcmp(name, var->VariableName, sizeof(var->VariableName)) ||
213                 efi_guidcmp(vendor, var->VendorGuid)) {
214                 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
215                 return -EINVAL;
216         }
217
218         if ((size <= 0) || (attributes == 0)){
219                 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
220                 return -EINVAL;
221         }
222
223         if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
224             efivar_validate(vendor, name, data, size) == false) {
225                 printk(KERN_ERR "efivars: Malformed variable content\n");
226                 return -EINVAL;
227         }
228
229         return 0;
230 }
231
232 static void
233 copy_out_compat(struct efi_variable *dst, struct compat_efi_variable *src)
234 {
235         memcpy(dst->VariableName, src->VariableName, EFI_VAR_NAME_LEN);
236         memcpy(dst->Data, src->Data, sizeof(src->Data));
237
238         dst->VendorGuid = src->VendorGuid;
239         dst->DataSize = src->DataSize;
240         dst->Attributes = src->Attributes;
241 }
242
243 /*
244  * We allow each variable to be edited via rewriting the
245  * entire efi variable structure.
246  */
247 static ssize_t
248 efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
249 {
250         struct efi_variable *new_var, *var = &entry->var;
251         efi_char16_t *name;
252         unsigned long size;
253         efi_guid_t vendor;
254         u32 attributes;
255         u8 *data;
256         int err;
257
258         if (in_compat_syscall()) {
259                 struct compat_efi_variable *compat;
260
261                 if (count != sizeof(*compat))
262                         return -EINVAL;
263
264                 compat = (struct compat_efi_variable *)buf;
265                 attributes = compat->Attributes;
266                 vendor = compat->VendorGuid;
267                 name = compat->VariableName;
268                 size = compat->DataSize;
269                 data = compat->Data;
270
271                 err = sanity_check(var, name, vendor, size, attributes, data);
272                 if (err)
273                         return err;
274
275                 copy_out_compat(&entry->var, compat);
276         } else {
277                 if (count != sizeof(struct efi_variable))
278                         return -EINVAL;
279
280                 new_var = (struct efi_variable *)buf;
281
282                 attributes = new_var->Attributes;
283                 vendor = new_var->VendorGuid;
284                 name = new_var->VariableName;
285                 size = new_var->DataSize;
286                 data = new_var->Data;
287
288                 err = sanity_check(var, name, vendor, size, attributes, data);
289                 if (err)
290                         return err;
291
292                 memcpy(&entry->var, new_var, count);
293         }
294
295         err = efivar_entry_set(entry, attributes, size, data, NULL);
296         if (err) {
297                 printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
298                 return -EIO;
299         }
300
301         return count;
302 }
303
304 static ssize_t
305 efivar_show_raw(struct efivar_entry *entry, char *buf)
306 {
307         struct efi_variable *var = &entry->var;
308         struct compat_efi_variable *compat;
309         size_t size;
310
311         if (!entry || !buf)
312                 return 0;
313
314         var->DataSize = 1024;
315         if (efivar_entry_get(entry, &entry->var.Attributes,
316                              &entry->var.DataSize, entry->var.Data))
317                 return -EIO;
318
319         if (in_compat_syscall()) {
320                 compat = (struct compat_efi_variable *)buf;
321
322                 size = sizeof(*compat);
323                 memcpy(compat->VariableName, var->VariableName,
324                         EFI_VAR_NAME_LEN);
325                 memcpy(compat->Data, var->Data, sizeof(compat->Data));
326
327                 compat->VendorGuid = var->VendorGuid;
328                 compat->DataSize = var->DataSize;
329                 compat->Attributes = var->Attributes;
330         } else {
331                 size = sizeof(*var);
332                 memcpy(buf, var, size);
333         }
334
335         return size;
336 }
337
338 /*
339  * Generic read/write functions that call the specific functions of
340  * the attributes...
341  */
342 static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
343                                 char *buf)
344 {
345         struct efivar_entry *var = to_efivar_entry(kobj);
346         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
347         ssize_t ret = -EIO;
348
349         if (!capable(CAP_SYS_ADMIN))
350                 return -EACCES;
351
352         if (efivar_attr->show) {
353                 ret = efivar_attr->show(var, buf);
354         }
355         return ret;
356 }
357
358 static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
359                                 const char *buf, size_t count)
360 {
361         struct efivar_entry *var = to_efivar_entry(kobj);
362         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
363         ssize_t ret = -EIO;
364
365         if (!capable(CAP_SYS_ADMIN))
366                 return -EACCES;
367
368         if (efivar_attr->store)
369                 ret = efivar_attr->store(var, buf, count);
370
371         return ret;
372 }
373
374 static const struct sysfs_ops efivar_attr_ops = {
375         .show = efivar_attr_show,
376         .store = efivar_attr_store,
377 };
378
379 static void efivar_release(struct kobject *kobj)
380 {
381         struct efivar_entry *var = to_efivar_entry(kobj);
382         kfree(var);
383 }
384
385 static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
386 static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
387 static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
388 static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
389 static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
390
391 static struct attribute *def_attrs[] = {
392         &efivar_attr_guid.attr,
393         &efivar_attr_size.attr,
394         &efivar_attr_attributes.attr,
395         &efivar_attr_data.attr,
396         &efivar_attr_raw_var.attr,
397         NULL,
398 };
399
400 static struct kobj_type efivar_ktype = {
401         .release = efivar_release,
402         .sysfs_ops = &efivar_attr_ops,
403         .default_attrs = def_attrs,
404 };
405
406 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
407                              struct bin_attribute *bin_attr,
408                              char *buf, loff_t pos, size_t count)
409 {
410         struct compat_efi_variable *compat = (struct compat_efi_variable *)buf;
411         struct efi_variable *new_var = (struct efi_variable *)buf;
412         struct efivar_entry *new_entry;
413         bool need_compat = in_compat_syscall();
414         efi_char16_t *name;
415         unsigned long size;
416         u32 attributes;
417         u8 *data;
418         int err;
419
420         if (!capable(CAP_SYS_ADMIN))
421                 return -EACCES;
422
423         if (need_compat) {
424                 if (count != sizeof(*compat))
425                         return -EINVAL;
426
427                 attributes = compat->Attributes;
428                 name = compat->VariableName;
429                 size = compat->DataSize;
430                 data = compat->Data;
431         } else {
432                 if (count != sizeof(*new_var))
433                         return -EINVAL;
434
435                 attributes = new_var->Attributes;
436                 name = new_var->VariableName;
437                 size = new_var->DataSize;
438                 data = new_var->Data;
439         }
440
441         if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
442             efivar_validate(new_var->VendorGuid, name, data,
443                             size) == false) {
444                 printk(KERN_ERR "efivars: Malformed variable content\n");
445                 return -EINVAL;
446         }
447
448         new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
449         if (!new_entry)
450                 return -ENOMEM;
451
452         if (need_compat)
453                 copy_out_compat(&new_entry->var, compat);
454         else
455                 memcpy(&new_entry->var, new_var, sizeof(*new_var));
456
457         err = efivar_entry_set(new_entry, attributes, size,
458                                data, &efivar_sysfs_list);
459         if (err) {
460                 if (err == -EEXIST)
461                         err = -EINVAL;
462                 goto out;
463         }
464
465         if (efivar_create_sysfs_entry(new_entry)) {
466                 printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
467                 kfree(new_entry);
468         }
469         return count;
470
471 out:
472         kfree(new_entry);
473         return err;
474 }
475
476 static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
477                              struct bin_attribute *bin_attr,
478                              char *buf, loff_t pos, size_t count)
479 {
480         struct efi_variable *del_var = (struct efi_variable *)buf;
481         struct compat_efi_variable *compat;
482         struct efivar_entry *entry;
483         efi_char16_t *name;
484         efi_guid_t vendor;
485         int err = 0;
486
487         if (!capable(CAP_SYS_ADMIN))
488                 return -EACCES;
489
490         if (in_compat_syscall()) {
491                 if (count != sizeof(*compat))
492                         return -EINVAL;
493
494                 compat = (struct compat_efi_variable *)buf;
495                 name = compat->VariableName;
496                 vendor = compat->VendorGuid;
497         } else {
498                 if (count != sizeof(*del_var))
499                         return -EINVAL;
500
501                 name = del_var->VariableName;
502                 vendor = del_var->VendorGuid;
503         }
504
505         if (efivar_entry_iter_begin())
506                 return -EINTR;
507         entry = efivar_entry_find(name, vendor, &efivar_sysfs_list, true);
508         if (!entry)
509                 err = -EINVAL;
510         else if (__efivar_entry_delete(entry))
511                 err = -EIO;
512
513         if (err) {
514                 efivar_entry_iter_end();
515                 return err;
516         }
517
518         if (!entry->scanning) {
519                 efivar_entry_iter_end();
520                 efivar_unregister(entry);
521         } else
522                 efivar_entry_iter_end();
523
524         /* It's dead Jim.... */
525         return count;
526 }
527
528 /**
529  * efivar_create_sysfs_entry - create a new entry in sysfs
530  * @new_var: efivar entry to create
531  *
532  * Returns 0 on success, negative error code on failure
533  */
534 static int
535 efivar_create_sysfs_entry(struct efivar_entry *new_var)
536 {
537         int short_name_size;
538         char *short_name;
539         unsigned long utf8_name_size;
540         efi_char16_t *variable_name = new_var->var.VariableName;
541         int ret;
542
543         /*
544          * Length of the variable bytes in UTF8, plus the '-' separator,
545          * plus the GUID, plus trailing NUL
546          */
547         utf8_name_size = ucs2_utf8size(variable_name);
548         short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
549
550         short_name = kmalloc(short_name_size, GFP_KERNEL);
551         if (!short_name)
552                 return -ENOMEM;
553
554         ucs2_as_utf8(short_name, variable_name, short_name_size);
555
556         /* This is ugly, but necessary to separate one vendor's
557            private variables from another's.         */
558         short_name[utf8_name_size] = '-';
559         efi_guid_to_str(&new_var->var.VendorGuid,
560                          short_name + utf8_name_size + 1);
561
562         new_var->kobj.kset = efivars_kset;
563
564         ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
565                                    NULL, "%s", short_name);
566         kfree(short_name);
567         if (ret)
568                 return ret;
569
570         kobject_uevent(&new_var->kobj, KOBJ_ADD);
571         if (efivar_entry_add(new_var, &efivar_sysfs_list)) {
572                 efivar_unregister(new_var);
573                 return -EINTR;
574         }
575
576         return 0;
577 }
578
579 static int
580 create_efivars_bin_attributes(void)
581 {
582         struct bin_attribute *attr;
583         int error;
584
585         /* new_var */
586         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
587         if (!attr)
588                 return -ENOMEM;
589
590         attr->attr.name = "new_var";
591         attr->attr.mode = 0200;
592         attr->write = efivar_create;
593         efivars_new_var = attr;
594
595         /* del_var */
596         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
597         if (!attr) {
598                 error = -ENOMEM;
599                 goto out_free;
600         }
601         attr->attr.name = "del_var";
602         attr->attr.mode = 0200;
603         attr->write = efivar_delete;
604         efivars_del_var = attr;
605
606         sysfs_bin_attr_init(efivars_new_var);
607         sysfs_bin_attr_init(efivars_del_var);
608
609         /* Register */
610         error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var);
611         if (error) {
612                 printk(KERN_ERR "efivars: unable to create new_var sysfs file"
613                         " due to error %d\n", error);
614                 goto out_free;
615         }
616
617         error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var);
618         if (error) {
619                 printk(KERN_ERR "efivars: unable to create del_var sysfs file"
620                         " due to error %d\n", error);
621                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
622                 goto out_free;
623         }
624
625         return 0;
626 out_free:
627         kfree(efivars_del_var);
628         efivars_del_var = NULL;
629         kfree(efivars_new_var);
630         efivars_new_var = NULL;
631         return error;
632 }
633
634 static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor,
635                                      unsigned long name_size, void *data)
636 {
637         struct efivar_entry *entry = data;
638
639         if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false))
640                 return 0;
641
642         memcpy(entry->var.VariableName, name, name_size);
643         memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
644
645         return 1;
646 }
647
648 static void efivar_update_sysfs_entries(struct work_struct *work)
649 {
650         struct efivar_entry *entry;
651         int err;
652
653         /* Add new sysfs entries */
654         while (1) {
655                 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
656                 if (!entry)
657                         return;
658
659                 err = efivar_init(efivar_update_sysfs_entry, entry,
660                                   false, &efivar_sysfs_list);
661                 if (!err)
662                         break;
663
664                 efivar_create_sysfs_entry(entry);
665         }
666
667         kfree(entry);
668 }
669
670 static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
671                                   unsigned long name_size, void *data)
672 {
673         struct efivar_entry *entry;
674
675         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
676         if (!entry)
677                 return -ENOMEM;
678
679         memcpy(entry->var.VariableName, name, name_size);
680         memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
681
682         efivar_create_sysfs_entry(entry);
683
684         return 0;
685 }
686
687 static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data)
688 {
689         int err = efivar_entry_remove(entry);
690
691         if (err)
692                 return err;
693         efivar_unregister(entry);
694         return 0;
695 }
696
697 static void efivars_sysfs_exit(void)
698 {
699         /* Remove all entries and destroy */
700         int err;
701
702         err = __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list,
703                                   NULL, NULL);
704         if (err) {
705                 pr_err("efivars: Failed to destroy sysfs entries\n");
706                 return;
707         }
708
709         if (efivars_new_var)
710                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
711         if (efivars_del_var)
712                 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var);
713         kfree(efivars_new_var);
714         kfree(efivars_del_var);
715         kset_unregister(efivars_kset);
716 }
717
718 int efivars_sysfs_init(void)
719 {
720         struct kobject *parent_kobj = efivars_kobject();
721         int error = 0;
722
723         if (!efi_enabled(EFI_RUNTIME_SERVICES))
724                 return -ENODEV;
725
726         /* No efivars has been registered yet */
727         if (!parent_kobj)
728                 return 0;
729
730         printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
731                EFIVARS_DATE);
732
733         efivars_kset = kset_create_and_add("vars", NULL, parent_kobj);
734         if (!efivars_kset) {
735                 printk(KERN_ERR "efivars: Subsystem registration failed.\n");
736                 return -ENOMEM;
737         }
738
739         efivar_init(efivars_sysfs_callback, NULL, true, &efivar_sysfs_list);
740
741         error = create_efivars_bin_attributes();
742         if (error) {
743                 efivars_sysfs_exit();
744                 return error;
745         }
746
747         INIT_WORK(&efivar_work, efivar_update_sysfs_entries);
748
749         return 0;
750 }
751 EXPORT_SYMBOL_GPL(efivars_sysfs_init);
752
753 module_init(efivars_sysfs_init);
754 module_exit(efivars_sysfs_exit);