diff options
Diffstat (limited to 'drivers/firmware/efivars.c')
-rw-r--r-- | drivers/firmware/efivars.c | 258 |
1 files changed, 131 insertions, 127 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index fe62aa392239..f4baa11d3644 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -80,6 +80,7 @@ | |||
80 | #include <linux/slab.h> | 80 | #include <linux/slab.h> |
81 | #include <linux/pstore.h> | 81 | #include <linux/pstore.h> |
82 | #include <linux/ctype.h> | 82 | #include <linux/ctype.h> |
83 | #include <linux/ucs2_string.h> | ||
83 | 84 | ||
84 | #include <linux/fs.h> | 85 | #include <linux/fs.h> |
85 | #include <linux/ramfs.h> | 86 | #include <linux/ramfs.h> |
@@ -103,6 +104,11 @@ MODULE_VERSION(EFIVARS_VERSION); | |||
103 | */ | 104 | */ |
104 | #define GUID_LEN 36 | 105 | #define GUID_LEN 36 |
105 | 106 | ||
107 | static bool efivars_pstore_disable = | ||
108 | IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE); | ||
109 | |||
110 | module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644); | ||
111 | |||
106 | /* | 112 | /* |
107 | * The maximum size of VariableName + Data = 1024 | 113 | * The maximum size of VariableName + Data = 1024 |
108 | * Therefore, it's reasonable to save that much | 114 | * Therefore, it's reasonable to save that much |
@@ -165,51 +171,7 @@ efivar_create_sysfs_entry(struct efivars *efivars, | |||
165 | 171 | ||
166 | static void efivar_update_sysfs_entries(struct work_struct *); | 172 | static void efivar_update_sysfs_entries(struct work_struct *); |
167 | static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); | 173 | static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); |
168 | 174 | static bool efivar_wq_enabled = true; | |
169 | /* Return the number of unicode characters in data */ | ||
170 | static unsigned long | ||
171 | utf16_strnlen(efi_char16_t *s, size_t maxlength) | ||
172 | { | ||
173 | unsigned long length = 0; | ||
174 | |||
175 | while (*s++ != 0 && length < maxlength) | ||
176 | length++; | ||
177 | return length; | ||
178 | } | ||
179 | |||
180 | static inline unsigned long | ||
181 | utf16_strlen(efi_char16_t *s) | ||
182 | { | ||
183 | return utf16_strnlen(s, ~0UL); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Return the number of bytes is the length of this string | ||
188 | * Note: this is NOT the same as the number of unicode characters | ||
189 | */ | ||
190 | static inline unsigned long | ||
191 | utf16_strsize(efi_char16_t *data, unsigned long maxlength) | ||
192 | { | ||
193 | return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t); | ||
194 | } | ||
195 | |||
196 | static inline int | ||
197 | utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len) | ||
198 | { | ||
199 | while (1) { | ||
200 | if (len == 0) | ||
201 | return 0; | ||
202 | if (*a < *b) | ||
203 | return -1; | ||
204 | if (*a > *b) | ||
205 | return 1; | ||
206 | if (*a == 0) /* implies *b == 0 */ | ||
207 | return 0; | ||
208 | a++; | ||
209 | b++; | ||
210 | len--; | ||
211 | } | ||
212 | } | ||
213 | 175 | ||
214 | static bool | 176 | static bool |
215 | validate_device_path(struct efi_variable *var, int match, u8 *buffer, | 177 | validate_device_path(struct efi_variable *var, int match, u8 *buffer, |
@@ -262,7 +224,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, | |||
262 | u16 filepathlength; | 224 | u16 filepathlength; |
263 | int i, desclength = 0, namelen; | 225 | int i, desclength = 0, namelen; |
264 | 226 | ||
265 | namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName)); | 227 | namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName)); |
266 | 228 | ||
267 | /* Either "Boot" or "Driver" followed by four digits of hex */ | 229 | /* Either "Boot" or "Driver" followed by four digits of hex */ |
268 | for (i = match; i < match+4; i++) { | 230 | for (i = match; i < match+4; i++) { |
@@ -285,7 +247,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, | |||
285 | * There's no stored length for the description, so it has to be | 247 | * There's no stored length for the description, so it has to be |
286 | * found by hand | 248 | * found by hand |
287 | */ | 249 | */ |
288 | desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; | 250 | desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; |
289 | 251 | ||
290 | /* Each boot entry must have a descriptor */ | 252 | /* Each boot entry must have a descriptor */ |
291 | if (!desclength) | 253 | if (!desclength) |
@@ -430,24 +392,12 @@ static efi_status_t | |||
430 | check_var_size_locked(struct efivars *efivars, u32 attributes, | 392 | check_var_size_locked(struct efivars *efivars, u32 attributes, |
431 | unsigned long size) | 393 | unsigned long size) |
432 | { | 394 | { |
433 | u64 storage_size, remaining_size, max_size; | ||
434 | efi_status_t status; | ||
435 | const struct efivar_operations *fops = efivars->ops; | 395 | const struct efivar_operations *fops = efivars->ops; |
436 | 396 | ||
437 | if (!efivars->ops->query_variable_info) | 397 | if (!efivars->ops->query_variable_store) |
438 | return EFI_UNSUPPORTED; | 398 | return EFI_UNSUPPORTED; |
439 | 399 | ||
440 | status = fops->query_variable_info(attributes, &storage_size, | 400 | return fops->query_variable_store(attributes, size); |
441 | &remaining_size, &max_size); | ||
442 | |||
443 | if (status != EFI_SUCCESS) | ||
444 | return status; | ||
445 | |||
446 | if (!storage_size || size > remaining_size || size > max_size || | ||
447 | (remaining_size - size) < (storage_size / 2)) | ||
448 | return EFI_OUT_OF_RESOURCES; | ||
449 | |||
450 | return status; | ||
451 | } | 401 | } |
452 | 402 | ||
453 | 403 | ||
@@ -587,7 +537,7 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | |||
587 | spin_lock_irq(&efivars->lock); | 537 | spin_lock_irq(&efivars->lock); |
588 | 538 | ||
589 | status = check_var_size_locked(efivars, new_var->Attributes, | 539 | status = check_var_size_locked(efivars, new_var->Attributes, |
590 | new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); | 540 | new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024)); |
591 | 541 | ||
592 | if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) | 542 | if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) |
593 | status = efivars->ops->set_variable(new_var->VariableName, | 543 | status = efivars->ops->set_variable(new_var->VariableName, |
@@ -765,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
765 | * QueryVariableInfo() isn't supported by the firmware. | 715 | * QueryVariableInfo() isn't supported by the firmware. |
766 | */ | 716 | */ |
767 | 717 | ||
768 | varsize = datasize + utf16_strsize(var->var.VariableName, 1024); | 718 | varsize = datasize + ucs2_strsize(var->var.VariableName, 1024); |
769 | status = check_var_size(efivars, attributes, varsize); | 719 | status = check_var_size(efivars, attributes, varsize); |
770 | 720 | ||
771 | if (status != EFI_SUCCESS) { | 721 | if (status != EFI_SUCCESS) { |
@@ -1217,7 +1167,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
1217 | 1167 | ||
1218 | inode = NULL; | 1168 | inode = NULL; |
1219 | 1169 | ||
1220 | len = utf16_strlen(entry->var.VariableName); | 1170 | len = ucs2_strlen(entry->var.VariableName); |
1221 | 1171 | ||
1222 | /* name, plus '-', plus GUID, plus NUL*/ | 1172 | /* name, plus '-', plus GUID, plus NUL*/ |
1223 | name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); | 1173 | name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); |
@@ -1309,9 +1259,7 @@ static const struct inode_operations efivarfs_dir_inode_operations = { | |||
1309 | .create = efivarfs_create, | 1259 | .create = efivarfs_create, |
1310 | }; | 1260 | }; |
1311 | 1261 | ||
1312 | static struct pstore_info efi_pstore_info; | 1262 | #ifdef CONFIG_EFI_VARS_PSTORE |
1313 | |||
1314 | #ifdef CONFIG_PSTORE | ||
1315 | 1263 | ||
1316 | static int efi_pstore_open(struct pstore_info *psi) | 1264 | static int efi_pstore_open(struct pstore_info *psi) |
1317 | { | 1265 | { |
@@ -1441,7 +1389,7 @@ static int efi_pstore_write(enum pstore_type_id type, | |||
1441 | 1389 | ||
1442 | spin_unlock_irqrestore(&efivars->lock, flags); | 1390 | spin_unlock_irqrestore(&efivars->lock, flags); |
1443 | 1391 | ||
1444 | if (reason == KMSG_DUMP_OOPS) | 1392 | if (reason == KMSG_DUMP_OOPS && efivar_wq_enabled) |
1445 | schedule_work(&efivar_work); | 1393 | schedule_work(&efivar_work); |
1446 | 1394 | ||
1447 | *id = part; | 1395 | *id = part; |
@@ -1477,8 +1425,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | |||
1477 | 1425 | ||
1478 | if (efi_guidcmp(entry->var.VendorGuid, vendor)) | 1426 | if (efi_guidcmp(entry->var.VendorGuid, vendor)) |
1479 | continue; | 1427 | continue; |
1480 | if (utf16_strncmp(entry->var.VariableName, efi_name, | 1428 | if (ucs2_strncmp(entry->var.VariableName, efi_name, |
1481 | utf16_strlen(efi_name))) { | 1429 | ucs2_strlen(efi_name))) { |
1482 | /* | 1430 | /* |
1483 | * Check if an old format, | 1431 | * Check if an old format, |
1484 | * which doesn't support holding | 1432 | * which doesn't support holding |
@@ -1490,8 +1438,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | |||
1490 | for (i = 0; i < DUMP_NAME_LEN; i++) | 1438 | for (i = 0; i < DUMP_NAME_LEN; i++) |
1491 | efi_name_old[i] = name_old[i]; | 1439 | efi_name_old[i] = name_old[i]; |
1492 | 1440 | ||
1493 | if (utf16_strncmp(entry->var.VariableName, efi_name_old, | 1441 | if (ucs2_strncmp(entry->var.VariableName, efi_name_old, |
1494 | utf16_strlen(efi_name_old))) | 1442 | ucs2_strlen(efi_name_old))) |
1495 | continue; | 1443 | continue; |
1496 | } | 1444 | } |
1497 | 1445 | ||
@@ -1514,38 +1462,6 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | |||
1514 | 1462 | ||
1515 | return 0; | 1463 | return 0; |
1516 | } | 1464 | } |
1517 | #else | ||
1518 | static int efi_pstore_open(struct pstore_info *psi) | ||
1519 | { | ||
1520 | return 0; | ||
1521 | } | ||
1522 | |||
1523 | static int efi_pstore_close(struct pstore_info *psi) | ||
1524 | { | ||
1525 | return 0; | ||
1526 | } | ||
1527 | |||
1528 | static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count, | ||
1529 | struct timespec *timespec, | ||
1530 | char **buf, struct pstore_info *psi) | ||
1531 | { | ||
1532 | return -1; | ||
1533 | } | ||
1534 | |||
1535 | static int efi_pstore_write(enum pstore_type_id type, | ||
1536 | enum kmsg_dump_reason reason, u64 *id, | ||
1537 | unsigned int part, int count, size_t size, | ||
1538 | struct pstore_info *psi) | ||
1539 | { | ||
1540 | return 0; | ||
1541 | } | ||
1542 | |||
1543 | static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | ||
1544 | struct timespec time, struct pstore_info *psi) | ||
1545 | { | ||
1546 | return 0; | ||
1547 | } | ||
1548 | #endif | ||
1549 | 1465 | ||
1550 | static struct pstore_info efi_pstore_info = { | 1466 | static struct pstore_info efi_pstore_info = { |
1551 | .owner = THIS_MODULE, | 1467 | .owner = THIS_MODULE, |
@@ -1557,6 +1473,24 @@ static struct pstore_info efi_pstore_info = { | |||
1557 | .erase = efi_pstore_erase, | 1473 | .erase = efi_pstore_erase, |
1558 | }; | 1474 | }; |
1559 | 1475 | ||
1476 | static void efivar_pstore_register(struct efivars *efivars) | ||
1477 | { | ||
1478 | efivars->efi_pstore_info = efi_pstore_info; | ||
1479 | efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); | ||
1480 | if (efivars->efi_pstore_info.buf) { | ||
1481 | efivars->efi_pstore_info.bufsize = 1024; | ||
1482 | efivars->efi_pstore_info.data = efivars; | ||
1483 | spin_lock_init(&efivars->efi_pstore_info.buf_lock); | ||
1484 | pstore_register(&efivars->efi_pstore_info); | ||
1485 | } | ||
1486 | } | ||
1487 | #else | ||
1488 | static void efivar_pstore_register(struct efivars *efivars) | ||
1489 | { | ||
1490 | return; | ||
1491 | } | ||
1492 | #endif | ||
1493 | |||
1560 | static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | 1494 | static ssize_t efivar_create(struct file *filp, struct kobject *kobj, |
1561 | struct bin_attribute *bin_attr, | 1495 | struct bin_attribute *bin_attr, |
1562 | char *buf, loff_t pos, size_t count) | 1496 | char *buf, loff_t pos, size_t count) |
@@ -1583,8 +1517,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
1583 | * Does this variable already exist? | 1517 | * Does this variable already exist? |
1584 | */ | 1518 | */ |
1585 | list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { | 1519 | list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { |
1586 | strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); | 1520 | strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024); |
1587 | strsize2 = utf16_strsize(new_var->VariableName, 1024); | 1521 | strsize2 = ucs2_strsize(new_var->VariableName, 1024); |
1588 | if (strsize1 == strsize2 && | 1522 | if (strsize1 == strsize2 && |
1589 | !memcmp(&(search_efivar->var.VariableName), | 1523 | !memcmp(&(search_efivar->var.VariableName), |
1590 | new_var->VariableName, strsize1) && | 1524 | new_var->VariableName, strsize1) && |
@@ -1600,7 +1534,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
1600 | } | 1534 | } |
1601 | 1535 | ||
1602 | status = check_var_size_locked(efivars, new_var->Attributes, | 1536 | status = check_var_size_locked(efivars, new_var->Attributes, |
1603 | new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); | 1537 | new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024)); |
1604 | 1538 | ||
1605 | if (status && status != EFI_UNSUPPORTED) { | 1539 | if (status && status != EFI_UNSUPPORTED) { |
1606 | spin_unlock_irq(&efivars->lock); | 1540 | spin_unlock_irq(&efivars->lock); |
@@ -1624,7 +1558,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
1624 | 1558 | ||
1625 | /* Create the entry in sysfs. Locking is not required here */ | 1559 | /* Create the entry in sysfs. Locking is not required here */ |
1626 | status = efivar_create_sysfs_entry(efivars, | 1560 | status = efivar_create_sysfs_entry(efivars, |
1627 | utf16_strsize(new_var->VariableName, | 1561 | ucs2_strsize(new_var->VariableName, |
1628 | 1024), | 1562 | 1024), |
1629 | new_var->VariableName, | 1563 | new_var->VariableName, |
1630 | &new_var->VendorGuid); | 1564 | &new_var->VendorGuid); |
@@ -1654,8 +1588,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
1654 | * Does this variable already exist? | 1588 | * Does this variable already exist? |
1655 | */ | 1589 | */ |
1656 | list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { | 1590 | list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { |
1657 | strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); | 1591 | strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024); |
1658 | strsize2 = utf16_strsize(del_var->VariableName, 1024); | 1592 | strsize2 = ucs2_strsize(del_var->VariableName, 1024); |
1659 | if (strsize1 == strsize2 && | 1593 | if (strsize1 == strsize2 && |
1660 | !memcmp(&(search_efivar->var.VariableName), | 1594 | !memcmp(&(search_efivar->var.VariableName), |
1661 | del_var->VariableName, strsize1) && | 1595 | del_var->VariableName, strsize1) && |
@@ -1694,16 +1628,17 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
1694 | return count; | 1628 | return count; |
1695 | } | 1629 | } |
1696 | 1630 | ||
1697 | static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) | 1631 | static bool variable_is_present(struct efivars *efivars, |
1632 | efi_char16_t *variable_name, | ||
1633 | efi_guid_t *vendor) | ||
1698 | { | 1634 | { |
1699 | struct efivar_entry *entry, *n; | 1635 | struct efivar_entry *entry, *n; |
1700 | struct efivars *efivars = &__efivars; | ||
1701 | unsigned long strsize1, strsize2; | 1636 | unsigned long strsize1, strsize2; |
1702 | bool found = false; | 1637 | bool found = false; |
1703 | 1638 | ||
1704 | strsize1 = utf16_strsize(variable_name, 1024); | 1639 | strsize1 = ucs2_strsize(variable_name, 1024); |
1705 | list_for_each_entry_safe(entry, n, &efivars->list, list) { | 1640 | list_for_each_entry_safe(entry, n, &efivars->list, list) { |
1706 | strsize2 = utf16_strsize(entry->var.VariableName, 1024); | 1641 | strsize2 = ucs2_strsize(entry->var.VariableName, 1024); |
1707 | if (strsize1 == strsize2 && | 1642 | if (strsize1 == strsize2 && |
1708 | !memcmp(variable_name, &(entry->var.VariableName), | 1643 | !memcmp(variable_name, &(entry->var.VariableName), |
1709 | strsize2) && | 1644 | strsize2) && |
@@ -1716,6 +1651,31 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) | |||
1716 | return found; | 1651 | return found; |
1717 | } | 1652 | } |
1718 | 1653 | ||
1654 | /* | ||
1655 | * Returns the size of variable_name, in bytes, including the | ||
1656 | * terminating NULL character, or variable_name_size if no NULL | ||
1657 | * character is found among the first variable_name_size bytes. | ||
1658 | */ | ||
1659 | static unsigned long var_name_strnsize(efi_char16_t *variable_name, | ||
1660 | unsigned long variable_name_size) | ||
1661 | { | ||
1662 | unsigned long len; | ||
1663 | efi_char16_t c; | ||
1664 | |||
1665 | /* | ||
1666 | * The variable name is, by definition, a NULL-terminated | ||
1667 | * string, so make absolutely sure that variable_name_size is | ||
1668 | * the value we expect it to be. If not, return the real size. | ||
1669 | */ | ||
1670 | for (len = 2; len <= variable_name_size; len += sizeof(c)) { | ||
1671 | c = variable_name[(len / sizeof(c)) - 1]; | ||
1672 | if (!c) | ||
1673 | break; | ||
1674 | } | ||
1675 | |||
1676 | return min(len, variable_name_size); | ||
1677 | } | ||
1678 | |||
1719 | static void efivar_update_sysfs_entries(struct work_struct *work) | 1679 | static void efivar_update_sysfs_entries(struct work_struct *work) |
1720 | { | 1680 | { |
1721 | struct efivars *efivars = &__efivars; | 1681 | struct efivars *efivars = &__efivars; |
@@ -1744,8 +1704,8 @@ static void efivar_update_sysfs_entries(struct work_struct *work) | |||
1744 | if (status != EFI_SUCCESS) { | 1704 | if (status != EFI_SUCCESS) { |
1745 | break; | 1705 | break; |
1746 | } else { | 1706 | } else { |
1747 | if (!variable_is_present(variable_name, | 1707 | if (!variable_is_present(efivars, |
1748 | &vendor)) { | 1708 | variable_name, &vendor)) { |
1749 | found = true; | 1709 | found = true; |
1750 | break; | 1710 | break; |
1751 | } | 1711 | } |
@@ -1756,10 +1716,13 @@ static void efivar_update_sysfs_entries(struct work_struct *work) | |||
1756 | if (!found) { | 1716 | if (!found) { |
1757 | kfree(variable_name); | 1717 | kfree(variable_name); |
1758 | break; | 1718 | break; |
1759 | } else | 1719 | } else { |
1720 | variable_name_size = var_name_strnsize(variable_name, | ||
1721 | variable_name_size); | ||
1760 | efivar_create_sysfs_entry(efivars, | 1722 | efivar_create_sysfs_entry(efivars, |
1761 | variable_name_size, | 1723 | variable_name_size, |
1762 | variable_name, &vendor); | 1724 | variable_name, &vendor); |
1725 | } | ||
1763 | } | 1726 | } |
1764 | } | 1727 | } |
1765 | 1728 | ||
@@ -1958,6 +1921,35 @@ void unregister_efivars(struct efivars *efivars) | |||
1958 | } | 1921 | } |
1959 | EXPORT_SYMBOL_GPL(unregister_efivars); | 1922 | EXPORT_SYMBOL_GPL(unregister_efivars); |
1960 | 1923 | ||
1924 | /* | ||
1925 | * Print a warning when duplicate EFI variables are encountered and | ||
1926 | * disable the sysfs workqueue since the firmware is buggy. | ||
1927 | */ | ||
1928 | static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid, | ||
1929 | unsigned long len16) | ||
1930 | { | ||
1931 | size_t i, len8 = len16 / sizeof(efi_char16_t); | ||
1932 | char *s8; | ||
1933 | |||
1934 | /* | ||
1935 | * Disable the workqueue since the algorithm it uses for | ||
1936 | * detecting new variables won't work with this buggy | ||
1937 | * implementation of GetNextVariableName(). | ||
1938 | */ | ||
1939 | efivar_wq_enabled = false; | ||
1940 | |||
1941 | s8 = kzalloc(len8, GFP_KERNEL); | ||
1942 | if (!s8) | ||
1943 | return; | ||
1944 | |||
1945 | for (i = 0; i < len8; i++) | ||
1946 | s8[i] = s16[i]; | ||
1947 | |||
1948 | printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n", | ||
1949 | s8, vendor_guid); | ||
1950 | kfree(s8); | ||
1951 | } | ||
1952 | |||
1961 | int register_efivars(struct efivars *efivars, | 1953 | int register_efivars(struct efivars *efivars, |
1962 | const struct efivar_operations *ops, | 1954 | const struct efivar_operations *ops, |
1963 | struct kobject *parent_kobj) | 1955 | struct kobject *parent_kobj) |
@@ -2006,6 +1998,25 @@ int register_efivars(struct efivars *efivars, | |||
2006 | &vendor_guid); | 1998 | &vendor_guid); |
2007 | switch (status) { | 1999 | switch (status) { |
2008 | case EFI_SUCCESS: | 2000 | case EFI_SUCCESS: |
2001 | variable_name_size = var_name_strnsize(variable_name, | ||
2002 | variable_name_size); | ||
2003 | |||
2004 | /* | ||
2005 | * Some firmware implementations return the | ||
2006 | * same variable name on multiple calls to | ||
2007 | * get_next_variable(). Terminate the loop | ||
2008 | * immediately as there is no guarantee that | ||
2009 | * we'll ever see a different variable name, | ||
2010 | * and may end up looping here forever. | ||
2011 | */ | ||
2012 | if (variable_is_present(efivars, variable_name, | ||
2013 | &vendor_guid)) { | ||
2014 | dup_variable_bug(variable_name, &vendor_guid, | ||
2015 | variable_name_size); | ||
2016 | status = EFI_NOT_FOUND; | ||
2017 | break; | ||
2018 | } | ||
2019 | |||
2009 | efivar_create_sysfs_entry(efivars, | 2020 | efivar_create_sysfs_entry(efivars, |
2010 | variable_name_size, | 2021 | variable_name_size, |
2011 | variable_name, | 2022 | variable_name, |
@@ -2025,15 +2036,8 @@ int register_efivars(struct efivars *efivars, | |||
2025 | if (error) | 2036 | if (error) |
2026 | unregister_efivars(efivars); | 2037 | unregister_efivars(efivars); |
2027 | 2038 | ||
2028 | efivars->efi_pstore_info = efi_pstore_info; | 2039 | if (!efivars_pstore_disable) |
2029 | 2040 | efivar_pstore_register(efivars); | |
2030 | efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); | ||
2031 | if (efivars->efi_pstore_info.buf) { | ||
2032 | efivars->efi_pstore_info.bufsize = 1024; | ||
2033 | efivars->efi_pstore_info.data = efivars; | ||
2034 | spin_lock_init(&efivars->efi_pstore_info.buf_lock); | ||
2035 | pstore_register(&efivars->efi_pstore_info); | ||
2036 | } | ||
2037 | 2041 | ||
2038 | register_filesystem(&efivarfs_type); | 2042 | register_filesystem(&efivarfs_type); |
2039 | 2043 | ||
@@ -2073,7 +2077,7 @@ efivars_init(void) | |||
2073 | ops.get_variable = efi.get_variable; | 2077 | ops.get_variable = efi.get_variable; |
2074 | ops.set_variable = efi.set_variable; | 2078 | ops.set_variable = efi.set_variable; |
2075 | ops.get_next_variable = efi.get_next_variable; | 2079 | ops.get_next_variable = efi.get_next_variable; |
2076 | ops.query_variable_info = efi.query_variable_info; | 2080 | ops.query_variable_store = efi_query_variable_store; |
2077 | 2081 | ||
2078 | error = register_efivars(&__efivars, &ops, efi_kobj); | 2082 | error = register_efivars(&__efivars, &ops, efi_kobj); |
2079 | if (error) | 2083 | if (error) |