Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.3-rc4 1066 lines 27 kB view raw
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#include <linux/slab.h> 81#include <linux/pstore.h> 82 83#include <asm/uaccess.h> 84 85#define EFIVARS_VERSION "0.08" 86#define EFIVARS_DATE "2004-May-17" 87 88MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); 89MODULE_DESCRIPTION("sysfs interface to EFI Variables"); 90MODULE_LICENSE("GPL"); 91MODULE_VERSION(EFIVARS_VERSION); 92 93#define DUMP_NAME_LEN 52 94 95/* 96 * The maximum size of VariableName + Data = 1024 97 * Therefore, it's reasonable to save that much 98 * space in each part of the structure, 99 * and we use a page for reading/writing. 100 */ 101 102struct efi_variable { 103 efi_char16_t VariableName[1024/sizeof(efi_char16_t)]; 104 efi_guid_t VendorGuid; 105 unsigned long DataSize; 106 __u8 Data[1024]; 107 efi_status_t Status; 108 __u32 Attributes; 109} __attribute__((packed)); 110 111 112struct efivar_entry { 113 struct efivars *efivars; 114 struct efi_variable var; 115 struct list_head list; 116 struct kobject kobj; 117}; 118 119struct efivar_attribute { 120 struct attribute attr; 121 ssize_t (*show) (struct efivar_entry *entry, char *buf); 122 ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); 123}; 124 125#define PSTORE_EFI_ATTRIBUTES \ 126 (EFI_VARIABLE_NON_VOLATILE | \ 127 EFI_VARIABLE_BOOTSERVICE_ACCESS | \ 128 EFI_VARIABLE_RUNTIME_ACCESS) 129 130#define EFIVAR_ATTR(_name, _mode, _show, _store) \ 131struct efivar_attribute efivar_attr_##_name = { \ 132 .attr = {.name = __stringify(_name), .mode = _mode}, \ 133 .show = _show, \ 134 .store = _store, \ 135}; 136 137#define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr) 138#define to_efivar_entry(obj) container_of(obj, struct efivar_entry, kobj) 139 140/* 141 * Prototype for sysfs creation function 142 */ 143static int 144efivar_create_sysfs_entry(struct efivars *efivars, 145 unsigned long variable_name_size, 146 efi_char16_t *variable_name, 147 efi_guid_t *vendor_guid); 148 149/* Return the number of unicode characters in data */ 150static unsigned long 151utf16_strnlen(efi_char16_t *s, size_t maxlength) 152{ 153 unsigned long length = 0; 154 155 while (*s++ != 0 && length < maxlength) 156 length++; 157 return length; 158} 159 160static inline unsigned long 161utf16_strlen(efi_char16_t *s) 162{ 163 return utf16_strnlen(s, ~0UL); 164} 165 166/* 167 * Return the number of bytes is the length of this string 168 * Note: this is NOT the same as the number of unicode characters 169 */ 170static inline unsigned long 171utf16_strsize(efi_char16_t *data, unsigned long maxlength) 172{ 173 return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t); 174} 175 176static inline int 177utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len) 178{ 179 while (1) { 180 if (len == 0) 181 return 0; 182 if (*a < *b) 183 return -1; 184 if (*a > *b) 185 return 1; 186 if (*a == 0) /* implies *b == 0 */ 187 return 0; 188 a++; 189 b++; 190 len--; 191 } 192} 193 194static efi_status_t 195get_var_data_locked(struct efivars *efivars, struct efi_variable *var) 196{ 197 efi_status_t status; 198 199 var->DataSize = 1024; 200 status = efivars->ops->get_variable(var->VariableName, 201 &var->VendorGuid, 202 &var->Attributes, 203 &var->DataSize, 204 var->Data); 205 return status; 206} 207 208static efi_status_t 209get_var_data(struct efivars *efivars, struct efi_variable *var) 210{ 211 efi_status_t status; 212 213 spin_lock(&efivars->lock); 214 status = get_var_data_locked(efivars, var); 215 spin_unlock(&efivars->lock); 216 217 if (status != EFI_SUCCESS) { 218 printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", 219 status); 220 } 221 return status; 222} 223 224static ssize_t 225efivar_guid_read(struct efivar_entry *entry, char *buf) 226{ 227 struct efi_variable *var = &entry->var; 228 char *str = buf; 229 230 if (!entry || !buf) 231 return 0; 232 233 efi_guid_unparse(&var->VendorGuid, str); 234 str += strlen(str); 235 str += sprintf(str, "\n"); 236 237 return str - buf; 238} 239 240static ssize_t 241efivar_attr_read(struct efivar_entry *entry, char *buf) 242{ 243 struct efi_variable *var = &entry->var; 244 char *str = buf; 245 efi_status_t status; 246 247 if (!entry || !buf) 248 return -EINVAL; 249 250 status = get_var_data(entry->efivars, var); 251 if (status != EFI_SUCCESS) 252 return -EIO; 253 254 if (var->Attributes & 0x1) 255 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); 256 if (var->Attributes & 0x2) 257 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); 258 if (var->Attributes & 0x4) 259 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); 260 return str - buf; 261} 262 263static ssize_t 264efivar_size_read(struct efivar_entry *entry, char *buf) 265{ 266 struct efi_variable *var = &entry->var; 267 char *str = buf; 268 efi_status_t status; 269 270 if (!entry || !buf) 271 return -EINVAL; 272 273 status = get_var_data(entry->efivars, var); 274 if (status != EFI_SUCCESS) 275 return -EIO; 276 277 str += sprintf(str, "0x%lx\n", var->DataSize); 278 return str - buf; 279} 280 281static ssize_t 282efivar_data_read(struct efivar_entry *entry, char *buf) 283{ 284 struct efi_variable *var = &entry->var; 285 efi_status_t status; 286 287 if (!entry || !buf) 288 return -EINVAL; 289 290 status = get_var_data(entry->efivars, var); 291 if (status != EFI_SUCCESS) 292 return -EIO; 293 294 memcpy(buf, var->Data, var->DataSize); 295 return var->DataSize; 296} 297/* 298 * We allow each variable to be edited via rewriting the 299 * entire efi variable structure. 300 */ 301static ssize_t 302efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) 303{ 304 struct efi_variable *new_var, *var = &entry->var; 305 struct efivars *efivars = entry->efivars; 306 efi_status_t status = EFI_NOT_FOUND; 307 308 if (count != sizeof(struct efi_variable)) 309 return -EINVAL; 310 311 new_var = (struct efi_variable *)buf; 312 /* 313 * If only updating the variable data, then the name 314 * and guid should remain the same 315 */ 316 if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) || 317 efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) { 318 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); 319 return -EINVAL; 320 } 321 322 if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){ 323 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); 324 return -EINVAL; 325 } 326 327 spin_lock(&efivars->lock); 328 status = efivars->ops->set_variable(new_var->VariableName, 329 &new_var->VendorGuid, 330 new_var->Attributes, 331 new_var->DataSize, 332 new_var->Data); 333 334 spin_unlock(&efivars->lock); 335 336 if (status != EFI_SUCCESS) { 337 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 338 status); 339 return -EIO; 340 } 341 342 memcpy(&entry->var, new_var, count); 343 return count; 344} 345 346static ssize_t 347efivar_show_raw(struct efivar_entry *entry, char *buf) 348{ 349 struct efi_variable *var = &entry->var; 350 efi_status_t status; 351 352 if (!entry || !buf) 353 return 0; 354 355 status = get_var_data(entry->efivars, var); 356 if (status != EFI_SUCCESS) 357 return -EIO; 358 359 memcpy(buf, var, sizeof(*var)); 360 return sizeof(*var); 361} 362 363/* 364 * Generic read/write functions that call the specific functions of 365 * the attributes... 366 */ 367static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr, 368 char *buf) 369{ 370 struct efivar_entry *var = to_efivar_entry(kobj); 371 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 372 ssize_t ret = -EIO; 373 374 if (!capable(CAP_SYS_ADMIN)) 375 return -EACCES; 376 377 if (efivar_attr->show) { 378 ret = efivar_attr->show(var, buf); 379 } 380 return ret; 381} 382 383static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, 384 const char *buf, size_t count) 385{ 386 struct efivar_entry *var = to_efivar_entry(kobj); 387 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 388 ssize_t ret = -EIO; 389 390 if (!capable(CAP_SYS_ADMIN)) 391 return -EACCES; 392 393 if (efivar_attr->store) 394 ret = efivar_attr->store(var, buf, count); 395 396 return ret; 397} 398 399static const struct sysfs_ops efivar_attr_ops = { 400 .show = efivar_attr_show, 401 .store = efivar_attr_store, 402}; 403 404static void efivar_release(struct kobject *kobj) 405{ 406 struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); 407 kfree(var); 408} 409 410static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL); 411static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL); 412static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL); 413static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL); 414static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw); 415 416static struct attribute *def_attrs[] = { 417 &efivar_attr_guid.attr, 418 &efivar_attr_size.attr, 419 &efivar_attr_attributes.attr, 420 &efivar_attr_data.attr, 421 &efivar_attr_raw_var.attr, 422 NULL, 423}; 424 425static struct kobj_type efivar_ktype = { 426 .release = efivar_release, 427 .sysfs_ops = &efivar_attr_ops, 428 .default_attrs = def_attrs, 429}; 430 431static struct pstore_info efi_pstore_info; 432 433static inline void 434efivar_unregister(struct efivar_entry *var) 435{ 436 kobject_put(&var->kobj); 437} 438 439#ifdef CONFIG_PSTORE 440 441static int efi_pstore_open(struct pstore_info *psi) 442{ 443 struct efivars *efivars = psi->data; 444 445 spin_lock(&efivars->lock); 446 efivars->walk_entry = list_first_entry(&efivars->list, 447 struct efivar_entry, list); 448 return 0; 449} 450 451static int efi_pstore_close(struct pstore_info *psi) 452{ 453 struct efivars *efivars = psi->data; 454 455 spin_unlock(&efivars->lock); 456 return 0; 457} 458 459static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 460 struct timespec *timespec, 461 char **buf, struct pstore_info *psi) 462{ 463 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 464 struct efivars *efivars = psi->data; 465 char name[DUMP_NAME_LEN]; 466 int i; 467 unsigned int part, size; 468 unsigned long time; 469 470 while (&efivars->walk_entry->list != &efivars->list) { 471 if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid, 472 vendor)) { 473 for (i = 0; i < DUMP_NAME_LEN; i++) { 474 name[i] = efivars->walk_entry->var.VariableName[i]; 475 } 476 if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) { 477 *id = part; 478 timespec->tv_sec = time; 479 timespec->tv_nsec = 0; 480 get_var_data_locked(efivars, &efivars->walk_entry->var); 481 size = efivars->walk_entry->var.DataSize; 482 *buf = kmalloc(size, GFP_KERNEL); 483 if (*buf == NULL) 484 return -ENOMEM; 485 memcpy(*buf, efivars->walk_entry->var.Data, 486 size); 487 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 488 struct efivar_entry, list); 489 return size; 490 } 491 } 492 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 493 struct efivar_entry, list); 494 } 495 return 0; 496} 497 498static int efi_pstore_write(enum pstore_type_id type, 499 enum kmsg_dump_reason reason, u64 *id, 500 unsigned int part, size_t size, struct pstore_info *psi) 501{ 502 char name[DUMP_NAME_LEN]; 503 char stub_name[DUMP_NAME_LEN]; 504 efi_char16_t efi_name[DUMP_NAME_LEN]; 505 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 506 struct efivars *efivars = psi->data; 507 struct efivar_entry *entry, *found = NULL; 508 int i, ret = 0; 509 510 sprintf(stub_name, "dump-type%u-%u-", type, part); 511 sprintf(name, "%s%lu", stub_name, get_seconds()); 512 513 spin_lock(&efivars->lock); 514 515 for (i = 0; i < DUMP_NAME_LEN; i++) 516 efi_name[i] = stub_name[i]; 517 518 /* 519 * Clean up any entries with the same name 520 */ 521 522 list_for_each_entry(entry, &efivars->list, list) { 523 get_var_data_locked(efivars, &entry->var); 524 525 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 526 continue; 527 if (utf16_strncmp(entry->var.VariableName, efi_name, 528 utf16_strlen(efi_name))) 529 continue; 530 /* Needs to be a prefix */ 531 if (entry->var.VariableName[utf16_strlen(efi_name)] == 0) 532 continue; 533 534 /* found */ 535 found = entry; 536 efivars->ops->set_variable(entry->var.VariableName, 537 &entry->var.VendorGuid, 538 PSTORE_EFI_ATTRIBUTES, 539 0, NULL); 540 } 541 542 if (found) 543 list_del(&found->list); 544 545 for (i = 0; i < DUMP_NAME_LEN; i++) 546 efi_name[i] = name[i]; 547 548 efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES, 549 size, psi->buf); 550 551 spin_unlock(&efivars->lock); 552 553 if (found) 554 efivar_unregister(found); 555 556 if (size) 557 ret = efivar_create_sysfs_entry(efivars, 558 utf16_strsize(efi_name, 559 DUMP_NAME_LEN * 2), 560 efi_name, &vendor); 561 562 *id = part; 563 return ret; 564}; 565 566static int efi_pstore_erase(enum pstore_type_id type, u64 id, 567 struct pstore_info *psi) 568{ 569 efi_pstore_write(type, 0, &id, (unsigned int)id, 0, psi); 570 571 return 0; 572} 573#else 574static int efi_pstore_open(struct pstore_info *psi) 575{ 576 return 0; 577} 578 579static int efi_pstore_close(struct pstore_info *psi) 580{ 581 return 0; 582} 583 584static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 585 struct timespec *timespec, 586 char **buf, struct pstore_info *psi) 587{ 588 return -1; 589} 590 591static int efi_pstore_write(enum pstore_type_id type, 592 enum kmsg_dump_reason reason, u64 *id, 593 unsigned int part, size_t size, struct pstore_info *psi) 594{ 595 return 0; 596} 597 598static int efi_pstore_erase(enum pstore_type_id type, u64 id, 599 struct pstore_info *psi) 600{ 601 return 0; 602} 603#endif 604 605static struct pstore_info efi_pstore_info = { 606 .owner = THIS_MODULE, 607 .name = "efi", 608 .open = efi_pstore_open, 609 .close = efi_pstore_close, 610 .read = efi_pstore_read, 611 .write = efi_pstore_write, 612 .erase = efi_pstore_erase, 613}; 614 615static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 616 struct bin_attribute *bin_attr, 617 char *buf, loff_t pos, size_t count) 618{ 619 struct efi_variable *new_var = (struct efi_variable *)buf; 620 struct efivars *efivars = bin_attr->private; 621 struct efivar_entry *search_efivar, *n; 622 unsigned long strsize1, strsize2; 623 efi_status_t status = EFI_NOT_FOUND; 624 int found = 0; 625 626 if (!capable(CAP_SYS_ADMIN)) 627 return -EACCES; 628 629 spin_lock(&efivars->lock); 630 631 /* 632 * Does this variable already exist? 633 */ 634 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 635 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 636 strsize2 = utf16_strsize(new_var->VariableName, 1024); 637 if (strsize1 == strsize2 && 638 !memcmp(&(search_efivar->var.VariableName), 639 new_var->VariableName, strsize1) && 640 !efi_guidcmp(search_efivar->var.VendorGuid, 641 new_var->VendorGuid)) { 642 found = 1; 643 break; 644 } 645 } 646 if (found) { 647 spin_unlock(&efivars->lock); 648 return -EINVAL; 649 } 650 651 /* now *really* create the variable via EFI */ 652 status = efivars->ops->set_variable(new_var->VariableName, 653 &new_var->VendorGuid, 654 new_var->Attributes, 655 new_var->DataSize, 656 new_var->Data); 657 658 if (status != EFI_SUCCESS) { 659 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 660 status); 661 spin_unlock(&efivars->lock); 662 return -EIO; 663 } 664 spin_unlock(&efivars->lock); 665 666 /* Create the entry in sysfs. Locking is not required here */ 667 status = efivar_create_sysfs_entry(efivars, 668 utf16_strsize(new_var->VariableName, 669 1024), 670 new_var->VariableName, 671 &new_var->VendorGuid); 672 if (status) { 673 printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n"); 674 } 675 return count; 676} 677 678static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 679 struct bin_attribute *bin_attr, 680 char *buf, loff_t pos, size_t count) 681{ 682 struct efi_variable *del_var = (struct efi_variable *)buf; 683 struct efivars *efivars = bin_attr->private; 684 struct efivar_entry *search_efivar, *n; 685 unsigned long strsize1, strsize2; 686 efi_status_t status = EFI_NOT_FOUND; 687 int found = 0; 688 689 if (!capable(CAP_SYS_ADMIN)) 690 return -EACCES; 691 692 spin_lock(&efivars->lock); 693 694 /* 695 * Does this variable already exist? 696 */ 697 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 698 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 699 strsize2 = utf16_strsize(del_var->VariableName, 1024); 700 if (strsize1 == strsize2 && 701 !memcmp(&(search_efivar->var.VariableName), 702 del_var->VariableName, strsize1) && 703 !efi_guidcmp(search_efivar->var.VendorGuid, 704 del_var->VendorGuid)) { 705 found = 1; 706 break; 707 } 708 } 709 if (!found) { 710 spin_unlock(&efivars->lock); 711 return -EINVAL; 712 } 713 /* force the Attributes/DataSize to 0 to ensure deletion */ 714 del_var->Attributes = 0; 715 del_var->DataSize = 0; 716 717 status = efivars->ops->set_variable(del_var->VariableName, 718 &del_var->VendorGuid, 719 del_var->Attributes, 720 del_var->DataSize, 721 del_var->Data); 722 723 if (status != EFI_SUCCESS) { 724 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 725 status); 726 spin_unlock(&efivars->lock); 727 return -EIO; 728 } 729 list_del(&search_efivar->list); 730 /* We need to release this lock before unregistering. */ 731 spin_unlock(&efivars->lock); 732 efivar_unregister(search_efivar); 733 734 /* It's dead Jim.... */ 735 return count; 736} 737 738/* 739 * Let's not leave out systab information that snuck into 740 * the efivars driver 741 */ 742static ssize_t systab_show(struct kobject *kobj, 743 struct kobj_attribute *attr, char *buf) 744{ 745 char *str = buf; 746 747 if (!kobj || !buf) 748 return -EINVAL; 749 750 if (efi.mps != EFI_INVALID_TABLE_ADDR) 751 str += sprintf(str, "MPS=0x%lx\n", efi.mps); 752 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) 753 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 754 if (efi.acpi != EFI_INVALID_TABLE_ADDR) 755 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 756 if (efi.smbios != EFI_INVALID_TABLE_ADDR) 757 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 758 if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 759 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 760 if (efi.boot_info != EFI_INVALID_TABLE_ADDR) 761 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); 762 if (efi.uga != EFI_INVALID_TABLE_ADDR) 763 str += sprintf(str, "UGA=0x%lx\n", efi.uga); 764 765 return str - buf; 766} 767 768static struct kobj_attribute efi_attr_systab = 769 __ATTR(systab, 0400, systab_show, NULL); 770 771static struct attribute *efi_subsys_attrs[] = { 772 &efi_attr_systab.attr, 773 NULL, /* maybe more in the future? */ 774}; 775 776static struct attribute_group efi_subsys_attr_group = { 777 .attrs = efi_subsys_attrs, 778}; 779 780static struct kobject *efi_kobj; 781 782/* 783 * efivar_create_sysfs_entry() 784 * Requires: 785 * variable_name_size = number of bytes required to hold 786 * variable_name (not counting the NULL 787 * character at the end. 788 * efivars->lock is not held on entry or exit. 789 * Returns 1 on failure, 0 on success 790 */ 791static int 792efivar_create_sysfs_entry(struct efivars *efivars, 793 unsigned long variable_name_size, 794 efi_char16_t *variable_name, 795 efi_guid_t *vendor_guid) 796{ 797 int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; 798 char *short_name; 799 struct efivar_entry *new_efivar; 800 801 short_name = kzalloc(short_name_size + 1, GFP_KERNEL); 802 new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); 803 804 if (!short_name || !new_efivar) { 805 kfree(short_name); 806 kfree(new_efivar); 807 return 1; 808 } 809 810 new_efivar->efivars = efivars; 811 memcpy(new_efivar->var.VariableName, variable_name, 812 variable_name_size); 813 memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); 814 815 /* Convert Unicode to normal chars (assume top bits are 0), 816 ala UTF-8 */ 817 for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { 818 short_name[i] = variable_name[i] & 0xFF; 819 } 820 /* This is ugly, but necessary to separate one vendor's 821 private variables from another's. */ 822 823 *(short_name + strlen(short_name)) = '-'; 824 efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); 825 826 new_efivar->kobj.kset = efivars->kset; 827 i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL, 828 "%s", short_name); 829 if (i) { 830 kfree(short_name); 831 kfree(new_efivar); 832 return 1; 833 } 834 835 kobject_uevent(&new_efivar->kobj, KOBJ_ADD); 836 kfree(short_name); 837 short_name = NULL; 838 839 spin_lock(&efivars->lock); 840 list_add(&new_efivar->list, &efivars->list); 841 spin_unlock(&efivars->lock); 842 843 return 0; 844} 845 846static int 847create_efivars_bin_attributes(struct efivars *efivars) 848{ 849 struct bin_attribute *attr; 850 int error; 851 852 /* new_var */ 853 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 854 if (!attr) 855 return -ENOMEM; 856 857 attr->attr.name = "new_var"; 858 attr->attr.mode = 0200; 859 attr->write = efivar_create; 860 attr->private = efivars; 861 efivars->new_var = attr; 862 863 /* del_var */ 864 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 865 if (!attr) { 866 error = -ENOMEM; 867 goto out_free; 868 } 869 attr->attr.name = "del_var"; 870 attr->attr.mode = 0200; 871 attr->write = efivar_delete; 872 attr->private = efivars; 873 efivars->del_var = attr; 874 875 sysfs_bin_attr_init(efivars->new_var); 876 sysfs_bin_attr_init(efivars->del_var); 877 878 /* Register */ 879 error = sysfs_create_bin_file(&efivars->kset->kobj, 880 efivars->new_var); 881 if (error) { 882 printk(KERN_ERR "efivars: unable to create new_var sysfs file" 883 " due to error %d\n", error); 884 goto out_free; 885 } 886 error = sysfs_create_bin_file(&efivars->kset->kobj, 887 efivars->del_var); 888 if (error) { 889 printk(KERN_ERR "efivars: unable to create del_var sysfs file" 890 " due to error %d\n", error); 891 sysfs_remove_bin_file(&efivars->kset->kobj, 892 efivars->new_var); 893 goto out_free; 894 } 895 896 return 0; 897out_free: 898 kfree(efivars->del_var); 899 efivars->del_var = NULL; 900 kfree(efivars->new_var); 901 efivars->new_var = NULL; 902 return error; 903} 904 905void unregister_efivars(struct efivars *efivars) 906{ 907 struct efivar_entry *entry, *n; 908 909 list_for_each_entry_safe(entry, n, &efivars->list, list) { 910 spin_lock(&efivars->lock); 911 list_del(&entry->list); 912 spin_unlock(&efivars->lock); 913 efivar_unregister(entry); 914 } 915 if (efivars->new_var) 916 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var); 917 if (efivars->del_var) 918 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); 919 kfree(efivars->new_var); 920 kfree(efivars->del_var); 921 kset_unregister(efivars->kset); 922} 923EXPORT_SYMBOL_GPL(unregister_efivars); 924 925int register_efivars(struct efivars *efivars, 926 const struct efivar_operations *ops, 927 struct kobject *parent_kobj) 928{ 929 efi_status_t status = EFI_NOT_FOUND; 930 efi_guid_t vendor_guid; 931 efi_char16_t *variable_name; 932 unsigned long variable_name_size = 1024; 933 int error = 0; 934 935 variable_name = kzalloc(variable_name_size, GFP_KERNEL); 936 if (!variable_name) { 937 printk(KERN_ERR "efivars: Memory allocation failed.\n"); 938 return -ENOMEM; 939 } 940 941 spin_lock_init(&efivars->lock); 942 INIT_LIST_HEAD(&efivars->list); 943 efivars->ops = ops; 944 945 efivars->kset = kset_create_and_add("vars", NULL, parent_kobj); 946 if (!efivars->kset) { 947 printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 948 error = -ENOMEM; 949 goto out; 950 } 951 952 /* 953 * Per EFI spec, the maximum storage allocated for both 954 * the variable name and variable data is 1024 bytes. 955 */ 956 957 do { 958 variable_name_size = 1024; 959 960 status = ops->get_next_variable(&variable_name_size, 961 variable_name, 962 &vendor_guid); 963 switch (status) { 964 case EFI_SUCCESS: 965 efivar_create_sysfs_entry(efivars, 966 variable_name_size, 967 variable_name, 968 &vendor_guid); 969 break; 970 case EFI_NOT_FOUND: 971 break; 972 default: 973 printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n", 974 status); 975 status = EFI_NOT_FOUND; 976 break; 977 } 978 } while (status != EFI_NOT_FOUND); 979 980 error = create_efivars_bin_attributes(efivars); 981 if (error) 982 unregister_efivars(efivars); 983 984 efivars->efi_pstore_info = efi_pstore_info; 985 986 efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 987 if (efivars->efi_pstore_info.buf) { 988 efivars->efi_pstore_info.bufsize = 1024; 989 efivars->efi_pstore_info.data = efivars; 990 spin_lock_init(&efivars->efi_pstore_info.buf_lock); 991 pstore_register(&efivars->efi_pstore_info); 992 } 993 994out: 995 kfree(variable_name); 996 997 return error; 998} 999EXPORT_SYMBOL_GPL(register_efivars); 1000 1001static struct efivars __efivars; 1002static struct efivar_operations ops; 1003 1004/* 1005 * For now we register the efi subsystem with the firmware subsystem 1006 * and the vars subsystem with the efi subsystem. In the future, it 1007 * might make sense to split off the efi subsystem into its own 1008 * driver, but for now only efivars will register with it, so just 1009 * include it here. 1010 */ 1011 1012static int __init 1013efivars_init(void) 1014{ 1015 int error = 0; 1016 1017 printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 1018 EFIVARS_DATE); 1019 1020 if (!efi_enabled) 1021 return 0; 1022 1023 /* For now we'll register the efi directory at /sys/firmware/efi */ 1024 efi_kobj = kobject_create_and_add("efi", firmware_kobj); 1025 if (!efi_kobj) { 1026 printk(KERN_ERR "efivars: Firmware registration failed.\n"); 1027 return -ENOMEM; 1028 } 1029 1030 ops.get_variable = efi.get_variable; 1031 ops.set_variable = efi.set_variable; 1032 ops.get_next_variable = efi.get_next_variable; 1033 error = register_efivars(&__efivars, &ops, efi_kobj); 1034 if (error) 1035 goto err_put; 1036 1037 /* Don't forget the systab entry */ 1038 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); 1039 if (error) { 1040 printk(KERN_ERR 1041 "efivars: Sysfs attribute export failed with error %d.\n", 1042 error); 1043 goto err_unregister; 1044 } 1045 1046 return 0; 1047 1048err_unregister: 1049 unregister_efivars(&__efivars); 1050err_put: 1051 kobject_put(efi_kobj); 1052 return error; 1053} 1054 1055static void __exit 1056efivars_exit(void) 1057{ 1058 if (efi_enabled) { 1059 unregister_efivars(&__efivars); 1060 kobject_put(efi_kobj); 1061 } 1062} 1063 1064module_init(efivars_init); 1065module_exit(efivars_exit); 1066