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 77MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); 78MODULE_DESCRIPTION("sysfs interface to EFI Variables"); 79MODULE_LICENSE("GPL"); 80MODULE_VERSION(EFIVARS_VERSION); 81MODULE_ALIAS("platform:efivars"); 82 83LIST_HEAD(efivar_sysfs_list); 84EXPORT_SYMBOL_GPL(efivar_sysfs_list); 85 86static struct kset *efivars_kset; 87 88static struct bin_attribute *efivars_new_var; 89static struct bin_attribute *efivars_del_var; 90 91struct 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 100struct 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) \ 107struct 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 */ 119static int 120efivar_create_sysfs_entry(struct efivar_entry *new_var); 121 122static ssize_t 123efivar_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 138static ssize_t 139efivar_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 171static ssize_t 172efivar_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 188static ssize_t 189efivar_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 204static inline int 205sanity_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 232static inline bool is_compat(void) 233{ 234 if (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) 235 return true; 236 237 return false; 238} 239 240static void 241copy_out_compat(struct efi_variable *dst, struct compat_efi_variable *src) 242{ 243 memcpy(dst->VariableName, src->VariableName, EFI_VAR_NAME_LEN); 244 memcpy(dst->Data, src->Data, sizeof(src->Data)); 245 246 dst->VendorGuid = src->VendorGuid; 247 dst->DataSize = src->DataSize; 248 dst->Attributes = src->Attributes; 249} 250 251/* 252 * We allow each variable to be edited via rewriting the 253 * entire efi variable structure. 254 */ 255static ssize_t 256efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) 257{ 258 struct efi_variable *new_var, *var = &entry->var; 259 efi_char16_t *name; 260 unsigned long size; 261 efi_guid_t vendor; 262 u32 attributes; 263 u8 *data; 264 int err; 265 266 if (is_compat()) { 267 struct compat_efi_variable *compat; 268 269 if (count != sizeof(*compat)) 270 return -EINVAL; 271 272 compat = (struct compat_efi_variable *)buf; 273 attributes = compat->Attributes; 274 vendor = compat->VendorGuid; 275 name = compat->VariableName; 276 size = compat->DataSize; 277 data = compat->Data; 278 279 err = sanity_check(var, name, vendor, size, attributes, data); 280 if (err) 281 return err; 282 283 copy_out_compat(&entry->var, compat); 284 } else { 285 if (count != sizeof(struct efi_variable)) 286 return -EINVAL; 287 288 new_var = (struct efi_variable *)buf; 289 290 attributes = new_var->Attributes; 291 vendor = new_var->VendorGuid; 292 name = new_var->VariableName; 293 size = new_var->DataSize; 294 data = new_var->Data; 295 296 err = sanity_check(var, name, vendor, size, attributes, data); 297 if (err) 298 return err; 299 300 memcpy(&entry->var, new_var, count); 301 } 302 303 err = efivar_entry_set(entry, attributes, size, data, NULL); 304 if (err) { 305 printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err); 306 return -EIO; 307 } 308 309 return count; 310} 311 312static ssize_t 313efivar_show_raw(struct efivar_entry *entry, char *buf) 314{ 315 struct efi_variable *var = &entry->var; 316 struct compat_efi_variable *compat; 317 size_t size; 318 319 if (!entry || !buf) 320 return 0; 321 322 var->DataSize = 1024; 323 if (efivar_entry_get(entry, &entry->var.Attributes, 324 &entry->var.DataSize, entry->var.Data)) 325 return -EIO; 326 327 if (is_compat()) { 328 compat = (struct compat_efi_variable *)buf; 329 330 size = sizeof(*compat); 331 memcpy(compat->VariableName, var->VariableName, 332 EFI_VAR_NAME_LEN); 333 memcpy(compat->Data, var->Data, sizeof(compat->Data)); 334 335 compat->VendorGuid = var->VendorGuid; 336 compat->DataSize = var->DataSize; 337 compat->Attributes = var->Attributes; 338 } else { 339 size = sizeof(*var); 340 memcpy(buf, var, size); 341 } 342 343 return size; 344} 345 346/* 347 * Generic read/write functions that call the specific functions of 348 * the attributes... 349 */ 350static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr, 351 char *buf) 352{ 353 struct efivar_entry *var = to_efivar_entry(kobj); 354 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 355 ssize_t ret = -EIO; 356 357 if (!capable(CAP_SYS_ADMIN)) 358 return -EACCES; 359 360 if (efivar_attr->show) { 361 ret = efivar_attr->show(var, buf); 362 } 363 return ret; 364} 365 366static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, 367 const char *buf, size_t count) 368{ 369 struct efivar_entry *var = to_efivar_entry(kobj); 370 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 371 ssize_t ret = -EIO; 372 373 if (!capable(CAP_SYS_ADMIN)) 374 return -EACCES; 375 376 if (efivar_attr->store) 377 ret = efivar_attr->store(var, buf, count); 378 379 return ret; 380} 381 382static const struct sysfs_ops efivar_attr_ops = { 383 .show = efivar_attr_show, 384 .store = efivar_attr_store, 385}; 386 387static void efivar_release(struct kobject *kobj) 388{ 389 struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); 390 kfree(var); 391} 392 393static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL); 394static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL); 395static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL); 396static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL); 397static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw); 398 399static struct attribute *def_attrs[] = { 400 &efivar_attr_guid.attr, 401 &efivar_attr_size.attr, 402 &efivar_attr_attributes.attr, 403 &efivar_attr_data.attr, 404 &efivar_attr_raw_var.attr, 405 NULL, 406}; 407 408static struct kobj_type efivar_ktype = { 409 .release = efivar_release, 410 .sysfs_ops = &efivar_attr_ops, 411 .default_attrs = def_attrs, 412}; 413 414static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 415 struct bin_attribute *bin_attr, 416 char *buf, loff_t pos, size_t count) 417{ 418 struct compat_efi_variable *compat = (struct compat_efi_variable *)buf; 419 struct efi_variable *new_var = (struct efi_variable *)buf; 420 struct efivar_entry *new_entry; 421 bool need_compat = is_compat(); 422 efi_char16_t *name; 423 unsigned long size; 424 u32 attributes; 425 u8 *data; 426 int err; 427 428 if (!capable(CAP_SYS_ADMIN)) 429 return -EACCES; 430 431 if (need_compat) { 432 if (count != sizeof(*compat)) 433 return -EINVAL; 434 435 attributes = compat->Attributes; 436 name = compat->VariableName; 437 size = compat->DataSize; 438 data = compat->Data; 439 } else { 440 if (count != sizeof(*new_var)) 441 return -EINVAL; 442 443 attributes = new_var->Attributes; 444 name = new_var->VariableName; 445 size = new_var->DataSize; 446 data = new_var->Data; 447 } 448 449 if ((attributes & ~EFI_VARIABLE_MASK) != 0 || 450 efivar_validate(new_var->VendorGuid, name, data, 451 size) == false) { 452 printk(KERN_ERR "efivars: Malformed variable content\n"); 453 return -EINVAL; 454 } 455 456 new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); 457 if (!new_entry) 458 return -ENOMEM; 459 460 if (need_compat) 461 copy_out_compat(&new_entry->var, compat); 462 else 463 memcpy(&new_entry->var, new_var, sizeof(*new_var)); 464 465 err = efivar_entry_set(new_entry, attributes, size, 466 data, &efivar_sysfs_list); 467 if (err) { 468 if (err == -EEXIST) 469 err = -EINVAL; 470 goto out; 471 } 472 473 if (efivar_create_sysfs_entry(new_entry)) { 474 printk(KERN_WARNING "efivars: failed to create sysfs entry.\n"); 475 kfree(new_entry); 476 } 477 return count; 478 479out: 480 kfree(new_entry); 481 return err; 482} 483 484static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 485 struct bin_attribute *bin_attr, 486 char *buf, loff_t pos, size_t count) 487{ 488 struct efi_variable *del_var = (struct efi_variable *)buf; 489 struct compat_efi_variable *compat; 490 struct efivar_entry *entry; 491 efi_char16_t *name; 492 efi_guid_t vendor; 493 int err = 0; 494 495 if (!capable(CAP_SYS_ADMIN)) 496 return -EACCES; 497 498 if (is_compat()) { 499 if (count != sizeof(*compat)) 500 return -EINVAL; 501 502 compat = (struct compat_efi_variable *)buf; 503 name = compat->VariableName; 504 vendor = compat->VendorGuid; 505 } else { 506 if (count != sizeof(*del_var)) 507 return -EINVAL; 508 509 name = del_var->VariableName; 510 vendor = del_var->VendorGuid; 511 } 512 513 efivar_entry_iter_begin(); 514 entry = efivar_entry_find(name, vendor, &efivar_sysfs_list, true); 515 if (!entry) 516 err = -EINVAL; 517 else if (__efivar_entry_delete(entry)) 518 err = -EIO; 519 520 if (err) { 521 efivar_entry_iter_end(); 522 return err; 523 } 524 525 if (!entry->scanning) { 526 efivar_entry_iter_end(); 527 efivar_unregister(entry); 528 } else 529 efivar_entry_iter_end(); 530 531 /* It's dead Jim.... */ 532 return count; 533} 534 535/** 536 * efivar_create_sysfs_entry - create a new entry in sysfs 537 * @new_var: efivar entry to create 538 * 539 * Returns 0 on success, negative error code on failure 540 */ 541static int 542efivar_create_sysfs_entry(struct efivar_entry *new_var) 543{ 544 int short_name_size; 545 char *short_name; 546 unsigned long utf8_name_size; 547 efi_char16_t *variable_name = new_var->var.VariableName; 548 int ret; 549 550 /* 551 * Length of the variable bytes in UTF8, plus the '-' separator, 552 * plus the GUID, plus trailing NUL 553 */ 554 utf8_name_size = ucs2_utf8size(variable_name); 555 short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1; 556 557 short_name = kmalloc(short_name_size, GFP_KERNEL); 558 if (!short_name) 559 return -ENOMEM; 560 561 ucs2_as_utf8(short_name, variable_name, short_name_size); 562 563 /* This is ugly, but necessary to separate one vendor's 564 private variables from another's. */ 565 short_name[utf8_name_size] = '-'; 566 efi_guid_to_str(&new_var->var.VendorGuid, 567 short_name + utf8_name_size + 1); 568 569 new_var->kobj.kset = efivars_kset; 570 571 ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype, 572 NULL, "%s", short_name); 573 kfree(short_name); 574 if (ret) 575 return ret; 576 577 kobject_uevent(&new_var->kobj, KOBJ_ADD); 578 efivar_entry_add(new_var, &efivar_sysfs_list); 579 580 return 0; 581} 582 583static int 584create_efivars_bin_attributes(void) 585{ 586 struct bin_attribute *attr; 587 int error; 588 589 /* new_var */ 590 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 591 if (!attr) 592 return -ENOMEM; 593 594 attr->attr.name = "new_var"; 595 attr->attr.mode = 0200; 596 attr->write = efivar_create; 597 efivars_new_var = attr; 598 599 /* del_var */ 600 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 601 if (!attr) { 602 error = -ENOMEM; 603 goto out_free; 604 } 605 attr->attr.name = "del_var"; 606 attr->attr.mode = 0200; 607 attr->write = efivar_delete; 608 efivars_del_var = attr; 609 610 sysfs_bin_attr_init(efivars_new_var); 611 sysfs_bin_attr_init(efivars_del_var); 612 613 /* Register */ 614 error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var); 615 if (error) { 616 printk(KERN_ERR "efivars: unable to create new_var sysfs file" 617 " due to error %d\n", error); 618 goto out_free; 619 } 620 621 error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var); 622 if (error) { 623 printk(KERN_ERR "efivars: unable to create del_var sysfs file" 624 " due to error %d\n", error); 625 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var); 626 goto out_free; 627 } 628 629 return 0; 630out_free: 631 kfree(efivars_del_var); 632 efivars_del_var = NULL; 633 kfree(efivars_new_var); 634 efivars_new_var = NULL; 635 return error; 636} 637 638static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor, 639 unsigned long name_size, void *data) 640{ 641 struct efivar_entry *entry = data; 642 643 if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false)) 644 return 0; 645 646 memcpy(entry->var.VariableName, name, name_size); 647 memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 648 649 return 1; 650} 651 652static void efivar_update_sysfs_entries(struct work_struct *work) 653{ 654 struct efivar_entry *entry; 655 int err; 656 657 /* Add new sysfs entries */ 658 while (1) { 659 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 660 if (!entry) 661 return; 662 663 err = efivar_init(efivar_update_sysfs_entry, entry, 664 true, false, &efivar_sysfs_list); 665 if (!err) 666 break; 667 668 efivar_create_sysfs_entry(entry); 669 } 670 671 kfree(entry); 672} 673 674static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor, 675 unsigned long name_size, void *data) 676{ 677 struct efivar_entry *entry; 678 679 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 680 if (!entry) 681 return -ENOMEM; 682 683 memcpy(entry->var.VariableName, name, name_size); 684 memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 685 686 efivar_create_sysfs_entry(entry); 687 688 return 0; 689} 690 691static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data) 692{ 693 efivar_entry_remove(entry); 694 efivar_unregister(entry); 695 return 0; 696} 697 698static void efivars_sysfs_exit(void) 699{ 700 /* Remove all entries and destroy */ 701 __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list, NULL, NULL); 702 703 if (efivars_new_var) 704 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var); 705 if (efivars_del_var) 706 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var); 707 kfree(efivars_new_var); 708 kfree(efivars_del_var); 709 kset_unregister(efivars_kset); 710} 711 712int efivars_sysfs_init(void) 713{ 714 struct kobject *parent_kobj = efivars_kobject(); 715 int error = 0; 716 717 if (!efi_enabled(EFI_RUNTIME_SERVICES)) 718 return -ENODEV; 719 720 /* No efivars has been registered yet */ 721 if (!parent_kobj) 722 return 0; 723 724 printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 725 EFIVARS_DATE); 726 727 efivars_kset = kset_create_and_add("vars", NULL, parent_kobj); 728 if (!efivars_kset) { 729 printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 730 return -ENOMEM; 731 } 732 733 efivar_init(efivars_sysfs_callback, NULL, false, 734 true, &efivar_sysfs_list); 735 736 error = create_efivars_bin_attributes(); 737 if (error) { 738 efivars_sysfs_exit(); 739 return error; 740 } 741 742 INIT_WORK(&efivar_work, efivar_update_sysfs_entries); 743 744 return 0; 745} 746EXPORT_SYMBOL_GPL(efivars_sysfs_init); 747 748module_init(efivars_sysfs_init); 749module_exit(efivars_sysfs_exit); 750