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

efi: split efisubsystem from efivars

This registers /sys/firmware/efi/{,systab,efivars/} whenever EFI is enabled
and the system is booted with EFI.

This allows
*) userspace to check for the existence of /sys/firmware/efi as a way
to determine whether or it is running on an EFI system.
*) 'mount -t efivarfs none /sys/firmware/efi/efivars' without manually
loading any modules.

[ Also, move the efivar API into vars.c and unconditionally compile it.
This allows us to move efivars.c, which now only contains the sysfs
variable code, into the firmware/efi directory. Note that the efivars.c
filename is kept to maintain backwards compatability with the old
efivars.ko module. With this patch it is now possible for efivarfs
to be built without CONFIG_EFI_VARS - Matt ]

Cc: Seiji Aguchi <seiji.aguchi@hds.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Mike Waychison <mikew@google.com>
Cc: Kay Sievers <kay@vrfy.org>
Cc: Jeremy Kerr <jk@ozlabs.org>
Cc: Matthew Garrett <mjg59@srcf.ucam.org>
Cc: Chun-Yi Lee <jlee@suse.com>
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Tobias Powalowski <tpowa@archlinux.org>
Signed-off-by: Tom Gundersen <teg@jklm.no>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>

authored by

Tom Gundersen and committed by
Matt Fleming
a9499fa7 d68772b7

