68 #include <linux/capability.h>
69 #include <linux/types.h>
70 #include <linux/errno.h>
73 #include <linux/module.h>
74 #include <linux/string.h>
79 #include <linux/device.h>
80 #include <linux/slab.h>
83 #include <asm/uaccess.h>
85 #define EFIVARS_VERSION "0.08"
86 #define EFIVARS_DATE "2004-May-17"
93 #define DUMP_NAME_LEN 52
125 #define PSTORE_EFI_ATTRIBUTES \
126 (EFI_VARIABLE_NON_VOLATILE | \
127 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
128 EFI_VARIABLE_RUNTIME_ACCESS)
130 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
131 struct efivar_attribute efivar_attr_##_name = { \
132 .attr = {.name = __stringify(_name), .mode = _mode}, \
137 #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
138 #define to_efivar_entry(obj) container_of(obj, struct efivar_entry, kobj)
145 unsigned long variable_name_size,
155 while (*s++ != 0 && length < maxlength)
160 static inline unsigned long
163 return utf16_strnlen(s, ~0
UL);
170 static inline unsigned long
203 if (len <
sizeof(*node))
206 while (offset <= len -
sizeof(*node) &&
207 node->
length >=
sizeof(*node) &&
228 validate_boot_order(
struct efi_variable *var,
int match,
u8 *buffer,
239 validate_load_option(
struct efi_variable *var,
int match,
u8 *buffer,
248 for (i = match; i < match+4; i++) {
262 filepathlength = buffer[4] | buffer[5] << 8;
268 desclength = utf16_strsize((
efi_char16_t *)(buffer + 6), len - 6) + 2;
279 if ((desclength + filepathlength + 6) > len)
285 return validate_device_path(var, match, buffer + desclength + 6,
301 validate_ascii_string(
struct efi_variable *var,
int match,
u8 *buffer,
306 for (i = 0; i < len; i++) {
324 {
"BootNext", validate_uint16 },
325 {
"BootOrder", validate_boot_order },
326 {
"DriverOrder", validate_boot_order },
327 {
"Boot*", validate_load_option },
328 {
"Driver*", validate_load_option },
329 {
"ConIn", validate_device_path },
330 {
"ConInDev", validate_device_path },
331 {
"ConOut", validate_device_path },
332 {
"ConOutDev", validate_device_path },
333 {
"ErrOut", validate_device_path },
334 {
"ErrOutDev", validate_device_path },
335 {
"Timeout", validate_uint16 },
336 {
"Lang", validate_ascii_string },
337 {
"PlatformLang", validate_ascii_string },
342 validate_var(
struct efi_variable *var,
u8 *data,
unsigned long len)
348 const char *
name = variable_validate[
i].
name;
351 for (match = 0; ; match++) {
361 return variable_validate[
i].
validate(var,
370 return variable_validate[
i].
validate(var,
379 get_var_data_locked(
struct efivars *efivars,
struct efi_variable *var)
393 get_var_data(
struct efivars *efivars,
struct efi_variable *var)
397 spin_lock(&efivars->lock);
398 status = get_var_data_locked(efivars, var);
399 spin_unlock(&efivars->lock);
434 status = get_var_data(entry->
efivars, var);
439 str +=
sprintf(str,
"EFI_VARIABLE_NON_VOLATILE\n");
441 str +=
sprintf(str,
"EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
443 str +=
sprintf(str,
"EFI_VARIABLE_RUNTIME_ACCESS\n");
445 str +=
sprintf(str,
"EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
448 "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
452 "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
454 str +=
sprintf(str,
"EFI_VARIABLE_APPEND_WRITE\n");
468 status = get_var_data(entry->
efivars, var);
485 status = get_var_data(entry->
efivars, var);
500 struct efivars *efivars = entry->
efivars;
518 printk(
KERN_ERR "efivars: DataSize & Attributes must be valid!\n");
523 validate_var(new_var, new_var->
Data, new_var->
DataSize) ==
false) {
528 spin_lock(&efivars->lock);
529 status = efivars->ops->set_variable(new_var->
VariableName,
535 spin_unlock(&efivars->lock);
556 status = get_var_data(entry->
efivars, var);
560 memcpy(buf, var,
sizeof(*var));
578 if (efivar_attr->
show) {
579 ret = efivar_attr->
show(var, buf);
585 const char *buf,
size_t count)
594 if (efivar_attr->
store)
595 ret = efivar_attr->
store(var, buf, count);
600 static const struct sysfs_ops efivar_attr_ops = {
601 .show = efivar_attr_show,
602 .store = efivar_attr_store,
605 static void efivar_release(
struct kobject *kobj)
615 static EFIVAR_ATTR(raw_var, 0600, efivar_show_raw, efivar_store_raw);
618 &efivar_attr_guid.attr,
619 &efivar_attr_size.attr,
620 &efivar_attr_attributes.attr,
621 &efivar_attr_data.attr,
622 &efivar_attr_raw_var.attr,
627 .release = efivar_release,
628 .sysfs_ops = &efivar_attr_ops,
629 .default_attrs = def_attrs,
642 static int efi_pstore_open(
struct pstore_info *psi)
644 struct efivars *efivars = psi->
data;
646 spin_lock(&efivars->lock);
652 static int efi_pstore_close(
struct pstore_info *psi)
654 struct efivars *efivars = psi->
data;
656 spin_unlock(&efivars->lock);
665 struct efivars *efivars = psi->
data;
671 while (&efivars->walk_entry->list != &efivars->list) {
672 if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
675 name[
i] = efivars->walk_entry->var.VariableName[
i];
677 if (
sscanf(name,
"dump-type%u-%u-%lu", type, &part, &time) == 3) {
681 get_var_data_locked(efivars, &efivars->walk_entry->var);
682 size = efivars->walk_entry->var.DataSize;
686 memcpy(*buf, efivars->walk_entry->var.Data,
688 efivars->walk_entry =
list_entry(efivars->walk_entry->list.next,
693 efivars->walk_entry =
list_entry(efivars->walk_entry->list.next,
701 unsigned int part,
size_t size,
struct pstore_info *psi)
707 struct efivars *efivars = psi->
data;
711 sprintf(stub_name,
"dump-type%u-%u-", type, part);
714 spin_lock(&efivars->lock);
717 efi_name[i] = stub_name[i];
724 get_var_data_locked(efivars, &entry->
var);
726 if (efi_guidcmp(entry->
var.VendorGuid, vendor))
728 if (utf16_strncmp(entry->
var.VariableName, efi_name,
729 utf16_strlen(efi_name)))
732 if (entry->
var.VariableName[utf16_strlen(efi_name)] == 0)
737 efivars->ops->set_variable(entry->
var.VariableName,
738 &entry->
var.VendorGuid,
747 efi_name[i] = name[i];
752 spin_unlock(&efivars->lock);
755 efivar_unregister(found);
758 ret = efivar_create_sysfs_entry(efivars,
759 utf16_strsize(efi_name,
770 efi_pstore_write(type, 0, &
id, (
unsigned int)
id, 0, psi);
775 static int efi_pstore_open(
struct pstore_info *psi)
780 static int efi_pstore_close(
struct pstore_info *psi)
786 struct timespec *timespec,
794 unsigned int part,
size_t size,
struct pstore_info *psi)
809 .open = efi_pstore_open,
810 .close = efi_pstore_close,
811 .read = efi_pstore_read,
812 .write = efi_pstore_write,
813 .erase = efi_pstore_erase,
818 char *buf, loff_t
pos,
size_t count)
821 struct efivars *efivars = bin_attr->
private;
823 unsigned long strsize1, strsize2;
831 validate_var(new_var, new_var->
Data, new_var->
DataSize) ==
false) {
836 spin_lock(&efivars->lock);
842 strsize1 = utf16_strsize(search_efivar->
var.VariableName, 1024);
844 if (strsize1 == strsize2 &&
845 !
memcmp(&(search_efivar->
var.VariableName),
847 !efi_guidcmp(search_efivar->
var.VendorGuid,
854 spin_unlock(&efivars->lock);
859 status = efivars->ops->set_variable(new_var->
VariableName,
868 spin_unlock(&efivars->lock);
871 spin_unlock(&efivars->lock);
874 status = efivar_create_sysfs_entry(efivars,
887 char *buf, loff_t pos,
size_t count)
890 struct efivars *efivars = bin_attr->
private;
892 unsigned long strsize1, strsize2;
899 spin_lock(&efivars->lock);
905 strsize1 = utf16_strsize(search_efivar->
var.VariableName, 1024);
907 if (strsize1 == strsize2 &&
908 !
memcmp(&(search_efivar->
var.VariableName),
910 !efi_guidcmp(search_efivar->
var.VendorGuid,
917 spin_unlock(&efivars->lock);
924 status = efivars->ops->set_variable(del_var->
VariableName,
933 spin_unlock(&efivars->lock);
938 spin_unlock(&efivars->lock);
939 efivar_unregister(search_efivar);
978 static struct attribute *efi_subsys_attrs[] = {
979 &efi_attr_systab.
attr,
984 .attrs = efi_subsys_attrs,
987 static struct kobject *efi_kobj;
999 efivar_create_sysfs_entry(
struct efivars *efivars,
1000 unsigned long variable_name_size,
1004 int i, short_name_size = variable_name_size /
sizeof(
efi_char16_t) + 38;
1008 short_name = kzalloc(short_name_size + 1,
GFP_KERNEL);
1011 if (!short_name || !new_efivar) {
1018 memcpy(new_efivar->
var.VariableName, variable_name,
1019 variable_name_size);
1024 for (i=0; i < (
int)(variable_name_size /
sizeof(
efi_char16_t)); i++) {
1025 short_name[
i] = variable_name[
i] & 0xFF;
1030 *(short_name +
strlen(short_name)) =
'-';
1031 efi_guid_unparse(vendor_guid, short_name +
strlen(short_name));
1033 new_efivar->
kobj.kset = efivars->kset;
1046 spin_lock(&efivars->lock);
1047 list_add(&new_efivar->
list, &efivars->list);
1048 spin_unlock(&efivars->lock);
1054 create_efivars_bin_attributes(
struct efivars *efivars)
1064 attr->
attr.name =
"new_var";
1065 attr->
attr.mode = 0200;
1066 attr->
write = efivar_create;
1068 efivars->new_var =
attr;
1076 attr->
attr.name =
"del_var";
1077 attr->
attr.mode = 0200;
1078 attr->
write = efivar_delete;
1080 efivars->del_var =
attr;
1090 " due to error %d\n", error);
1097 " due to error %d\n", error);
1105 kfree(efivars->del_var);
1106 efivars->del_var =
NULL;
1107 kfree(efivars->new_var);
1108 efivars->new_var =
NULL;
1117 spin_lock(&efivars->lock);
1119 spin_unlock(&efivars->lock);
1120 efivar_unregister(entry);
1122 if (efivars->new_var)
1124 if (efivars->del_var)
1126 kfree(efivars->new_var);
1127 kfree(efivars->del_var);
1133 const struct efivar_operations *ops,
1139 unsigned long variable_name_size = 1024;
1142 variable_name = kzalloc(variable_name_size,
GFP_KERNEL);
1143 if (!variable_name) {
1149 INIT_LIST_HEAD(&efivars->list);
1153 if (!efivars->kset) {
1165 variable_name_size = 1024;
1167 status = ops->get_next_variable(&variable_name_size,
1172 efivar_create_sysfs_entry(efivars,
1187 error = create_efivars_bin_attributes(efivars);
1191 efivars->efi_pstore_info = efi_pstore_info;
1194 if (efivars->efi_pstore_info.buf) {
1195 efivars->efi_pstore_info.bufsize = 1024;
1196 efivars->efi_pstore_info.data =
efivars;
1202 kfree(variable_name);
1208 static struct efivars __efivars;
1209 static struct efivar_operations ops;
1248 "efivars: Sysfs attribute export failed with error %d.\n",
1250 goto err_unregister;