diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efivars.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 528ce47c1368..5633018c34af 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -103,8 +103,6 @@ struct efivars { | |||
103 | struct kset *kset; | 103 | struct kset *kset; |
104 | struct bin_attribute *new_var, *del_var; | 104 | struct bin_attribute *new_var, *del_var; |
105 | }; | 105 | }; |
106 | static struct efivars __efivars; | ||
107 | static struct efivars *efivars = &__efivars; | ||
108 | 106 | ||
109 | /* | 107 | /* |
110 | * The maximum size of VariableName + Data = 1024 | 108 | * The maximum size of VariableName + Data = 1024 |
@@ -124,6 +122,7 @@ struct efi_variable { | |||
124 | 122 | ||
125 | 123 | ||
126 | struct efivar_entry { | 124 | struct efivar_entry { |
125 | struct efivars *efivars; | ||
127 | struct efi_variable var; | 126 | struct efi_variable var; |
128 | struct list_head list; | 127 | struct list_head list; |
129 | struct kobject kobj; | 128 | struct kobject kobj; |
@@ -150,9 +149,10 @@ struct efivar_attribute efivar_attr_##_name = { \ | |||
150 | * Prototype for sysfs creation function | 149 | * Prototype for sysfs creation function |
151 | */ | 150 | */ |
152 | static int | 151 | static int |
153 | efivar_create_sysfs_entry(unsigned long variable_name_size, | 152 | efivar_create_sysfs_entry(struct efivars *efivars, |
154 | efi_char16_t *variable_name, | 153 | unsigned long variable_name_size, |
155 | efi_guid_t *vendor_guid); | 154 | efi_char16_t *variable_name, |
155 | efi_guid_t *vendor_guid); | ||
156 | 156 | ||
157 | /* Return the number of unicode characters in data */ | 157 | /* Return the number of unicode characters in data */ |
158 | static unsigned long | 158 | static unsigned long |
@@ -176,7 +176,7 @@ utf8_strsize(efi_char16_t *data, unsigned long maxlength) | |||
176 | } | 176 | } |
177 | 177 | ||
178 | static efi_status_t | 178 | static efi_status_t |
179 | get_var_data(struct efi_variable *var) | 179 | get_var_data(struct efivars *efivars, struct efi_variable *var) |
180 | { | 180 | { |
181 | efi_status_t status; | 181 | efi_status_t status; |
182 | 182 | ||
@@ -221,7 +221,7 @@ efivar_attr_read(struct efivar_entry *entry, char *buf) | |||
221 | if (!entry || !buf) | 221 | if (!entry || !buf) |
222 | return -EINVAL; | 222 | return -EINVAL; |
223 | 223 | ||
224 | status = get_var_data(var); | 224 | status = get_var_data(entry->efivars, var); |
225 | if (status != EFI_SUCCESS) | 225 | if (status != EFI_SUCCESS) |
226 | return -EIO; | 226 | return -EIO; |
227 | 227 | ||
@@ -244,7 +244,7 @@ efivar_size_read(struct efivar_entry *entry, char *buf) | |||
244 | if (!entry || !buf) | 244 | if (!entry || !buf) |
245 | return -EINVAL; | 245 | return -EINVAL; |
246 | 246 | ||
247 | status = get_var_data(var); | 247 | status = get_var_data(entry->efivars, var); |
248 | if (status != EFI_SUCCESS) | 248 | if (status != EFI_SUCCESS) |
249 | return -EIO; | 249 | return -EIO; |
250 | 250 | ||
@@ -261,7 +261,7 @@ efivar_data_read(struct efivar_entry *entry, char *buf) | |||
261 | if (!entry || !buf) | 261 | if (!entry || !buf) |
262 | return -EINVAL; | 262 | return -EINVAL; |
263 | 263 | ||
264 | status = get_var_data(var); | 264 | status = get_var_data(entry->efivars, var); |
265 | if (status != EFI_SUCCESS) | 265 | if (status != EFI_SUCCESS) |
266 | return -EIO; | 266 | return -EIO; |
267 | 267 | ||
@@ -276,6 +276,7 @@ static ssize_t | |||
276 | efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | 276 | efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) |
277 | { | 277 | { |
278 | struct efi_variable *new_var, *var = &entry->var; | 278 | struct efi_variable *new_var, *var = &entry->var; |
279 | struct efivars *efivars = entry->efivars; | ||
279 | efi_status_t status = EFI_NOT_FOUND; | 280 | efi_status_t status = EFI_NOT_FOUND; |
280 | 281 | ||
281 | if (count != sizeof(struct efi_variable)) | 282 | if (count != sizeof(struct efi_variable)) |
@@ -325,7 +326,7 @@ efivar_show_raw(struct efivar_entry *entry, char *buf) | |||
325 | if (!entry || !buf) | 326 | if (!entry || !buf) |
326 | return 0; | 327 | return 0; |
327 | 328 | ||
328 | status = get_var_data(var); | 329 | status = get_var_data(entry->efivars, var); |
329 | if (status != EFI_SUCCESS) | 330 | if (status != EFI_SUCCESS) |
330 | return -EIO; | 331 | return -EIO; |
331 | 332 | ||
@@ -413,6 +414,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
413 | char *buf, loff_t pos, size_t count) | 414 | char *buf, loff_t pos, size_t count) |
414 | { | 415 | { |
415 | struct efi_variable *new_var = (struct efi_variable *)buf; | 416 | struct efi_variable *new_var = (struct efi_variable *)buf; |
417 | struct efivars *efivars = bin_attr->private; | ||
416 | struct efivar_entry *search_efivar, *n; | 418 | struct efivar_entry *search_efivar, *n; |
417 | unsigned long strsize1, strsize2; | 419 | unsigned long strsize1, strsize2; |
418 | efi_status_t status = EFI_NOT_FOUND; | 420 | efi_status_t status = EFI_NOT_FOUND; |
@@ -459,8 +461,11 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
459 | spin_unlock(&efivars->lock); | 461 | spin_unlock(&efivars->lock); |
460 | 462 | ||
461 | /* Create the entry in sysfs. Locking is not required here */ | 463 | /* Create the entry in sysfs. Locking is not required here */ |
462 | status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName, | 464 | status = efivar_create_sysfs_entry(efivars, |
463 | 1024), new_var->VariableName, &new_var->VendorGuid); | 465 | utf8_strsize(new_var->VariableName, |
466 | 1024), | ||
467 | new_var->VariableName, | ||
468 | &new_var->VendorGuid); | ||
464 | if (status) { | 469 | if (status) { |
465 | printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n"); | 470 | printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n"); |
466 | } | 471 | } |
@@ -472,6 +477,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
472 | char *buf, loff_t pos, size_t count) | 477 | char *buf, loff_t pos, size_t count) |
473 | { | 478 | { |
474 | struct efi_variable *del_var = (struct efi_variable *)buf; | 479 | struct efi_variable *del_var = (struct efi_variable *)buf; |
480 | struct efivars *efivars = bin_attr->private; | ||
475 | struct efivar_entry *search_efivar, *n; | 481 | struct efivar_entry *search_efivar, *n; |
476 | unsigned long strsize1, strsize2; | 482 | unsigned long strsize1, strsize2; |
477 | efi_status_t status = EFI_NOT_FOUND; | 483 | efi_status_t status = EFI_NOT_FOUND; |
@@ -580,9 +586,10 @@ static struct kobject *efi_kobj; | |||
580 | * Returns 1 on failure, 0 on success | 586 | * Returns 1 on failure, 0 on success |
581 | */ | 587 | */ |
582 | static int | 588 | static int |
583 | efivar_create_sysfs_entry(unsigned long variable_name_size, | 589 | efivar_create_sysfs_entry(struct efivars *efivars, |
584 | efi_char16_t *variable_name, | 590 | unsigned long variable_name_size, |
585 | efi_guid_t *vendor_guid) | 591 | efi_char16_t *variable_name, |
592 | efi_guid_t *vendor_guid) | ||
586 | { | 593 | { |
587 | int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; | 594 | int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; |
588 | char *short_name; | 595 | char *short_name; |
@@ -597,6 +604,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size, | |||
597 | return 1; | 604 | return 1; |
598 | } | 605 | } |
599 | 606 | ||
607 | new_efivar->efivars = efivars; | ||
600 | memcpy(new_efivar->var.VariableName, variable_name, | 608 | memcpy(new_efivar->var.VariableName, variable_name, |
601 | variable_name_size); | 609 | variable_name_size); |
602 | memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); | 610 | memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); |
@@ -691,6 +699,8 @@ out_free: | |||
691 | return error; | 699 | return error; |
692 | } | 700 | } |
693 | 701 | ||
702 | static struct efivars __efivars; | ||
703 | |||
694 | /* | 704 | /* |
695 | * For now we register the efi subsystem with the firmware subsystem | 705 | * For now we register the efi subsystem with the firmware subsystem |
696 | * and the vars subsystem with the efi subsystem. In the future, it | 706 | * and the vars subsystem with the efi subsystem. In the future, it |
@@ -706,6 +716,7 @@ efivars_init(void) | |||
706 | efi_guid_t vendor_guid; | 716 | efi_guid_t vendor_guid; |
707 | efi_char16_t *variable_name; | 717 | efi_char16_t *variable_name; |
708 | unsigned long variable_name_size = 1024; | 718 | unsigned long variable_name_size = 1024; |
719 | struct efivars *efivars = &__efivars; | ||
709 | int error = 0; | 720 | int error = 0; |
710 | 721 | ||
711 | if (!efi_enabled) | 722 | if (!efi_enabled) |
@@ -751,9 +762,10 @@ efivars_init(void) | |||
751 | &vendor_guid); | 762 | &vendor_guid); |
752 | switch (status) { | 763 | switch (status) { |
753 | case EFI_SUCCESS: | 764 | case EFI_SUCCESS: |
754 | efivar_create_sysfs_entry(variable_name_size, | 765 | efivar_create_sysfs_entry(efivars, |
755 | variable_name, | 766 | variable_name_size, |
756 | &vendor_guid); | 767 | variable_name, |
768 | &vendor_guid); | ||
757 | break; | 769 | break; |
758 | case EFI_NOT_FOUND: | 770 | case EFI_NOT_FOUND: |
759 | break; | 771 | break; |
@@ -788,6 +800,7 @@ out_free: | |||
788 | static void __exit | 800 | static void __exit |
789 | efivars_exit(void) | 801 | efivars_exit(void) |
790 | { | 802 | { |
803 | struct efivars *efivars = &__efivars; | ||
791 | struct efivar_entry *entry, *n; | 804 | struct efivar_entry *entry, *n; |
792 | 805 | ||
793 | list_for_each_entry_safe(entry, n, &efivars->list, list) { | 806 | list_for_each_entry_safe(entry, n, &efivars->list, list) { |