2 * EFI Variables - efivars.c
4 * Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
6 * This code takes all variables accessible from EFI runtime and
7 * exports them via /proc
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
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.
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.
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
32 * 10 Dec 2002 - Matt Domsch <Matt_Domsch@dell.com>
33 * fix locking per Peter Chubb's findings
35 * 25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
36 * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
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
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
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.
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
58 * 26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
59 * v0.01 release to linux-ia64@linuxia64.org
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() */
69 #include <linux/module.h>
70 #include <linux/smp.h>
71 #include <linux/efi.h>
73 #include <asm/uaccess.h>
75 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
76 MODULE_DESCRIPTION("/proc interface to EFI Variables");
77 MODULE_LICENSE("GPL");
79 #define EFIVARS_VERSION "0.06 2002-Dec-10"
82 efivar_read(char *page, char **start, off_t off,
83 int count, int *eof, void *data);
85 efivar_write(struct file *file, const char *buffer,
86 unsigned long count, void *data);
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.
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;
103 } __attribute__((packed)) efi_variable_t;
106 typedef struct _efivar_entry_t {
108 struct proc_dir_entry *entry;
109 struct list_head list;
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.
120 static spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED;
121 static LIST_HEAD(efivar_list);
122 static struct proc_dir_entry *efi_vars_dir;
124 #define efivar_entry(n) list_entry(n, efivar_entry_t, list)
126 /* Return the number of unicode characters in data */
128 utf8_strlen(efi_char16_t *data, unsigned long maxlength)
130 unsigned long length = 0;
131 while (*data++ != 0 && length < maxlength)
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)
141 return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
146 proc_calc_metrics(char *page, char **start, off_t off,
147 int count, int *eof, int len)
149 if (len <= off+count) *eof = 1;
152 if (len>count) len = count;
158 * efivar_create_proc_entry()
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
167 efivar_create_proc_entry(unsigned long variable_name_size,
168 efi_char16_t *variable_name,
169 efi_guid_t *vendor_guid)
171 int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
173 efivar_entry_t *new_efivar;
175 short_name = kmalloc(short_name_size+1, GFP_KERNEL);
176 new_efivar = kmalloc(sizeof(efivar_entry_t), GFP_KERNEL);
178 if (!short_name || !new_efivar) {
179 if (short_name) kfree(short_name);
180 if (new_efivar) kfree(new_efivar);
183 memset(short_name, 0, short_name_size+1);
184 memset(new_efivar, 0, sizeof(efivar_entry_t));
186 memcpy(new_efivar->var.VariableName, variable_name,
188 memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
190 /* Convert Unicode to normal chars (assume top bits are 0),
192 for (i=0; i< (int) (variable_name_size / sizeof(efi_char16_t)); i++) {
193 short_name[i] = variable_name[i] & 0xFF;
196 /* This is ugly, but necessary to separate one vendor's
197 private variables from another's. */
199 *(short_name + strlen(short_name)) = '-';
200 efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
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;
207 new_efivar->entry->data = new_efivar;
208 new_efivar->entry->read_proc = efivar_read;
209 new_efivar->entry->write_proc = efivar_write;
211 spin_lock(&efivars_lock);
212 list_add(&new_efivar->list, &efivar_list);
213 spin_unlock(&efivars_lock);
220 /***********************************************************
224 * Returns: number of bytes written, or -EINVAL on failure
225 ***********************************************************/
228 efivar_read(char *page, char **start, off_t off, int count, int *eof, void *data)
230 int len = sizeof(efi_variable_t);
231 efivar_entry_t *efi_var = data;
232 efi_variable_t *var_data = (efi_variable_t *)page;
234 if (!page || !data) return -EINVAL;
236 spin_lock(&efivars_lock);
239 memcpy(var_data, &efi_var->var, len);
241 var_data->DataSize = 1024;
242 var_data->Status = efi.get_variable(var_data->VariableName,
243 &var_data->VendorGuid,
244 &var_data->Attributes,
249 spin_unlock(&efivars_lock);
251 return proc_calc_metrics(page, start, off, count, eof, len);
254 /***********************************************************
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
261 * Returns: var_data->DataSize on success, errno on failure
263 ***********************************************************/
265 efivar_write(struct file *file, const char *buffer,
266 unsigned long count, void *data)
268 unsigned long strsize1, strsize2;
270 struct list_head *pos, *n;
271 unsigned long size = sizeof(efi_variable_t);
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);
279 if (!capable(CAP_SYS_ADMIN))
284 var_data = kmalloc(size, GFP_KERNEL);
289 if (copy_from_user(var_data, buffer, size)) {
295 spin_lock(&efivars_lock);
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.
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)) {
315 if (found) efivar = search_efivar;
317 status = efi.set_variable(var_data->VariableName,
318 &var_data->VendorGuid,
319 var_data->Attributes,
323 if (status != EFI_SUCCESS) {
324 printk(KERN_WARNING "set_variable() failed: status=%lx\n", status);
327 spin_unlock(&efivars_lock);
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);
339 spin_unlock(&efivars_lock);
341 /* If this is a new variable, set up the proc entry for it. */
343 efivar_create_proc_entry(utf8_strsize(var_data->VariableName,
345 var_data->VariableName,
346 &var_data->VendorGuid);
355 * The EFI system table contains pointers to the SAL system table,
356 * HCDP, ACPI, SMBIOS, etc, that may be useful to applications.
359 efi_systab_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
363 ssize_t size, length;
365 const int max_nr_entries = 7; /* num ptrs to tables we could expose */
366 const int max_line_len = 80;
372 proc_buffer = kmalloc(max_nr_entries * max_line_len, GFP_KERNEL);
378 length += sprintf(proc_buffer + length, "MPS=0x%lx\n", __pa(efi.mps));
380 length += sprintf(proc_buffer + length, "ACPI20=0x%lx\n", __pa(efi.acpi20));
382 length += sprintf(proc_buffer + length, "ACPI=0x%lx\n", __pa(efi.acpi));
384 length += sprintf(proc_buffer + length, "SMBIOS=0x%lx\n", __pa(efi.smbios));
386 length += sprintf(proc_buffer + length, "SAL=0x%lx\n", __pa(efi.sal_systab));
388 length += sprintf(proc_buffer + length, "HCDP=0x%lx\n", __pa(efi.hcdp));
390 length += sprintf(proc_buffer + length, "BOOTINFO=0x%lx\n", __pa(efi.boot_info));
392 if (pos != (unsigned) pos || pos >= length) {
397 data = proc_buffer + pos;
401 if (copy_to_user(buffer, data, size)) {
414 static struct proc_dir_entry *efi_systab_entry;
415 static struct file_operations efi_systab_fops = {
416 .read = efi_systab_read,
423 efi_guid_t vendor_guid;
424 efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL);
425 unsigned long variable_name_size = 1024;
427 printk(KERN_INFO "EFI Variables Facility v%s\n", EFIVARS_VERSION);
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
435 efi_dir = proc_mkdir("efi", NULL);
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;
441 efi_vars_dir = proc_mkdir("vars", efi_dir);
443 /* Per EFI spec, the maximum storage allocated for both
444 the variable name and variable data is 1024 bytes.
447 memset(variable_name, 0, 1024);
450 variable_name_size=1024;
452 status = efi.get_next_variable(&variable_name_size,
459 efivar_create_proc_entry(variable_name_size,
466 printk(KERN_WARNING "get_next_variable: status=%lx\n", status);
467 status = EFI_NOT_FOUND;
471 } while (status != EFI_NOT_FOUND);
473 kfree(variable_name);
480 struct list_head *pos, *n;
481 efivar_entry_t *efivar;
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);
492 spin_unlock(&efivars_lock);
494 remove_proc_entry(efi_vars_dir->name, efi_dir);
497 module_init(efivars_init);
498 module_exit(efivars_exit);
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
505 * ---------------------------------------------------------------------------
508 * c-brace-imaginary-offset: 0
510 * c-argdecl-indent: 4
512 * c-continued-statement-offset: 4
513 * c-continued-brace-offset: 0
514 * indent-tabs-mode: nil