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.1-rc5 1057 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, struct pstore_info *psi) 461{ 462 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 463 struct efivars *efivars = psi->data; 464 char name[DUMP_NAME_LEN]; 465 int i; 466 unsigned int part, size; 467 unsigned long time; 468 469 while (&efivars->walk_entry->list != &efivars->list) { 470 if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid, 471 vendor)) { 472 for (i = 0; i < DUMP_NAME_LEN; i++) { 473 name[i] = efivars->walk_entry->var.VariableName[i]; 474 } 475 if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) { 476 *id = part; 477 timespec->tv_sec = time; 478 timespec->tv_nsec = 0; 479 get_var_data_locked(efivars, &efivars->walk_entry->var); 480 size = efivars->walk_entry->var.DataSize; 481 memcpy(psi->buf, efivars->walk_entry->var.Data, size); 482 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 483 struct efivar_entry, list); 484 return size; 485 } 486 } 487 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 488 struct efivar_entry, list); 489 } 490 return 0; 491} 492 493static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part, 494 size_t size, struct pstore_info *psi) 495{ 496 char name[DUMP_NAME_LEN]; 497 char stub_name[DUMP_NAME_LEN]; 498 efi_char16_t efi_name[DUMP_NAME_LEN]; 499 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 500 struct efivars *efivars = psi->data; 501 struct efivar_entry *entry, *found = NULL; 502 int i; 503 504 sprintf(stub_name, "dump-type%u-%u-", type, part); 505 sprintf(name, "%s%lu", stub_name, get_seconds()); 506 507 spin_lock(&efivars->lock); 508 509 for (i = 0; i < DUMP_NAME_LEN; i++) 510 efi_name[i] = stub_name[i]; 511 512 /* 513 * Clean up any entries with the same name 514 */ 515 516 list_for_each_entry(entry, &efivars->list, list) { 517 get_var_data_locked(efivars, &entry->var); 518 519 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 520 continue; 521 if (utf16_strncmp(entry->var.VariableName, efi_name, 522 utf16_strlen(efi_name))) 523 continue; 524 /* Needs to be a prefix */ 525 if (entry->var.VariableName[utf16_strlen(efi_name)] == 0) 526 continue; 527 528 /* found */ 529 found = entry; 530 efivars->ops->set_variable(entry->var.VariableName, 531 &entry->var.VendorGuid, 532 PSTORE_EFI_ATTRIBUTES, 533 0, NULL); 534 } 535 536 if (found) 537 list_del(&found->list); 538 539 for (i = 0; i < DUMP_NAME_LEN; i++) 540 efi_name[i] = name[i]; 541 542 efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES, 543 size, psi->buf); 544 545 spin_unlock(&efivars->lock); 546 547 if (found) 548 efivar_unregister(found); 549 550 if (size) 551 efivar_create_sysfs_entry(efivars, 552 utf16_strsize(efi_name, 553 DUMP_NAME_LEN * 2), 554 efi_name, &vendor); 555 556 return part; 557}; 558 559static int efi_pstore_erase(enum pstore_type_id type, u64 id, 560 struct pstore_info *psi) 561{ 562 efi_pstore_write(type, id, 0, psi); 563 564 return 0; 565} 566#else 567static int efi_pstore_open(struct pstore_info *psi) 568{ 569 return 0; 570} 571 572static int efi_pstore_close(struct pstore_info *psi) 573{ 574 return 0; 575} 576 577static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 578 struct timespec *time, struct pstore_info *psi) 579{ 580 return -1; 581} 582 583static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part, 584 size_t size, struct pstore_info *psi) 585{ 586 return 0; 587} 588 589static int efi_pstore_erase(enum pstore_type_id type, u64 id, 590 struct pstore_info *psi) 591{ 592 return 0; 593} 594#endif 595 596static struct pstore_info efi_pstore_info = { 597 .owner = THIS_MODULE, 598 .name = "efi", 599 .open = efi_pstore_open, 600 .close = efi_pstore_close, 601 .read = efi_pstore_read, 602 .write = efi_pstore_write, 603 .erase = efi_pstore_erase, 604}; 605 606static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 607 struct bin_attribute *bin_attr, 608 char *buf, loff_t pos, size_t count) 609{ 610 struct efi_variable *new_var = (struct efi_variable *)buf; 611 struct efivars *efivars = bin_attr->private; 612 struct efivar_entry *search_efivar, *n; 613 unsigned long strsize1, strsize2; 614 efi_status_t status = EFI_NOT_FOUND; 615 int found = 0; 616 617 if (!capable(CAP_SYS_ADMIN)) 618 return -EACCES; 619 620 spin_lock(&efivars->lock); 621 622 /* 623 * Does this variable already exist? 624 */ 625 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 626 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 627 strsize2 = utf16_strsize(new_var->VariableName, 1024); 628 if (strsize1 == strsize2 && 629 !memcmp(&(search_efivar->var.VariableName), 630 new_var->VariableName, strsize1) && 631 !efi_guidcmp(search_efivar->var.VendorGuid, 632 new_var->VendorGuid)) { 633 found = 1; 634 break; 635 } 636 } 637 if (found) { 638 spin_unlock(&efivars->lock); 639 return -EINVAL; 640 } 641 642 /* now *really* create the variable via EFI */ 643 status = efivars->ops->set_variable(new_var->VariableName, 644 &new_var->VendorGuid, 645 new_var->Attributes, 646 new_var->DataSize, 647 new_var->Data); 648 649 if (status != EFI_SUCCESS) { 650 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 651 status); 652 spin_unlock(&efivars->lock); 653 return -EIO; 654 } 655 spin_unlock(&efivars->lock); 656 657 /* Create the entry in sysfs. Locking is not required here */ 658 status = efivar_create_sysfs_entry(efivars, 659 utf16_strsize(new_var->VariableName, 660 1024), 661 new_var->VariableName, 662 &new_var->VendorGuid); 663 if (status) { 664 printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n"); 665 } 666 return count; 667} 668 669static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 670 struct bin_attribute *bin_attr, 671 char *buf, loff_t pos, size_t count) 672{ 673 struct efi_variable *del_var = (struct efi_variable *)buf; 674 struct efivars *efivars = bin_attr->private; 675 struct efivar_entry *search_efivar, *n; 676 unsigned long strsize1, strsize2; 677 efi_status_t status = EFI_NOT_FOUND; 678 int found = 0; 679 680 if (!capable(CAP_SYS_ADMIN)) 681 return -EACCES; 682 683 spin_lock(&efivars->lock); 684 685 /* 686 * Does this variable already exist? 687 */ 688 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 689 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 690 strsize2 = utf16_strsize(del_var->VariableName, 1024); 691 if (strsize1 == strsize2 && 692 !memcmp(&(search_efivar->var.VariableName), 693 del_var->VariableName, strsize1) && 694 !efi_guidcmp(search_efivar->var.VendorGuid, 695 del_var->VendorGuid)) { 696 found = 1; 697 break; 698 } 699 } 700 if (!found) { 701 spin_unlock(&efivars->lock); 702 return -EINVAL; 703 } 704 /* force the Attributes/DataSize to 0 to ensure deletion */ 705 del_var->Attributes = 0; 706 del_var->DataSize = 0; 707 708 status = efivars->ops->set_variable(del_var->VariableName, 709 &del_var->VendorGuid, 710 del_var->Attributes, 711 del_var->DataSize, 712 del_var->Data); 713 714 if (status != EFI_SUCCESS) { 715 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 716 status); 717 spin_unlock(&efivars->lock); 718 return -EIO; 719 } 720 list_del(&search_efivar->list); 721 /* We need to release this lock before unregistering. */ 722 spin_unlock(&efivars->lock); 723 efivar_unregister(search_efivar); 724 725 /* It's dead Jim.... */ 726 return count; 727} 728 729/* 730 * Let's not leave out systab information that snuck into 731 * the efivars driver 732 */ 733static ssize_t systab_show(struct kobject *kobj, 734 struct kobj_attribute *attr, char *buf) 735{ 736 char *str = buf; 737 738 if (!kobj || !buf) 739 return -EINVAL; 740 741 if (efi.mps != EFI_INVALID_TABLE_ADDR) 742 str += sprintf(str, "MPS=0x%lx\n", efi.mps); 743 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) 744 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 745 if (efi.acpi != EFI_INVALID_TABLE_ADDR) 746 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 747 if (efi.smbios != EFI_INVALID_TABLE_ADDR) 748 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 749 if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 750 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 751 if (efi.boot_info != EFI_INVALID_TABLE_ADDR) 752 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); 753 if (efi.uga != EFI_INVALID_TABLE_ADDR) 754 str += sprintf(str, "UGA=0x%lx\n", efi.uga); 755 756 return str - buf; 757} 758 759static struct kobj_attribute efi_attr_systab = 760 __ATTR(systab, 0400, systab_show, NULL); 761 762static struct attribute *efi_subsys_attrs[] = { 763 &efi_attr_systab.attr, 764 NULL, /* maybe more in the future? */ 765}; 766 767static struct attribute_group efi_subsys_attr_group = { 768 .attrs = efi_subsys_attrs, 769}; 770 771static struct kobject *efi_kobj; 772 773/* 774 * efivar_create_sysfs_entry() 775 * Requires: 776 * variable_name_size = number of bytes required to hold 777 * variable_name (not counting the NULL 778 * character at the end. 779 * efivars->lock is not held on entry or exit. 780 * Returns 1 on failure, 0 on success 781 */ 782static int 783efivar_create_sysfs_entry(struct efivars *efivars, 784 unsigned long variable_name_size, 785 efi_char16_t *variable_name, 786 efi_guid_t *vendor_guid) 787{ 788 int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; 789 char *short_name; 790 struct efivar_entry *new_efivar; 791 792 short_name = kzalloc(short_name_size + 1, GFP_KERNEL); 793 new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); 794 795 if (!short_name || !new_efivar) { 796 kfree(short_name); 797 kfree(new_efivar); 798 return 1; 799 } 800 801 new_efivar->efivars = efivars; 802 memcpy(new_efivar->var.VariableName, variable_name, 803 variable_name_size); 804 memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); 805 806 /* Convert Unicode to normal chars (assume top bits are 0), 807 ala UTF-8 */ 808 for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { 809 short_name[i] = variable_name[i] & 0xFF; 810 } 811 /* This is ugly, but necessary to separate one vendor's 812 private variables from another's. */ 813 814 *(short_name + strlen(short_name)) = '-'; 815 efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); 816 817 new_efivar->kobj.kset = efivars->kset; 818 i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL, 819 "%s", short_name); 820 if (i) { 821 kfree(short_name); 822 kfree(new_efivar); 823 return 1; 824 } 825 826 kobject_uevent(&new_efivar->kobj, KOBJ_ADD); 827 kfree(short_name); 828 short_name = NULL; 829 830 spin_lock(&efivars->lock); 831 list_add(&new_efivar->list, &efivars->list); 832 spin_unlock(&efivars->lock); 833 834 return 0; 835} 836 837static int 838create_efivars_bin_attributes(struct efivars *efivars) 839{ 840 struct bin_attribute *attr; 841 int error; 842 843 /* new_var */ 844 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 845 if (!attr) 846 return -ENOMEM; 847 848 attr->attr.name = "new_var"; 849 attr->attr.mode = 0200; 850 attr->write = efivar_create; 851 attr->private = efivars; 852 efivars->new_var = attr; 853 854 /* del_var */ 855 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 856 if (!attr) { 857 error = -ENOMEM; 858 goto out_free; 859 } 860 attr->attr.name = "del_var"; 861 attr->attr.mode = 0200; 862 attr->write = efivar_delete; 863 attr->private = efivars; 864 efivars->del_var = attr; 865 866 sysfs_bin_attr_init(efivars->new_var); 867 sysfs_bin_attr_init(efivars->del_var); 868 869 /* Register */ 870 error = sysfs_create_bin_file(&efivars->kset->kobj, 871 efivars->new_var); 872 if (error) { 873 printk(KERN_ERR "efivars: unable to create new_var sysfs file" 874 " due to error %d\n", error); 875 goto out_free; 876 } 877 error = sysfs_create_bin_file(&efivars->kset->kobj, 878 efivars->del_var); 879 if (error) { 880 printk(KERN_ERR "efivars: unable to create del_var sysfs file" 881 " due to error %d\n", error); 882 sysfs_remove_bin_file(&efivars->kset->kobj, 883 efivars->new_var); 884 goto out_free; 885 } 886 887 return 0; 888out_free: 889 kfree(efivars->del_var); 890 efivars->del_var = NULL; 891 kfree(efivars->new_var); 892 efivars->new_var = NULL; 893 return error; 894} 895 896void unregister_efivars(struct efivars *efivars) 897{ 898 struct efivar_entry *entry, *n; 899 900 list_for_each_entry_safe(entry, n, &efivars->list, list) { 901 spin_lock(&efivars->lock); 902 list_del(&entry->list); 903 spin_unlock(&efivars->lock); 904 efivar_unregister(entry); 905 } 906 if (efivars->new_var) 907 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var); 908 if (efivars->del_var) 909 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); 910 kfree(efivars->new_var); 911 kfree(efivars->del_var); 912 kset_unregister(efivars->kset); 913} 914EXPORT_SYMBOL_GPL(unregister_efivars); 915 916int register_efivars(struct efivars *efivars, 917 const struct efivar_operations *ops, 918 struct kobject *parent_kobj) 919{ 920 efi_status_t status = EFI_NOT_FOUND; 921 efi_guid_t vendor_guid; 922 efi_char16_t *variable_name; 923 unsigned long variable_name_size = 1024; 924 int error = 0; 925 926 variable_name = kzalloc(variable_name_size, GFP_KERNEL); 927 if (!variable_name) { 928 printk(KERN_ERR "efivars: Memory allocation failed.\n"); 929 return -ENOMEM; 930 } 931 932 spin_lock_init(&efivars->lock); 933 INIT_LIST_HEAD(&efivars->list); 934 efivars->ops = ops; 935 936 efivars->kset = kset_create_and_add("vars", NULL, parent_kobj); 937 if (!efivars->kset) { 938 printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 939 error = -ENOMEM; 940 goto out; 941 } 942 943 /* 944 * Per EFI spec, the maximum storage allocated for both 945 * the variable name and variable data is 1024 bytes. 946 */ 947 948 do { 949 variable_name_size = 1024; 950 951 status = ops->get_next_variable(&variable_name_size, 952 variable_name, 953 &vendor_guid); 954 switch (status) { 955 case EFI_SUCCESS: 956 efivar_create_sysfs_entry(efivars, 957 variable_name_size, 958 variable_name, 959 &vendor_guid); 960 break; 961 case EFI_NOT_FOUND: 962 break; 963 default: 964 printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n", 965 status); 966 status = EFI_NOT_FOUND; 967 break; 968 } 969 } while (status != EFI_NOT_FOUND); 970 971 error = create_efivars_bin_attributes(efivars); 972 if (error) 973 unregister_efivars(efivars); 974 975 efivars->efi_pstore_info = efi_pstore_info; 976 977 efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 978 if (efivars->efi_pstore_info.buf) { 979 efivars->efi_pstore_info.bufsize = 1024; 980 efivars->efi_pstore_info.data = efivars; 981 mutex_init(&efivars->efi_pstore_info.buf_mutex); 982 pstore_register(&efivars->efi_pstore_info); 983 } 984 985out: 986 kfree(variable_name); 987 988 return error; 989} 990EXPORT_SYMBOL_GPL(register_efivars); 991 992static struct efivars __efivars; 993static struct efivar_operations ops; 994 995/* 996 * For now we register the efi subsystem with the firmware subsystem 997 * and the vars subsystem with the efi subsystem. In the future, it 998 * might make sense to split off the efi subsystem into its own 999 * driver, but for now only efivars will register with it, so just 1000 * include it here. 1001 */ 1002 1003static int __init 1004efivars_init(void) 1005{ 1006 int error = 0; 1007 1008 printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 1009 EFIVARS_DATE); 1010 1011 if (!efi_enabled) 1012 return 0; 1013 1014 /* For now we'll register the efi directory at /sys/firmware/efi */ 1015 efi_kobj = kobject_create_and_add("efi", firmware_kobj); 1016 if (!efi_kobj) { 1017 printk(KERN_ERR "efivars: Firmware registration failed.\n"); 1018 return -ENOMEM; 1019 } 1020 1021 ops.get_variable = efi.get_variable; 1022 ops.set_variable = efi.set_variable; 1023 ops.get_next_variable = efi.get_next_variable; 1024 error = register_efivars(&__efivars, &ops, efi_kobj); 1025 if (error) 1026 goto err_put; 1027 1028 /* Don't forget the systab entry */ 1029 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); 1030 if (error) { 1031 printk(KERN_ERR 1032 "efivars: Sysfs attribute export failed with error %d.\n", 1033 error); 1034 goto err_unregister; 1035 } 1036 1037 return 0; 1038 1039err_unregister: 1040 unregister_efivars(&__efivars); 1041err_put: 1042 kobject_put(efi_kobj); 1043 return error; 1044} 1045 1046static void __exit 1047efivars_exit(void) 1048{ 1049 if (efi_enabled) { 1050 unregister_efivars(&__efivars); 1051 kobject_put(efi_kobj); 1052 } 1053} 1054 1055module_init(efivars_init); 1056module_exit(efivars_exit); 1057