aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2013-02-08 10:37:06 -0500
committerMatt Fleming <matt.fleming@intel.com>2013-04-17 08:27:06 -0400
commita9499fa7cd3fd4824a7202d00c766b269fa3bda6 (patch)
tree02d1ba3dcf46f6dd1765ef645b223ea0d4758ae6 /drivers/firmware
parentd68772b7c83f4b518be15ae96f4827c8ed02f684 (diff)
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>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/efi/Makefile2
-rw-r--r--drivers/firmware/efi/efi.c134
-rw-r--r--drivers/firmware/efi/efivars.c617
-rw-r--r--drivers/firmware/efi/vars.c (renamed from drivers/firmware/efivars.c)769
5 files changed, 765 insertions, 758 deletions
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 31bf68c93593..299fad6b5867 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -4,7 +4,6 @@
4obj-$(CONFIG_DMI) += dmi_scan.o 4obj-$(CONFIG_DMI) += dmi_scan.o
5obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o 5obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
6obj-$(CONFIG_EDD) += edd.o 6obj-$(CONFIG_EDD) += edd.o
7obj-$(CONFIG_EFI_VARS) += efivars.o
8obj-$(CONFIG_EFI_PCDP) += pcdp.o 7obj-$(CONFIG_EFI_PCDP) += pcdp.o
9obj-$(CONFIG_DELL_RBU) += dell_rbu.o 8obj-$(CONFIG_DELL_RBU) += dell_rbu.o
10obj-$(CONFIG_DCDBAS) += dcdbas.o 9obj-$(CONFIG_DCDBAS) += dcdbas.o
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index e03cd51525c2..99245ab5a79c 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -1,4 +1,6 @@
1# 1#
2# Makefile for linux kernel 2# Makefile for linux kernel
3# 3#
4obj-y += efi.o vars.o
5obj-$(CONFIG_EFI_VARS) += efivars.o
4obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o 6obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
new file mode 100644
index 000000000000..32bdf4f8e432
--- /dev/null
+++ b/drivers/firmware/efi/efi.c
@@ -0,0 +1,134 @@
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
22static struct kobject *efi_kobj;
23static struct kobject *efivars_kobj;
24
25/*
26 * Let's not leave out systab information that snuck into
27 * the efivars driver
28 */
29static 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
55static struct kobj_attribute efi_attr_systab =
56 __ATTR(systab, 0400, systab_show, NULL);
57
58static struct attribute *efi_subsys_attrs[] = {
59 &efi_attr_systab.attr,
60 NULL, /* maybe more in the future? */
61};
62
63static struct attribute_group efi_subsys_attr_group = {
64 .attrs = efi_subsys_attrs,
65};
66
67static struct efivars generic_efivars;
68static struct efivar_operations generic_ops;
69
70static 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
80static 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 */
90static 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
125err_remove_group:
126 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
127err_unregister:
128 generic_ops_unregister();
129err_put:
130 kobject_put(efi_kobj);
131 return error;
132}
133
134subsys_initcall(efisubsys_init);
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
new file mode 100644
index 000000000000..70635b3b59d3
--- /dev/null
+++ b/drivers/firmware/efi/efivars.c
@@ -0,0 +1,617 @@
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
74MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
75MODULE_DESCRIPTION("sysfs interface to EFI Variables");
76MODULE_LICENSE("GPL");
77MODULE_VERSION(EFIVARS_VERSION);
78
79LIST_HEAD(efivar_sysfs_list);
80EXPORT_SYMBOL_GPL(efivar_sysfs_list);
81
82static struct kset *efivars_kset;
83
84static struct bin_attribute *efivars_new_var;
85static struct bin_attribute *efivars_del_var;
86
87struct 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) \
94struct 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 */
106static int
107efivar_create_sysfs_entry(struct efivar_entry *new_var);
108
109static ssize_t
110efivar_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
125static ssize_t
126efivar_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
158static ssize_t
159efivar_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
175static ssize_t
176efivar_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 */
194static ssize_t
195efivar_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
237static ssize_t
238efivar_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 */
259static 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
275static 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
291static const struct sysfs_ops efivar_attr_ops = {
292 .show = efivar_attr_show,
293 .store = efivar_attr_store,
294};
295
296static void efivar_release(struct kobject *kobj)
297{
298 struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
299 kfree(var);
300}
301
302static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
303static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
304static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
305static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
306static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
307
308static 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
317static struct kobj_type efivar_ktype = {
318 .release = efivar_release,
319 .sysfs_ops = &efivar_attr_ops,
320 .default_attrs = def_attrs,
321};
322
323static 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
360out:
361 kfree(new_entry);
362 return err;
363}
364
365static 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 */
401static int
402efivar_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
452static int
453create_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;
499out_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
507static 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
521static 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
545static 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
562static 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
569void 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
583int 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}
614EXPORT_SYMBOL_GPL(efivars_sysfs_init);
615
616module_init(efivars_sysfs_init);
617module_exit(efivars_sysfs_exit);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efi/vars.c
index af396758482f..dd1c20a426fa 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efi/vars.c
@@ -1,12 +1,9 @@
1/* 1/*
2 * EFI Variables - efivars.c 2 * Originally from efivars.c
3 * 3 *
4 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com> 4 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
5 * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com> 5 * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
6 * 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 7 * 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 8 * 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 9 * the Free Software Foundation; either version 2 of the License, or
@@ -20,49 +17,6 @@
20 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 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 */ 20 */
67 21
68#include <linux/capability.h> 22#include <linux/capability.h>
@@ -75,65 +29,16 @@
75#include <linux/smp.h> 29#include <linux/smp.h>
76#include <linux/efi.h> 30#include <linux/efi.h>
77#include <linux/sysfs.h> 31#include <linux/sysfs.h>
78#include <linux/kobject.h>
79#include <linux/device.h> 32#include <linux/device.h>
80#include <linux/slab.h> 33#include <linux/slab.h>
81#include <linux/ctype.h> 34#include <linux/ctype.h>
82 35
83#include <linux/fs.h>
84#include <linux/ramfs.h>
85#include <linux/pagemap.h>
86
87#include <asm/uaccess.h>
88
89#define EFIVARS_VERSION "0.08"
90#define EFIVARS_DATE "2004-May-17"
91
92MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
93MODULE_DESCRIPTION("sysfs interface to EFI Variables");
94MODULE_LICENSE("GPL");
95MODULE_VERSION(EFIVARS_VERSION);
96
97LIST_HEAD(efivar_sysfs_list);
98EXPORT_SYMBOL_GPL(efivar_sysfs_list);
99
100struct efivar_attribute {
101 struct attribute attr;
102 ssize_t (*show) (struct efivar_entry *entry, char *buf);
103 ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
104};
105
106/* Private pointer to registered efivars */ 36/* Private pointer to registered efivars */
107static struct efivars *__efivars; 37static struct efivars *__efivars;
108 38
109static struct kset *efivars_kset;
110
111static struct bin_attribute *efivars_new_var;
112static struct bin_attribute *efivars_del_var;
113
114#define EFIVAR_ATTR(_name, _mode, _show, _store) \
115struct efivar_attribute efivar_attr_##_name = { \
116 .attr = {.name = __stringify(_name), .mode = _mode}, \
117 .show = _show, \
118 .store = _store, \
119};
120
121#define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
122#define to_efivar_entry(obj) container_of(obj, struct efivar_entry, kobj)
123
124/*
125 * Prototype for sysfs creation function
126 */
127static int
128efivar_create_sysfs_entry(struct efivar_entry *new_var);
129
130/*
131 * Prototype for workqueue functions updating sysfs entry
132 */
133
134static void efivar_update_sysfs_entries(struct work_struct *);
135static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
136static bool efivar_wq_enabled = true; 39static bool efivar_wq_enabled = true;
40DECLARE_WORK(efivar_work, NULL);
41EXPORT_SYMBOL_GPL(efivar_work);
137 42
138static bool 43static bool
139validate_device_path(struct efi_variable *var, int match, u8 *buffer, 44validate_device_path(struct efi_variable *var, int match, u8 *buffer,
@@ -343,220 +248,6 @@ check_var_size(u32 attributes, unsigned long size)
343 return status; 248 return status;
344} 249}
345 250
346static ssize_t
347efivar_guid_read(struct efivar_entry *entry, char *buf)
348{
349 struct efi_variable *var = &entry->var;
350 char *str = buf;
351
352 if (!entry || !buf)
353 return 0;
354
355 efi_guid_unparse(&var->VendorGuid, str);
356 str += strlen(str);
357 str += sprintf(str, "\n");
358
359 return str - buf;
360}
361
362static ssize_t
363efivar_attr_read(struct efivar_entry *entry, char *buf)
364{
365 struct efi_variable *var = &entry->var;
366 char *str = buf;
367
368 if (!entry || !buf)
369 return -EINVAL;
370
371 var->DataSize = 1024;
372 if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
373 return -EIO;
374
375 if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
376 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
377 if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
378 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
379 if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
380 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
381 if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
382 str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
383 if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
384 str += sprintf(str,
385 "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
386 if (var->Attributes &
387 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
388 str += sprintf(str,
389 "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
390 if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
391 str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
392 return str - buf;
393}
394
395static ssize_t
396efivar_size_read(struct efivar_entry *entry, char *buf)
397{
398 struct efi_variable *var = &entry->var;
399 char *str = buf;
400
401 if (!entry || !buf)
402 return -EINVAL;
403
404 var->DataSize = 1024;
405 if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
406 return -EIO;
407
408 str += sprintf(str, "0x%lx\n", var->DataSize);
409 return str - buf;
410}
411
412static ssize_t
413efivar_data_read(struct efivar_entry *entry, char *buf)
414{
415 struct efi_variable *var = &entry->var;
416
417 if (!entry || !buf)
418 return -EINVAL;
419
420 var->DataSize = 1024;
421 if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
422 return -EIO;
423
424 memcpy(buf, var->Data, var->DataSize);
425 return var->DataSize;
426}
427/*
428 * We allow each variable to be edited via rewriting the
429 * entire efi variable structure.
430 */
431static ssize_t
432efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
433{
434 struct efi_variable *new_var, *var = &entry->var;
435 int err;
436
437 if (count != sizeof(struct efi_variable))
438 return -EINVAL;
439
440 new_var = (struct efi_variable *)buf;
441 /*
442 * If only updating the variable data, then the name
443 * and guid should remain the same
444 */
445 if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
446 efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
447 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
448 return -EINVAL;
449 }
450
451 if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
452 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
453 return -EINVAL;
454 }
455
456 if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
457 efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
458 printk(KERN_ERR "efivars: Malformed variable content\n");
459 return -EINVAL;
460 }
461
462 memcpy(&entry->var, new_var, count);
463
464 err = efivar_entry_set(entry, new_var->Attributes,
465 new_var->DataSize, new_var->Data, false);
466 if (err) {
467 printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
468 return -EIO;
469 }
470
471 return count;
472}
473
474static ssize_t
475efivar_show_raw(struct efivar_entry *entry, char *buf)
476{
477 struct efi_variable *var = &entry->var;
478
479 if (!entry || !buf)
480 return 0;
481
482 var->DataSize = 1024;
483 if (efivar_entry_get(entry, &entry->var.Attributes,
484 &entry->var.DataSize, entry->var.Data))
485 return -EIO;
486
487 memcpy(buf, var, sizeof(*var));
488
489 return sizeof(*var);
490}
491
492/*
493 * Generic read/write functions that call the specific functions of
494 * the attributes...
495 */
496static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
497 char *buf)
498{
499 struct efivar_entry *var = to_efivar_entry(kobj);
500 struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
501 ssize_t ret = -EIO;
502
503 if (!capable(CAP_SYS_ADMIN))
504 return -EACCES;
505
506 if (efivar_attr->show) {
507 ret = efivar_attr->show(var, buf);
508 }
509 return ret;
510}
511
512static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
513 const char *buf, size_t count)
514{
515 struct efivar_entry *var = to_efivar_entry(kobj);
516 struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
517 ssize_t ret = -EIO;
518
519 if (!capable(CAP_SYS_ADMIN))
520 return -EACCES;
521
522 if (efivar_attr->store)
523 ret = efivar_attr->store(var, buf, count);
524
525 return ret;
526}
527
528static const struct sysfs_ops efivar_attr_ops = {
529 .show = efivar_attr_show,
530 .store = efivar_attr_store,
531};
532
533static void efivar_release(struct kobject *kobj)
534{
535 struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
536 kfree(var);
537}
538
539static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
540static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
541static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
542static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
543static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
544
545static struct attribute *def_attrs[] = {
546 &efivar_attr_guid.attr,
547 &efivar_attr_size.attr,
548 &efivar_attr_attributes.attr,
549 &efivar_attr_data.attr,
550 &efivar_attr_raw_var.attr,
551 NULL,
552};
553
554static struct kobj_type efivar_ktype = {
555 .release = efivar_release,
556 .sysfs_ops = &efivar_attr_ops,
557 .default_attrs = def_attrs,
558};
559
560static int efi_status_to_err(efi_status_t status) 251static int efi_status_to_err(efi_status_t status)
561{ 252{
562 int err; 253 int err;
@@ -590,78 +281,6 @@ static int efi_status_to_err(efi_status_t status)
590 return err; 281 return err;
591} 282}
592 283
593static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
594 struct bin_attribute *bin_attr,
595 char *buf, loff_t pos, size_t count)
596{
597 struct efi_variable *new_var = (struct efi_variable *)buf;
598 struct efivar_entry *new_entry;
599 int err;
600
601 if (!capable(CAP_SYS_ADMIN))
602 return -EACCES;
603
604 if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
605 efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
606 printk(KERN_ERR "efivars: Malformed variable content\n");
607 return -EINVAL;
608 }
609
610 new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
611 if (!new_entry)
612 return -ENOMEM;
613
614 memcpy(&new_entry->var, new_var, sizeof(*new_var));
615
616 err = efivar_entry_set(new_entry, new_var->Attributes, new_var->DataSize,
617 new_var->Data, &efivar_sysfs_list);
618 if (err) {
619 if (err == -EEXIST)
620 err = -EINVAL;
621 goto out;
622 }
623
624 if (efivar_create_sysfs_entry(new_entry)) {
625 printk(KERN_WARNING "efivars: failed to create sysfs entry.\n");
626 kfree(new_entry);
627 }
628 return count;
629
630out:
631 kfree(new_entry);
632 return err;
633}
634
635static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
636 struct bin_attribute *bin_attr,
637 char *buf, loff_t pos, size_t count)
638{
639 struct efi_variable *del_var = (struct efi_variable *)buf;
640 struct efivar_entry *entry;
641 int err = 0;
642
643 if (!capable(CAP_SYS_ADMIN))
644 return -EACCES;
645
646 efivar_entry_iter_begin();
647 entry = efivar_entry_find(del_var->VariableName, del_var->VendorGuid,
648 &efivar_sysfs_list, true);
649 if (!entry)
650 err = -EINVAL;
651 else if (__efivar_entry_delete(entry))
652 err = -EIO;
653
654 efivar_entry_iter_end();
655
656 if (err)
657 return err;
658
659 efivar_unregister(entry);
660
661 /* It's dead Jim.... */
662 return count;
663}
664
665static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor, 284static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
666 struct list_head *head) 285 struct list_head *head)
667{ 286{
@@ -684,20 +303,6 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
684 return found; 303 return found;
685} 304}
686 305
687static int efivar_update_sysfs_entry(efi_char16_t *name, efi_guid_t vendor,
688 unsigned long name_size, void *data)
689{
690 struct efivar_entry *entry = data;
691
692 if (efivar_entry_find(name, vendor, &efivar_sysfs_list, false))
693 return 0;
694
695 memcpy(entry->var.VariableName, name, name_size);
696 memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
697
698 return 1;
699}
700
701/* 306/*
702 * Returns the size of variable_name, in bytes, including the 307 * Returns the size of variable_name, in bytes, including the
703 * terminating NULL character, or variable_name_size if no NULL 308 * terminating NULL character, or variable_name_size if no NULL
@@ -723,210 +328,6 @@ static unsigned long var_name_strnsize(efi_char16_t *variable_name,
723 return min(len, variable_name_size); 328 return min(len, variable_name_size);
724} 329}
725 330
726static void efivar_update_sysfs_entries(struct work_struct *work)
727{
728 struct efivar_entry *entry;
729 int err;
730
731 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
732 if (!entry)
733 return;
734
735 /* Add new sysfs entries */
736 while (1) {
737 memset(entry, 0, sizeof(*entry));
738
739 err = efivar_init(efivar_update_sysfs_entry, entry,
740 true, false, &efivar_sysfs_list);
741 if (!err)
742 break;
743
744 efivar_create_sysfs_entry(entry);
745 }
746
747 kfree(entry);
748}
749
750/*
751 * Let's not leave out systab information that snuck into
752 * the efivars driver
753 */
754static ssize_t systab_show(struct kobject *kobj,
755 struct kobj_attribute *attr, char *buf)
756{
757 char *str = buf;
758
759 if (!kobj || !buf)
760 return -EINVAL;
761
762 if (efi.mps != EFI_INVALID_TABLE_ADDR)
763 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
764 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
765 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
766 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
767 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
768 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
769 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
770 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
771 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
772 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
773 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
774 if (efi.uga != EFI_INVALID_TABLE_ADDR)
775 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
776
777 return str - buf;
778}
779
780static struct kobj_attribute efi_attr_systab =
781 __ATTR(systab, 0400, systab_show, NULL);
782
783static struct attribute *efi_subsys_attrs[] = {
784 &efi_attr_systab.attr,
785 NULL, /* maybe more in the future? */
786};
787
788static struct attribute_group efi_subsys_attr_group = {
789 .attrs = efi_subsys_attrs,
790};
791
792static struct kobject *efi_kobj;
793
794/**
795 * efivar_create_sysfs_entry - create a new entry in sysfs
796 * @new_var: efivar entry to create
797 *
798 * Returns 1 on failure, 0 on success
799 */
800static int
801efivar_create_sysfs_entry(struct efivar_entry *new_var)
802{
803 int i, short_name_size;
804 char *short_name;
805 unsigned long variable_name_size;
806 efi_char16_t *variable_name;
807
808 variable_name = new_var->var.VariableName;
809 variable_name_size = utf16_strlen(variable_name) * sizeof(efi_char16_t);
810
811 /*
812 * Length of the variable bytes in ASCII, plus the '-' separator,
813 * plus the GUID, plus trailing NUL
814 */
815 short_name_size = variable_name_size / sizeof(efi_char16_t)
816 + 1 + EFI_VARIABLE_GUID_LEN + 1;
817
818 short_name = kzalloc(short_name_size, GFP_KERNEL);
819
820 if (!short_name) {
821 kfree(short_name);
822 return 1;
823 }
824
825 /* Convert Unicode to normal chars (assume top bits are 0),
826 ala UTF-8 */
827 for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
828 short_name[i] = variable_name[i] & 0xFF;
829 }
830 /* This is ugly, but necessary to separate one vendor's
831 private variables from another's. */
832
833 *(short_name + strlen(short_name)) = '-';
834 efi_guid_unparse(&new_var->var.VendorGuid,
835 short_name + strlen(short_name));
836
837 new_var->kobj.kset = efivars_kset;
838
839 i = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
840 NULL, "%s", short_name);
841 kfree(short_name);
842 if (i)
843 return 1;
844
845 kobject_uevent(&new_var->kobj, KOBJ_ADD);
846 efivar_entry_add(new_var, &efivar_sysfs_list);
847
848 return 0;
849}
850
851static int
852create_efivars_bin_attributes(void)
853{
854 struct bin_attribute *attr;
855 int error;
856
857 /* new_var */
858 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
859 if (!attr)
860 return -ENOMEM;
861
862 attr->attr.name = "new_var";
863 attr->attr.mode = 0200;
864 attr->write = efivar_create;
865 efivars_new_var = attr;
866
867 /* del_var */
868 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
869 if (!attr) {
870 error = -ENOMEM;
871 goto out_free;
872 }
873 attr->attr.name = "del_var";
874 attr->attr.mode = 0200;
875 attr->write = efivar_delete;
876 efivars_del_var = attr;
877
878 sysfs_bin_attr_init(efivars_new_var);
879 sysfs_bin_attr_init(efivars_del_var);
880
881 /* Register */
882 error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_new_var);
883 if (error) {
884 printk(KERN_ERR "efivars: unable to create new_var sysfs file"
885 " due to error %d\n", error);
886 goto out_free;
887 }
888
889 error = sysfs_create_bin_file(&efivars_kset->kobj, efivars_del_var);
890 if (error) {
891 printk(KERN_ERR "efivars: unable to create del_var sysfs file"
892 " due to error %d\n", error);
893 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
894 goto out_free;
895 }
896
897 return 0;
898out_free:
899 kfree(efivars_del_var);
900 efivars_del_var = NULL;
901 kfree(efivars_new_var);
902 efivars_new_var = NULL;
903 return error;
904}
905
906static int efivars_sysfs_callback(efi_char16_t *name, efi_guid_t vendor,
907 unsigned long name_size, void *data)
908{
909 struct efivar_entry *entry;
910
911 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
912 if (!entry)
913 return -ENOMEM;
914
915 memcpy(entry->var.VariableName, name, name_size);
916 memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
917
918 efivar_create_sysfs_entry(entry);
919
920 return 0;
921}
922
923static int efivar_sysfs_destroy(struct efivar_entry *entry, void *data)
924{
925 efivar_entry_remove(entry);
926 efivar_unregister(entry);
927 return 0;
928}
929
930/* 331/*
931 * Print a warning when duplicate EFI variables are encountered and 332 * Print a warning when duplicate EFI variables are encountered and
932 * disable the sysfs workqueue since the firmware is buggy. 333 * disable the sysfs workqueue since the firmware is buggy.
@@ -956,59 +357,6 @@ static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
956 kfree(s8); 357 kfree(s8);
957} 358}
958 359
959static struct kobject *efivars_kobj;
960
961void efivars_sysfs_exit(void)
962{
963 /* Remove all entries and destroy */
964 __efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list, NULL, NULL);
965
966 if (efivars_new_var)
967 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_new_var);
968 if (efivars_del_var)
969 sysfs_remove_bin_file(&efivars_kset->kobj, efivars_del_var);
970 kfree(efivars_new_var);
971 kfree(efivars_del_var);
972 kobject_put(efivars_kobj);
973 kset_unregister(efivars_kset);
974}
975
976int efivars_sysfs_init(void)
977{
978 struct kobject *parent_kobj = efivars_kobject();
979 int error = 0;
980
981 /* No efivars has been registered yet */
982 if (!parent_kobj)
983 return 0;
984
985 printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
986 EFIVARS_DATE);
987
988 efivars_kset = kset_create_and_add("vars", NULL, parent_kobj);
989 if (!efivars_kset) {
990 printk(KERN_ERR "efivars: Subsystem registration failed.\n");
991 return -ENOMEM;
992 }
993
994 efivars_kobj = kobject_create_and_add("efivars", parent_kobj);
995 if (!efivars_kobj) {
996 pr_err("efivars: Subsystem registration failed.\n");
997 kset_unregister(efivars_kset);
998 return -ENOMEM;
999 }
1000
1001 efivar_init(efivars_sysfs_callback, NULL, false,
1002 true, &efivar_sysfs_list);
1003
1004 error = create_efivars_bin_attributes();
1005 if (error)
1006 efivars_sysfs_exit();
1007
1008 return error;
1009}
1010EXPORT_SYMBOL_GPL(efivars_sysfs_init);
1011
1012/** 360/**
1013 * efivar_init - build the initial list of EFI variables 361 * efivar_init - build the initial list of EFI variables
1014 * @func: callback function to invoke for every variable 362 * @func: callback function to invoke for every variable
@@ -1154,17 +502,16 @@ static void efivar_entry_list_del_unlock(struct efivar_entry *entry)
1154 * __efivar_entry_delete - delete an EFI variable 502 * __efivar_entry_delete - delete an EFI variable
1155 * @entry: entry containing EFI variable to delete 503 * @entry: entry containing EFI variable to delete
1156 * 504 *
1157 * Delete the variable from the firmware and remove @entry from the 505 * Delete the variable from the firmware but leave @entry on the
1158 * variable list. It is the caller's responsibility to free @entry 506 * variable list.
1159 * once we return.
1160 * 507 *
1161 * This function differs from efivar_entry_delete() because it is 508 * This function differs from efivar_entry_delete() because it does
1162 * safe to be called from within a efivar_entry_iter_begin() and 509 * not remove @entry from the variable list. Also, it is safe to be
510 * called from within a efivar_entry_iter_begin() and
1163 * efivar_entry_iter_end() region, unlike efivar_entry_delete(). 511 * efivar_entry_iter_end() region, unlike efivar_entry_delete().
1164 * 512 *
1165 * Returns 0 on success, or a converted EFI status code if 513 * Returns 0 on success, or a converted EFI status code if
1166 * set_variable() fails. If set_variable() fails the entry remains 514 * set_variable() fails.
1167 * on the list.
1168 */ 515 */
1169int __efivar_entry_delete(struct efivar_entry *entry) 516int __efivar_entry_delete(struct efivar_entry *entry)
1170{ 517{
@@ -1176,12 +523,8 @@ int __efivar_entry_delete(struct efivar_entry *entry)
1176 status = ops->set_variable(entry->var.VariableName, 523 status = ops->set_variable(entry->var.VariableName,
1177 &entry->var.VendorGuid, 524 &entry->var.VendorGuid,
1178 0, 0, NULL); 525 0, 0, NULL);
1179 if (status)
1180 return efi_status_to_err(status);
1181
1182 list_del(&entry->list);
1183 526
1184 return 0; 527 return efi_status_to_err(status);
1185} 528}
1186EXPORT_SYMBOL_GPL(__efivar_entry_delete); 529EXPORT_SYMBOL_GPL(__efivar_entry_delete);
1187 530
@@ -1259,6 +602,7 @@ int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
1259 spin_unlock_irq(&__efivars->lock); 602 spin_unlock_irq(&__efivars->lock);
1260 603
1261 return efi_status_to_err(status); 604 return efi_status_to_err(status);
605
1262} 606}
1263EXPORT_SYMBOL_GPL(efivar_entry_set); 607EXPORT_SYMBOL_GPL(efivar_entry_set);
1264 608
@@ -1289,7 +633,7 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
1289 if (!ops->query_variable_info) 633 if (!ops->query_variable_info)
1290 return -ENOSYS; 634 return -ENOSYS;
1291 635
1292 if (!block && !spin_trylock_irqsave(&__efivars->lock, flags)) 636 if (!block && spin_trylock_irqsave(&__efivars->lock, flags))
1293 return -EBUSY; 637 return -EBUSY;
1294 else 638 else
1295 spin_lock_irqsave(&__efivars->lock, flags); 639 spin_lock_irqsave(&__efivars->lock, flags);
@@ -1703,92 +1047,3 @@ out:
1703 return rv; 1047 return rv;
1704} 1048}
1705EXPORT_SYMBOL_GPL(efivars_unregister); 1049EXPORT_SYMBOL_GPL(efivars_unregister);
1706
1707static struct efivars generic_efivars;
1708static struct efivar_operations generic_ops;
1709
1710static int generic_ops_register(void)
1711{
1712 int error;
1713
1714 generic_ops.get_variable = efi.get_variable;
1715 generic_ops.set_variable = efi.set_variable;
1716 generic_ops.get_next_variable = efi.get_next_variable;
1717 generic_ops.query_variable_info = efi.query_variable_info;
1718
1719 error = efivars_register(&generic_efivars, &generic_ops, efi_kobj);
1720 if (error)
1721 return error;
1722
1723 error = efivars_sysfs_init();
1724 if (error)
1725 efivars_unregister(&generic_efivars);
1726
1727 return error;
1728}
1729
1730static void generic_ops_unregister(void)
1731{
1732 efivars_sysfs_exit();
1733 efivars_unregister(&generic_efivars);
1734}
1735
1736/*
1737 * For now we register the efi subsystem with the firmware subsystem
1738 * and the vars subsystem with the efi subsystem. In the future, it
1739 * might make sense to split off the efi subsystem into its own
1740 * driver, but for now only efivars will register with it, so just
1741 * include it here.
1742 */
1743
1744static int __init
1745efivars_init(void)
1746{
1747 int error;
1748
1749 if (!efi_enabled(EFI_RUNTIME_SERVICES))
1750 return 0;
1751
1752 /* Register the efi directory at /sys/firmware/efi */
1753 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
1754 if (!efi_kobj) {
1755 printk(KERN_ERR "efivars: Firmware registration failed.\n");
1756 return -ENOMEM;
1757 }
1758
1759 error = generic_ops_register();
1760 if (error)
1761 goto err_put;
1762
1763 /* Don't forget the systab entry */
1764 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
1765 if (error) {
1766 printk(KERN_ERR
1767 "efivars: Sysfs attribute export failed with error %d.\n",
1768 error);
1769 goto err_unregister;
1770 }
1771
1772 return 0;
1773
1774err_unregister:
1775 generic_ops_unregister();
1776err_put:
1777 kobject_put(efi_kobj);
1778 return error;
1779}
1780
1781static void __exit
1782efivars_exit(void)
1783{
1784 cancel_work_sync(&efivar_work);
1785
1786 if (efi_enabled(EFI_RUNTIME_SERVICES)) {
1787 generic_ops_unregister();
1788 kobject_put(efi_kobj);
1789 }
1790}
1791
1792module_init(efivars_init);
1793module_exit(efivars_exit);
1794