root/drivers/firmware/efi/efivars.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. efivar_guid_read
  2. efivar_attr_read
  3. efivar_size_read
  4. efivar_data_read
  5. sanity_check
  6. copy_out_compat
  7. efivar_store_raw
  8. efivar_show_raw
  9. efivar_attr_show
  10. efivar_attr_store
  11. efivar_release
  12. efivar_create
  13. efivar_delete
  14. efivar_create_sysfs_entry
  15. create_efivars_bin_attributes
  16. efivar_update_sysfs_entry
  17. efivar_update_sysfs_entries
  18. efivars_sysfs_callback
  19. efivar_sysfs_destroy
  20. efivars_sysfs_exit
  21. efivars_sysfs_init

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

/* [<][>][^][v][top][bottom][index][help] */