+769 -761
+1 -1
MAINTAINERS
··· 2987 2987 F: arch/x86/boot/compressed/eboot.[ch] 2988 2988 F: arch/x86/include/asm/efi.h 2989 2989 F: arch/x86/platform/efi/* 2990 - F: drivers/firmware/efivars.c 2990 + F: drivers/firmware/efi/* 2991 2991 F: include/linux/efi*.h 2992 2992 2993 2993 EFI VARIABLE FILESYSTEM
-1
drivers/firmware/Makefile
··· 4 4 obj-$(CONFIG_DMI) += dmi_scan.o 5 5 obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o 6 6 obj-$(CONFIG_EDD) += edd.o 7 - obj-$(CONFIG_EFI_VARS) += efivars.o 8 7 obj-$(CONFIG_EFI_PCDP) += pcdp.o 9 8 obj-$(CONFIG_DELL_RBU) += dell_rbu.o 10 9 obj-$(CONFIG_DCDBAS) += dcdbas.o
+2
drivers/firmware/efi/Makefile
··· 1 1 # 2 2 # Makefile for linux kernel 3 3 # 4 + obj-y += efi.o vars.o 5 + obj-$(CONFIG_EFI_VARS) += efivars.o 4 6 obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
+134
drivers/firmware/efi/efi.c
··· 1 + /* 2 + * efi.c - EFI subsystem 3 + * 4 + * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com> 5 + * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com> 6 + * Copyright (C) 2013 Tom Gundersen <teg@jklm.no> 7 + * 8 + * This code registers /sys/firmware/efi{,/efivars} when EFI is supported, 9 + * allowing the efivarfs to be mounted or the efivars module to be loaded. 10 + * The existance of /sys/firmware/efi may also be used by userspace to 11 + * determine that the system supports EFI. 12 + * 13 + * This file is released under the GPLv2. 14 + */ 15 + 16 + #include <linux/kobject.h> 17 + #include <linux/module.h> 18 + #include <linux/init.h> 19 + #include <linux/device.h> 20 + #include <linux/efi.h> 21 + 22 + static struct kobject *efi_kobj; 23 + static struct kobject *efivars_kobj; 24 + 25 + /* 26 + * Let's not leave out systab information that snuck into 27 + * the efivars driver 28 + */ 29 + static ssize_t systab_show(struct kobject *kobj, 30 + struct kobj_attribute *attr, char *buf) 31 + { 32 + char *str = buf; 33 + 34 + if (!kobj || !buf) 35 + return -EINVAL; 36 + 37 + if (efi.mps != EFI_INVALID_TABLE_ADDR) 38 + str += sprintf(str, "MPS=0x%lx\n", efi.mps); 39 + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) 40 + str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 41 + if (efi.acpi != EFI_INVALID_TABLE_ADDR) 42 + str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 43 + if (efi.smbios != EFI_INVALID_TABLE_ADDR) 44 + str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 45 + if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 46 + str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 47 + if (efi.boot_info != EFI_INVALID_TABLE_ADDR) 48 + str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); 49 + if (efi.uga != EFI_INVALID_TABLE_ADDR) 50 + str += sprintf(str, "UGA=0x%lx\n", efi.uga); 51 + 52 + return str - buf; 53 + } 54 + 55 + static struct kobj_attribute efi_attr_systab = 56 + __ATTR(systab, 0400, systab_show, NULL); 57 + 58 + static struct attribute *efi_subsys_attrs[] = { 59 + &efi_attr_systab.attr, 60 + NULL, /* maybe more in the future? */ 61 + }; 62 + 63 + static struct attribute_group efi_subsys_attr_group = { 64 + .attrs = efi_subsys_attrs, 65 + }; 66 + 67 + static struct efivars generic_efivars; 68 + static struct efivar_operations generic_ops; 69 + 70 + static int generic_ops_register(void) 71 + { 72 + generic_ops.get_variable = efi.get_variable; 73 + generic_ops.set_variable = efi.set_variable; 74 + generic_ops.get_next_variable = efi.get_next_variable; 75 + generic_ops.query_variable_info = efi.query_variable_info; 76 + 77 + return efivars_register(&generic_efivars, &generic_ops, efi_kobj); 78 + } 79 + 80 + static void generic_ops_unregister(void) 81 + { 82 + efivars_unregister(&generic_efivars); 83 + } 84 + 85 + /* 86 + * We register the efi subsystem with the firmware subsystem and the 87 + * efivars subsystem with the efi subsystem, if the system was booted with 88 + * EFI. 89 + */ 90 + static int __init efisubsys_init(void) 91 + { 92 + int error; 93 + 94 + if (!efi_enabled(EFI_BOOT)) 95 + return 0; 96 + 97 + /* We register the efi directory at /sys/firmware/efi */ 98 + efi_kobj = kobject_create_and_add("efi", firmware_kobj); 99 + if (!efi_kobj) { 100 + pr_err("efi: Firmware registration failed.\n"); 101 + return -ENOMEM; 102 + } 103 + 104 + error = generic_ops_register(); 105 + if (error) 106 + goto err_put; 107 + 108 + error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); 109 + if (error) { 110 + pr_err("efi: Sysfs attribute export failed with error %d.\n", 111 + error); 112 + goto err_unregister; 113 + } 114 + 115 + /* and the standard mountpoint for efivarfs */ 116 + efivars_kobj = kobject_create_and_add("efivars", efi_kobj); 117 + if (!efivars_kobj) { 118 + pr_err("efivars: Subsystem registration failed.\n"); 119 + error = -ENOMEM; 120 + goto err_remove_group; 121 + } 122 + 123 + return 0; 124 + 125 + err_remove_group: 126 + sysfs_remove_group(efi_kobj, &efi_subsys_attr_group); 127 + err_unregister: 128 + generic_ops_unregister(); 129 + err_put: 130 + kobject_put(efi_kobj); 131 + return error; 132 + } 133 + 134 + subsys_initcall(efisubsys_init);
+617
drivers/firmware/efi/efivars.c
··· 1 + /* 2 + * Originally from 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/efi.h> 69 + #include <linux/module.h> 70 + 71 + #define EFIVARS_VERSION "0.08" 72 + #define EFIVARS_DATE "2004-May-17" 73 + 74 + MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); 75 + MODULE_DESCRIPTION("sysfs interface to EFI Variables"); 76 + MODULE_LICENSE("GPL"); 77 + MODULE_VERSION(EFIVARS_VERSION); 78 + 79 + LIST_HEAD(efivar_sysfs_list); 80 + EXPORT_SYMBOL_GPL(efivar_sysfs_list); 81 + 82 + static struct kset *efivars_kset; 83 + 84 + static struct bin_attribute *efivars_new_var; 85 + static struct bin_attribute *efivars_del_var; 86 + 87 + struct efivar_attribute { 88 + struct attribute attr; 89 + ssize_t (*show) (struct efivar_entry *entry, char *buf); 90 + ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); 91 + }; 92 + 93 + #define EFIVAR_ATTR(_name, _mode, _show, _store) \ 94 + struct efivar_attribute efivar_attr_##_name = { \ 95 + .attr = {.name = __stringify(_name), .mode = _mode}, \ 96 + .show = _show, \ 97 + .store = _store, \ 98 + }; 99 + 100 + #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr) 101 + #define to_efivar_entry(obj) container_of(obj, struct efivar_entry, kobj) 102 + 103 + /* 104 + * Prototype for sysfs creation function 105 + */ 106 + static int 107 + efivar_create_sysfs_entry(struct efivar_entry *new_var); 108 + 109 + static ssize_t 110 + efivar_guid_read(struct efivar_entry *entry, char *buf) 111 + { 112 + struct efi_variable *var = &entry->var; 113 + char *str = buf; 114 + 115 + if (!entry || !buf) 116 + return 0; 117 + 118 + efi_guid_unparse(&var->VendorGuid, str); 119 + str += strlen(str); 120 + str += sprintf(str, "\n"); 121 + 122 + return str - buf; 123 + } 124 + 125 + static ssize_t 126 + efivar_attr_read(struct efivar_entry *entry, char *buf) 127 + { 128 + struct efi_variable *var = &entry->var; 129 + char *str = buf; 130 + 131 + if (!entry || !buf) 132 + return -EINVAL; 133 + 134 + var->DataSize = 1024; 135 + if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) 136 + return -EIO; 137 + 138 + if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) 139 + str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); 140 + if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) 141 + str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); 142 + if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) 143 + str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); 144 + if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) 145 + str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); 146 + if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) 147 + str += sprintf(str, 148 + "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); 149 + if (var->Attributes & 150 + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) 151 + str += sprintf(str, 152 + "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); 153 + if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) 154 + str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); 155 + return str - buf; 156 + } 157 + 158 + static ssize_t 159 + efivar_size_read(struct efivar_entry *entry, char *buf) 160 + { 161 + struct efi_variable *var = &entry->var; 162 + char *str = buf; 163 + 164 + if (!entry || !buf) 165 + return -EINVAL; 166 + 167 + var->DataSize = 1024; 168 + if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) 169 + return -EIO; 170 + 171 + str += sprintf(str, "0x%lx\n", var->DataSize); 172 + return str - buf; 173 + } 174 + 175 + static ssize_t 176 + efivar_data_read(struct efivar_entry *entry, char *buf) 177 + { 178 + struct efi_variable *var = &entry->var; 179 + 180 + if (!entry || !buf) 181 + return -EINVAL; 182 + 183 + var->DataSize = 1024; 184 + if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) 185 + return -EIO; 186 + 187 + memcpy(buf, var->Data, var->DataSize); 188 + return var->DataSize; 189 + } 190 + /* 191 + * We allow each variable to be edited via rewriting the 192 + * entire efi variable structure. 193 + */ 194 + static ssize_t 195 + efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) 196 + { 197 + struct efi_variable *new_var, *var = &entry->var; 198 + int err; 199 + 200 + if (count != sizeof(struct efi_variable)) 201 + return -EINVAL; 202 + 203 + new_var = (struct efi_variable *)buf; 204 + /* 205 + * If only updating the variable data, then the name 206 + * and guid should remain the same 207 + */ 208 + if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) || 209 + efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) { 210 + printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); 211 + return -EINVAL; 212 + } 213 + 214 + if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){ 215 + printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); 216 + return -EINVAL; 217 + } 218 + 219 + if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 220 + efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) { 221 + printk(KERN_ERR "efivars: Malformed variable content\n"); 222 + return -EINVAL; 223 + } 224 + 225 + memcpy(&entry->var, new_var, count); 226 + 227 + err = efivar_entry_set(entry, new_var->Attributes, 228 + new_var->DataSize, new_var->Data, false); 229 + if (err) { 230 + printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err); 231 + return -EIO; 232 + } 233 + 234 + return count; 235 + } 236 + 237 + static ssize_t 238 + efivar_show_raw(struct efivar_entry *entry, char *buf) 239 + { 240 + struct efi_variable *var = &entry->var; 241 + 242 + if (!entry || !buf) 243 + return 0; 244 + 245 + var->DataSize = 1024; 246 + if (efivar_entry_get(entry, &entry->var.Attributes, 247 + &entry->var.DataSize, entry->var.Data)) 248 + return -EIO; 249 + 250 + memcpy(buf, var, sizeof(*var)); 251 + 252 + return sizeof(*var); 253 + } 254 + 255 + /* 256 + * Generic read/write functions that call the specific functions of 257 + * the attributes... 258 + */ 259 + static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr, 260 + char *buf) 261 + { 262 + struct efivar_entry *var = to_efivar_entry(kobj); 263 + struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 264 + ssize_t ret = -EIO; 265 + 266 + if (!capable(CAP_SYS_ADMIN)) 267 + return -EACCES; 268 + 269 + if (efivar_attr->show) { 270 + ret = efivar_attr->show(var, buf); 271 + } 272 + return ret; 273 + } 274 + 275 + static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, 276 + const char *buf, size_t count) 277 + { 278 + struct efivar_entry *var = to_efivar_entry(kobj); 279 + struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 280 + ssize_t ret = -EIO; 281 + 282 + if (!capable(CAP_SYS_ADMIN)) 283 + return -EACCES; 284 + 285 + if (efivar_attr->store) 286 + ret = efivar_attr->store(var, buf, count); 287 + 288 + return ret; 289 + } 290 + 291 + static const struct sysfs_ops efivar_attr_ops = { 292 + .show = efivar_attr_show, 293 + .store = efivar_attr_store, 294 + }; 295 + 296 + static void efivar_release(struct kobject *kobj) 297 + { 298 + struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); 299 + kfree(var); 300 + } 301 + 302 + static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL); 303 + static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL); 304 + static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL); 305 + static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL); 306 + static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw); 307 + 308 + static struct attribute *def_attrs[] = { 309 + &efivar_attr_guid.attr, 310 + &efivar_attr_size.attr, 311 + &efivar_attr_attributes.attr, 312 + &efivar_attr_data.attr, 313 + &efivar_attr_raw_var.attr, 314 + NULL, 315 + }; 316 + 317 + static struct kobj_type efivar_ktype = { 318 + .release = efivar_release, 319 + .sysfs_ops = &efivar_attr_ops, 320 + .default_attrs = def_attrs, 321 + }; 322 + 323 + static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 324 + struct bin_attribute *bin_attr, 325 + char *buf, loff_t pos, size_t count) 326 + { 327 + struct efi_variable *new_var = (struct efi_variable *)buf; 328 + struct efivar_entry *new_entry; 329 + int err; 330 + 331 + if (!capable(CAP_SYS_ADMIN)) 332 + return -EACCES; 333 + 334 + if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 335 + efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) { 336 + printk(KERN_ERR "efivars: Malformed variable content\n"); 337 + return -EINVAL; 338 + } 339 + 340 + new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); 341 + if (!new_entry) 342 + return -ENOMEM; 343 + 344 + memcpy(&new_entry->var, new_var, sizeof(*new_var)); 345 + 346 + err = efivar_entry_set(new_entry, new_var->Attributes, new_var->DataSize, 347 + new_var->Data, &efivar_sysfs_list); 348 + if (err) { 349 + if (err == -EEXIST) 350 + err = -EINVAL; 351 + goto out; 352 + } 353 + 354 + if (efivar_create_sysfs_entry(new_entry)) { 355 + printk(KERN_WARNING "efivars: failed to create sysfs entry.\n"); 356 + kfree(new_entry); 357 + } 358 + return count; 359 + 360 + out: 361 + kfree(new_entry); 362 + return err; 363 + } 364 + 365 + static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 366 + struct bin_attribute *bin_attr, 367 + char *buf, loff_t pos, size_t count) 368 + { 369 + struct efi_variable *del_var = (struct efi_variable *)buf; 370 + struct efivar_entry *entry; 371 + int err = 0; 372 + 373 + if (!capable(CAP_SYS_ADMIN)) 374 + return -EACCES; 375 + 376 + efivar_entry_iter_begin(); 377 + entry = efivar_entry_find(del_var->VariableName, del_var->VendorGuid, 378 + &efivar_sysfs_list, true); 379 + if (!entry) 380 + err = -EINVAL; 381 + else if (__efivar_entry_delete(entry)) 382 + err = -EIO; 383 + 384 + efivar_entry_iter_end(); 385 + 386 + if (err) 387 + return err; 388 + 389 + efivar_unregister(entry); 390 + 391 + /* It's dead Jim.... */ 392 + return count; 393 + } 394 + 395 + /** 396 + * efivar_create_sysfs_entry - create a new entry in sysfs 397 + * @new_var: efivar entry to create 398 + * 399 + * Returns 1 on failure, 0 on success 400 + */ 401 + static int 402 + efivar_create_sysfs_entry(struct efivar_entry *new_var) 403 + { 404 + int i, short_name_size; 405 + char *short_name; 406 + unsigned long variable_name_size; 407 + efi_char16_t *variable_name; 408 + 409 + variable_name = new_var->var.VariableName; 410 + variable_name_size = utf16_strlen(variable_name) * sizeof(efi_char16_t); 411 + 412 + /* 413 + * Length of the variable bytes in ASCII, plus the '-' separator, 414 + * plus the GUID, plus trailing NUL 415 + */ 416 + short_name_size = variable_name_size / sizeof(efi_char16_t) 417 + + 1 + EFI_VARIABLE_GUID_LEN + 1; 418 + 419 + short_name = kzalloc(short_name_size, GFP_KERNEL); 420 + 421 + if (!short_name) { 422 + kfree(short_name); 423 + return 1; 424 + } 425 + 426 + /* Convert Unicode to normal chars (assume top bits are 0), 427 + ala UTF-8 */ 428 + for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { 429 + short_name[i] = variable_name[i] & 0xFF; 430 + } 431 + /* This is ugly, but necessary to separate one vendor's 432 + private variables from another's. */ 433 + 434 + *(short_name + strlen(short_name)) = '-'; 435 + efi_guid_unparse(&new_var->var.VendorGuid, 436 + short_name + strlen(short_name)); 437 + 438 + new_var->kobj.kset = efivars_kset; 439 + 440 + i = kobject_init_and_add(&new_var->kobj, &efivar_ktype, 441 + NULL, "%s", short_name); 442 + kfree(short_name); 443 + if (i) 444 + return 1; 445 + 446 + kobject_uevent(&new_var->kobj, KOBJ_ADD); 447 + efivar_entry_add(new_var, &efivar_sysfs_list); 448 + 449 + return 0; 450 + } 451 + 452 + static int 453 + create_efivars_bin_attributes(void) 454 + { 455 + struct bin_attribute *attr; 456 + int error; 457 + 458 + /* new_var */ 459 + attr = kzalloc(sizeof(*attr), GFP_KERNEL); 460 + if (!attr) 461 + return -ENOMEM; 462 + 463 + attr->attr.name = "new_var"; 464 + attr->attr.mode = 0200; 465 + attr->write = efivar_create; 466 + efivars_new_var = attr; 467 + 468 + /* del_var */ 469 + attr = kzalloc(sizeof(*attr), GFP_KERNEL); 470 + if (!attr) { 471 + error = -ENOMEM; 472 + goto out_free; 473 + } 474 + attr->attr.name = "del_var"; 475 + attr->attr.mode = 0200; 476 + attr->write = efivar_delete; 477 + efivars_del_var = attr; 478 + 479 + sysfs_bin_attr_init(efivars_new_var); 480 + sysfs_bin_attr_init(efivars_del_var); 481 + 482 + /* Register */ 483 + error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var); 484 + if (error) { 485 + printk(KERN_ERR "efivars: unable to create new_var sysfs file" 486 + " due to error %d\n", error); 487 + goto out_free; 488 + } 489 + 490 + error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var); 491 + if (error) { 492 + printk(KERN_ERR "efivars: unable to create del_var sysfs file" 493 + " due to error %d\n", error); 494 + sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var); 495 + goto out_free; 496 + } 497 + 498 + return 0; 499 + out_free: 500 + kfree(efivars_del_var); 501 + efivars_del_var = NULL; 502 + kfree(efivars_new_var); 503 + efivars_new_var = NULL; 504 + return error; 505 + } 506 + 507 + static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor, 508 + unsigned long name_size, void *data) 509 + { 510 + struct efivar_entry *entry = data; 511 + 512 + if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false)) 513 + return 0; 514 + 515 + memcpy(entry->var.VariableName, name, name_size); 516 + memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 517 + 518 + return 1; 519 + } 520 + 521 + static void efivar_update_sysfs_entries(struct work_struct *work) 522 + { 523 + struct efivar_entry *entry; 524 + int err; 525 + 526 + entry = kzalloc(sizeof(*entry), GFP_KERNEL); 527 + if (!entry) 528 + return; 529 + 530 + /* Add new sysfs entries */ 531 + while (1) { 532 + memset(entry, 0, sizeof(*entry)); 533 + 534 + err = efivar_init(efivar_update_sysfs_entry, entry, 535 + true, false, &efivar_sysfs_list); 536 + if (!err) 537 + break; 538 + 539 + efivar_create_sysfs_entry(entry); 540 + } 541 + 542 + kfree(entry); 543 + } 544 + 545 + static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor, 546 + unsigned long name_size, void *data) 547 + { 548 + struct efivar_entry *entry; 549 + 550 + entry = kzalloc(sizeof(*entry), GFP_KERNEL); 551 + if (!entry) 552 + return -ENOMEM; 553 + 554 + memcpy(entry->var.VariableName, name, name_size); 555 + memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 556 + 557 + efivar_create_sysfs_entry(entry); 558 + 559 + return 0; 560 + } 561 + 562 + static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data) 563 + { 564 + efivar_entry_remove(entry); 565 + efivar_unregister(entry); 566 + return 0; 567 + } 568 + 569 + void efivars_sysfs_exit(void) 570 + { 571 + /* Remove all entries and destroy */ 572 + __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list, NULL, NULL); 573 + 574 + if (efivars_new_var) 575 + sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var); 576 + if (efivars_del_var) 577 + sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var); 578 + kfree(efivars_new_var); 579 + kfree(efivars_del_var); 580 + kset_unregister(efivars_kset); 581 + } 582 + 583 + int efivars_sysfs_init(void) 584 + { 585 + struct kobject *parent_kobj = efivars_kobject(); 586 + int error = 0; 587 + 588 + /* No efivars has been registered yet */ 589 + if (!parent_kobj) 590 + return 0; 591 + 592 + printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 593 + EFIVARS_DATE); 594 + 595 + efivars_kset = kset_create_and_add("vars", NULL, parent_kobj); 596 + if (!efivars_kset) { 597 + printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 598 + return -ENOMEM; 599 + } 600 + 601 + efivar_init(efivars_sysfs_callback, NULL, false, 602 + true, &efivar_sysfs_list); 603 + 604 + error = create_efivars_bin_attributes(); 605 + if (error) { 606 + efivars_sysfs_exit(); 607 + return error; 608 + } 609 + 610 + INIT_WORK(&efivar_work, efivar_update_sysfs_entries); 611 + 612 + return 0; 613 + } 614 + EXPORT_SYMBOL_GPL(efivars_sysfs_init); 615 + 616 + module_init(efivars_sysfs_init); 617 + module_exit(efivars_sysfs_exit);
+12 -757
drivers/firmware/efivars.c drivers/firmware/efi/vars.c
··· 1 1 /* 2 - * EFI Variables - efivars.c 2 + * Originally from efivars.c 3 3 * 4 4 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com> 5 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 6 * 10 7 * This program is free software; you can redistribute it and/or modify 11 8 * it under the terms of the GNU General Public License as published by ··· 17 20 * You should have received a copy of the GNU General Public License 18 21 * along with this program; if not, write to the Free Software 19 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 - * 21 - * Changelog: 22 - * 23 - * 17 May 2004 - Matt Domsch <Matt_Domsch@dell.com> 24 - * remove check for efi_enabled in exit 25 - * add MODULE_VERSION 26 - * 27 - * 26 Apr 2004 - Matt Domsch <Matt_Domsch@dell.com> 28 - * minor bug fixes 29 - * 30 - * 21 Apr 2004 - Matt Tolentino <matthew.e.tolentino@intel.com) 31 - * converted driver to export variable information via sysfs 32 - * and moved to drivers/firmware directory 33 - * bumped revision number to v0.07 to reflect conversion & move 34 - * 35 - * 10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com> 36 - * fix locking per Peter Chubb's findings 37 - * 38 - * 25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com> 39 - * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse() 40 - * 41 - * 12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com> 42 - * use list_for_each_safe when deleting vars. 43 - * remove ifdef CONFIG_SMP around include <linux/smp.h> 44 - * v0.04 release to linux-ia64@linuxia64.org 45 - * 46 - * 20 April 2001 - Matt Domsch <Matt_Domsch@dell.com> 47 - * Moved vars from /proc/efi to /proc/efi/vars, and made 48 - * efi.c own the /proc/efi directory. 49 - * v0.03 release to linux-ia64@linuxia64.org 50 - * 51 - * 26 March 2001 - Matt Domsch <Matt_Domsch@dell.com> 52 - * At the request of Stephane, moved ownership of /proc/efi 53 - * to efi.c, and now efivars lives under /proc/efi/vars. 54 - * 55 - * 12 March 2001 - Matt Domsch <Matt_Domsch@dell.com> 56 - * Feedback received from Stephane Eranian incorporated. 57 - * efivar_write() checks copy_from_user() return value. 58 - * efivar_read/write() returns proper errno. 59 - * v0.02 release to linux-ia64@linuxia64.org 60 - * 61 - * 26 February 2001 - Matt Domsch <Matt_Domsch@dell.com> 62 - * v0.01 release to linux-ia64@linuxia64.org 63 23 */ 64 24 65 25 #include <linux/capability.h> ··· 29 75 #include <linux/smp.h> 30 76 #include <linux/efi.h> 31 77 #include <linux/sysfs.h> 32 - #include <linux/kobject.h> 33 78 #include <linux/device.h> 34 79 #include <linux/slab.h> 35 80 #include <linux/ctype.h> 36 81 37 - #include <linux/fs.h> 38 - #include <linux/ramfs.h> 39 - #include <linux/pagemap.h> 40 - 41 - #include <asm/uaccess.h> 42 - 43 - #define EFIVARS_VERSION "0.08" 44 - #define EFIVARS_DATE "2004-May-17" 45 - 46 - MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); 47 - MODULE_DESCRIPTION("sysfs interface to EFI Variables"); 48 - MODULE_LICENSE("GPL"); 49 - MODULE_VERSION(EFIVARS_VERSION); 50 - 51 - LIST_HEAD(efivar_sysfs_list); 52 - EXPORT_SYMBOL_GPL(efivar_sysfs_list); 53 - 54 - struct efivar_attribute { 55 - struct attribute attr; 56 - ssize_t (*show) (struct efivar_entry *entry, char *buf); 57 - ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); 58 - }; 59 - 60 82 /* Private pointer to registered efivars */ 61 83 static struct efivars *__efivars; 62 84 63 - static struct kset *efivars_kset; 64 - 65 - static struct bin_attribute *efivars_new_var; 66 - static struct bin_attribute *efivars_del_var; 67 - 68 - #define EFIVAR_ATTR(_name, _mode, _show, _store) \ 69 - struct efivar_attribute efivar_attr_##_name = { \ 70 - .attr = {.name = __stringify(_name), .mode = _mode}, \ 71 - .show = _show, \ 72 - .store = _store, \ 73 - }; 74 - 75 - #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr) 76 - #define to_efivar_entry(obj) container_of(obj, struct efivar_entry, kobj) 77 - 78 - /* 79 - * Prototype for sysfs creation function 80 - */ 81 - static int 82 - efivar_create_sysfs_entry(struct efivar_entry *new_var); 83 - 84 - /* 85 - * Prototype for workqueue functions updating sysfs entry 86 - */ 87 - 88 - static void efivar_update_sysfs_entries(struct work_struct *); 89 - static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); 90 85 static bool efivar_wq_enabled = true; 86 + DECLARE_WORK(efivar_work, NULL); 87 + EXPORT_SYMBOL_GPL(efivar_work); 91 88 92 89 static bool 93 90 validate_device_path(struct efi_variable *var, int match, u8 *buffer, ··· 248 343 return status; 249 344 } 250 345 251 - static ssize_t 252 - efivar_guid_read(struct efivar_entry *entry, char *buf) 253 - { 254 - struct efi_variable *var = &entry->var; 255 - char *str = buf; 256 - 257 - if (!entry || !buf) 258 - return 0; 259 - 260 - efi_guid_unparse(&var->VendorGuid, str); 261 - str += strlen(str); 262 - str += sprintf(str, "\n"); 263 - 264 - return str - buf; 265 - } 266 - 267 - static ssize_t 268 - efivar_attr_read(struct efivar_entry *entry, char *buf) 269 - { 270 - struct efi_variable *var = &entry->var; 271 - char *str = buf; 272 - 273 - if (!entry || !buf) 274 - return -EINVAL; 275 - 276 - var->DataSize = 1024; 277 - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) 278 - return -EIO; 279 - 280 - if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) 281 - str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); 282 - if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) 283 - str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); 284 - if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) 285 - str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); 286 - if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) 287 - str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); 288 - if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) 289 - str += sprintf(str, 290 - "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); 291 - if (var->Attributes & 292 - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) 293 - str += sprintf(str, 294 - "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); 295 - if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) 296 - str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); 297 - return str - buf; 298 - } 299 - 300 - static ssize_t 301 - efivar_size_read(struct efivar_entry *entry, char *buf) 302 - { 303 - struct efi_variable *var = &entry->var; 304 - char *str = buf; 305 - 306 - if (!entry || !buf) 307 - return -EINVAL; 308 - 309 - var->DataSize = 1024; 310 - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) 311 - return -EIO; 312 - 313 - str += sprintf(str, "0x%lx\n", var->DataSize); 314 - return str - buf; 315 - } 316 - 317 - static ssize_t 318 - efivar_data_read(struct efivar_entry *entry, char *buf) 319 - { 320 - struct efi_variable *var = &entry->var; 321 - 322 - if (!entry || !buf) 323 - return -EINVAL; 324 - 325 - var->DataSize = 1024; 326 - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) 327 - return -EIO; 328 - 329 - memcpy(buf, var->Data, var->DataSize); 330 - return var->DataSize; 331 - } 332 - /* 333 - * We allow each variable to be edited via rewriting the 334 - * entire efi variable structure. 335 - */ 336 - static ssize_t 337 - efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) 338 - { 339 - struct efi_variable *new_var, *var = &entry->var; 340 - int err; 341 - 342 - if (count != sizeof(struct efi_variable)) 343 - return -EINVAL; 344 - 345 - new_var = (struct efi_variable *)buf; 346 - /* 347 - * If only updating the variable data, then the name 348 - * and guid should remain the same 349 - */ 350 - if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) || 351 - efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) { 352 - printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); 353 - return -EINVAL; 354 - } 355 - 356 - if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){ 357 - printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); 358 - return -EINVAL; 359 - } 360 - 361 - if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 362 - efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) { 363 - printk(KERN_ERR "efivars: Malformed variable content\n"); 364 - return -EINVAL; 365 - } 366 - 367 - memcpy(&entry->var, new_var, count); 368 - 369 - err = efivar_entry_set(entry, new_var->Attributes, 370 - new_var->DataSize, new_var->Data, false); 371 - if (err) { 372 - printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err); 373 - return -EIO; 374 - } 375 - 376 - return count; 377 - } 378 - 379 - static ssize_t 380 - efivar_show_raw(struct efivar_entry *entry, char *buf) 381 - { 382 - struct efi_variable *var = &entry->var; 383 - 384 - if (!entry || !buf) 385 - return 0; 386 - 387 - var->DataSize = 1024; 388 - if (efivar_entry_get(entry, &entry->var.Attributes, 389 - &entry->var.DataSize, entry->var.Data)) 390 - return -EIO; 391 - 392 - memcpy(buf, var, sizeof(*var)); 393 - 394 - return sizeof(*var); 395 - } 396 - 397 - /* 398 - * Generic read/write functions that call the specific functions of 399 - * the attributes... 400 - */ 401 - static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr, 402 - char *buf) 403 - { 404 - struct efivar_entry *var = to_efivar_entry(kobj); 405 - struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 406 - ssize_t ret = -EIO; 407 - 408 - if (!capable(CAP_SYS_ADMIN)) 409 - return -EACCES; 410 - 411 - if (efivar_attr->show) { 412 - ret = efivar_attr->show(var, buf); 413 - } 414 - return ret; 415 - } 416 - 417 - static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, 418 - const char *buf, size_t count) 419 - { 420 - struct efivar_entry *var = to_efivar_entry(kobj); 421 - struct efivar_attribute *efivar_attr = to_efivar_attr(attr); 422 - ssize_t ret = -EIO; 423 - 424 - if (!capable(CAP_SYS_ADMIN)) 425 - return -EACCES; 426 - 427 - if (efivar_attr->store) 428 - ret = efivar_attr->store(var, buf, count); 429 - 430 - return ret; 431 - } 432 - 433 - static const struct sysfs_ops efivar_attr_ops = { 434 - .show = efivar_attr_show, 435 - .store = efivar_attr_store, 436 - }; 437 - 438 - static void efivar_release(struct kobject *kobj) 439 - { 440 - struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); 441 - kfree(var); 442 - } 443 - 444 - static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL); 445 - static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL); 446 - static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL); 447 - static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL); 448 - static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw); 449 - 450 - static struct attribute *def_attrs[] = { 451 - &efivar_attr_guid.attr, 452 - &efivar_attr_size.attr, 453 - &efivar_attr_attributes.attr, 454 - &efivar_attr_data.attr, 455 - &efivar_attr_raw_var.attr, 456 - NULL, 457 - }; 458 - 459 - static struct kobj_type efivar_ktype = { 460 - .release = efivar_release, 461 - .sysfs_ops = &efivar_attr_ops, 462 - .default_attrs = def_attrs, 463 - }; 464 - 465 346 static int efi_status_to_err(efi_status_t status) 466 347 { 467 348 int err; ··· 281 590 return err; 282 591 } 283 592 284 - static ssize_t efivar_create(struct file *filp, struct kobject *kobj, 285 - struct bin_attribute *bin_attr, 286 - char *buf, loff_t pos, size_t count) 287 - { 288 - struct efi_variable *new_var = (struct efi_variable *)buf; 289 - struct efivar_entry *new_entry; 290 - int err; 291 - 292 - if (!capable(CAP_SYS_ADMIN)) 293 - return -EACCES; 294 - 295 - if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || 296 - efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) { 297 - printk(KERN_ERR "efivars: Malformed variable content\n"); 298 - return -EINVAL; 299 - } 300 - 301 - new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); 302 - if (!new_entry) 303 - return -ENOMEM; 304 - 305 - memcpy(&new_entry->var, new_var, sizeof(*new_var)); 306 - 307 - err = efivar_entry_set(new_entry, new_var->Attributes, new_var->DataSize, 308 - new_var->Data, &efivar_sysfs_list); 309 - if (err) { 310 - if (err == -EEXIST) 311 - err = -EINVAL; 312 - goto out; 313 - } 314 - 315 - if (efivar_create_sysfs_entry(new_entry)) { 316 - printk(KERN_WARNING "efivars: failed to create sysfs entry.\n"); 317 - kfree(new_entry); 318 - } 319 - return count; 320 - 321 - out: 322 - kfree(new_entry); 323 - return err; 324 - } 325 - 326 - static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, 327 - struct bin_attribute *bin_attr, 328 - char *buf, loff_t pos, size_t count) 329 - { 330 - struct efi_variable *del_var = (struct efi_variable *)buf; 331 - struct efivar_entry *entry; 332 - int err = 0; 333 - 334 - if (!capable(CAP_SYS_ADMIN)) 335 - return -EACCES; 336 - 337 - efivar_entry_iter_begin(); 338 - entry = efivar_entry_find(del_var->VariableName, del_var->VendorGuid, 339 - &efivar_sysfs_list, true); 340 - if (!entry) 341 - err = -EINVAL; 342 - else if (__efivar_entry_delete(entry)) 343 - err = -EIO; 344 - 345 - efivar_entry_iter_end(); 346 - 347 - if (err) 348 - return err; 349 - 350 - efivar_unregister(entry); 351 - 352 - /* It's dead Jim.... */ 353 - return count; 354 - } 355 - 356 593 static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor, 357 594 struct list_head *head) 358 595 { ··· 301 682 } 302 683 } 303 684 return found; 304 - } 305 - 306 - static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor, 307 - unsigned long name_size, void *data) 308 - { 309 - struct efivar_entry *entry = data; 310 - 311 - if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false)) 312 - return 0; 313 - 314 - memcpy(entry->var.VariableName, name, name_size); 315 - memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 316 - 317 - return 1; 318 685 } 319 686 320 687 /* ··· 326 721 } 327 722 328 723 return min(len, variable_name_size); 329 - } 330 - 331 - static void efivar_update_sysfs_entries(struct work_struct *work) 332 - { 333 - struct efivar_entry *entry; 334 - int err; 335 - 336 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 337 - if (!entry) 338 - return; 339 - 340 - /* Add new sysfs entries */ 341 - while (1) { 342 - memset(entry, 0, sizeof(*entry)); 343 - 344 - err = efivar_init(efivar_update_sysfs_entry, entry, 345 - true, false, &efivar_sysfs_list); 346 - if (!err) 347 - break; 348 - 349 - efivar_create_sysfs_entry(entry); 350 - } 351 - 352 - kfree(entry); 353 - } 354 - 355 - /* 356 - * Let's not leave out systab information that snuck into 357 - * the efivars driver 358 - */ 359 - static ssize_t systab_show(struct kobject *kobj, 360 - struct kobj_attribute *attr, char *buf) 361 - { 362 - char *str = buf; 363 - 364 - if (!kobj || !buf) 365 - return -EINVAL; 366 - 367 - if (efi.mps != EFI_INVALID_TABLE_ADDR) 368 - str += sprintf(str, "MPS=0x%lx\n", efi.mps); 369 - if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) 370 - str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 371 - if (efi.acpi != EFI_INVALID_TABLE_ADDR) 372 - str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 373 - if (efi.smbios != EFI_INVALID_TABLE_ADDR) 374 - str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 375 - if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 376 - str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 377 - if (efi.boot_info != EFI_INVALID_TABLE_ADDR) 378 - str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); 379 - if (efi.uga != EFI_INVALID_TABLE_ADDR) 380 - str += sprintf(str, "UGA=0x%lx\n", efi.uga); 381 - 382 - return str - buf; 383 - } 384 - 385 - static struct kobj_attribute efi_attr_systab = 386 - __ATTR(systab, 0400, systab_show, NULL); 387 - 388 - static struct attribute *efi_subsys_attrs[] = { 389 - &efi_attr_systab.attr, 390 - NULL, /* maybe more in the future? */ 391 - }; 392 - 393 - static struct attribute_group efi_subsys_attr_group = { 394 - .attrs = efi_subsys_attrs, 395 - }; 396 - 397 - static struct kobject *efi_kobj; 398 - 399 - /** 400 - * efivar_create_sysfs_entry - create a new entry in sysfs 401 - * @new_var: efivar entry to create 402 - * 403 - * Returns 1 on failure, 0 on success 404 - */ 405 - static int 406 - efivar_create_sysfs_entry(struct efivar_entry *new_var) 407 - { 408 - int i, short_name_size; 409 - char *short_name; 410 - unsigned long variable_name_size; 411 - efi_char16_t *variable_name; 412 - 413 - variable_name = new_var->var.VariableName; 414 - variable_name_size = utf16_strlen(variable_name) * sizeof(efi_char16_t); 415 - 416 - /* 417 - * Length of the variable bytes in ASCII, plus the '-' separator, 418 - * plus the GUID, plus trailing NUL 419 - */ 420 - short_name_size = variable_name_size / sizeof(efi_char16_t) 421 - + 1 + EFI_VARIABLE_GUID_LEN + 1; 422 - 423 - short_name = kzalloc(short_name_size, GFP_KERNEL); 424 - 425 - if (!short_name) { 426 - kfree(short_name); 427 - return 1; 428 - } 429 - 430 - /* Convert Unicode to normal chars (assume top bits are 0), 431 - ala UTF-8 */ 432 - for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { 433 - short_name[i] = variable_name[i] & 0xFF; 434 - } 435 - /* This is ugly, but necessary to separate one vendor's 436 - private variables from another's. */ 437 - 438 - *(short_name + strlen(short_name)) = '-'; 439 - efi_guid_unparse(&new_var->var.VendorGuid, 440 - short_name + strlen(short_name)); 441 - 442 - new_var->kobj.kset = efivars_kset; 443 - 444 - i = kobject_init_and_add(&new_var->kobj, &efivar_ktype, 445 - NULL, "%s", short_name); 446 - kfree(short_name); 447 - if (i) 448 - return 1; 449 - 450 - kobject_uevent(&new_var->kobj, KOBJ_ADD); 451 - efivar_entry_add(new_var, &efivar_sysfs_list); 452 - 453 - return 0; 454 - } 455 - 456 - static int 457 - create_efivars_bin_attributes(void) 458 - { 459 - struct bin_attribute *attr; 460 - int error; 461 - 462 - /* new_var */ 463 - attr = kzalloc(sizeof(*attr), GFP_KERNEL); 464 - if (!attr) 465 - return -ENOMEM; 466 - 467 - attr->attr.name = "new_var"; 468 - attr->attr.mode = 0200; 469 - attr->write = efivar_create; 470 - efivars_new_var = attr; 471 - 472 - /* del_var */ 473 - attr = kzalloc(sizeof(*attr), GFP_KERNEL); 474 - if (!attr) { 475 - error = -ENOMEM; 476 - goto out_free; 477 - } 478 - attr->attr.name = "del_var"; 479 - attr->attr.mode = 0200; 480 - attr->write = efivar_delete; 481 - efivars_del_var = attr; 482 - 483 - sysfs_bin_attr_init(efivars_new_var); 484 - sysfs_bin_attr_init(efivars_del_var); 485 - 486 - /* Register */ 487 - error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var); 488 - if (error) { 489 - printk(KERN_ERR "efivars: unable to create new_var sysfs file" 490 - " due to error %d\n", error); 491 - goto out_free; 492 - } 493 - 494 - error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var); 495 - if (error) { 496 - printk(KERN_ERR "efivars: unable to create del_var sysfs file" 497 - " due to error %d\n", error); 498 - sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var); 499 - goto out_free; 500 - } 501 - 502 - return 0; 503 - out_free: 504 - kfree(efivars_del_var); 505 - efivars_del_var = NULL; 506 - kfree(efivars_new_var); 507 - efivars_new_var = NULL; 508 - return error; 509 - } 510 - 511 - static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor, 512 - unsigned long name_size, void *data) 513 - { 514 - struct efivar_entry *entry; 515 - 516 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 517 - if (!entry) 518 - return -ENOMEM; 519 - 520 - memcpy(entry->var.VariableName, name, name_size); 521 - memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); 522 - 523 - efivar_create_sysfs_entry(entry); 524 - 525 - return 0; 526 - } 527 - 528 - static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data) 529 - { 530 - efivar_entry_remove(entry); 531 - efivar_unregister(entry); 532 - return 0; 533 724 } 534 725 535 726 /* ··· 356 955 s8, vendor_guid); 357 956 kfree(s8); 358 957 } 359 - 360 - static struct kobject *efivars_kobj; 361 - 362 - void efivars_sysfs_exit(void) 363 - { 364 - /* Remove all entries and destroy */ 365 - __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list, NULL, NULL); 366 - 367 - if (efivars_new_var) 368 - sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var); 369 - if (efivars_del_var) 370 - sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var); 371 - kfree(efivars_new_var); 372 - kfree(efivars_del_var); 373 - kobject_put(efivars_kobj); 374 - kset_unregister(efivars_kset); 375 - } 376 - 377 - int efivars_sysfs_init(void) 378 - { 379 - struct kobject *parent_kobj = efivars_kobject(); 380 - int error = 0; 381 - 382 - /* No efivars has been registered yet */ 383 - if (!parent_kobj) 384 - return 0; 385 - 386 - printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, 387 - EFIVARS_DATE); 388 - 389 - efivars_kset = kset_create_and_add("vars", NULL, parent_kobj); 390 - if (!efivars_kset) { 391 - printk(KERN_ERR "efivars: Subsystem registration failed.\n"); 392 - return -ENOMEM; 393 - } 394 - 395 - efivars_kobj = kobject_create_and_add("efivars", parent_kobj); 396 - if (!efivars_kobj) { 397 - pr_err("efivars: Subsystem registration failed.\n"); 398 - kset_unregister(efivars_kset); 399 - return -ENOMEM; 400 - } 401 - 402 - efivar_init(efivars_sysfs_callback, NULL, false, 403 - true, &efivar_sysfs_list); 404 - 405 - error = create_efivars_bin_attributes(); 406 - if (error) 407 - efivars_sysfs_exit(); 408 - 409 - return error; 410 - } 411 - EXPORT_SYMBOL_GPL(efivars_sysfs_init); 412 958 413 959 /** 414 960 * efivar_init - build the initial list of EFI variables ··· 502 1154 * __efivar_entry_delete - delete an EFI variable 503 1155 * @entry: entry containing EFI variable to delete 504 1156 * 505 - * Delete the variable from the firmware and remove @entry from the 506 - * variable list. It is the caller's responsibility to free @entry 507 - * once we return. 1157 + * Delete the variable from the firmware but leave @entry on the 1158 + * variable list. 508 1159 * 509 - * This function differs from efivar_entry_delete() because it is 510 - * safe to be called from within a efivar_entry_iter_begin() and 1160 + * This function differs from efivar_entry_delete() because it does 1161 + * not remove @entry from the variable list. Also, it is safe to be 1162 + * called from within a efivar_entry_iter_begin() and 511 1163 * efivar_entry_iter_end() region, unlike efivar_entry_delete(). 512 1164 * 513 1165 * Returns 0 on success, or a converted EFI status code if 514 - * set_variable() fails. If set_variable() fails the entry remains 515 - * on the list. 1166 + * set_variable() fails. 516 1167 */ 517 1168 int __efivar_entry_delete(struct efivar_entry *entry) 518 1169 { ··· 523 1176 status = ops->set_variable(entry->var.VariableName, 524 1177 &entry->var.VendorGuid, 525 1178 0, 0, NULL); 526 - if (status) 527 - return efi_status_to_err(status); 528 1179 529 - list_del(&entry->list); 530 - 531 - return 0; 1180 + return efi_status_to_err(status); 532 1181 } 533 1182 EXPORT_SYMBOL_GPL(__efivar_entry_delete); 534 1183 ··· 602 1259 spin_unlock_irq(&__efivars->lock); 603 1260 604 1261 return efi_status_to_err(status); 1262 + 605 1263 } 606 1264 EXPORT_SYMBOL_GPL(efivar_entry_set); 607 1265 ··· 633 1289 if (!ops->query_variable_info) 634 1290 return -ENOSYS; 635 1291 636 - if (!block && !spin_trylock_irqsave(&__efivars->lock, flags)) 1292 + if (!block && spin_trylock_irqsave(&__efivars->lock, flags)) 637 1293 return -EBUSY; 638 1294 else 639 1295 spin_lock_irqsave(&__efivars->lock, flags); ··· 1047 1703 return rv; 1048 1704 } 1049 1705 EXPORT_SYMBOL_GPL(efivars_unregister); 1050 - 1051 - static struct efivars generic_efivars; 1052 - static struct efivar_operations generic_ops; 1053 - 1054 - static int generic_ops_register(void) 1055 - { 1056 - int error; 1057 - 1058 - generic_ops.get_variable = efi.get_variable; 1059 - generic_ops.set_variable = efi.set_variable; 1060 - generic_ops.get_next_variable = efi.get_next_variable; 1061 - generic_ops.query_variable_info = efi.query_variable_info; 1062 - 1063 - error = efivars_register(&generic_efivars, &generic_ops, efi_kobj); 1064 - if (error) 1065 - return error; 1066 - 1067 - error = efivars_sysfs_init(); 1068 - if (error) 1069 - efivars_unregister(&generic_efivars); 1070 - 1071 - return error; 1072 - } 1073 - 1074 - static void generic_ops_unregister(void) 1075 - { 1076 - efivars_sysfs_exit(); 1077 - efivars_unregister(&generic_efivars); 1078 - } 1079 - 1080 - /* 1081 - * For now we register the efi subsystem with the firmware subsystem 1082 - * and the vars subsystem with the efi subsystem. In the future, it 1083 - * might make sense to split off the efi subsystem into its own 1084 - * driver, but for now only efivars will register with it, so just 1085 - * include it here. 1086 - */ 1087 - 1088 - static int __init 1089 - efivars_init(void) 1090 - { 1091 - int error; 1092 - 1093 - if (!efi_enabled(EFI_RUNTIME_SERVICES)) 1094 - return 0; 1095 - 1096 - /* Register the efi directory at /sys/firmware/efi */ 1097 - efi_kobj = kobject_create_and_add("efi", firmware_kobj); 1098 - if (!efi_kobj) { 1099 - printk(KERN_ERR "efivars: Firmware registration failed.\n"); 1100 - return -ENOMEM; 1101 - } 1102 - 1103 - error = generic_ops_register(); 1104 - if (error) 1105 - goto err_put; 1106 - 1107 - /* Don't forget the systab entry */ 1108 - error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); 1109 - if (error) { 1110 - printk(KERN_ERR 1111 - "efivars: Sysfs attribute export failed with error %d.\n", 1112 - error); 1113 - goto err_unregister; 1114 - } 1115 - 1116 - return 0; 1117 - 1118 - err_unregister: 1119 - generic_ops_unregister(); 1120 - err_put: 1121 - kobject_put(efi_kobj); 1122 - return error; 1123 - } 1124 - 1125 - static void __exit 1126 - efivars_exit(void) 1127 - { 1128 - cancel_work_sync(&efivar_work); 1129 - 1130 - if (efi_enabled(EFI_RUNTIME_SERVICES)) { 1131 - generic_ops_unregister(); 1132 - kobject_put(efi_kobj); 1133 - } 1134 - } 1135 - 1136 - module_init(efivars_init); 1137 - module_exit(efivars_exit); 1138 -
+1 -1
fs/efivarfs/Kconfig
··· 1 1 config EFIVAR_FS 2 2 tristate "EFI Variable filesystem" 3 - depends on EFI_VARS 3 + depends on EFI 4 4 help 5 5 efivarfs is a replacement filesystem for the old EFI 6 6 variable support via sysfs, as it doesn't suffer from the
+2 -1
include/linux/efi.h
··· 742 742 return utf16_strnlen(s, ~0UL); 743 743 } 744 744 745 - #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE) 746 745 /* 747 746 * Return the number of bytes is the length of this string 748 747 * Note: this is NOT the same as the number of unicode characters ··· 871 872 872 873 bool efivar_validate(struct efi_variable *var, u8 *data, unsigned long len); 873 874 875 + extern struct work_struct efivar_work; 874 876 void efivar_run_worker(void); 875 877 878 + #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE) 876 879 int efivars_sysfs_init(void); 877 880 878 881 #endif /* CONFIG_EFI_VARS */