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.5-rc7 1262 lines 32 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 bool 195validate_device_path(struct efi_variable *var, int match, u8 *buffer, 196 unsigned long len) 197{ 198 struct efi_generic_dev_path *node; 199 int offset = 0; 200 201 node = (struct efi_generic_dev_path *)buffer; 202 203 if (len < sizeof(*node)) 204 return false; 205 206 while (offset <= len - sizeof(*node) && 207 node->length >= sizeof(*node) && 208 node->length <= len - offset) { 209 offset += node->length; 210 211 if ((node->type == EFI_DEV_END_PATH || 212 node->type == EFI_DEV_END_PATH2) && 213 node->sub_type == EFI_DEV_END_ENTIRE) 214 return true; 215 216 node = (struct efi_generic_dev_path *)(buffer + offset); 217 } 218 219 /* 220 * If we're here then either node->length pointed past the end 221 * of the buffer or we reached the end of the buffer without 222 * finding a device path end node. 223 */ 224 return false; 225} 226 227static bool 228validate_boot_order(struct efi_variable *var, int match, u8 *buffer, 229 unsigned long len) 230{ 231 /* An array of 16-bit integers */ 232 if ((len % 2) != 0) 233 return false; 234 235 return true; 236} 237 238static bool 239validate_load_option(struct efi_variable *var, int match, u8 *buffer, 240 unsigned long len) 241{ 242 u16 filepathlength; 243 int i, desclength = 0, namelen; 244 245 namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName)); 246 247 /* Either "Boot" or "Driver" followed by four digits of hex */ 248 for (i = match; i < match+4; i++) { 249 if (var->VariableName[i] > 127 || 250 hex_to_bin(var->VariableName[i] & 0xff) < 0) 251 return true; 252 } 253 254 /* Reject it if there's 4 digits of hex and then further content */ 255 if (namelen > match + 4) 256 return false; 257 258 /* A valid entry must be at least 8 bytes */ 259 if (len < 8) 260 return false; 261 262 filepathlength = buffer[4] | buffer[5] << 8; 263 264 /* 265 * There's no stored length for the description, so it has to be 266 * found by hand 267 */ 268 desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; 269 270 /* Each boot entry must have a descriptor */ 271 if (!desclength) 272 return false; 273 274 /* 275 * If the sum of the length of the description, the claimed filepath 276 * length and the original header are greater than the length of the 277 * variable, it's malformed 278 */ 279 if ((desclength + filepathlength + 6) > len) 280 return false; 281 282 /* 283 * And, finally, check the filepath 284 */ 285 return validate_device_path(var, match, buffer + desclength + 6, 286 filepathlength); 287} 288 289static bool 290validate_uint16(struct efi_variable *var, int match, u8 *buffer, 291 unsigned long len) 292{ 293 /* A single 16-bit integer */ 294 if (len != 2) 295 return false; 296 297 return true; 298} 299 300static bool 301validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, 302 unsigned long len) 303{ 304 int i; 305 306 for (i = 0; i < len; i++) { 307 if (buffer[i] > 127) 308 return false; 309 310 if (buffer[i] == 0) 311 return true; 312 } 313 314 return false; 315} 316 317struct variable_validate { 318 char *name; 319 bool (*validate)(struct efi_variable *var, int match, u8 *data, 320 unsigned long len); 321}; 322 323static const struct variable_validate variable_validate[] = { 324 { "BootNext", validate_uint16 }, 325 { "BootOrder", validate_boot_order }, 326 { "DriverOrder", validate_boot_order }, 327 { "Boot*", validate_load_option }, 328 { "Driver*", validate_load_option }, 329 { "ConIn", validate_device_path }, 330 { "ConInDev", validate_device_path }, 331 { "ConOut", validate_device_path }, 332 { "ConOutDev", validate_device_path }, 333 { "ErrOut", validate_device_path }, 334 { "ErrOutDev", validate_device_path }, 335 { "Timeout", validate_uint16 }, 336 { "Lang", validate_ascii_string }, 337 { "PlatformLang", validate_ascii_string }, 338 { "", NULL }, 339}; 340 341static bool 342validate_var(struct efi_variable *var, u8 *data, unsigned long len) 343{ 344 int i; 345 u16 *unicode_name = var->VariableName; 346 347 for (i = 0; variable_validate[i].validate != NULL; i++) { 348 const char *name = variable_validate[i].name; 349 int match; 350 351 for (match = 0; ; match++) { 352 char c = name[match]; 353 u16 u = unicode_name[match]; 354 355 /* All special variables are plain ascii */ 356 if (u > 127) 357 return true; 358 359 /* Wildcard in the matching name means we've matched */ 360 if (c == '*') 361 return variable_validate[i].validate(var, 362 match, data, len); 363 364 /* Case sensitive match */ 365 if (c != u) 366 break; 367 368 /* Reached the end of the string while matching */ 369 if (!c) 370 return variable_validate[i].validate(var, 371 match, data, len); 372 } 373 } 374 375 return true; 376} 377 378static efi_status_t 379get_var_data_locked(struct efivars *efivars, struct efi_variable *var) 380{ 381 efi_status_t status; 382 383 var->DataSize = 1024; 384 status = efivars->ops->get_variable(var->VariableName, 385 &var->VendorGuid, 386 &var->Attributes, 387 &var->DataSize, 388 var->Data); 389 return status; 390} 391 392static efi_status_t 393get_var_data(struct efivars *efivars, struct efi_variable *var) 394{ 395 efi_status_t status; 396 397 spin_lock(&efivars->lock); 398 status = get_var_data_locked(efivars, var); 399 spin_unlock(&efivars->lock); 400 401 if (status != EFI_SUCCESS) { 402 printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", 403 status); 404 } 405 return status; 406} 407 408static ssize_t 409efivar_guid_read(struct efivar_entry *entry, char *buf) 410{ 411 struct efi_variable *var = &entry->var; 412 char *str = buf; 413 414 if (!entry || !buf) 415 return 0; 416 417 efi_guid_unparse(&var->VendorGuid, str); 418 str += strlen(str); 419 str += sprintf(str, "\n"); 420 421 return str - buf; 422} 423 424static ssize_t 425efivar_attr_read(struct efivar_entry *entry, char *buf) 426{ 427 struct efi_variable *var = &entry->var; 428 char *str = buf; 429 efi_status_t status; 430 431 if (!entry || !buf) 432 return -EINVAL; 433 434 status = get_var_data(entry->efivars, var); 435 if (status != EFI_SUCCESS) 436 return -EIO; 437 438 if (var->Attributes & 0x1) 439 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); 440 if (var->Attributes & 0x2) 441 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); 442 if (var->Attributes & 0x4) 443 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); 444 return str - buf; 445} 446 447static ssize_t 448efivar_size_read(struct efivar_entry *entry, char *buf) 449{ 450 struct efi_variable *var = &entry->var; 451 char *str = buf; 452 efi_status_t status; 453 454 if (!entry || !buf) 455 return -EINVAL; 456 457 status = get_var_data(entry->efivars, var); 458 if (status != EFI_SUCCESS) 459 return -EIO; 460 461 str += sprintf(str, "0x%lx\n", var->DataSize); 462 return str - buf; 463} 464 465static ssize_t 466efivar_data_read(struct efivar_entry *entry, char *buf) 467{ 468 struct efi_variable *var = &entry->var; 469 efi_status_t status; 470 471 if (!entry || !buf) 472 return -EINVAL; 473 474 status = get_var_data(entry->efivars, var); 475 if (status != EFI_SUCCESS) 476 return -EIO; 477 478 memcpy(buf, var->Data, var->DataSize); 479 return var->DataSize; 480} 481/* 482 * We allow each variable to be edited via rewriting the 483 * entire efi variable structure. 484 */ 485static ssize_t 486efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) 487{ 488 struct efi_variable *new_var, *var = &entry->var; 489 struct efivars *efivars = entry->efivars; 490 efi_status_t status = EFI_NOT_FOUND; 491 492 if (count != sizeof(struct efi_variable)) 493 return -EINVAL; 494 495 new_var = (struct efi_variable *)buf; 496 /* 497 * If only updating the variable data, then the name 498 * and guid should remain the same 499 */ 500 if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) || 501 efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) { 502 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); 503 return -EINVAL; 504 } 505 506 if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){ 507 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); 508 return -EINVAL; 509 } 510 511 if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 512 validate_var(new_var, new_var->Data, new_var->DataSize) == false) { 513 printk(KERN_ERR "efivars: Malformed variable content\n"); 514 return -EINVAL; 515 } 516 517 spin_lock(&efivars->lock); 518 status = efivars->ops->set_variable(new_var->VariableName, 519 &new_var->VendorGuid, 520 new_var->Attributes, 521 new_var->DataSize, 522 new_var->Data); 523 524 spin_unlock(&efivars->lock); 525 526 if (status != EFI_SUCCESS) { 527 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 528 status); 529 return -EIO; 530 } 531 532 memcpy(&entry->var, new_var, count); 533 return count; 534} 535 536static ssize_t 537efivar_show_raw(struct efivar_entry *entry, char *buf) 538{ 539 struct efi_variable *var = &entry->var; 540 efi_status_t status; 541 542 if (!entry || !buf) 543 return 0; 544 545 status = get_var_data(entry->efivars, var); 546 if (status != EFI_SUCCESS) 547 return -EIO; 548 549 memcpy(buf, var, sizeof(*var)); 550 return sizeof(*var); 551} 552 553/* 554 * Generic read/write functions that call the specific functions of 555 * the attributes... 556 */ 557static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr, 558 char *buf) 559{ 560 struct efivar_entry *var = to_efivar_entry(kobj); 561 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 562 ssize_t ret = -EIO; 563 564 if (!capable(CAP_SYS_ADMIN)) 565 return -EACCES; 566 567 if (efivar_attr->show) { 568 ret = efivar_attr->show(var, buf); 569 } 570 return ret; 571} 572 573static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, 574 const char *buf, size_t count) 575{ 576 struct efivar_entry *var = to_efivar_entry(kobj); 577 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 578 ssize_t ret = -EIO; 579 580 if (!capable(CAP_SYS_ADMIN)) 581 return -EACCES; 582 583 if (efivar_attr->store) 584 ret = efivar_attr->store(var, buf, count); 585 586 return ret; 587} 588 589static const struct sysfs_ops efivar_attr_ops = { 590 .show = efivar_attr_show, 591 .store = efivar_attr_store, 592}; 593 594static void efivar_release(struct kobject *kobj) 595{ 596 struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); 597 kfree(var); 598} 599 600static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL); 601static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL); 602static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL); 603static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL); 604static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw); 605 606static struct attribute *def_attrs[] = { 607 &efivar_attr_guid.attr, 608 &efivar_attr_size.attr, 609 &efivar_attr_attributes.attr, 610 &efivar_attr_data.attr, 611 &efivar_attr_raw_var.attr, 612 NULL, 613}; 614 615static struct kobj_type efivar_ktype = { 616 .release = efivar_release, 617 .sysfs_ops = &efivar_attr_ops, 618 .default_attrs = def_attrs, 619}; 620 621static struct pstore_info efi_pstore_info; 622 623static inline void 624efivar_unregister(struct efivar_entry *var) 625{ 626 kobject_put(&var->kobj); 627} 628 629#ifdef CONFIG_PSTORE 630 631static int efi_pstore_open(struct pstore_info *psi) 632{ 633 struct efivars *efivars = psi->data; 634 635 spin_lock(&efivars->lock); 636 efivars->walk_entry = list_first_entry(&efivars->list, 637 struct efivar_entry, list); 638 return 0; 639} 640 641static int efi_pstore_close(struct pstore_info *psi) 642{ 643 struct efivars *efivars = psi->data; 644 645 spin_unlock(&efivars->lock); 646 return 0; 647} 648 649static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 650 struct timespec *timespec, 651 char **buf, struct pstore_info *psi) 652{ 653 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 654 struct efivars *efivars = psi->data; 655 char name[DUMP_NAME_LEN]; 656 int i; 657 unsigned int part, size; 658 unsigned long time; 659 660 while (&efivars->walk_entry->list != &efivars->list) { 661 if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid, 662 vendor)) { 663 for (i = 0; i < DUMP_NAME_LEN; i++) { 664 name[i] = efivars->walk_entry->var.VariableName[i]; 665 } 666 if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) { 667 *id = part; 668 timespec->tv_sec = time; 669 timespec->tv_nsec = 0; 670 get_var_data_locked(efivars, &efivars->walk_entry->var); 671 size = efivars->walk_entry->var.DataSize; 672 *buf = kmalloc(size, GFP_KERNEL); 673 if (*buf == NULL) 674 return -ENOMEM; 675 memcpy(*buf, efivars->walk_entry->var.Data, 676 size); 677 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 678 struct efivar_entry, list); 679 return size; 680 } 681 } 682 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 683 struct efivar_entry, list); 684 } 685 return 0; 686} 687 688static int efi_pstore_write(enum pstore_type_id type, 689 enum kmsg_dump_reason reason, u64 *id, 690 unsigned int part, size_t size, struct pstore_info *psi) 691{ 692 char name[DUMP_NAME_LEN]; 693 char stub_name[DUMP_NAME_LEN]; 694 efi_char16_t efi_name[DUMP_NAME_LEN]; 695 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 696 struct efivars *efivars = psi->data; 697 struct efivar_entry *entry, *found = NULL; 698 int i, ret = 0; 699 700 sprintf(stub_name, "dump-type%u-%u-", type, part); 701 sprintf(name, "%s%lu", stub_name, get_seconds()); 702 703 spin_lock(&efivars->lock); 704 705 for (i = 0; i < DUMP_NAME_LEN; i++) 706 efi_name[i] = stub_name[i]; 707 708 /* 709 * Clean up any entries with the same name 710 */ 711 712 list_for_each_entry(entry, &efivars->list, list) { 713 get_var_data_locked(efivars, &entry->var); 714 715 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 716 continue; 717 if (utf16_strncmp(entry->var.VariableName, efi_name, 718 utf16_strlen(efi_name))) 719 continue; 720 /* Needs to be a prefix */ 721 if (entry->var.VariableName[utf16_strlen(efi_name)] == 0) 722 continue; 723 724 /* found */ 725 found = entry; 726 efivars->ops->set_variable(entry->var.VariableName, 727 &entry->var.VendorGuid, 728 PSTORE_EFI_ATTRIBUTES, 729 0, NULL); 730 } 731 732 if (found) 733 list_del(&found->list); 734 735 for (i = 0; i < DUMP_NAME_LEN; i++) 736 efi_name[i] = name[i]; 737 738 efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES, 739 size, psi->buf); 740 741 spin_unlock(&efivars->lock); 742 743 if (found) 744 efivar_unregister(found); 745 746 if (size) 747 ret = efivar_create_sysfs_entry(efivars, 748 utf16_strsize(efi_name, 749 DUMP_NAME_LEN * 2), 750 efi_name, &vendor); 751 752 *id = part; 753 return ret; 754}; 755 756static int efi_pstore_erase(enum pstore_type_id type, u64 id, 757 struct pstore_info *psi) 758{ 759 efi_pstore_write(type, 0, &id, (unsigned int)id, 0, psi); 760 761 return 0; 762} 763#else 764static int efi_pstore_open(struct pstore_info *psi) 765{ 766 return 0; 767} 768 769static int efi_pstore_close(struct pstore_info *psi) 770{ 771 return 0; 772} 773 774static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 775 struct timespec *timespec, 776 char **buf, struct pstore_info *psi) 777{ 778 return -1; 779} 780 781static int efi_pstore_write(enum pstore_type_id type, 782 enum kmsg_dump_reason reason, u64 *id, 783 unsigned int part, size_t size, struct pstore_info *psi) 784{ 785 return 0; 786} 787 788static int efi_pstore_erase(enum pstore_type_id type, u64 id, 789 struct pstore_info *psi) 790{ 791 return 0; 792} 793#endif 794 795static struct pstore_info efi_pstore_info = { 796 .owner = THIS_MODULE, 797 .name = "efi", 798 .open = efi_pstore_open, 799 .close = efi_pstore_close, 800 .read = efi_pstore_read, 801 .write = efi_pstore_write, 802 .erase = efi_pstore_erase, 803}; 804 805static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 806 struct bin_attribute *bin_attr, 807 char *buf, loff_t pos, size_t count) 808{ 809 struct efi_variable *new_var = (struct efi_variable *)buf; 810 struct efivars *efivars = bin_attr->private; 811 struct efivar_entry *search_efivar, *n; 812 unsigned long strsize1, strsize2; 813 efi_status_t status = EFI_NOT_FOUND; 814 int found = 0; 815 816 if (!capable(CAP_SYS_ADMIN)) 817 return -EACCES; 818 819 if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 820 validate_var(new_var, new_var->Data, new_var->DataSize) == false) { 821 printk(KERN_ERR "efivars: Malformed variable content\n"); 822 return -EINVAL; 823 } 824 825 spin_lock(&efivars->lock); 826 827 /* 828 * Does this variable already exist? 829 */ 830 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 831 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 832 strsize2 = utf16_strsize(new_var->VariableName, 1024); 833 if (strsize1 == strsize2 && 834 !memcmp(&(search_efivar->var.VariableName), 835 new_var->VariableName, strsize1) && 836 !efi_guidcmp(search_efivar->var.VendorGuid, 837 new_var->VendorGuid)) { 838 found = 1; 839 break; 840 } 841 } 842 if (found) { 843 spin_unlock(&efivars->lock); 844 return -EINVAL; 845 } 846 847 /* now *really* create the variable via EFI */ 848 status = efivars->ops->set_variable(new_var->VariableName, 849 &new_var->VendorGuid, 850 new_var->Attributes, 851 new_var->DataSize, 852 new_var->Data); 853 854 if (status != EFI_SUCCESS) { 855 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 856 status); 857 spin_unlock(&efivars->lock); 858 return -EIO; 859 } 860 spin_unlock(&efivars->lock); 861 862 /* Create the entry in sysfs. Locking is not required here */ 863 status = efivar_create_sysfs_entry(efivars, 864 utf16_strsize(new_var->VariableName, 865 1024), 866 new_var->VariableName, 867 &new_var->VendorGuid); 868 if (status) { 869 printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n"); 870 } 871 return count; 872} 873 874static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 875 struct bin_attribute *bin_attr, 876 char *buf, loff_t pos, size_t count) 877{ 878 struct efi_variable *del_var = (struct efi_variable *)buf; 879 struct efivars *efivars = bin_attr->private; 880 struct efivar_entry *search_efivar, *n; 881 unsigned long strsize1, strsize2; 882 efi_status_t status = EFI_NOT_FOUND; 883 int found = 0; 884 885 if (!capable(CAP_SYS_ADMIN)) 886 return -EACCES; 887 888 spin_lock(&efivars->lock); 889 890 /* 891 * Does this variable already exist? 892 */ 893 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 894 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 895 strsize2 = utf16_strsize(del_var->VariableName, 1024); 896 if (strsize1 == strsize2 && 897 !memcmp(&(search_efivar->var.VariableName), 898 del_var->VariableName, strsize1) && 899 !efi_guidcmp(search_efivar->var.VendorGuid, 900 del_var->VendorGuid)) { 901 found = 1; 902 break; 903 } 904 } 905 if (!found) { 906 spin_unlock(&efivars->lock); 907 return -EINVAL; 908 } 909 /* force the Attributes/DataSize to 0 to ensure deletion */ 910 del_var->Attributes = 0; 911 del_var->DataSize = 0; 912 913 status = efivars->ops->set_variable(del_var->VariableName, 914 &del_var->VendorGuid, 915 del_var->Attributes, 916 del_var->DataSize, 917 del_var->Data); 918 919 if (status != EFI_SUCCESS) { 920 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 921 status); 922 spin_unlock(&efivars->lock); 923 return -EIO; 924 } 925 list_del(&search_efivar->list); 926 /* We need to release this lock before unregistering. */ 927 spin_unlock(&efivars->lock); 928 efivar_unregister(search_efivar); 929 930 /* It's dead Jim.... */ 931 return count; 932} 933 934/* 935 * Let's not leave out systab information that snuck into 936 * the efivars driver 937 */ 938static ssize_t systab_show(struct kobject *kobj, 939 struct kobj_attribute *attr, char *buf) 940{ 941 char *str = buf; 942 943 if (!kobj || !buf) 944 return -EINVAL; 945 946 if (efi.mps != EFI_INVALID_TABLE_ADDR) 947 str += sprintf(str, "MPS=0x%lx\n", efi.mps); 948 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) 949 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 950 if (efi.acpi != EFI_INVALID_TABLE_ADDR) 951 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 952 if (efi.smbios != EFI_INVALID_TABLE_ADDR) 953 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 954 if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 955 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 956 if (efi.boot_info != EFI_INVALID_TABLE_ADDR) 957 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); 958 if (efi.uga != EFI_INVALID_TABLE_ADDR) 959 str += sprintf(str, "UGA=0x%lx\n", efi.uga); 960 961 return str - buf; 962} 963 964static struct kobj_attribute efi_attr_systab = 965 __ATTR(systab, 0400, systab_show, NULL); 966 967static struct attribute *efi_subsys_attrs[] = { 968 &efi_attr_systab.attr, 969 NULL, /* maybe more in the future? */ 970}; 971 972static struct attribute_group efi_subsys_attr_group = { 973 .attrs = efi_subsys_attrs, 974}; 975 976static struct kobject *efi_kobj; 977 978/* 979 * efivar_create_sysfs_entry() 980 * Requires: 981 * variable_name_size = number of bytes required to hold 982 * variable_name (not counting the NULL 983 * character at the end. 984 * efivars->lock is not held on entry or exit. 985 * Returns 1 on failure, 0 on success 986 */ 987static int 988efivar_create_sysfs_entry(struct efivars *efivars, 989 unsigned long variable_name_size, 990 efi_char16_t *variable_name, 991 efi_guid_t *vendor_guid) 992{ 993 int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; 994 char *short_name; 995 struct efivar_entry *new_efivar; 996 997 short_name = kzalloc(short_name_size + 1, GFP_KERNEL); 998 new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); 999 1000 if (!short_name || !new_efivar) { 1001 kfree(short_name); 1002 kfree(new_efivar); 1003 return 1; 1004 } 1005 1006 new_efivar->efivars = efivars; 1007 memcpy(new_efivar->var.VariableName, variable_name, 1008 variable_name_size); 1009 memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); 1010 1011 /* Convert Unicode to normal chars (assume top bits are 0), 1012 ala UTF-8 */ 1013 for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { 1014 short_name[i] = variable_name[i] & 0xFF; 1015 } 1016 /* This is ugly, but necessary to separate one vendor's 1017 private variables from another's. */ 1018 1019 *(short_name + strlen(short_name)) = '-'; 1020 efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); 1021 1022 new_efivar->kobj.kset = efivars->kset; 1023 i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL, 1024 "%s", short_name); 1025 if (i) { 1026 kfree(short_name); 1027 kfree(new_efivar); 1028 return 1; 1029 } 1030 1031 kobject_uevent(&new_efivar->kobj, KOBJ_ADD); 1032 kfree(short_name); 1033 short_name = NULL; 1034 1035 spin_lock(&efivars->lock); 1036 list_add(&new_efivar->list, &efivars->list); 1037 spin_unlock(&efivars->lock); 1038 1039 return 0; 1040} 1041 1042static int 1043create_efivars_bin_attributes(struct efivars *efivars) 1044{ 1045 struct bin_attribute *attr; 1046 int error; 1047 1048 /* new_var */ 1049 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 1050 if (!attr) 1051 return -ENOMEM; 1052 1053 attr->attr.name = "new_var"; 1054 attr->attr.mode = 0200; 1055 attr->write = efivar_create; 1056 attr->private = efivars; 1057 efivars->new_var = attr; 1058 1059 /* del_var */ 1060 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 1061 if (!attr) { 1062 error = -ENOMEM; 1063 goto out_free; 1064 } 1065 attr->attr.name = "del_var"; 1066 attr->attr.mode = 0200; 1067 attr->write = efivar_delete; 1068 attr->private = efivars; 1069 efivars->del_var = attr; 1070 1071 sysfs_bin_attr_init(efivars->new_var); 1072 sysfs_bin_attr_init(efivars->del_var); 1073 1074 /* Register */ 1075 error = sysfs_create_bin_file(&efivars->kset->kobj, 1076 efivars->new_var); 1077 if (error) { 1078 printk(KERN_ERR "efivars: unable to create new_var sysfs file" 1079 " due to error %d\n", error); 1080 goto out_free; 1081 } 1082 error = sysfs_create_bin_file(&efivars->kset->kobj, 1083 efivars->del_var); 1084 if (error) { 1085 printk(KERN_ERR "efivars: unable to create del_var sysfs file" 1086 " due to error %d\n", error); 1087 sysfs_remove_bin_file(&efivars->kset->kobj, 1088 efivars->new_var); 1089 goto out_free; 1090 } 1091 1092 return 0; 1093out_free: 1094 kfree(efivars->del_var); 1095 efivars->del_var = NULL; 1096 kfree(efivars->new_var); 1097 efivars->new_var = NULL; 1098 return error; 1099} 1100 1101void unregister_efivars(struct efivars *efivars) 1102{ 1103 struct efivar_entry *entry, *n; 1104 1105 list_for_each_entry_safe(entry, n, &efivars->list, list) { 1106 spin_lock(&efivars->lock); 1107 list_del(&entry->list); 1108 spin_unlock(&efivars->lock); 1109 efivar_unregister(entry); 1110 } 1111 if (efivars->new_var) 1112 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var); 1113 if (efivars->del_var) 1114 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); 1115 kfree(efivars->new_var); 1116 kfree(efivars->del_var); 1117 kset_unregister(efivars->kset); 1118} 1119EXPORT_SYMBOL_GPL(unregister_efivars); 1120 1121int register_efivars(struct efivars *efivars, 1122 const struct efivar_operations *ops, 1123 struct kobject *parent_kobj) 1124{ 1125 efi_status_t status = EFI_NOT_FOUND; 1126 efi_guid_t vendor_guid; 1127 efi_char16_t *variable_name; 1128 unsigned long variable_name_size = 1024; 1129 int error = 0; 1130 1131 variable_name = kzalloc(variable_name_size, GFP_KERNEL); 1132 if (!variable_name) { 1133 printk(KERN_ERR "efivars: Memory allocation failed.\n"); 1134 return -ENOMEM; 1135 } 1136 1137 spin_lock_init(&efivars->lock); 1138 INIT_LIST_HEAD(&efivars->list); 1139 efivars->ops = ops; 1140 1141 efivars->kset = kset_create_and_add("vars", NULL, parent_kobj); 1142 if (!efivars->kset) { 1143 printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 1144 error = -ENOMEM; 1145 goto out; 1146 } 1147 1148 /* 1149 * Per EFI spec, the maximum storage allocated for both 1150 * the variable name and variable data is 1024 bytes. 1151 */ 1152 1153 do { 1154 variable_name_size = 1024; 1155 1156 status = ops->get_next_variable(&variable_name_size, 1157 variable_name, 1158 &vendor_guid); 1159 switch (status) { 1160 case EFI_SUCCESS: 1161 efivar_create_sysfs_entry(efivars, 1162 variable_name_size, 1163 variable_name, 1164 &vendor_guid); 1165 break; 1166 case EFI_NOT_FOUND: 1167 break; 1168 default: 1169 printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n", 1170 status); 1171 status = EFI_NOT_FOUND; 1172 break; 1173 } 1174 } while (status != EFI_NOT_FOUND); 1175 1176 error = create_efivars_bin_attributes(efivars); 1177 if (error) 1178 unregister_efivars(efivars); 1179 1180 efivars->efi_pstore_info = efi_pstore_info; 1181 1182 efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 1183 if (efivars->efi_pstore_info.buf) { 1184 efivars->efi_pstore_info.bufsize = 1024; 1185 efivars->efi_pstore_info.data = efivars; 1186 spin_lock_init(&efivars->efi_pstore_info.buf_lock); 1187 pstore_register(&efivars->efi_pstore_info); 1188 } 1189 1190out: 1191 kfree(variable_name); 1192 1193 return error; 1194} 1195EXPORT_SYMBOL_GPL(register_efivars); 1196 1197static struct efivars __efivars; 1198static struct efivar_operations ops; 1199 1200/* 1201 * For now we register the efi subsystem with the firmware subsystem 1202 * and the vars subsystem with the efi subsystem. In the future, it 1203 * might make sense to split off the efi subsystem into its own 1204 * driver, but for now only efivars will register with it, so just 1205 * include it here. 1206 */ 1207 1208static int __init 1209efivars_init(void) 1210{ 1211 int error = 0; 1212 1213 printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 1214 EFIVARS_DATE); 1215 1216 if (!efi_enabled) 1217 return 0; 1218 1219 /* For now we'll register the efi directory at /sys/firmware/efi */ 1220 efi_kobj = kobject_create_and_add("efi", firmware_kobj); 1221 if (!efi_kobj) { 1222 printk(KERN_ERR "efivars: Firmware registration failed.\n"); 1223 return -ENOMEM; 1224 } 1225 1226 ops.get_variable = efi.get_variable; 1227 ops.set_variable = efi.set_variable; 1228 ops.get_next_variable = efi.get_next_variable; 1229 error = register_efivars(&__efivars, &ops, efi_kobj); 1230 if (error) 1231 goto err_put; 1232 1233 /* Don't forget the systab entry */ 1234 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); 1235 if (error) { 1236 printk(KERN_ERR 1237 "efivars: Sysfs attribute export failed with error %d.\n", 1238 error); 1239 goto err_unregister; 1240 } 1241 1242 return 0; 1243 1244err_unregister: 1245 unregister_efivars(&__efivars); 1246err_put: 1247 kobject_put(efi_kobj); 1248 return error; 1249} 1250 1251static void __exit 1252efivars_exit(void) 1253{ 1254 if (efi_enabled) { 1255 unregister_efivars(&__efivars); 1256 kobject_put(efi_kobj); 1257 } 1258} 1259 1260module_init(efivars_init); 1261module_exit(efivars_exit); 1262