diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efivars.c | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 34c8783a2aa8..eab4ec41c523 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -125,7 +125,6 @@ struct efi_variable { | |||
125 | } __attribute__((packed)); | 125 | } __attribute__((packed)); |
126 | 126 | ||
127 | struct efivar_entry { | 127 | struct efivar_entry { |
128 | struct efivars *efivars; | ||
129 | struct efi_variable var; | 128 | struct efi_variable var; |
130 | struct list_head list; | 129 | struct list_head list; |
131 | struct kobject kobj; | 130 | struct kobject kobj; |
@@ -137,8 +136,8 @@ struct efivar_attribute { | |||
137 | ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); | 136 | ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); |
138 | }; | 137 | }; |
139 | 138 | ||
140 | static struct efivars __efivars; | 139 | /* Private pointer to registered efivars */ |
141 | static struct efivar_operations ops; | 140 | static struct efivars *__efivars; |
142 | 141 | ||
143 | #define PSTORE_EFI_ATTRIBUTES \ | 142 | #define PSTORE_EFI_ATTRIBUTES \ |
144 | (EFI_VARIABLE_NON_VOLATILE | \ | 143 | (EFI_VARIABLE_NON_VOLATILE | \ |
@@ -479,7 +478,7 @@ efivar_attr_read(struct efivar_entry *entry, char *buf) | |||
479 | if (!entry || !buf) | 478 | if (!entry || !buf) |
480 | return -EINVAL; | 479 | return -EINVAL; |
481 | 480 | ||
482 | status = get_var_data(entry->efivars, var); | 481 | status = get_var_data(__efivars, var); |
483 | if (status != EFI_SUCCESS) | 482 | if (status != EFI_SUCCESS) |
484 | return -EIO; | 483 | return -EIO; |
485 | 484 | ||
@@ -513,7 +512,7 @@ efivar_size_read(struct efivar_entry *entry, char *buf) | |||
513 | if (!entry || !buf) | 512 | if (!entry || !buf) |
514 | return -EINVAL; | 513 | return -EINVAL; |
515 | 514 | ||
516 | status = get_var_data(entry->efivars, var); | 515 | status = get_var_data(__efivars, var); |
517 | if (status != EFI_SUCCESS) | 516 | if (status != EFI_SUCCESS) |
518 | return -EIO; | 517 | return -EIO; |
519 | 518 | ||
@@ -530,7 +529,7 @@ efivar_data_read(struct efivar_entry *entry, char *buf) | |||
530 | if (!entry || !buf) | 529 | if (!entry || !buf) |
531 | return -EINVAL; | 530 | return -EINVAL; |
532 | 531 | ||
533 | status = get_var_data(entry->efivars, var); | 532 | status = get_var_data(__efivars, var); |
534 | if (status != EFI_SUCCESS) | 533 | if (status != EFI_SUCCESS) |
535 | return -EIO; | 534 | return -EIO; |
536 | 535 | ||
@@ -545,7 +544,7 @@ static ssize_t | |||
545 | efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | 544 | efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) |
546 | { | 545 | { |
547 | struct efi_variable *new_var, *var = &entry->var; | 546 | struct efi_variable *new_var, *var = &entry->var; |
548 | struct efivars *efivars = entry->efivars; | 547 | struct efivars *efivars = __efivars; |
549 | efi_status_t status = EFI_NOT_FOUND; | 548 | efi_status_t status = EFI_NOT_FOUND; |
550 | 549 | ||
551 | if (count != sizeof(struct efi_variable)) | 550 | if (count != sizeof(struct efi_variable)) |
@@ -606,7 +605,7 @@ efivar_show_raw(struct efivar_entry *entry, char *buf) | |||
606 | if (!entry || !buf) | 605 | if (!entry || !buf) |
607 | return 0; | 606 | return 0; |
608 | 607 | ||
609 | status = get_var_data(entry->efivars, var); | 608 | status = get_var_data(__efivars, var); |
610 | if (status != EFI_SUCCESS) | 609 | if (status != EFI_SUCCESS) |
611 | return -EIO; | 610 | return -EIO; |
612 | 611 | ||
@@ -728,7 +727,7 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
728 | const char __user *userbuf, size_t count, loff_t *ppos) | 727 | const char __user *userbuf, size_t count, loff_t *ppos) |
729 | { | 728 | { |
730 | struct efivar_entry *var = file->private_data; | 729 | struct efivar_entry *var = file->private_data; |
731 | struct efivars *efivars; | 730 | struct efivars *efivars = __efivars; |
732 | efi_status_t status; | 731 | efi_status_t status; |
733 | void *data; | 732 | void *data; |
734 | u32 attributes; | 733 | u32 attributes; |
@@ -746,8 +745,6 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
746 | if (attributes & ~(EFI_VARIABLE_MASK)) | 745 | if (attributes & ~(EFI_VARIABLE_MASK)) |
747 | return -EINVAL; | 746 | return -EINVAL; |
748 | 747 | ||
749 | efivars = var->efivars; | ||
750 | |||
751 | /* | 748 | /* |
752 | * Ensure that the user can't allocate arbitrarily large | 749 | * Ensure that the user can't allocate arbitrarily large |
753 | * amounts of memory. Pick a default size of 64K if | 750 | * amounts of memory. Pick a default size of 64K if |
@@ -855,7 +852,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, | |||
855 | size_t count, loff_t *ppos) | 852 | size_t count, loff_t *ppos) |
856 | { | 853 | { |
857 | struct efivar_entry *var = file->private_data; | 854 | struct efivar_entry *var = file->private_data; |
858 | struct efivars *efivars = var->efivars; | 855 | struct efivars *efivars = __efivars; |
859 | efi_status_t status; | 856 | efi_status_t status; |
860 | unsigned long datasize = 0; | 857 | unsigned long datasize = 0; |
861 | u32 attributes; | 858 | u32 attributes; |
@@ -1009,7 +1006,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, | |||
1009 | umode_t mode, bool excl) | 1006 | umode_t mode, bool excl) |
1010 | { | 1007 | { |
1011 | struct inode *inode; | 1008 | struct inode *inode; |
1012 | struct efivars *efivars = &__efivars; | 1009 | struct efivars *efivars = __efivars; |
1013 | struct efivar_entry *var; | 1010 | struct efivar_entry *var; |
1014 | int namelen, i = 0, err = 0; | 1011 | int namelen, i = 0, err = 0; |
1015 | 1012 | ||
@@ -1038,7 +1035,6 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, | |||
1038 | var->var.VariableName[i] = '\0'; | 1035 | var->var.VariableName[i] = '\0'; |
1039 | 1036 | ||
1040 | inode->i_private = var; | 1037 | inode->i_private = var; |
1041 | var->efivars = efivars; | ||
1042 | var->kobj.kset = efivars->kset; | 1038 | var->kobj.kset = efivars->kset; |
1043 | 1039 | ||
1044 | err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", | 1040 | err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", |
@@ -1063,7 +1059,7 @@ out: | |||
1063 | static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) | 1059 | static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) |
1064 | { | 1060 | { |
1065 | struct efivar_entry *var = dentry->d_inode->i_private; | 1061 | struct efivar_entry *var = dentry->d_inode->i_private; |
1066 | struct efivars *efivars = var->efivars; | 1062 | struct efivars *efivars = __efivars; |
1067 | efi_status_t status; | 1063 | efi_status_t status; |
1068 | 1064 | ||
1069 | spin_lock_irq(&efivars->lock); | 1065 | spin_lock_irq(&efivars->lock); |
@@ -1175,7 +1171,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
1175 | struct inode *inode = NULL; | 1171 | struct inode *inode = NULL; |
1176 | struct dentry *root; | 1172 | struct dentry *root; |
1177 | struct efivar_entry *entry, *n; | 1173 | struct efivar_entry *entry, *n; |
1178 | struct efivars *efivars = &__efivars; | 1174 | struct efivars *efivars = __efivars; |
1179 | char *name; | 1175 | char *name; |
1180 | int err = -ENOMEM; | 1176 | int err = -ENOMEM; |
1181 | 1177 | ||
@@ -1302,7 +1298,7 @@ static const struct inode_operations efivarfs_dir_inode_operations = { | |||
1302 | 1298 | ||
1303 | static int efi_pstore_open(struct pstore_info *psi) | 1299 | static int efi_pstore_open(struct pstore_info *psi) |
1304 | { | 1300 | { |
1305 | struct efivars *efivars = psi->data; | 1301 | struct efivars *efivars = __efivars; |
1306 | 1302 | ||
1307 | spin_lock_irq(&efivars->lock); | 1303 | spin_lock_irq(&efivars->lock); |
1308 | efivars->walk_entry = list_first_entry(&efivars->list, | 1304 | efivars->walk_entry = list_first_entry(&efivars->list, |
@@ -1312,7 +1308,7 @@ static int efi_pstore_open(struct pstore_info *psi) | |||
1312 | 1308 | ||
1313 | static int efi_pstore_close(struct pstore_info *psi) | 1309 | static int efi_pstore_close(struct pstore_info *psi) |
1314 | { | 1310 | { |
1315 | struct efivars *efivars = psi->data; | 1311 | struct efivars *efivars = __efivars; |
1316 | 1312 | ||
1317 | spin_unlock_irq(&efivars->lock); | 1313 | spin_unlock_irq(&efivars->lock); |
1318 | return 0; | 1314 | return 0; |
@@ -1323,7 +1319,7 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, | |||
1323 | char **buf, struct pstore_info *psi) | 1319 | char **buf, struct pstore_info *psi) |
1324 | { | 1320 | { |
1325 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; | 1321 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; |
1326 | struct efivars *efivars = psi->data; | 1322 | struct efivars *efivars = __efivars; |
1327 | char name[DUMP_NAME_LEN]; | 1323 | char name[DUMP_NAME_LEN]; |
1328 | int i; | 1324 | int i; |
1329 | int cnt; | 1325 | int cnt; |
@@ -1386,7 +1382,7 @@ static int efi_pstore_write(enum pstore_type_id type, | |||
1386 | char name[DUMP_NAME_LEN]; | 1382 | char name[DUMP_NAME_LEN]; |
1387 | efi_char16_t efi_name[DUMP_NAME_LEN]; | 1383 | efi_char16_t efi_name[DUMP_NAME_LEN]; |
1388 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; | 1384 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; |
1389 | struct efivars *efivars = psi->data; | 1385 | struct efivars *efivars = __efivars; |
1390 | int i, ret = 0; | 1386 | int i, ret = 0; |
1391 | efi_status_t status = EFI_NOT_FOUND; | 1387 | efi_status_t status = EFI_NOT_FOUND; |
1392 | unsigned long flags; | 1388 | unsigned long flags; |
@@ -1443,7 +1439,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | |||
1443 | char name_old[DUMP_NAME_LEN]; | 1439 | char name_old[DUMP_NAME_LEN]; |
1444 | efi_char16_t efi_name_old[DUMP_NAME_LEN]; | 1440 | efi_char16_t efi_name_old[DUMP_NAME_LEN]; |
1445 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; | 1441 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; |
1446 | struct efivars *efivars = psi->data; | 1442 | struct efivars *efivars = __efivars; |
1447 | struct efivar_entry *entry, *found = NULL; | 1443 | struct efivar_entry *entry, *found = NULL; |
1448 | int i; | 1444 | int i; |
1449 | 1445 | ||
@@ -1535,7 +1531,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
1535 | char *buf, loff_t pos, size_t count) | 1531 | char *buf, loff_t pos, size_t count) |
1536 | { | 1532 | { |
1537 | struct efi_variable *new_var = (struct efi_variable *)buf; | 1533 | struct efi_variable *new_var = (struct efi_variable *)buf; |
1538 | struct efivars *efivars = bin_attr->private; | 1534 | struct efivars *efivars = __efivars; |
1539 | struct efivar_entry *search_efivar, *n; | 1535 | struct efivar_entry *search_efivar, *n; |
1540 | unsigned long strsize1, strsize2; | 1536 | unsigned long strsize1, strsize2; |
1541 | efi_status_t status = EFI_NOT_FOUND; | 1537 | efi_status_t status = EFI_NOT_FOUND; |
@@ -1612,7 +1608,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
1612 | char *buf, loff_t pos, size_t count) | 1608 | char *buf, loff_t pos, size_t count) |
1613 | { | 1609 | { |
1614 | struct efi_variable *del_var = (struct efi_variable *)buf; | 1610 | struct efi_variable *del_var = (struct efi_variable *)buf; |
1615 | struct efivars *efivars = bin_attr->private; | 1611 | struct efivars *efivars = __efivars; |
1616 | struct efivar_entry *search_efivar, *n; | 1612 | struct efivar_entry *search_efivar, *n; |
1617 | unsigned long strsize1, strsize2; | 1613 | unsigned long strsize1, strsize2; |
1618 | efi_status_t status = EFI_NOT_FOUND; | 1614 | efi_status_t status = EFI_NOT_FOUND; |
@@ -1670,7 +1666,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
1670 | static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) | 1666 | static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) |
1671 | { | 1667 | { |
1672 | struct efivar_entry *entry, *n; | 1668 | struct efivar_entry *entry, *n; |
1673 | struct efivars *efivars = &__efivars; | 1669 | struct efivars *efivars = __efivars; |
1674 | unsigned long strsize1, strsize2; | 1670 | unsigned long strsize1, strsize2; |
1675 | bool found = false; | 1671 | bool found = false; |
1676 | 1672 | ||
@@ -1716,7 +1712,7 @@ static unsigned long var_name_strnsize(efi_char16_t *variable_name, | |||
1716 | 1712 | ||
1717 | static void efivar_update_sysfs_entries(struct work_struct *work) | 1713 | static void efivar_update_sysfs_entries(struct work_struct *work) |
1718 | { | 1714 | { |
1719 | struct efivars *efivars = &__efivars; | 1715 | struct efivars *efivars = __efivars; |
1720 | efi_guid_t vendor; | 1716 | efi_guid_t vendor; |
1721 | efi_char16_t *variable_name; | 1717 | efi_char16_t *variable_name; |
1722 | unsigned long variable_name_size = 1024; | 1718 | unsigned long variable_name_size = 1024; |
@@ -1843,7 +1839,6 @@ efivar_create_sysfs_entry(struct efivars *efivars, | |||
1843 | return 1; | 1839 | return 1; |
1844 | } | 1840 | } |
1845 | 1841 | ||
1846 | new_efivar->efivars = efivars; | ||
1847 | memcpy(new_efivar->var.VariableName, variable_name, | 1842 | memcpy(new_efivar->var.VariableName, variable_name, |
1848 | variable_name_size); | 1843 | variable_name_size); |
1849 | memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); | 1844 | memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t)); |
@@ -1942,6 +1937,8 @@ void unregister_efivars(struct efivars *efivars) | |||
1942 | { | 1937 | { |
1943 | struct efivar_entry *entry, *n; | 1938 | struct efivar_entry *entry, *n; |
1944 | 1939 | ||
1940 | __efivars = NULL; | ||
1941 | |||
1945 | list_for_each_entry_safe(entry, n, &efivars->list, list) { | 1942 | list_for_each_entry_safe(entry, n, &efivars->list, list) { |
1946 | spin_lock_irq(&efivars->lock); | 1943 | spin_lock_irq(&efivars->lock); |
1947 | list_del(&entry->list); | 1944 | list_del(&entry->list); |
@@ -1998,6 +1995,8 @@ int register_efivars(struct efivars *efivars, | |||
1998 | unsigned long variable_name_size = 1024; | 1995 | unsigned long variable_name_size = 1024; |
1999 | int error = 0; | 1996 | int error = 0; |
2000 | 1997 | ||
1998 | __efivars = efivars; | ||
1999 | |||
2001 | variable_name = kzalloc(variable_name_size, GFP_KERNEL); | 2000 | variable_name = kzalloc(variable_name_size, GFP_KERNEL); |
2002 | if (!variable_name) { | 2001 | if (!variable_name) { |
2003 | printk(KERN_ERR "efivars: Memory allocation failed.\n"); | 2002 | printk(KERN_ERR "efivars: Memory allocation failed.\n"); |
@@ -2085,6 +2084,24 @@ out: | |||
2085 | } | 2084 | } |
2086 | EXPORT_SYMBOL_GPL(register_efivars); | 2085 | EXPORT_SYMBOL_GPL(register_efivars); |
2087 | 2086 | ||
2087 | static struct efivars generic_efivars; | ||
2088 | static struct efivar_operations generic_ops; | ||
2089 | |||
2090 | static int generic_ops_register(void) | ||
2091 | { | ||
2092 | generic_ops.get_variable = efi.get_variable; | ||
2093 | generic_ops.set_variable = efi.set_variable; | ||
2094 | generic_ops.get_next_variable = efi.get_next_variable; | ||
2095 | generic_ops.query_variable_info = efi.query_variable_info; | ||
2096 | |||
2097 | return register_efivars(&generic_efivars, &generic_ops, efi_kobj); | ||
2098 | } | ||
2099 | |||
2100 | static void generic_ops_unregister(void) | ||
2101 | { | ||
2102 | unregister_efivars(&generic_efivars); | ||
2103 | } | ||
2104 | |||
2088 | /* | 2105 | /* |
2089 | * For now we register the efi subsystem with the firmware subsystem | 2106 | * For now we register the efi subsystem with the firmware subsystem |
2090 | * and the vars subsystem with the efi subsystem. In the future, it | 2107 | * and the vars subsystem with the efi subsystem. In the future, it |
@@ -2111,12 +2128,7 @@ efivars_init(void) | |||
2111 | return -ENOMEM; | 2128 | return -ENOMEM; |
2112 | } | 2129 | } |
2113 | 2130 | ||
2114 | ops.get_variable = efi.get_variable; | 2131 | error = generic_ops_register(); |
2115 | ops.set_variable = efi.set_variable; | ||
2116 | ops.get_next_variable = efi.get_next_variable; | ||
2117 | ops.query_variable_info = efi.query_variable_info; | ||
2118 | |||
2119 | error = register_efivars(&__efivars, &ops, efi_kobj); | ||
2120 | if (error) | 2132 | if (error) |
2121 | goto err_put; | 2133 | goto err_put; |
2122 | 2134 | ||
@@ -2132,7 +2144,7 @@ efivars_init(void) | |||
2132 | return 0; | 2144 | return 0; |
2133 | 2145 | ||
2134 | err_unregister: | 2146 | err_unregister: |
2135 | unregister_efivars(&__efivars); | 2147 | generic_ops_unregister(); |
2136 | err_put: | 2148 | err_put: |
2137 | kobject_put(efi_kobj); | 2149 | kobject_put(efi_kobj); |
2138 | return error; | 2150 | return error; |
@@ -2144,7 +2156,7 @@ efivars_exit(void) | |||
2144 | cancel_work_sync(&efivar_work); | 2156 | cancel_work_sync(&efivar_work); |
2145 | 2157 | ||
2146 | if (efi_enabled(EFI_RUNTIME_SERVICES)) { | 2158 | if (efi_enabled(EFI_RUNTIME_SERVICES)) { |
2147 | unregister_efivars(&__efivars); | 2159 | generic_ops_unregister(); |
2148 | kobject_put(efi_kobj); | 2160 | kobject_put(efi_kobj); |
2149 | } | 2161 | } |
2150 | } | 2162 | } |