more debug output
[linux-2.4.git] / arch / ia64 / kernel / efivars.c
1 /*
2  * EFI Variables - efivars.c
3  *
4  * Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
5  *
6  * This code takes all variables accessible from EFI runtime and
7  *  exports them via /proc
8  *
9  * Reads to /proc/efi/vars/varname return an efi_variable_t structure.
10  * Writes to /proc/efi/vars/varname must be an efi_variable_t structure.
11  * Writes with DataSize = 0 or Attributes = 0 deletes the variable.
12  * Writes with a new value in VariableName+VendorGuid creates
13  * a new variable.
14  *
15  *
16  *  This program is free software; you can redistribute it and/or modify
17  *  it under the terms of the GNU General Public License as published by
18  *  the Free Software Foundation; either version 2 of the License, or
19  *  (at your option) any later version.
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  *
30  * Changelog:
31  *
32  *  10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
33  *   fix locking per Peter Chubb's findings
34  * 
35  *  25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
36  *   move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
37  *
38  *  12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
39  *   use list_for_each_safe when deleting vars.
40  *   remove ifdef CONFIG_SMP around include <linux/smp.h>
41  *   v0.04 release to linux-ia64@linuxia64.org
42  *
43  *  20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
44  *   Moved vars from /proc/efi to /proc/efi/vars, and made
45  *   efi.c own the /proc/efi directory.
46  *   v0.03 release to linux-ia64@linuxia64.org
47  *
48  *  26 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
49  *   At the request of Stephane, moved ownership of /proc/efi
50  *   to efi.c, and now efivars lives under /proc/efi/vars.
51  *
52  *  12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
53  *   Feedback received from Stephane Eranian incorporated.
54  *   efivar_write() checks copy_from_user() return value.
55  *   efivar_read/write() returns proper errno.
56  *   v0.02 release to linux-ia64@linuxia64.org
57  *
58  *  26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
59  *   v0.01 release to linux-ia64@linuxia64.org
60  */
61
62 #include <linux/config.h>
63 #include <linux/types.h>
64 #include <linux/errno.h>
65 #include <linux/init.h>
66 #include <linux/proc_fs.h>
67 #include <linux/sched.h>                /* for capable() */
68 #include <linux/mm.h>
69 #include <linux/module.h>
70 #include <linux/smp.h>
71 #include <linux/efi.h>
72
73 #include <asm/uaccess.h>
74
75 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
76 MODULE_DESCRIPTION("/proc interface to EFI Variables");
77 MODULE_LICENSE("GPL");
78
79 #define EFIVARS_VERSION "0.06 2002-Dec-10"
80
81 static int
82 efivar_read(char *page, char **start, off_t off,
83             int count, int *eof, void *data);
84 static int
85 efivar_write(struct file *file, const char *buffer,
86              unsigned long count, void *data);
87
88
89 /*
90  * The maximum size of VariableName + Data = 1024
91  * Therefore, it's reasonable to save that much
92  * space in each part of the structure,
93  * and we use a page for reading/writing.
94  */
95
96 typedef struct _efi_variable_t {
97         efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
98         efi_guid_t    VendorGuid;
99         unsigned long DataSize;
100         __u8          Data[1024];
101         efi_status_t  Status;
102         __u32         Attributes;
103 } __attribute__((packed)) efi_variable_t;
104
105
106 typedef struct _efivar_entry_t {
107         efi_variable_t          var;
108         struct proc_dir_entry   *entry;
109         struct list_head        list;
110 } efivar_entry_t;
111
112 /*
113   efivars_lock protects two things:
114   1) efivar_list - adds, removals, reads, writes
115   2) efi.[gs]et_variable() calls.
116   It must not be held when creating proc entries or calling kmalloc.
117   efi.get_next_variable() is only called from efivars_init(),
118   which is protected by the BKL, so that path is safe.
119 */
120 static spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED;
121 static LIST_HEAD(efivar_list);
122 static struct proc_dir_entry *efi_vars_dir;
123
124 #define efivar_entry(n) list_entry(n, efivar_entry_t, list)
125
126 /* Return the number of unicode characters in data */
127 static unsigned long
128 utf8_strlen(efi_char16_t *data, unsigned long maxlength)
129 {
130         unsigned long length = 0;
131         while (*data++ != 0 && length < maxlength)
132                 length++;
133         return length;
134 }
135
136 /* Return the number of bytes is the length of this string */
137 /* Note: this is NOT the same as the number of unicode characters */
138 static inline unsigned long
139 utf8_strsize(efi_char16_t *data, unsigned long maxlength)
140 {
141         return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
142 }
143
144
145 static int
146 proc_calc_metrics(char *page, char **start, off_t off,
147                   int count, int *eof, int len)
148 {
149         if (len <= off+count) *eof = 1;
150         *start = page + off;
151         len -= off;
152         if (len>count) len = count;
153         if (len<0) len = 0;
154         return len;
155 }
156
157 /*
158  * efivar_create_proc_entry()
159  * Requires:
160  *    variable_name_size = number of bytes required to hold
161  *                         variable_name (not counting the NULL
162  *                         character at the end.
163  *    efivars_lock is not held on entry or exit.
164  * Returns 1 on failure, 0 on success
165  */
166 static int
167 efivar_create_proc_entry(unsigned long variable_name_size,
168                          efi_char16_t *variable_name,
169                          efi_guid_t *vendor_guid)
170 {
171         int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
172         char *short_name;
173         efivar_entry_t *new_efivar;
174
175         short_name = kmalloc(short_name_size+1, GFP_KERNEL);
176         new_efivar = kmalloc(sizeof(efivar_entry_t), GFP_KERNEL);
177
178         if (!short_name || !new_efivar)  {
179                 if (short_name)        kfree(short_name);
180                 if (new_efivar)        kfree(new_efivar);
181                 return 1;
182         }
183         memset(short_name, 0, short_name_size+1);
184         memset(new_efivar, 0, sizeof(efivar_entry_t));
185
186         memcpy(new_efivar->var.VariableName, variable_name,
187                variable_name_size);
188         memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
189
190         /* Convert Unicode to normal chars (assume top bits are 0),
191            ala UTF-8 */
192         for (i=0; i< (int) (variable_name_size / sizeof(efi_char16_t)); i++) {
193                 short_name[i] = variable_name[i] & 0xFF;
194         }
195
196         /* This is ugly, but necessary to separate one vendor's
197            private variables from another's.         */
198
199         *(short_name + strlen(short_name)) = '-';
200         efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
201
202         /* Create the entry in proc */
203         new_efivar->entry = create_proc_entry(short_name, 0600, efi_vars_dir);
204         kfree(short_name); short_name = NULL;
205         if (!new_efivar->entry) return 1;
206
207         new_efivar->entry->data = new_efivar;
208         new_efivar->entry->read_proc = efivar_read;
209         new_efivar->entry->write_proc = efivar_write;
210
211         spin_lock(&efivars_lock);
212         list_add(&new_efivar->list, &efivar_list);
213         spin_unlock(&efivars_lock);
214
215         return 0;
216 }
217
218
219
220 /***********************************************************
221  * efivar_read()
222  * Requires:
223  * Modifies: page
224  * Returns: number of bytes written, or -EINVAL on failure
225  ***********************************************************/
226
227 static int
228 efivar_read(char *page, char **start, off_t off, int count, int *eof, void *data)
229 {
230         int len = sizeof(efi_variable_t);
231         efivar_entry_t *efi_var = data;
232         efi_variable_t *var_data = (efi_variable_t *)page;
233
234         if (!page || !data) return -EINVAL;
235
236         spin_lock(&efivars_lock);
237         MOD_INC_USE_COUNT;
238
239         memcpy(var_data, &efi_var->var, len);
240
241         var_data->DataSize = 1024;
242         var_data->Status = efi.get_variable(var_data->VariableName,
243                                             &var_data->VendorGuid,
244                                             &var_data->Attributes,
245                                             &var_data->DataSize,
246                                             var_data->Data);
247
248         MOD_DEC_USE_COUNT;
249         spin_unlock(&efivars_lock);
250
251         return proc_calc_metrics(page, start, off, count, eof, len);
252 }
253
254 /***********************************************************
255  * efivar_write()
256  * Requires: data is an efi_setvariable_t data type,
257  *           properly filled in, possibly by a call
258  *           first to efivar_read().
259  *           Caller must have CAP_SYS_ADMIN
260  * Modifies: NVRAM
261  * Returns: var_data->DataSize on success, errno on failure
262  *
263  ***********************************************************/
264 static int
265 efivar_write(struct file *file, const char *buffer,
266              unsigned long count, void *data)
267 {
268         unsigned long strsize1, strsize2;
269         int found=0;
270         struct list_head *pos, *n;
271         unsigned long size = sizeof(efi_variable_t);
272         efi_status_t status;
273         efivar_entry_t *efivar = data, *search_efivar = NULL;
274         efi_variable_t *var_data;
275         if (!data || count != size) {
276                 printk(KERN_WARNING "efivars: improper struct of size 0x%lx passed.\n", count);
277                 return -EINVAL;
278         }
279         if (!capable(CAP_SYS_ADMIN))
280                 return -EACCES;
281
282         MOD_INC_USE_COUNT;
283
284         var_data = kmalloc(size, GFP_KERNEL);
285         if (!var_data) {
286                 MOD_DEC_USE_COUNT;
287                 return -ENOMEM;
288         }
289         if (copy_from_user(var_data, buffer, size)) {
290                 MOD_DEC_USE_COUNT;
291                 kfree(var_data);
292                 return -EFAULT;
293         }
294
295         spin_lock(&efivars_lock);
296
297         /* Since the data ptr we've currently got is probably for
298            a different variable find the right variable.
299            This allows any properly formatted data structure to
300            be written to any of the files in /proc/efi/vars and it will work.
301         */
302         list_for_each_safe(pos, n, &efivar_list) {
303                 search_efivar = efivar_entry(pos);
304                 strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
305                 strsize2 = utf8_strsize(var_data->VariableName, 1024);
306                 if ( strsize1 == strsize2 &&
307                      !memcmp(&(search_efivar->var.VariableName),
308                              var_data->VariableName, strsize1) &&
309                      !efi_guidcmp(search_efivar->var.VendorGuid,
310                                   var_data->VendorGuid)) {
311                         found = 1;
312                         break;
313                 }
314         }
315         if (found) efivar = search_efivar;
316
317         status = efi.set_variable(var_data->VariableName,
318                                   &var_data->VendorGuid,
319                                   var_data->Attributes,
320                                   var_data->DataSize,
321                                   var_data->Data);
322
323         if (status != EFI_SUCCESS) {
324                 printk(KERN_WARNING "set_variable() failed: status=%lx\n", status);
325                 kfree(var_data);
326                 MOD_DEC_USE_COUNT;
327                 spin_unlock(&efivars_lock);
328                 return -EIO;
329         }
330
331
332         if (!var_data->DataSize || !var_data->Attributes) {
333                 /* We just deleted the NVRAM variable */
334                 remove_proc_entry(efivar->entry->name, efi_vars_dir);
335                 list_del(&efivar->list);
336                 kfree(efivar);
337         }
338
339         spin_unlock(&efivars_lock);
340
341         /* If this is a new variable, set up the proc entry for it. */
342         if (!found) {
343                 efivar_create_proc_entry(utf8_strsize(var_data->VariableName,
344                                                       1024),
345                                          var_data->VariableName,
346                                          &var_data->VendorGuid);
347         }
348
349         kfree(var_data);
350         MOD_DEC_USE_COUNT;
351         return size;
352 }
353
354 /*
355  * The EFI system table contains pointers to the SAL system table,
356  * HCDP, ACPI, SMBIOS, etc, that may be useful to applications.
357  */
358 static ssize_t
359 efi_systab_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
360 {
361         void *data;
362         u8 *proc_buffer;
363         ssize_t size, length;
364         int ret;
365         const int max_nr_entries = 7;   /* num ptrs to tables we could expose */
366         const int max_line_len = 80;
367         loff_t pos = *ppos;
368
369         if (!efi.systab)
370                 return 0;
371
372         proc_buffer = kmalloc(max_nr_entries * max_line_len, GFP_KERNEL);
373         if (!proc_buffer)
374                 return -ENOMEM;
375
376         length = 0;
377         if (efi.mps)
378                 length += sprintf(proc_buffer + length, "MPS=0x%lx\n", __pa(efi.mps));
379         if (efi.acpi20)
380                 length += sprintf(proc_buffer + length, "ACPI20=0x%lx\n", __pa(efi.acpi20));
381         if (efi.acpi)
382                 length += sprintf(proc_buffer + length, "ACPI=0x%lx\n", __pa(efi.acpi));
383         if (efi.smbios)
384                 length += sprintf(proc_buffer + length, "SMBIOS=0x%lx\n", __pa(efi.smbios));
385         if (efi.sal_systab)
386                 length += sprintf(proc_buffer + length, "SAL=0x%lx\n", __pa(efi.sal_systab));
387         if (efi.hcdp)
388                 length += sprintf(proc_buffer + length, "HCDP=0x%lx\n", __pa(efi.hcdp));
389         if (efi.boot_info)
390                 length += sprintf(proc_buffer + length, "BOOTINFO=0x%lx\n", __pa(efi.boot_info));
391
392         if (pos != (unsigned) pos || pos >= length) {
393                 ret = 0;
394                 goto out;
395         }
396
397         data = proc_buffer + pos;
398         size = length - pos;
399         if (size > count)
400                 size = count;
401         if (copy_to_user(buffer, data, size)) {
402                 ret = -EFAULT;
403                 goto out;
404         }
405
406         *ppos = pos + size;
407         ret = size;
408
409 out:
410         kfree(proc_buffer);
411         return ret;
412 }
413
414 static struct proc_dir_entry *efi_systab_entry;
415 static struct file_operations efi_systab_fops = {
416         .read = efi_systab_read,
417 };
418
419 static int __init
420 efivars_init(void)
421 {
422         efi_status_t status;
423         efi_guid_t vendor_guid;
424         efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL);
425         unsigned long variable_name_size = 1024;
426
427         printk(KERN_INFO "EFI Variables Facility v%s\n", EFIVARS_VERSION);
428
429         /* Since efi.c happens before procfs is available,
430            we create the directory here if it doesn't
431            already exist.  There's probably a better way
432            to do this.
433         */
434         if (!efi_dir)
435                 efi_dir = proc_mkdir("efi", NULL);
436
437         efi_systab_entry = create_proc_entry("systab", S_IRUSR | S_IRGRP, efi_dir);
438         if (efi_systab_entry)
439                 efi_systab_entry->proc_fops = &efi_systab_fops;
440
441         efi_vars_dir = proc_mkdir("vars", efi_dir);
442
443         /* Per EFI spec, the maximum storage allocated for both
444            the variable name and variable data is 1024 bytes.
445         */
446
447         memset(variable_name, 0, 1024);
448
449         do {
450                 variable_name_size=1024;
451
452                 status = efi.get_next_variable(&variable_name_size,
453                                                variable_name,
454                                                &vendor_guid);
455
456
457                 switch (status) {
458                 case EFI_SUCCESS:
459                         efivar_create_proc_entry(variable_name_size,
460                                                  variable_name,
461                                                  &vendor_guid);
462                         break;
463                 case EFI_NOT_FOUND:
464                         break;
465                 default:
466                         printk(KERN_WARNING "get_next_variable: status=%lx\n", status);
467                         status = EFI_NOT_FOUND;
468                         break;
469                 }
470
471         } while (status != EFI_NOT_FOUND);
472
473         kfree(variable_name);
474         return 0;
475 }
476
477 static void __exit
478 efivars_exit(void)
479 {
480         struct list_head *pos, *n;
481         efivar_entry_t *efivar;
482
483         spin_lock(&efivars_lock);
484         if (efi_systab_entry)
485                 remove_proc_entry(efi_systab_entry->name, efi_dir);
486         list_for_each_safe(pos, n, &efivar_list) {
487                 efivar = efivar_entry(pos);
488                 remove_proc_entry(efivar->entry->name, efi_vars_dir);
489                 list_del(&efivar->list);
490                 kfree(efivar);
491         }
492         spin_unlock(&efivars_lock);
493
494         remove_proc_entry(efi_vars_dir->name, efi_dir);
495 }
496
497 module_init(efivars_init);
498 module_exit(efivars_exit);
499
500 /*
501  * Overrides for Emacs so that we follow Linus's tabbing style.
502  * Emacs will notice this stuff at the end of the file and automatically
503  * adjust the settings for this buffer only.  This must remain at the end
504  * of the file.
505  * ---------------------------------------------------------------------------
506  * Local variables:
507  * c-indent-level: 4
508  * c-brace-imaginary-offset: 0
509  * c-brace-offset: -4
510  * c-argdecl-indent: 4
511  * c-label-offset: -4
512  * c-continued-statement-offset: 4
513  * c-continued-brace-offset: 0
514  * indent-tabs-mode: nil
515  * tab-width: 8
516  * End:
517  */