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.7-rc3 1273 lines 33 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 & EFI_VARIABLE_NON_VOLATILE) 439 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); 440 if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) 441 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); 442 if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) 443 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); 444 if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) 445 str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); 446 if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) 447 str += sprintf(str, 448 "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); 449 if (var->Attributes & 450 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) 451 str += sprintf(str, 452 "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); 453 if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) 454 str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); 455 return str - buf; 456} 457 458static ssize_t 459efivar_size_read(struct efivar_entry *entry, char *buf) 460{ 461 struct efi_variable *var = &entry->var; 462 char *str = buf; 463 efi_status_t status; 464 465 if (!entry || !buf) 466 return -EINVAL; 467 468 status = get_var_data(entry->efivars, var); 469 if (status != EFI_SUCCESS) 470 return -EIO; 471 472 str += sprintf(str, "0x%lx\n", var->DataSize); 473 return str - buf; 474} 475 476static ssize_t 477efivar_data_read(struct efivar_entry *entry, char *buf) 478{ 479 struct efi_variable *var = &entry->var; 480 efi_status_t status; 481 482 if (!entry || !buf) 483 return -EINVAL; 484 485 status = get_var_data(entry->efivars, var); 486 if (status != EFI_SUCCESS) 487 return -EIO; 488 489 memcpy(buf, var->Data, var->DataSize); 490 return var->DataSize; 491} 492/* 493 * We allow each variable to be edited via rewriting the 494 * entire efi variable structure. 495 */ 496static ssize_t 497efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) 498{ 499 struct efi_variable *new_var, *var = &entry->var; 500 struct efivars *efivars = entry->efivars; 501 efi_status_t status = EFI_NOT_FOUND; 502 503 if (count != sizeof(struct efi_variable)) 504 return -EINVAL; 505 506 new_var = (struct efi_variable *)buf; 507 /* 508 * If only updating the variable data, then the name 509 * and guid should remain the same 510 */ 511 if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) || 512 efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) { 513 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); 514 return -EINVAL; 515 } 516 517 if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){ 518 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); 519 return -EINVAL; 520 } 521 522 if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 523 validate_var(new_var, new_var->Data, new_var->DataSize) == false) { 524 printk(KERN_ERR "efivars: Malformed variable content\n"); 525 return -EINVAL; 526 } 527 528 spin_lock(&efivars->lock); 529 status = efivars->ops->set_variable(new_var->VariableName, 530 &new_var->VendorGuid, 531 new_var->Attributes, 532 new_var->DataSize, 533 new_var->Data); 534 535 spin_unlock(&efivars->lock); 536 537 if (status != EFI_SUCCESS) { 538 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 539 status); 540 return -EIO; 541 } 542 543 memcpy(&entry->var, new_var, count); 544 return count; 545} 546 547static ssize_t 548efivar_show_raw(struct efivar_entry *entry, char *buf) 549{ 550 struct efi_variable *var = &entry->var; 551 efi_status_t status; 552 553 if (!entry || !buf) 554 return 0; 555 556 status = get_var_data(entry->efivars, var); 557 if (status != EFI_SUCCESS) 558 return -EIO; 559 560 memcpy(buf, var, sizeof(*var)); 561 return sizeof(*var); 562} 563 564/* 565 * Generic read/write functions that call the specific functions of 566 * the attributes... 567 */ 568static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr, 569 char *buf) 570{ 571 struct efivar_entry *var = to_efivar_entry(kobj); 572 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 573 ssize_t ret = -EIO; 574 575 if (!capable(CAP_SYS_ADMIN)) 576 return -EACCES; 577 578 if (efivar_attr->show) { 579 ret = efivar_attr->show(var, buf); 580 } 581 return ret; 582} 583 584static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, 585 const char *buf, size_t count) 586{ 587 struct efivar_entry *var = to_efivar_entry(kobj); 588 struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 589 ssize_t ret = -EIO; 590 591 if (!capable(CAP_SYS_ADMIN)) 592 return -EACCES; 593 594 if (efivar_attr->store) 595 ret = efivar_attr->store(var, buf, count); 596 597 return ret; 598} 599 600static const struct sysfs_ops efivar_attr_ops = { 601 .show = efivar_attr_show, 602 .store = efivar_attr_store, 603}; 604 605static void efivar_release(struct kobject *kobj) 606{ 607 struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); 608 kfree(var); 609} 610 611static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL); 612static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL); 613static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL); 614static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL); 615static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw); 616 617static struct attribute *def_attrs[] = { 618 &efivar_attr_guid.attr, 619 &efivar_attr_size.attr, 620 &efivar_attr_attributes.attr, 621 &efivar_attr_data.attr, 622 &efivar_attr_raw_var.attr, 623 NULL, 624}; 625 626static struct kobj_type efivar_ktype = { 627 .release = efivar_release, 628 .sysfs_ops = &efivar_attr_ops, 629 .default_attrs = def_attrs, 630}; 631 632static struct pstore_info efi_pstore_info; 633 634static inline void 635efivar_unregister(struct efivar_entry *var) 636{ 637 kobject_put(&var->kobj); 638} 639 640#ifdef CONFIG_PSTORE 641 642static int efi_pstore_open(struct pstore_info *psi) 643{ 644 struct efivars *efivars = psi->data; 645 646 spin_lock(&efivars->lock); 647 efivars->walk_entry = list_first_entry(&efivars->list, 648 struct efivar_entry, list); 649 return 0; 650} 651 652static int efi_pstore_close(struct pstore_info *psi) 653{ 654 struct efivars *efivars = psi->data; 655 656 spin_unlock(&efivars->lock); 657 return 0; 658} 659 660static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 661 struct timespec *timespec, 662 char **buf, struct pstore_info *psi) 663{ 664 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 665 struct efivars *efivars = psi->data; 666 char name[DUMP_NAME_LEN]; 667 int i; 668 unsigned int part, size; 669 unsigned long time; 670 671 while (&efivars->walk_entry->list != &efivars->list) { 672 if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid, 673 vendor)) { 674 for (i = 0; i < DUMP_NAME_LEN; i++) { 675 name[i] = efivars->walk_entry->var.VariableName[i]; 676 } 677 if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) { 678 *id = part; 679 timespec->tv_sec = time; 680 timespec->tv_nsec = 0; 681 get_var_data_locked(efivars, &efivars->walk_entry->var); 682 size = efivars->walk_entry->var.DataSize; 683 *buf = kmalloc(size, GFP_KERNEL); 684 if (*buf == NULL) 685 return -ENOMEM; 686 memcpy(*buf, efivars->walk_entry->var.Data, 687 size); 688 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 689 struct efivar_entry, list); 690 return size; 691 } 692 } 693 efivars->walk_entry = list_entry(efivars->walk_entry->list.next, 694 struct efivar_entry, list); 695 } 696 return 0; 697} 698 699static int efi_pstore_write(enum pstore_type_id type, 700 enum kmsg_dump_reason reason, u64 *id, 701 unsigned int part, size_t size, struct pstore_info *psi) 702{ 703 char name[DUMP_NAME_LEN]; 704 char stub_name[DUMP_NAME_LEN]; 705 efi_char16_t efi_name[DUMP_NAME_LEN]; 706 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 707 struct efivars *efivars = psi->data; 708 struct efivar_entry *entry, *found = NULL; 709 int i, ret = 0; 710 711 sprintf(stub_name, "dump-type%u-%u-", type, part); 712 sprintf(name, "%s%lu", stub_name, get_seconds()); 713 714 spin_lock(&efivars->lock); 715 716 for (i = 0; i < DUMP_NAME_LEN; i++) 717 efi_name[i] = stub_name[i]; 718 719 /* 720 * Clean up any entries with the same name 721 */ 722 723 list_for_each_entry(entry, &efivars->list, list) { 724 get_var_data_locked(efivars, &entry->var); 725 726 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 727 continue; 728 if (utf16_strncmp(entry->var.VariableName, efi_name, 729 utf16_strlen(efi_name))) 730 continue; 731 /* Needs to be a prefix */ 732 if (entry->var.VariableName[utf16_strlen(efi_name)] == 0) 733 continue; 734 735 /* found */ 736 found = entry; 737 efivars->ops->set_variable(entry->var.VariableName, 738 &entry->var.VendorGuid, 739 PSTORE_EFI_ATTRIBUTES, 740 0, NULL); 741 } 742 743 if (found) 744 list_del(&found->list); 745 746 for (i = 0; i < DUMP_NAME_LEN; i++) 747 efi_name[i] = name[i]; 748 749 efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES, 750 size, psi->buf); 751 752 spin_unlock(&efivars->lock); 753 754 if (found) 755 efivar_unregister(found); 756 757 if (size) 758 ret = efivar_create_sysfs_entry(efivars, 759 utf16_strsize(efi_name, 760 DUMP_NAME_LEN * 2), 761 efi_name, &vendor); 762 763 *id = part; 764 return ret; 765}; 766 767static int efi_pstore_erase(enum pstore_type_id type, u64 id, 768 struct pstore_info *psi) 769{ 770 efi_pstore_write(type, 0, &id, (unsigned int)id, 0, psi); 771 772 return 0; 773} 774#else 775static int efi_pstore_open(struct pstore_info *psi) 776{ 777 return 0; 778} 779 780static int efi_pstore_close(struct pstore_info *psi) 781{ 782 return 0; 783} 784 785static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 786 struct timespec *timespec, 787 char **buf, struct pstore_info *psi) 788{ 789 return -1; 790} 791 792static int efi_pstore_write(enum pstore_type_id type, 793 enum kmsg_dump_reason reason, u64 *id, 794 unsigned int part, size_t size, struct pstore_info *psi) 795{ 796 return 0; 797} 798 799static int efi_pstore_erase(enum pstore_type_id type, u64 id, 800 struct pstore_info *psi) 801{ 802 return 0; 803} 804#endif 805 806static struct pstore_info efi_pstore_info = { 807 .owner = THIS_MODULE, 808 .name = "efi", 809 .open = efi_pstore_open, 810 .close = efi_pstore_close, 811 .read = efi_pstore_read, 812 .write = efi_pstore_write, 813 .erase = efi_pstore_erase, 814}; 815 816static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 817 struct bin_attribute *bin_attr, 818 char *buf, loff_t pos, size_t count) 819{ 820 struct efi_variable *new_var = (struct efi_variable *)buf; 821 struct efivars *efivars = bin_attr->private; 822 struct efivar_entry *search_efivar, *n; 823 unsigned long strsize1, strsize2; 824 efi_status_t status = EFI_NOT_FOUND; 825 int found = 0; 826 827 if (!capable(CAP_SYS_ADMIN)) 828 return -EACCES; 829 830 if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 831 validate_var(new_var, new_var->Data, new_var->DataSize) == false) { 832 printk(KERN_ERR "efivars: Malformed variable content\n"); 833 return -EINVAL; 834 } 835 836 spin_lock(&efivars->lock); 837 838 /* 839 * Does this variable already exist? 840 */ 841 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 842 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 843 strsize2 = utf16_strsize(new_var->VariableName, 1024); 844 if (strsize1 == strsize2 && 845 !memcmp(&(search_efivar->var.VariableName), 846 new_var->VariableName, strsize1) && 847 !efi_guidcmp(search_efivar->var.VendorGuid, 848 new_var->VendorGuid)) { 849 found = 1; 850 break; 851 } 852 } 853 if (found) { 854 spin_unlock(&efivars->lock); 855 return -EINVAL; 856 } 857 858 /* now *really* create the variable via EFI */ 859 status = efivars->ops->set_variable(new_var->VariableName, 860 &new_var->VendorGuid, 861 new_var->Attributes, 862 new_var->DataSize, 863 new_var->Data); 864 865 if (status != EFI_SUCCESS) { 866 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 867 status); 868 spin_unlock(&efivars->lock); 869 return -EIO; 870 } 871 spin_unlock(&efivars->lock); 872 873 /* Create the entry in sysfs. Locking is not required here */ 874 status = efivar_create_sysfs_entry(efivars, 875 utf16_strsize(new_var->VariableName, 876 1024), 877 new_var->VariableName, 878 &new_var->VendorGuid); 879 if (status) { 880 printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n"); 881 } 882 return count; 883} 884 885static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 886 struct bin_attribute *bin_attr, 887 char *buf, loff_t pos, size_t count) 888{ 889 struct efi_variable *del_var = (struct efi_variable *)buf; 890 struct efivars *efivars = bin_attr->private; 891 struct efivar_entry *search_efivar, *n; 892 unsigned long strsize1, strsize2; 893 efi_status_t status = EFI_NOT_FOUND; 894 int found = 0; 895 896 if (!capable(CAP_SYS_ADMIN)) 897 return -EACCES; 898 899 spin_lock(&efivars->lock); 900 901 /* 902 * Does this variable already exist? 903 */ 904 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 905 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 906 strsize2 = utf16_strsize(del_var->VariableName, 1024); 907 if (strsize1 == strsize2 && 908 !memcmp(&(search_efivar->var.VariableName), 909 del_var->VariableName, strsize1) && 910 !efi_guidcmp(search_efivar->var.VendorGuid, 911 del_var->VendorGuid)) { 912 found = 1; 913 break; 914 } 915 } 916 if (!found) { 917 spin_unlock(&efivars->lock); 918 return -EINVAL; 919 } 920 /* force the Attributes/DataSize to 0 to ensure deletion */ 921 del_var->Attributes = 0; 922 del_var->DataSize = 0; 923 924 status = efivars->ops->set_variable(del_var->VariableName, 925 &del_var->VendorGuid, 926 del_var->Attributes, 927 del_var->DataSize, 928 del_var->Data); 929 930 if (status != EFI_SUCCESS) { 931 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", 932 status); 933 spin_unlock(&efivars->lock); 934 return -EIO; 935 } 936 list_del(&search_efivar->list); 937 /* We need to release this lock before unregistering. */ 938 spin_unlock(&efivars->lock); 939 efivar_unregister(search_efivar); 940 941 /* It's dead Jim.... */ 942 return count; 943} 944 945/* 946 * Let's not leave out systab information that snuck into 947 * the efivars driver 948 */ 949static ssize_t systab_show(struct kobject *kobj, 950 struct kobj_attribute *attr, char *buf) 951{ 952 char *str = buf; 953 954 if (!kobj || !buf) 955 return -EINVAL; 956 957 if (efi.mps != EFI_INVALID_TABLE_ADDR) 958 str += sprintf(str, "MPS=0x%lx\n", efi.mps); 959 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) 960 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 961 if (efi.acpi != EFI_INVALID_TABLE_ADDR) 962 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 963 if (efi.smbios != EFI_INVALID_TABLE_ADDR) 964 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 965 if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 966 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 967 if (efi.boot_info != EFI_INVALID_TABLE_ADDR) 968 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); 969 if (efi.uga != EFI_INVALID_TABLE_ADDR) 970 str += sprintf(str, "UGA=0x%lx\n", efi.uga); 971 972 return str - buf; 973} 974 975static struct kobj_attribute efi_attr_systab = 976 __ATTR(systab, 0400, systab_show, NULL); 977 978static struct attribute *efi_subsys_attrs[] = { 979 &efi_attr_systab.attr, 980 NULL, /* maybe more in the future? */ 981}; 982 983static struct attribute_group efi_subsys_attr_group = { 984 .attrs = efi_subsys_attrs, 985}; 986 987static struct kobject *efi_kobj; 988 989/* 990 * efivar_create_sysfs_entry() 991 * Requires: 992 * variable_name_size = number of bytes required to hold 993 * variable_name (not counting the NULL 994 * character at the end. 995 * efivars->lock is not held on entry or exit. 996 * Returns 1 on failure, 0 on success 997 */ 998static int 999efivar_create_sysfs_entry(struct efivars *efivars, 1000 unsigned long variable_name_size, 1001 efi_char16_t *variable_name, 1002 efi_guid_t *vendor_guid) 1003{ 1004 int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; 1005 char *short_name; 1006 struct efivar_entry *new_efivar; 1007 1008 short_name = kzalloc(short_name_size + 1, GFP_KERNEL); 1009 new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); 1010 1011 if (!short_name || !new_efivar) { 1012 kfree(short_name); 1013 kfree(new_efivar); 1014 return 1; 1015 } 1016 1017 new_efivar->efivars = efivars; 1018 memcpy(new_efivar->var.VariableName, variable_name, 1019 variable_name_size); 1020 memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); 1021 1022 /* Convert Unicode to normal chars (assume top bits are 0), 1023 ala UTF-8 */ 1024 for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { 1025 short_name[i] = variable_name[i] & 0xFF; 1026 } 1027 /* This is ugly, but necessary to separate one vendor's 1028 private variables from another's. */ 1029 1030 *(short_name + strlen(short_name)) = '-'; 1031 efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); 1032 1033 new_efivar->kobj.kset = efivars->kset; 1034 i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL, 1035 "%s", short_name); 1036 if (i) { 1037 kfree(short_name); 1038 kfree(new_efivar); 1039 return 1; 1040 } 1041 1042 kobject_uevent(&new_efivar->kobj, KOBJ_ADD); 1043 kfree(short_name); 1044 short_name = NULL; 1045 1046 spin_lock(&efivars->lock); 1047 list_add(&new_efivar->list, &efivars->list); 1048 spin_unlock(&efivars->lock); 1049 1050 return 0; 1051} 1052 1053static int 1054create_efivars_bin_attributes(struct efivars *efivars) 1055{ 1056 struct bin_attribute *attr; 1057 int error; 1058 1059 /* new_var */ 1060 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 1061 if (!attr) 1062 return -ENOMEM; 1063 1064 attr->attr.name = "new_var"; 1065 attr->attr.mode = 0200; 1066 attr->write = efivar_create; 1067 attr->private = efivars; 1068 efivars->new_var = attr; 1069 1070 /* del_var */ 1071 attr = kzalloc(sizeof(*attr), GFP_KERNEL); 1072 if (!attr) { 1073 error = -ENOMEM; 1074 goto out_free; 1075 } 1076 attr->attr.name = "del_var"; 1077 attr->attr.mode = 0200; 1078 attr->write = efivar_delete; 1079 attr->private = efivars; 1080 efivars->del_var = attr; 1081 1082 sysfs_bin_attr_init(efivars->new_var); 1083 sysfs_bin_attr_init(efivars->del_var); 1084 1085 /* Register */ 1086 error = sysfs_create_bin_file(&efivars->kset->kobj, 1087 efivars->new_var); 1088 if (error) { 1089 printk(KERN_ERR "efivars: unable to create new_var sysfs file" 1090 " due to error %d\n", error); 1091 goto out_free; 1092 } 1093 error = sysfs_create_bin_file(&efivars->kset->kobj, 1094 efivars->del_var); 1095 if (error) { 1096 printk(KERN_ERR "efivars: unable to create del_var sysfs file" 1097 " due to error %d\n", error); 1098 sysfs_remove_bin_file(&efivars->kset->kobj, 1099 efivars->new_var); 1100 goto out_free; 1101 } 1102 1103 return 0; 1104out_free: 1105 kfree(efivars->del_var); 1106 efivars->del_var = NULL; 1107 kfree(efivars->new_var); 1108 efivars->new_var = NULL; 1109 return error; 1110} 1111 1112void unregister_efivars(struct efivars *efivars) 1113{ 1114 struct efivar_entry *entry, *n; 1115 1116 list_for_each_entry_safe(entry, n, &efivars->list, list) { 1117 spin_lock(&efivars->lock); 1118 list_del(&entry->list); 1119 spin_unlock(&efivars->lock); 1120 efivar_unregister(entry); 1121 } 1122 if (efivars->new_var) 1123 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var); 1124 if (efivars->del_var) 1125 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); 1126 kfree(efivars->new_var); 1127 kfree(efivars->del_var); 1128 kset_unregister(efivars->kset); 1129} 1130EXPORT_SYMBOL_GPL(unregister_efivars); 1131 1132int register_efivars(struct efivars *efivars, 1133 const struct efivar_operations *ops, 1134 struct kobject *parent_kobj) 1135{ 1136 efi_status_t status = EFI_NOT_FOUND; 1137 efi_guid_t vendor_guid; 1138 efi_char16_t *variable_name; 1139 unsigned long variable_name_size = 1024; 1140 int error = 0; 1141 1142 variable_name = kzalloc(variable_name_size, GFP_KERNEL); 1143 if (!variable_name) { 1144 printk(KERN_ERR "efivars: Memory allocation failed.\n"); 1145 return -ENOMEM; 1146 } 1147 1148 spin_lock_init(&efivars->lock); 1149 INIT_LIST_HEAD(&efivars->list); 1150 efivars->ops = ops; 1151 1152 efivars->kset = kset_create_and_add("vars", NULL, parent_kobj); 1153 if (!efivars->kset) { 1154 printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 1155 error = -ENOMEM; 1156 goto out; 1157 } 1158 1159 /* 1160 * Per EFI spec, the maximum storage allocated for both 1161 * the variable name and variable data is 1024 bytes. 1162 */ 1163 1164 do { 1165 variable_name_size = 1024; 1166 1167 status = ops->get_next_variable(&variable_name_size, 1168 variable_name, 1169 &vendor_guid); 1170 switch (status) { 1171 case EFI_SUCCESS: 1172 efivar_create_sysfs_entry(efivars, 1173 variable_name_size, 1174 variable_name, 1175 &vendor_guid); 1176 break; 1177 case EFI_NOT_FOUND: 1178 break; 1179 default: 1180 printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n", 1181 status); 1182 status = EFI_NOT_FOUND; 1183 break; 1184 } 1185 } while (status != EFI_NOT_FOUND); 1186 1187 error = create_efivars_bin_attributes(efivars); 1188 if (error) 1189 unregister_efivars(efivars); 1190 1191 efivars->efi_pstore_info = efi_pstore_info; 1192 1193 efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 1194 if (efivars->efi_pstore_info.buf) { 1195 efivars->efi_pstore_info.bufsize = 1024; 1196 efivars->efi_pstore_info.data = efivars; 1197 spin_lock_init(&efivars->efi_pstore_info.buf_lock); 1198 pstore_register(&efivars->efi_pstore_info); 1199 } 1200 1201out: 1202 kfree(variable_name); 1203 1204 return error; 1205} 1206EXPORT_SYMBOL_GPL(register_efivars); 1207 1208static struct efivars __efivars; 1209static struct efivar_operations ops; 1210 1211/* 1212 * For now we register the efi subsystem with the firmware subsystem 1213 * and the vars subsystem with the efi subsystem. In the future, it 1214 * might make sense to split off the efi subsystem into its own 1215 * driver, but for now only efivars will register with it, so just 1216 * include it here. 1217 */ 1218 1219static int __init 1220efivars_init(void) 1221{ 1222 int error = 0; 1223 1224 printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 1225 EFIVARS_DATE); 1226 1227 if (!efi_enabled) 1228 return 0; 1229 1230 /* For now we'll register the efi directory at /sys/firmware/efi */ 1231 efi_kobj = kobject_create_and_add("efi", firmware_kobj); 1232 if (!efi_kobj) { 1233 printk(KERN_ERR "efivars: Firmware registration failed.\n"); 1234 return -ENOMEM; 1235 } 1236 1237 ops.get_variable = efi.get_variable; 1238 ops.set_variable = efi.set_variable; 1239 ops.get_next_variable = efi.get_next_variable; 1240 error = register_efivars(&__efivars, &ops, efi_kobj); 1241 if (error) 1242 goto err_put; 1243 1244 /* Don't forget the systab entry */ 1245 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); 1246 if (error) { 1247 printk(KERN_ERR 1248 "efivars: Sysfs attribute export failed with error %d.\n", 1249 error); 1250 goto err_unregister; 1251 } 1252 1253 return 0; 1254 1255err_unregister: 1256 unregister_efivars(&__efivars); 1257err_put: 1258 kobject_put(efi_kobj); 1259 return error; 1260} 1261 1262static void __exit 1263efivars_exit(void) 1264{ 1265 if (efi_enabled) { 1266 unregister_efivars(&__efivars); 1267 kobject_put(efi_kobj); 1268 } 1269} 1270 1271module_init(efivars_init); 1272module_exit(efivars_exit); 1273