diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efivars.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index f22bfcf2b968..b10b7d7bd7de 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -89,19 +89,26 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables"); | |||
89 | MODULE_LICENSE("GPL"); | 89 | MODULE_LICENSE("GPL"); |
90 | MODULE_VERSION(EFIVARS_VERSION); | 90 | MODULE_VERSION(EFIVARS_VERSION); |
91 | 91 | ||
92 | struct efivar_operations { | ||
93 | efi_get_variable_t *get_variable; | ||
94 | efi_get_next_variable_t *get_next_variable; | ||
95 | efi_set_variable_t *set_variable; | ||
96 | }; | ||
97 | |||
92 | struct efivars { | 98 | struct efivars { |
93 | /* | 99 | /* |
94 | * ->lock protects two things: | 100 | * ->lock protects two things: |
95 | * 1) ->list - adds, removals, reads, writes | 101 | * 1) ->list - adds, removals, reads, writes |
96 | * 2) efi.[gs]et_variable() calls. | 102 | * 2) ops.[gs]et_variable() calls. |
97 | * It must not be held when creating sysfs entries or calling kmalloc. | 103 | * It must not be held when creating sysfs entries or calling kmalloc. |
98 | * efi.get_next_variable() is only called from register_efivars(), | 104 | * ops.get_next_variable() is only called from register_efivars(), |
99 | * which is protected by the BKL, so that path is safe. | 105 | * which is protected by the BKL, so that path is safe. |
100 | */ | 106 | */ |
101 | spinlock_t lock; | 107 | spinlock_t lock; |
102 | struct list_head list; | 108 | struct list_head list; |
103 | struct kset *kset; | 109 | struct kset *kset; |
104 | struct bin_attribute *new_var, *del_var; | 110 | struct bin_attribute *new_var, *del_var; |
111 | const struct efivar_operations *ops; | ||
105 | }; | 112 | }; |
106 | 113 | ||
107 | /* | 114 | /* |
@@ -182,11 +189,11 @@ get_var_data(struct efivars *efivars, struct efi_variable *var) | |||
182 | 189 | ||
183 | spin_lock(&efivars->lock); | 190 | spin_lock(&efivars->lock); |
184 | var->DataSize = 1024; | 191 | var->DataSize = 1024; |
185 | status = efi.get_variable(var->VariableName, | 192 | status = efivars->ops->get_variable(var->VariableName, |
186 | &var->VendorGuid, | 193 | &var->VendorGuid, |
187 | &var->Attributes, | 194 | &var->Attributes, |
188 | &var->DataSize, | 195 | &var->DataSize, |
189 | var->Data); | 196 | var->Data); |
190 | spin_unlock(&efivars->lock); | 197 | spin_unlock(&efivars->lock); |
191 | if (status != EFI_SUCCESS) { | 198 | if (status != EFI_SUCCESS) { |
192 | printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", | 199 | printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", |
@@ -299,11 +306,11 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | |||
299 | } | 306 | } |
300 | 307 | ||
301 | spin_lock(&efivars->lock); | 308 | spin_lock(&efivars->lock); |
302 | status = efi.set_variable(new_var->VariableName, | 309 | status = efivars->ops->set_variable(new_var->VariableName, |
303 | &new_var->VendorGuid, | 310 | &new_var->VendorGuid, |
304 | new_var->Attributes, | 311 | new_var->Attributes, |
305 | new_var->DataSize, | 312 | new_var->DataSize, |
306 | new_var->Data); | 313 | new_var->Data); |
307 | 314 | ||
308 | spin_unlock(&efivars->lock); | 315 | spin_unlock(&efivars->lock); |
309 | 316 | ||
@@ -446,11 +453,11 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
446 | } | 453 | } |
447 | 454 | ||
448 | /* now *really* create the variable via EFI */ | 455 | /* now *really* create the variable via EFI */ |
449 | status = efi.set_variable(new_var->VariableName, | 456 | status = efivars->ops->set_variable(new_var->VariableName, |
450 | &new_var->VendorGuid, | 457 | &new_var->VendorGuid, |
451 | new_var->Attributes, | 458 | new_var->Attributes, |
452 | new_var->DataSize, | 459 | new_var->DataSize, |
453 | new_var->Data); | 460 | new_var->Data); |
454 | 461 | ||
455 | if (status != EFI_SUCCESS) { | 462 | if (status != EFI_SUCCESS) { |
456 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", | 463 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", |
@@ -511,11 +518,11 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
511 | del_var->Attributes = 0; | 518 | del_var->Attributes = 0; |
512 | del_var->DataSize = 0; | 519 | del_var->DataSize = 0; |
513 | 520 | ||
514 | status = efi.set_variable(del_var->VariableName, | 521 | status = efivars->ops->set_variable(del_var->VariableName, |
515 | &del_var->VendorGuid, | 522 | &del_var->VendorGuid, |
516 | del_var->Attributes, | 523 | del_var->Attributes, |
517 | del_var->DataSize, | 524 | del_var->DataSize, |
518 | del_var->Data); | 525 | del_var->Data); |
519 | 526 | ||
520 | if (status != EFI_SUCCESS) { | 527 | if (status != EFI_SUCCESS) { |
521 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", | 528 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", |
@@ -719,6 +726,7 @@ static void unregister_efivars(struct efivars *efivars) | |||
719 | } | 726 | } |
720 | 727 | ||
721 | static int register_efivars(struct efivars *efivars, | 728 | static int register_efivars(struct efivars *efivars, |
729 | const struct efivar_operations *ops, | ||
722 | struct kobject *parent_kobj) | 730 | struct kobject *parent_kobj) |
723 | { | 731 | { |
724 | efi_status_t status = EFI_NOT_FOUND; | 732 | efi_status_t status = EFI_NOT_FOUND; |
@@ -735,6 +743,7 @@ static int register_efivars(struct efivars *efivars, | |||
735 | 743 | ||
736 | spin_lock_init(&efivars->lock); | 744 | spin_lock_init(&efivars->lock); |
737 | INIT_LIST_HEAD(&efivars->list); | 745 | INIT_LIST_HEAD(&efivars->list); |
746 | efivars->ops = ops; | ||
738 | 747 | ||
739 | efivars->kset = kset_create_and_add("vars", NULL, parent_kobj); | 748 | efivars->kset = kset_create_and_add("vars", NULL, parent_kobj); |
740 | if (!efivars->kset) { | 749 | if (!efivars->kset) { |
@@ -751,7 +760,7 @@ static int register_efivars(struct efivars *efivars, | |||
751 | do { | 760 | do { |
752 | variable_name_size = 1024; | 761 | variable_name_size = 1024; |
753 | 762 | ||
754 | status = efi.get_next_variable(&variable_name_size, | 763 | status = ops->get_next_variable(&variable_name_size, |
755 | variable_name, | 764 | variable_name, |
756 | &vendor_guid); | 765 | &vendor_guid); |
757 | switch (status) { | 766 | switch (status) { |
@@ -782,6 +791,7 @@ out: | |||
782 | } | 791 | } |
783 | 792 | ||
784 | static struct efivars __efivars; | 793 | static struct efivars __efivars; |
794 | static struct efivar_operations ops; | ||
785 | 795 | ||
786 | /* | 796 | /* |
787 | * For now we register the efi subsystem with the firmware subsystem | 797 | * For now we register the efi subsystem with the firmware subsystem |
@@ -809,7 +819,10 @@ efivars_init(void) | |||
809 | return -ENOMEM; | 819 | return -ENOMEM; |
810 | } | 820 | } |
811 | 821 | ||
812 | error = register_efivars(&__efivars, efi_kobj); | 822 | ops.get_variable = efi.get_variable; |
823 | ops.set_variable = efi.set_variable; | ||
824 | ops.get_next_variable = efi.get_next_variable; | ||
825 | error = register_efivars(&__efivars, &ops, efi_kobj); | ||
813 | 826 | ||
814 | /* Don't forget the systab entry */ | 827 | /* Don't forget the systab entry */ |
815 | error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); | 828 | error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group); |