Skip to content

Commit

Permalink
efivars: Parameterize operations.
Browse files Browse the repository at this point in the history
Instead of letting efivars access struct efi directly when dealing with
variables, use an operations structure.  This allows a later change to
reuse the efivars logic without having to pretend to support everything
in struct efi.

Signed-off-by: Mike Waychison <mikew@google.com>
Cc: Matt Domsch <Matt_Domsch@dell.com>,
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Mike Waychison authored and Greg Kroah-Hartman committed Mar 14, 2011
1 parent 76b53f7 commit 3295814
Showing 1 changed file with 37 additions and 24 deletions.
61 changes: 37 additions & 24 deletions drivers/firmware/efivars.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,26 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");
MODULE_LICENSE("GPL");
MODULE_VERSION(EFIVARS_VERSION);

struct efivar_operations {
efi_get_variable_t *get_variable;
efi_get_next_variable_t *get_next_variable;
efi_set_variable_t *set_variable;
};

struct efivars {
/*
* ->lock protects two things:
* 1) ->list - adds, removals, reads, writes
* 2) efi.[gs]et_variable() calls.
* 2) ops.[gs]et_variable() calls.
* It must not be held when creating sysfs entries or calling kmalloc.
* efi.get_next_variable() is only called from register_efivars(),
* ops.get_next_variable() is only called from register_efivars(),
* which is protected by the BKL, so that path is safe.
*/
spinlock_t lock;
struct list_head list;
struct kset *kset;
struct bin_attribute *new_var, *del_var;
const struct efivar_operations *ops;
};

/*
Expand Down Expand Up @@ -182,11 +189,11 @@ get_var_data(struct efivars *efivars, struct efi_variable *var)

spin_lock(&efivars->lock);
var->DataSize = 1024;
status = efi.get_variable(var->VariableName,
&var->VendorGuid,
&var->Attributes,
&var->DataSize,
var->Data);
status = efivars->ops->get_variable(var->VariableName,
&var->VendorGuid,
&var->Attributes,
&var->DataSize,
var->Data);
spin_unlock(&efivars->lock);
if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
Expand Down Expand Up @@ -299,11 +306,11 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
}

spin_lock(&efivars->lock);
status = efi.set_variable(new_var->VariableName,
&new_var->VendorGuid,
new_var->Attributes,
new_var->DataSize,
new_var->Data);
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
new_var->Attributes,
new_var->DataSize,
new_var->Data);

spin_unlock(&efivars->lock);

Expand Down Expand Up @@ -446,11 +453,11 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
}

/* now *really* create the variable via EFI */
status = efi.set_variable(new_var->VariableName,
&new_var->VendorGuid,
new_var->Attributes,
new_var->DataSize,
new_var->Data);
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
new_var->Attributes,
new_var->DataSize,
new_var->Data);

if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
Expand Down Expand Up @@ -511,11 +518,11 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
del_var->Attributes = 0;
del_var->DataSize = 0;

status = efi.set_variable(del_var->VariableName,
&del_var->VendorGuid,
del_var->Attributes,
del_var->DataSize,
del_var->Data);
status = efivars->ops->set_variable(del_var->VariableName,
&del_var->VendorGuid,
del_var->Attributes,
del_var->DataSize,
del_var->Data);

if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
Expand Down Expand Up @@ -719,6 +726,7 @@ static void unregister_efivars(struct efivars *efivars)
}

static int register_efivars(struct efivars *efivars,
const struct efivar_operations *ops,
struct kobject *parent_kobj)
{
efi_status_t status = EFI_NOT_FOUND;
Expand All @@ -735,6 +743,7 @@ static int register_efivars(struct efivars *efivars,

spin_lock_init(&efivars->lock);
INIT_LIST_HEAD(&efivars->list);
efivars->ops = ops;

efivars->kset = kset_create_and_add("vars", NULL, parent_kobj);
if (!efivars->kset) {
Expand All @@ -751,7 +760,7 @@ static int register_efivars(struct efivars *efivars,
do {
variable_name_size = 1024;

status = efi.get_next_variable(&variable_name_size,
status = ops->get_next_variable(&variable_name_size,
variable_name,
&vendor_guid);
switch (status) {
Expand Down Expand Up @@ -782,6 +791,7 @@ static int register_efivars(struct efivars *efivars,
}

static struct efivars __efivars;
static struct efivar_operations ops;

/*
* For now we register the efi subsystem with the firmware subsystem
Expand Down Expand Up @@ -809,7 +819,10 @@ efivars_init(void)
return -ENOMEM;
}

error = register_efivars(&__efivars, efi_kobj);
ops.get_variable = efi.get_variable;
ops.set_variable = efi.set_variable;
ops.get_next_variable = efi.get_next_variable;
error = register_efivars(&__efivars, &ops, efi_kobj);

/* Don't forget the systab entry */
error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
Expand Down

0 comments on commit 3295814

Please sign in to comment.