linux/drivers/firmware/efivars.c
<<
>>
Prefs
   1/*
   2 * EFI Variables - 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_unparse()
  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/capability.h>
  69#include <linux/types.h>
  70#include <linux/errno.h>
  71#include <linux/init.h>
  72#include <linux/mm.h>
  73#include <linux/module.h>
  74#include <linux/string.h>
  75#include <linux/smp.h>
  76#include <linux/efi.h>
  77#include <linux/sysfs.h>
  78#include <linux/kobject.h>
  79#include <linux/device.h>
  80
  81#include <asm/uaccess.h>
  82
  83#define EFIVARS_VERSION "0.08"
  84#define EFIVARS_DATE "2004-May-17"
  85
  86MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
  87MODULE_DESCRIPTION("sysfs interface to EFI Variables");
  88MODULE_LICENSE("GPL");
  89MODULE_VERSION(EFIVARS_VERSION);
  90
  91/*
  92 * efivars_lock protects two things:
  93 * 1) efivar_list - adds, removals, reads, writes
  94 * 2) efi.[gs]et_variable() calls.
  95 * It must not be held when creating sysfs entries or calling kmalloc.
  96 * efi.get_next_variable() is only called from efivars_init(),
  97 * which is protected by the BKL, so that path is safe.
  98 */
  99static DEFINE_SPINLOCK(efivars_lock);
 100static LIST_HEAD(efivar_list);
 101
 102/*
 103 * The maximum size of VariableName + Data = 1024
 104 * Therefore, it's reasonable to save that much
 105 * space in each part of the structure,
 106 * and we use a page for reading/writing.
 107 */
 108
 109struct efi_variable {
 110        efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
 111        efi_guid_t    VendorGuid;
 112        unsigned long DataSize;
 113        __u8          Data[1024];
 114        efi_status_t  Status;
 115        __u32         Attributes;
 116} __attribute__((packed));
 117
 118
 119struct efivar_entry {
 120        struct efi_variable var;
 121        struct list_head list;
 122        struct kobject kobj;
 123};
 124
 125struct efivar_attribute {
 126        struct attribute attr;
 127        ssize_t (*show) (struct efivar_entry *entry, char *buf);
 128        ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
 129};
 130
 131
 132#define EFI_ATTR(_name, _mode, _show, _store) \
 133struct subsys_attribute efi_attr_##_name = { \
 134        .attr = {.name = __stringify(_name), .mode = _mode}, \
 135        .show = _show, \
 136        .store = _store, \
 137};
 138
 139#define EFIVAR_ATTR(_name, _mode, _show, _store) \
 140struct efivar_attribute efivar_attr_##_name = { \
 141        .attr = {.name = __stringify(_name), .mode = _mode}, \
 142        .show = _show, \
 143        .store = _store, \
 144};
 145
 146#define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
 147struct subsys_attribute var_subsys_attr_##_name = { \
 148        .attr = {.name = __stringify(_name), .mode = _mode}, \
 149        .show = _show, \
 150        .store = _store, \
 151};
 152
 153#define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
 154#define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
 155
 156/*
 157 * Prototype for sysfs creation function
 158 */
 159static int
 160efivar_create_sysfs_entry(unsigned long variable_name_size,
 161                                efi_char16_t *variable_name,
 162                                efi_guid_t *vendor_guid);
 163
 164/* Return the number of unicode characters in data */
 165static unsigned long
 166utf8_strlen(efi_char16_t *data, unsigned long maxlength)
 167{
 168        unsigned long length = 0;
 169
 170        while (*data++ != 0 && length < maxlength)
 171                length++;
 172        return length;
 173}
 174
 175/*
 176 * Return the number of bytes is the length of this string
 177 * Note: this is NOT the same as the number of unicode characters
 178 */
 179static inline unsigned long
 180utf8_strsize(efi_char16_t *data, unsigned long maxlength)
 181{
 182        return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
 183}
 184
 185static efi_status_t
 186get_var_data(struct efi_variable *var)
 187{
 188        efi_status_t status;
 189
 190        spin_lock(&efivars_lock);
 191        var->DataSize = 1024;
 192        status = efi.get_variable(var->VariableName,
 193                                &var->VendorGuid,
 194                                &var->Attributes,
 195                                &var->DataSize,
 196                                var->Data);
 197        spin_unlock(&efivars_lock);
 198        if (status != EFI_SUCCESS) {
 199                printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
 200                        status);
 201        }
 202        return status;
 203}
 204
 205static ssize_t
 206efivar_guid_read(struct efivar_entry *entry, char *buf)
 207{
 208        struct efi_variable *var = &entry->var;
 209        char *str = buf;
 210
 211        if (!entry || !buf)
 212                return 0;
 213
 214        efi_guid_unparse(&var->VendorGuid, str);
 215        str += strlen(str);
 216        str += sprintf(str, "\n");
 217
 218        return str - buf;
 219}
 220
 221static ssize_t
 222efivar_attr_read(struct efivar_entry *entry, char *buf)
 223{
 224        struct efi_variable *var = &entry->var;
 225        char *str = buf;
 226        efi_status_t status;
 227
 228        if (!entry || !buf)
 229                return -EINVAL;
 230
 231        status = get_var_data(var);
 232        if (status != EFI_SUCCESS)
 233                return -EIO;
 234
 235        if (var->Attributes & 0x1)
 236                str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
 237        if (var->Attributes & 0x2)
 238                str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
 239        if (var->Attributes & 0x4)
 240                str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
 241        return str - buf;
 242}
 243
 244static ssize_t
 245efivar_size_read(struct efivar_entry *entry, char *buf)
 246{
 247        struct efi_variable *var = &entry->var;
 248        char *str = buf;
 249        efi_status_t status;
 250
 251        if (!entry || !buf)
 252                return -EINVAL;
 253
 254        status = get_var_data(var);
 255        if (status != EFI_SUCCESS)
 256                return -EIO;
 257
 258        str += sprintf(str, "0x%lx\n", var->DataSize);
 259        return str - buf;
 260}
 261
 262static ssize_t
 263efivar_data_read(struct efivar_entry *entry, char *buf)
 264{
 265        struct efi_variable *var = &entry->var;
 266        efi_status_t status;
 267
 268        if (!entry || !buf)
 269                return -EINVAL;
 270
 271        status = get_var_data(var);
 272        if (status != EFI_SUCCESS)
 273                return -EIO;
 274
 275        memcpy(buf, var->Data, var->DataSize);
 276        return var->DataSize;
 277}
 278/*
 279 * We allow each variable to be edited via rewriting the
 280 * entire efi variable structure.
 281 */
 282static ssize_t
 283efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
 284{
 285        struct efi_variable *new_var, *var = &entry->var;
 286        efi_status_t status = EFI_NOT_FOUND;
 287
 288        if (count != sizeof(struct efi_variable))
 289                return -EINVAL;
 290
 291        new_var = (struct efi_variable *)buf;
 292        /*
 293         * If only updating the variable data, then the name
 294         * and guid should remain the same
 295         */
 296        if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
 297                efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
 298                printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
 299                return -EINVAL;
 300        }
 301
 302        if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
 303                printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
 304                return -EINVAL;
 305        }
 306
 307        spin_lock(&efivars_lock);
 308        status = efi.set_variable(new_var->VariableName,
 309                                        &new_var->VendorGuid,
 310                                        new_var->Attributes,
 311                                        new_var->DataSize,
 312                                        new_var->Data);
 313
 314        spin_unlock(&efivars_lock);
 315
 316        if (status != EFI_SUCCESS) {
 317                printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 318                        status);
 319                return -EIO;
 320        }
 321
 322        memcpy(&entry->var, new_var, count);
 323        return count;
 324}
 325
 326static ssize_t
 327efivar_show_raw(struct efivar_entry *entry, char *buf)
 328{
 329        struct efi_variable *var = &entry->var;
 330        efi_status_t status;
 331
 332        if (!entry || !buf)
 333                return 0;
 334
 335        status = get_var_data(var);
 336        if (status != EFI_SUCCESS)
 337                return -EIO;
 338
 339        memcpy(buf, var, sizeof(*var));
 340        return sizeof(*var);
 341}
 342
 343/*
 344 * Generic read/write functions that call the specific functions of
 345 * the atttributes...
 346 */
 347static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
 348                                char *buf)
 349{
 350        struct efivar_entry *var = to_efivar_entry(kobj);
 351        struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
 352        ssize_t ret = -EIO;
 353
 354        if (!capable(CAP_SYS_ADMIN))
 355                return -EACCES;
 356
 357        if (efivar_attr->show) {
 358                ret = efivar_attr->show(var, buf);
 359        }
 360        return ret;
 361}
 362
 363static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
 364                                const char *buf, size_t count)
 365{
 366        struct efivar_entry *var = to_efivar_entry(kobj);
 367        struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
 368        ssize_t ret = -EIO;
 369
 370        if (!capable(CAP_SYS_ADMIN))
 371                return -EACCES;
 372
 373        if (efivar_attr->store)
 374                ret = efivar_attr->store(var, buf, count);
 375
 376        return ret;
 377}
 378
 379static struct sysfs_ops efivar_attr_ops = {
 380        .show = efivar_attr_show,
 381        .store = efivar_attr_store,
 382};
 383
 384static void efivar_release(struct kobject *kobj)
 385{
 386        struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
 387        kfree(var);
 388}
 389
 390static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
 391static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
 392static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
 393static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
 394static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
 395
 396static struct attribute *def_attrs[] = {
 397        &efivar_attr_guid.attr,
 398        &efivar_attr_size.attr,
 399        &efivar_attr_attributes.attr,
 400        &efivar_attr_data.attr,
 401        &efivar_attr_raw_var.attr,
 402        NULL,
 403};
 404
 405static struct kobj_type efivar_ktype = {
 406        .release = efivar_release,
 407        .sysfs_ops = &efivar_attr_ops,
 408        .default_attrs = def_attrs,
 409};
 410
 411static ssize_t
 412dummy(struct kset *kset, char *buf)
 413{
 414        return -ENODEV;
 415}
 416
 417static inline void
 418efivar_unregister(struct efivar_entry *var)
 419{
 420        kobject_unregister(&var->kobj);
 421}
 422
 423
 424static ssize_t
 425efivar_create(struct kset *kset, const char *buf, size_t count)
 426{
 427        struct efi_variable *new_var = (struct efi_variable *)buf;
 428        struct efivar_entry *search_efivar, *n;
 429        unsigned long strsize1, strsize2;
 430        efi_status_t status = EFI_NOT_FOUND;
 431        int found = 0;
 432
 433        if (!capable(CAP_SYS_ADMIN))
 434                return -EACCES;
 435
 436        spin_lock(&efivars_lock);
 437
 438        /*
 439         * Does this variable already exist?
 440         */
 441        list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
 442                strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 443                strsize2 = utf8_strsize(new_var->VariableName, 1024);
 444                if (strsize1 == strsize2 &&
 445                        !memcmp(&(search_efivar->var.VariableName),
 446                                new_var->VariableName, strsize1) &&
 447                        !efi_guidcmp(search_efivar->var.VendorGuid,
 448                                new_var->VendorGuid)) {
 449                        found = 1;
 450                        break;
 451                }
 452        }
 453        if (found) {
 454                spin_unlock(&efivars_lock);
 455                return -EINVAL;
 456        }
 457
 458        /* now *really* create the variable via EFI */
 459        status = efi.set_variable(new_var->VariableName,
 460                        &new_var->VendorGuid,
 461                        new_var->Attributes,
 462                        new_var->DataSize,
 463                        new_var->Data);
 464
 465        if (status != EFI_SUCCESS) {
 466                printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 467                        status);
 468                spin_unlock(&efivars_lock);
 469                return -EIO;
 470        }
 471        spin_unlock(&efivars_lock);
 472
 473        /* Create the entry in sysfs.  Locking is not required here */
 474        status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName,
 475                        1024), new_var->VariableName, &new_var->VendorGuid);
 476        if (status) {
 477                printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n");
 478        }
 479        return count;
 480}
 481
 482static ssize_t
 483efivar_delete(struct kset *kset, const char *buf, size_t count)
 484{
 485        struct efi_variable *del_var = (struct efi_variable *)buf;
 486        struct efivar_entry *search_efivar, *n;
 487        unsigned long strsize1, strsize2;
 488        efi_status_t status = EFI_NOT_FOUND;
 489        int found = 0;
 490
 491        if (!capable(CAP_SYS_ADMIN))
 492                return -EACCES;
 493
 494        spin_lock(&efivars_lock);
 495
 496        /*
 497         * Does this variable already exist?
 498         */
 499        list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
 500                strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 501                strsize2 = utf8_strsize(del_var->VariableName, 1024);
 502                if (strsize1 == strsize2 &&
 503                        !memcmp(&(search_efivar->var.VariableName),
 504                                del_var->VariableName, strsize1) &&
 505                        !efi_guidcmp(search_efivar->var.VendorGuid,
 506                                del_var->VendorGuid)) {
 507                        found = 1;
 508                        break;
 509                }
 510        }
 511        if (!found) {
 512                spin_unlock(&efivars_lock);
 513                return -EINVAL;
 514        }
 515        /* force the Attributes/DataSize to 0 to ensure deletion */
 516        del_var->Attributes = 0;
 517        del_var->DataSize = 0;
 518
 519        status = efi.set_variable(del_var->VariableName,
 520                        &del_var->VendorGuid,
 521                        del_var->Attributes,
 522                        del_var->DataSize,
 523                        del_var->Data);
 524
 525        if (status != EFI_SUCCESS) {
 526                printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 527                        status);
 528                spin_unlock(&efivars_lock);
 529                return -EIO;
 530        }
 531        list_del(&search_efivar->list);
 532        /* We need to release this lock before unregistering. */
 533        spin_unlock(&efivars_lock);
 534        efivar_unregister(search_efivar);
 535
 536        /* It's dead Jim.... */
 537        return count;
 538}
 539
 540static VAR_SUBSYS_ATTR(new_var, 0200, dummy, efivar_create);
 541static VAR_SUBSYS_ATTR(del_var, 0200, dummy, efivar_delete);
 542
 543static struct subsys_attribute *var_subsys_attrs[] = {
 544        &var_subsys_attr_new_var,
 545        &var_subsys_attr_del_var,
 546        NULL,
 547};
 548
 549/*
 550 * Let's not leave out systab information that snuck into
 551 * the efivars driver
 552 */
 553static ssize_t
 554systab_read(struct kset *kset, char *buf)
 555{
 556        char *str = buf;
 557
 558        if (!kset || !buf)
 559                return -EINVAL;
 560
 561        if (efi.mps != EFI_INVALID_TABLE_ADDR)
 562                str += sprintf(str, "MPS=0x%lx\n", efi.mps);
 563        if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
 564                str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
 565        if (efi.acpi != EFI_INVALID_TABLE_ADDR)
 566                str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
 567        if (efi.smbios != EFI_INVALID_TABLE_ADDR)
 568                str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
 569        if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
 570                str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
 571        if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
 572                str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
 573        if (efi.uga != EFI_INVALID_TABLE_ADDR)
 574                str += sprintf(str, "UGA=0x%lx\n", efi.uga);
 575
 576        return str - buf;
 577}
 578
 579static EFI_ATTR(systab, 0400, systab_read, NULL);
 580
 581static struct subsys_attribute *efi_subsys_attrs[] = {
 582        &efi_attr_systab,
 583        NULL,   /* maybe more in the future? */
 584};
 585
 586static decl_subsys(vars, &efivar_ktype, NULL);
 587static decl_subsys(efi, NULL, NULL);
 588
 589/*
 590 * efivar_create_sysfs_entry()
 591 * Requires:
 592 *    variable_name_size = number of bytes required to hold
 593 *                         variable_name (not counting the NULL
 594 *                         character at the end.
 595 *    efivars_lock is not held on entry or exit.
 596 * Returns 1 on failure, 0 on success
 597 */
 598static int
 599efivar_create_sysfs_entry(unsigned long variable_name_size,
 600                        efi_char16_t *variable_name,
 601                        efi_guid_t *vendor_guid)
 602{
 603        int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
 604        char *short_name;
 605        struct efivar_entry *new_efivar;
 606
 607        short_name = kzalloc(short_name_size + 1, GFP_KERNEL);
 608        new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
 609
 610        if (!short_name || !new_efivar)  {
 611                kfree(short_name);
 612                kfree(new_efivar);
 613                return 1;
 614        }
 615
 616        memcpy(new_efivar->var.VariableName, variable_name,
 617                variable_name_size);
 618        memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
 619
 620        /* Convert Unicode to normal chars (assume top bits are 0),
 621           ala UTF-8 */
 622        for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
 623                short_name[i] = variable_name[i] & 0xFF;
 624        }
 625        /* This is ugly, but necessary to separate one vendor's
 626           private variables from another's.         */
 627
 628        *(short_name + strlen(short_name)) = '-';
 629        efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
 630
 631        kobject_set_name(&new_efivar->kobj, "%s", short_name);
 632        kobj_set_kset_s(new_efivar, vars_subsys);
 633        i = kobject_register(&new_efivar->kobj);
 634        if (i) {
 635                kfree(short_name);
 636                kfree(new_efivar);
 637                return 1;
 638        }
 639
 640        kfree(short_name);
 641        short_name = NULL;
 642
 643        spin_lock(&efivars_lock);
 644        list_add(&new_efivar->list, &efivar_list);
 645        spin_unlock(&efivars_lock);
 646
 647        return 0;
 648}
 649/*
 650 * For now we register the efi subsystem with the firmware subsystem
 651 * and the vars subsystem with the efi subsystem.  In the future, it
 652 * might make sense to split off the efi subsystem into its own
 653 * driver, but for now only efivars will register with it, so just
 654 * include it here.
 655 */
 656
 657static int __init
 658efivars_init(void)
 659{
 660        efi_status_t status = EFI_NOT_FOUND;
 661        efi_guid_t vendor_guid;
 662        efi_char16_t *variable_name;
 663        struct subsys_attribute *attr;
 664        unsigned long variable_name_size = 1024;
 665        int i, error = 0;
 666
 667        if (!efi_enabled)
 668                return -ENODEV;
 669
 670        variable_name = kzalloc(variable_name_size, GFP_KERNEL);
 671        if (!variable_name) {
 672                printk(KERN_ERR "efivars: Memory allocation failed.\n");
 673                return -ENOMEM;
 674        }
 675
 676        printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
 677               EFIVARS_DATE);
 678
 679        /*
 680         * For now we'll register the efi subsys within this driver
 681         */
 682
 683        error = firmware_register(&efi_subsys);
 684
 685        if (error) {
 686                printk(KERN_ERR "efivars: Firmware registration failed with error %d.\n", error);
 687                goto out_free;
 688        }
 689
 690        kobj_set_kset_s(&vars_subsys, efi_subsys);
 691
 692        error = subsystem_register(&vars_subsys);
 693
 694        if (error) {
 695                printk(KERN_ERR "efivars: Subsystem registration failed with error %d.\n", error);
 696                goto out_firmware_unregister;
 697        }
 698
 699        /*
 700         * Per EFI spec, the maximum storage allocated for both
 701         * the variable name and variable data is 1024 bytes.
 702         */
 703
 704        do {
 705                variable_name_size = 1024;
 706
 707                status = efi.get_next_variable(&variable_name_size,
 708                                                variable_name,
 709                                                &vendor_guid);
 710                switch (status) {
 711                case EFI_SUCCESS:
 712                        efivar_create_sysfs_entry(variable_name_size,
 713                                                        variable_name,
 714                                                        &vendor_guid);
 715                        break;
 716                case EFI_NOT_FOUND:
 717                        break;
 718                default:
 719                        printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
 720                                status);
 721                        status = EFI_NOT_FOUND;
 722                        break;
 723                }
 724        } while (status != EFI_NOT_FOUND);
 725
 726        /*
 727         * Now add attributes to allow creation of new vars
 728         * and deletion of existing ones...
 729         */
 730
 731        for (i = 0; (attr = var_subsys_attrs[i]) && !error; i++) {
 732                if (attr->show && attr->store)
 733                        error = subsys_create_file(&vars_subsys, attr);
 734        }
 735
 736        /* Don't forget the systab entry */
 737
 738        for (i = 0; (attr = efi_subsys_attrs[i]) && !error; i++) {
 739                if (attr->show)
 740                        error = subsys_create_file(&efi_subsys, attr);
 741        }
 742
 743        if (error)
 744                printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
 745        else
 746                goto out_free;
 747
 748        subsystem_unregister(&vars_subsys);
 749
 750out_firmware_unregister:
 751        firmware_unregister(&efi_subsys);
 752
 753out_free:
 754        kfree(variable_name);
 755
 756        return error;
 757}
 758
 759static void __exit
 760efivars_exit(void)
 761{
 762        struct efivar_entry *entry, *n;
 763
 764        list_for_each_entry_safe(entry, n, &efivar_list, list) {
 765                spin_lock(&efivars_lock);
 766                list_del(&entry->list);
 767                spin_unlock(&efivars_lock);
 768                efivar_unregister(entry);
 769        }
 770
 771        subsystem_unregister(&vars_subsys);
 772        firmware_unregister(&efi_subsys);
 773}
 774
 775module_init(efivars_init);
 776module_exit(efivars_exit);
 777
 778
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.