]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/firmware/efivars.c
efi: Add support for using efivars as a pstore backend
[karo-tx-linux.git] / drivers / firmware / efivars.c
1 /*
2  * EFI Variables - efivars.c
3  *
4  * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
5  * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
6  *
7  * This code takes all variables accessible from EFI runtime and
8  *  exports them via sysfs
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * Changelog:
25  *
26  *  17 May 2004 - Matt Domsch <Matt_Domsch@dell.com>
27  *   remove check for efi_enabled in exit
28  *   add MODULE_VERSION
29  *
30  *  26 Apr 2004 - Matt Domsch <Matt_Domsch@dell.com>
31  *   minor bug fixes
32  *
33  *  21 Apr 2004 - Matt Tolentino <matthew.e.tolentino@intel.com)
34  *   converted driver to export variable information via sysfs
35  *   and moved to drivers/firmware directory
36  *   bumped revision number to v0.07 to reflect conversion & move
37  *
38  *  10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
39  *   fix locking per Peter Chubb's findings
40  *
41  *  25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
42  *   move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
43  *
44  *  12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
45  *   use list_for_each_safe when deleting vars.
46  *   remove ifdef CONFIG_SMP around include <linux/smp.h>
47  *   v0.04 release to linux-ia64@linuxia64.org
48  *
49  *  20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
50  *   Moved vars from /proc/efi to /proc/efi/vars, and made
51  *   efi.c own the /proc/efi directory.
52  *   v0.03 release to linux-ia64@linuxia64.org
53  *
54  *  26 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
55  *   At the request of Stephane, moved ownership of /proc/efi
56  *   to efi.c, and now efivars lives under /proc/efi/vars.
57  *
58  *  12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
59  *   Feedback received from Stephane Eranian incorporated.
60  *   efivar_write() checks copy_from_user() return value.
61  *   efivar_read/write() returns proper errno.
62  *   v0.02 release to linux-ia64@linuxia64.org
63  *
64  *  26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
65  *   v0.01 release to linux-ia64@linuxia64.org
66  */
67
68 #include <linux/capability.h>
69 #include <linux/types.h>
70 #include <linux/errno.h>
71 #include <linux/init.h>
72 #include <linux/mm.h>
73 #include <linux/module.h>
74 #include <linux/string.h>
75 #include <linux/smp.h>
76 #include <linux/efi.h>
77 #include <linux/sysfs.h>
78 #include <linux/kobject.h>
79 #include <linux/device.h>
80 #include <linux/slab.h>
81 #include <linux/pstore.h>
82
83 #include <asm/uaccess.h>
84
85 #define EFIVARS_VERSION "0.08"
86 #define EFIVARS_DATE "2004-May-17"
87
88 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
89 MODULE_DESCRIPTION("sysfs interface to EFI Variables");
90 MODULE_LICENSE("GPL");
91 MODULE_VERSION(EFIVARS_VERSION);
92
93 #define DUMP_NAME_LEN 52
94
95 /*
96  * The maximum size of VariableName + Data = 1024
97  * Therefore, it's reasonable to save that much
98  * space in each part of the structure,
99  * and we use a page for reading/writing.
100  */
101
102 struct efi_variable {
103         efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
104         efi_guid_t    VendorGuid;
105         unsigned long DataSize;
106         __u8          Data[1024];
107         efi_status_t  Status;
108         __u32         Attributes;
109 } __attribute__((packed));
110
111
112 struct efivar_entry {
113         struct efivars *efivars;
114         struct efi_variable var;
115         struct list_head list;
116         struct kobject kobj;
117 };
118
119 struct efivar_attribute {
120         struct attribute attr;
121         ssize_t (*show) (struct efivar_entry *entry, char *buf);
122         ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
123 };
124
125
126 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
127 struct efivar_attribute efivar_attr_##_name = { \
128         .attr = {.name = __stringify(_name), .mode = _mode}, \
129         .show = _show, \
130         .store = _store, \
131 };
132
133 #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
134 #define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
135
136 /*
137  * Prototype for sysfs creation function
138  */
139 static int
140 efivar_create_sysfs_entry(struct efivars *efivars,
141                           unsigned long variable_name_size,
142                           efi_char16_t *variable_name,
143                           efi_guid_t *vendor_guid);
144
145 /* Return the number of unicode characters in data */
146 static unsigned long
147 utf8_strlen(efi_char16_t *data, unsigned long maxlength)
148 {
149         unsigned long length = 0;
150
151         while (*data++ != 0 && length < maxlength)
152                 length++;
153         return length;
154 }
155
156 /*
157  * Return the number of bytes is the length of this string
158  * Note: this is NOT the same as the number of unicode characters
159  */
160 static inline unsigned long
161 utf8_strsize(efi_char16_t *data, unsigned long maxlength)
162 {
163         return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
164 }
165
166 static efi_status_t
167 get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
168 {
169         efi_status_t status;
170
171         var->DataSize = 1024;
172         status = efivars->ops->get_variable(var->VariableName,
173                                             &var->VendorGuid,
174                                             &var->Attributes,
175                                             &var->DataSize,
176                                             var->Data);
177         return status;
178 }
179
180 static efi_status_t
181 get_var_data(struct efivars *efivars, struct efi_variable *var)
182 {
183         efi_status_t status;
184
185         spin_lock(&efivars->lock);
186         status = get_var_data_locked(efivars, var);
187         spin_unlock(&efivars->lock);
188
189         if (status != EFI_SUCCESS) {
190                 printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
191                         status);
192         }
193         return status;
194 }
195
196 static ssize_t
197 efivar_guid_read(struct efivar_entry *entry, char *buf)
198 {
199         struct efi_variable *var = &entry->var;
200         char *str = buf;
201
202         if (!entry || !buf)
203                 return 0;
204
205         efi_guid_unparse(&var->VendorGuid, str);
206         str += strlen(str);
207         str += sprintf(str, "\n");
208
209         return str - buf;
210 }
211
212 static ssize_t
213 efivar_attr_read(struct efivar_entry *entry, char *buf)
214 {
215         struct efi_variable *var = &entry->var;
216         char *str = buf;
217         efi_status_t status;
218
219         if (!entry || !buf)
220                 return -EINVAL;
221
222         status = get_var_data(entry->efivars, var);
223         if (status != EFI_SUCCESS)
224                 return -EIO;
225
226         if (var->Attributes & 0x1)
227                 str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
228         if (var->Attributes & 0x2)
229                 str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
230         if (var->Attributes & 0x4)
231                 str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
232         return str - buf;
233 }
234
235 static ssize_t
236 efivar_size_read(struct efivar_entry *entry, char *buf)
237 {
238         struct efi_variable *var = &entry->var;
239         char *str = buf;
240         efi_status_t status;
241
242         if (!entry || !buf)
243                 return -EINVAL;
244
245         status = get_var_data(entry->efivars, var);
246         if (status != EFI_SUCCESS)
247                 return -EIO;
248
249         str += sprintf(str, "0x%lx\n", var->DataSize);
250         return str - buf;
251 }
252
253 static ssize_t
254 efivar_data_read(struct efivar_entry *entry, char *buf)
255 {
256         struct efi_variable *var = &entry->var;
257         efi_status_t status;
258
259         if (!entry || !buf)
260                 return -EINVAL;
261
262         status = get_var_data(entry->efivars, var);
263         if (status != EFI_SUCCESS)
264                 return -EIO;
265
266         memcpy(buf, var->Data, var->DataSize);
267         return var->DataSize;
268 }
269 /*
270  * We allow each variable to be edited via rewriting the
271  * entire efi variable structure.
272  */
273 static ssize_t
274 efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
275 {
276         struct efi_variable *new_var, *var = &entry->var;
277         struct efivars *efivars = entry->efivars;
278         efi_status_t status = EFI_NOT_FOUND;
279
280         if (count != sizeof(struct efi_variable))
281                 return -EINVAL;
282
283         new_var = (struct efi_variable *)buf;
284         /*
285          * If only updating the variable data, then the name
286          * and guid should remain the same
287          */
288         if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) ||
289                 efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) {
290                 printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n");
291                 return -EINVAL;
292         }
293
294         if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){
295                 printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
296                 return -EINVAL;
297         }
298
299         spin_lock(&efivars->lock);
300         status = efivars->ops->set_variable(new_var->VariableName,
301                                             &new_var->VendorGuid,
302                                             new_var->Attributes,
303                                             new_var->DataSize,
304                                             new_var->Data);
305
306         spin_unlock(&efivars->lock);
307
308         if (status != EFI_SUCCESS) {
309                 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
310                         status);
311                 return -EIO;
312         }
313
314         memcpy(&entry->var, new_var, count);
315         return count;
316 }
317
318 static ssize_t
319 efivar_show_raw(struct efivar_entry *entry, char *buf)
320 {
321         struct efi_variable *var = &entry->var;
322         efi_status_t status;
323
324         if (!entry || !buf)
325                 return 0;
326
327         status = get_var_data(entry->efivars, var);
328         if (status != EFI_SUCCESS)
329                 return -EIO;
330
331         memcpy(buf, var, sizeof(*var));
332         return sizeof(*var);
333 }
334
335 /*
336  * Generic read/write functions that call the specific functions of
337  * the attributes...
338  */
339 static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
340                                 char *buf)
341 {
342         struct efivar_entry *var = to_efivar_entry(kobj);
343         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
344         ssize_t ret = -EIO;
345
346         if (!capable(CAP_SYS_ADMIN))
347                 return -EACCES;
348
349         if (efivar_attr->show) {
350                 ret = efivar_attr->show(var, buf);
351         }
352         return ret;
353 }
354
355 static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
356                                 const char *buf, size_t count)
357 {
358         struct efivar_entry *var = to_efivar_entry(kobj);
359         struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
360         ssize_t ret = -EIO;
361
362         if (!capable(CAP_SYS_ADMIN))
363                 return -EACCES;
364
365         if (efivar_attr->store)
366                 ret = efivar_attr->store(var, buf, count);
367
368         return ret;
369 }
370
371 static const struct sysfs_ops efivar_attr_ops = {
372         .show = efivar_attr_show,
373         .store = efivar_attr_store,
374 };
375
376 static void efivar_release(struct kobject *kobj)
377 {
378         struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
379         kfree(var);
380 }
381
382 static EFIVAR_ATTR(guid, 0400, efivar_guid_read, NULL);
383 static EFIVAR_ATTR(attributes, 0400, efivar_attr_read, NULL);
384 static EFIVAR_ATTR(size, 0400, efivar_size_read, NULL);
385 static EFIVAR_ATTR(data, 0400, efivar_data_read, NULL);
386 static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
387
388 static struct attribute *def_attrs[] = {
389         &efivar_attr_guid.attr,
390         &efivar_attr_size.attr,
391         &efivar_attr_attributes.attr,
392         &efivar_attr_data.attr,
393         &efivar_attr_raw_var.attr,
394         NULL,
395 };
396
397 static struct kobj_type efivar_ktype = {
398         .release = efivar_release,
399         .sysfs_ops = &efivar_attr_ops,
400         .default_attrs = def_attrs,
401 };
402
403 static struct pstore_info efi_pstore_info;
404
405 static inline void
406 efivar_unregister(struct efivar_entry *var)
407 {
408         kobject_put(&var->kobj);
409 }
410
411 #ifdef CONFIG_PSTORE
412
413 static int efi_pstore_open(struct pstore_info *psi)
414 {
415         struct efivars *efivars = psi->data;
416
417         spin_lock(&efivars->lock);
418         efivars->walk_entry = list_first_entry(&efivars->list,
419                                                struct efivar_entry, list);
420         return 0;
421 }
422
423 static int efi_pstore_close(struct pstore_info *psi)
424 {
425         struct efivars *efivars = psi->data;
426
427         spin_unlock(&efivars->lock);
428         return 0;
429 }
430
431 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
432                                struct timespec *timespec, struct pstore_info *psi)
433 {
434         efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
435         struct efivars *efivars = psi->data;
436         char name[DUMP_NAME_LEN];
437         int i;
438         unsigned int part, size;
439         unsigned long time;
440
441         while (&efivars->walk_entry->list != &efivars->list) {
442                 if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
443                                  vendor)) {
444                         for (i = 0; i < DUMP_NAME_LEN; i++) {
445                                 name[i] = efivars->walk_entry->var.VariableName[i];
446                         }
447                         if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
448                                 *id = part;
449                                 timespec->tv_sec = time;
450                                 timespec->tv_nsec = 0;
451                                 get_var_data_locked(efivars, &efivars->walk_entry->var);
452                                 size = efivars->walk_entry->var.DataSize;
453                                 memcpy(psi->buf, efivars->walk_entry->var.Data, size);
454                                 efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
455                                                    struct efivar_entry, list);
456                                 return size;
457                         }
458                 }
459                 efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
460                                                  struct efivar_entry, list);
461         }
462         return 0;
463 }
464
465 static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
466                             size_t size, struct pstore_info *psi)
467 {
468         char name[DUMP_NAME_LEN];
469         char stub_name[DUMP_NAME_LEN];
470         efi_char16_t efi_name[DUMP_NAME_LEN];
471         efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
472         struct efivars *efivars = psi->data;
473         struct efivar_entry *entry, *found = NULL;
474         int i;
475
476         sprintf(stub_name, "dump-type%u-%u-", type, part);
477         sprintf(name, "%s%lu", stub_name, get_seconds());
478
479         spin_lock(&efivars->lock);
480
481         for (i = 0; i < DUMP_NAME_LEN; i++)
482                 efi_name[i] = stub_name[i];
483
484         /*
485          * Clean up any entries with the same name
486          */
487
488         list_for_each_entry(entry, &efivars->list, list) {
489                 get_var_data_locked(efivars, &entry->var);
490
491                 for (i = 0; i < DUMP_NAME_LEN; i++) {
492                         if (efi_name[i] == 0) {
493                                 found = entry;
494                                 efivars->ops->set_variable(entry->var.VariableName,
495                                                            &entry->var.VendorGuid,
496                                                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
497                                                            0, NULL);
498                                 break;
499                         } else if (efi_name[i] != entry->var.VariableName[i]) {
500                                 break;
501                         }
502                 }
503         }
504
505         if (found)
506                 list_del(&found->list);
507
508         for (i = 0; i < DUMP_NAME_LEN; i++)
509                 efi_name[i] = name[i];
510
511         efivars->ops->set_variable(efi_name, &vendor,
512                                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
513                                    size, psi->buf);
514
515         spin_unlock(&efivars->lock);
516
517         if (found)
518                 efivar_unregister(found);
519
520         if (size)
521                 efivar_create_sysfs_entry(efivars, utf8_strsize(efi_name, DUMP_NAME_LEN * 2),
522                                           efi_name, &vendor);
523
524         return part;
525 };
526
527 static int efi_pstore_erase(enum pstore_type_id type, u64 id,
528                             struct pstore_info *psi)
529 {
530         efi_pstore_write(type, id, 0, psi);
531
532         return 0;
533 }
534 #else
535 static int efi_pstore_open(struct pstore_info *psi)
536 {
537         return 0;
538 }
539
540 static int efi_pstore_close(struct pstore_info *psi)
541 {
542         return 0;
543 }
544
545 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
546                                struct timespec *time, struct pstore_info *psi)
547 {
548         return -1;
549 }
550
551 static u64 efi_pstore_write(enum pstore_type_id type, int part, size_t size,
552                             struct pstore_info *psi)
553 {
554         return 0;
555 }
556
557 static int efi_pstore_erase(enum pstore_type_id type, u64 id,
558                             struct pstore_info *psi)
559 {
560         return 0;
561 }
562 #endif
563
564 static struct pstore_info efi_pstore_info = {
565         .owner          = THIS_MODULE,
566         .name           = "efi",
567         .open           = efi_pstore_open,
568         .close          = efi_pstore_close,
569         .read           = efi_pstore_read,
570         .write          = efi_pstore_write,
571         .erase          = efi_pstore_erase,
572 };
573
574 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
575                              struct bin_attribute *bin_attr,
576                              char *buf, loff_t pos, size_t count)
577 {
578         struct efi_variable *new_var = (struct efi_variable *)buf;
579         struct efivars *efivars = bin_attr->private;
580         struct efivar_entry *search_efivar, *n;
581         unsigned long strsize1, strsize2;
582         efi_status_t status = EFI_NOT_FOUND;
583         int found = 0;
584
585         if (!capable(CAP_SYS_ADMIN))
586                 return -EACCES;
587
588         spin_lock(&efivars->lock);
589
590         /*
591          * Does this variable already exist?
592          */
593         list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
594                 strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
595                 strsize2 = utf8_strsize(new_var->VariableName, 1024);
596                 if (strsize1 == strsize2 &&
597                         !memcmp(&(search_efivar->var.VariableName),
598                                 new_var->VariableName, strsize1) &&
599                         !efi_guidcmp(search_efivar->var.VendorGuid,
600                                 new_var->VendorGuid)) {
601                         found = 1;
602                         break;
603                 }
604         }
605         if (found) {
606                 spin_unlock(&efivars->lock);
607                 return -EINVAL;
608         }
609
610         /* now *really* create the variable via EFI */
611         status = efivars->ops->set_variable(new_var->VariableName,
612                                             &new_var->VendorGuid,
613                                             new_var->Attributes,
614                                             new_var->DataSize,
615                                             new_var->Data);
616
617         if (status != EFI_SUCCESS) {
618                 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
619                         status);
620                 spin_unlock(&efivars->lock);
621                 return -EIO;
622         }
623         spin_unlock(&efivars->lock);
624
625         /* Create the entry in sysfs.  Locking is not required here */
626         status = efivar_create_sysfs_entry(efivars,
627                                            utf8_strsize(new_var->VariableName,
628                                                         1024),
629                                            new_var->VariableName,
630                                            &new_var->VendorGuid);
631         if (status) {
632                 printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n");
633         }
634         return count;
635 }
636
637 static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
638                              struct bin_attribute *bin_attr,
639                              char *buf, loff_t pos, size_t count)
640 {
641         struct efi_variable *del_var = (struct efi_variable *)buf;
642         struct efivars *efivars = bin_attr->private;
643         struct efivar_entry *search_efivar, *n;
644         unsigned long strsize1, strsize2;
645         efi_status_t status = EFI_NOT_FOUND;
646         int found = 0;
647
648         if (!capable(CAP_SYS_ADMIN))
649                 return -EACCES;
650
651         spin_lock(&efivars->lock);
652
653         /*
654          * Does this variable already exist?
655          */
656         list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
657                 strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
658                 strsize2 = utf8_strsize(del_var->VariableName, 1024);
659                 if (strsize1 == strsize2 &&
660                         !memcmp(&(search_efivar->var.VariableName),
661                                 del_var->VariableName, strsize1) &&
662                         !efi_guidcmp(search_efivar->var.VendorGuid,
663                                 del_var->VendorGuid)) {
664                         found = 1;
665                         break;
666                 }
667         }
668         if (!found) {
669                 spin_unlock(&efivars->lock);
670                 return -EINVAL;
671         }
672         /* force the Attributes/DataSize to 0 to ensure deletion */
673         del_var->Attributes = 0;
674         del_var->DataSize = 0;
675
676         status = efivars->ops->set_variable(del_var->VariableName,
677                                             &del_var->VendorGuid,
678                                             del_var->Attributes,
679                                             del_var->DataSize,
680                                             del_var->Data);
681
682         if (status != EFI_SUCCESS) {
683                 printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
684                         status);
685                 spin_unlock(&efivars->lock);
686                 return -EIO;
687         }
688         list_del(&search_efivar->list);
689         /* We need to release this lock before unregistering. */
690         spin_unlock(&efivars->lock);
691         efivar_unregister(search_efivar);
692
693         /* It's dead Jim.... */
694         return count;
695 }
696
697 /*
698  * Let's not leave out systab information that snuck into
699  * the efivars driver
700  */
701 static ssize_t systab_show(struct kobject *kobj,
702                            struct kobj_attribute *attr, char *buf)
703 {
704         char *str = buf;
705
706         if (!kobj || !buf)
707                 return -EINVAL;
708
709         if (efi.mps != EFI_INVALID_TABLE_ADDR)
710                 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
711         if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
712                 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
713         if (efi.acpi != EFI_INVALID_TABLE_ADDR)
714                 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
715         if (efi.smbios != EFI_INVALID_TABLE_ADDR)
716                 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
717         if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
718                 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
719         if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
720                 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
721         if (efi.uga != EFI_INVALID_TABLE_ADDR)
722                 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
723
724         return str - buf;
725 }
726
727 static struct kobj_attribute efi_attr_systab =
728                         __ATTR(systab, 0400, systab_show, NULL);
729
730 static struct attribute *efi_subsys_attrs[] = {
731         &efi_attr_systab.attr,
732         NULL,   /* maybe more in the future? */
733 };
734
735 static struct attribute_group efi_subsys_attr_group = {
736         .attrs = efi_subsys_attrs,
737 };
738
739 static struct kobject *efi_kobj;
740
741 /*
742  * efivar_create_sysfs_entry()
743  * Requires:
744  *    variable_name_size = number of bytes required to hold
745  *                         variable_name (not counting the NULL
746  *                         character at the end.
747  *    efivars->lock is not held on entry or exit.
748  * Returns 1 on failure, 0 on success
749  */
750 static int
751 efivar_create_sysfs_entry(struct efivars *efivars,
752                           unsigned long variable_name_size,
753                           efi_char16_t *variable_name,
754                           efi_guid_t *vendor_guid)
755 {
756         int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
757         char *short_name;
758         struct efivar_entry *new_efivar;
759
760         short_name = kzalloc(short_name_size + 1, GFP_KERNEL);
761         new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
762
763         if (!short_name || !new_efivar)  {
764                 kfree(short_name);
765                 kfree(new_efivar);
766                 return 1;
767         }
768
769         new_efivar->efivars = efivars;
770         memcpy(new_efivar->var.VariableName, variable_name,
771                 variable_name_size);
772         memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
773
774         /* Convert Unicode to normal chars (assume top bits are 0),
775            ala UTF-8 */
776         for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
777                 short_name[i] = variable_name[i] & 0xFF;
778         }
779         /* This is ugly, but necessary to separate one vendor's
780            private variables from another's.         */
781
782         *(short_name + strlen(short_name)) = '-';
783         efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
784
785         new_efivar->kobj.kset = efivars->kset;
786         i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL,
787                                  "%s", short_name);
788         if (i) {
789                 kfree(short_name);
790                 kfree(new_efivar);
791                 return 1;
792         }
793
794         kobject_uevent(&new_efivar->kobj, KOBJ_ADD);
795         kfree(short_name);
796         short_name = NULL;
797
798         spin_lock(&efivars->lock);
799         list_add(&new_efivar->list, &efivars->list);
800         spin_unlock(&efivars->lock);
801
802         return 0;
803 }
804
805 static int
806 create_efivars_bin_attributes(struct efivars *efivars)
807 {
808         struct bin_attribute *attr;
809         int error;
810
811         /* new_var */
812         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
813         if (!attr)
814                 return -ENOMEM;
815
816         attr->attr.name = "new_var";
817         attr->attr.mode = 0200;
818         attr->write = efivar_create;
819         attr->private = efivars;
820         efivars->new_var = attr;
821
822         /* del_var */
823         attr = kzalloc(sizeof(*attr), GFP_KERNEL);
824         if (!attr) {
825                 error = -ENOMEM;
826                 goto out_free;
827         }
828         attr->attr.name = "del_var";
829         attr->attr.mode = 0200;
830         attr->write = efivar_delete;
831         attr->private = efivars;
832         efivars->del_var = attr;
833
834         sysfs_bin_attr_init(efivars->new_var);
835         sysfs_bin_attr_init(efivars->del_var);
836
837         /* Register */
838         error = sysfs_create_bin_file(&efivars->kset->kobj,
839                                       efivars->new_var);
840         if (error) {
841                 printk(KERN_ERR "efivars: unable to create new_var sysfs file"
842                         " due to error %d\n", error);
843                 goto out_free;
844         }
845         error = sysfs_create_bin_file(&efivars->kset->kobj,
846                                       efivars->del_var);
847         if (error) {
848                 printk(KERN_ERR "efivars: unable to create del_var sysfs file"
849                         " due to error %d\n", error);
850                 sysfs_remove_bin_file(&efivars->kset->kobj,
851                                       efivars->new_var);
852                 goto out_free;
853         }
854
855         return 0;
856 out_free:
857         kfree(efivars->del_var);
858         efivars->del_var = NULL;
859         kfree(efivars->new_var);
860         efivars->new_var = NULL;
861         return error;
862 }
863
864 void unregister_efivars(struct efivars *efivars)
865 {
866         struct efivar_entry *entry, *n;
867
868         list_for_each_entry_safe(entry, n, &efivars->list, list) {
869                 spin_lock(&efivars->lock);
870                 list_del(&entry->list);
871                 spin_unlock(&efivars->lock);
872                 efivar_unregister(entry);
873         }
874         if (efivars->new_var)
875                 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var);
876         if (efivars->del_var)
877                 sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
878         kfree(efivars->new_var);
879         kfree(efivars->del_var);
880         kset_unregister(efivars->kset);
881 }
882 EXPORT_SYMBOL_GPL(unregister_efivars);
883
884 int register_efivars(struct efivars *efivars,
885                      const struct efivar_operations *ops,
886                      struct kobject *parent_kobj)
887 {
888         efi_status_t status = EFI_NOT_FOUND;
889         efi_guid_t vendor_guid;
890         efi_char16_t *variable_name;
891         unsigned long variable_name_size = 1024;
892         int error = 0;
893
894         variable_name = kzalloc(variable_name_size, GFP_KERNEL);
895         if (!variable_name) {
896                 printk(KERN_ERR "efivars: Memory allocation failed.\n");
897                 return -ENOMEM;
898         }
899
900         spin_lock_init(&efivars->lock);
901         INIT_LIST_HEAD(&efivars->list);
902         efivars->ops = ops;
903
904         efivars->kset = kset_create_and_add("vars", NULL, parent_kobj);
905         if (!efivars->kset) {
906                 printk(KERN_ERR "efivars: Subsystem registration failed.\n");
907                 error = -ENOMEM;
908                 goto out;
909         }
910
911         /*
912          * Per EFI spec, the maximum storage allocated for both
913          * the variable name and variable data is 1024 bytes.
914          */
915
916         do {
917                 variable_name_size = 1024;
918
919                 status = ops->get_next_variable(&variable_name_size,
920                                                 variable_name,
921                                                 &vendor_guid);
922                 switch (status) {
923                 case EFI_SUCCESS:
924                         efivar_create_sysfs_entry(efivars,
925                                                   variable_name_size,
926                                                   variable_name,
927                                                   &vendor_guid);
928                         break;
929                 case EFI_NOT_FOUND:
930                         break;
931                 default:
932                         printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
933                                 status);
934                         status = EFI_NOT_FOUND;
935                         break;
936                 }
937         } while (status != EFI_NOT_FOUND);
938
939         error = create_efivars_bin_attributes(efivars);
940         if (error)
941                 unregister_efivars(efivars);
942
943         efivars->efi_pstore_info = efi_pstore_info;
944
945         efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
946         if (efivars->efi_pstore_info.buf) {
947                 efivars->efi_pstore_info.bufsize = 1024;
948                 efivars->efi_pstore_info.data = efivars;
949                 mutex_init(&efivars->efi_pstore_info.buf_mutex);
950                 pstore_register(&efivars->efi_pstore_info);
951         }
952
953 out:
954         kfree(variable_name);
955
956         return error;
957 }
958 EXPORT_SYMBOL_GPL(register_efivars);
959
960 static struct efivars __efivars;
961 static struct efivar_operations ops;
962
963 /*
964  * For now we register the efi subsystem with the firmware subsystem
965  * and the vars subsystem with the efi subsystem.  In the future, it
966  * might make sense to split off the efi subsystem into its own
967  * driver, but for now only efivars will register with it, so just
968  * include it here.
969  */
970
971 static int __init
972 efivars_init(void)
973 {
974         int error = 0;
975
976         printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
977                EFIVARS_DATE);
978
979         if (!efi_enabled)
980                 return 0;
981
982         /* For now we'll register the efi directory at /sys/firmware/efi */
983         efi_kobj = kobject_create_and_add("efi", firmware_kobj);
984         if (!efi_kobj) {
985                 printk(KERN_ERR "efivars: Firmware registration failed.\n");
986                 return -ENOMEM;
987         }
988
989         ops.get_variable = efi.get_variable;
990         ops.set_variable = efi.set_variable;
991         ops.get_next_variable = efi.get_next_variable;
992         error = register_efivars(&__efivars, &ops, efi_kobj);
993         if (error)
994                 goto err_put;
995
996         /* Don't forget the systab entry */
997         error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
998         if (error) {
999                 printk(KERN_ERR
1000                        "efivars: Sysfs attribute export failed with error %d.\n",
1001                        error);
1002                 goto err_unregister;
1003         }
1004
1005         return 0;
1006
1007 err_unregister:
1008         unregister_efivars(&__efivars);
1009 err_put:
1010         kobject_put(efi_kobj);
1011         return error;
1012 }
1013
1014 static void __exit
1015 efivars_exit(void)
1016 {
1017         if (efi_enabled) {
1018                 unregister_efivars(&__efivars);
1019                 kobject_put(efi_kobj);
1020         }
1021 }
1022
1023 module_init(efivars_init);
1024 module_exit(efivars_exit);
1025