| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Originally from efivars.c |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com> |
|---|
| 5 | 6 | * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | | - * |
|---|
| 17 | | - * You should have received a copy of the GNU General Public License |
|---|
| 18 | | - * along with this program; if not, write to the Free Software |
|---|
| 19 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 20 | 7 | */ |
|---|
| 21 | 8 | |
|---|
| 22 | 9 | #include <linux/capability.h> |
|---|
| .. | .. |
|---|
| 44 | 31 | * 3) (un)registration of __efivars |
|---|
| 45 | 32 | */ |
|---|
| 46 | 33 | static DEFINE_SEMAPHORE(efivars_lock); |
|---|
| 47 | | - |
|---|
| 48 | | -static bool efivar_wq_enabled = true; |
|---|
| 49 | | -DECLARE_WORK(efivar_work, NULL); |
|---|
| 50 | | -EXPORT_SYMBOL_GPL(efivar_work); |
|---|
| 51 | 34 | |
|---|
| 52 | 35 | static bool |
|---|
| 53 | 36 | validate_device_path(efi_char16_t *var_name, int match, u8 *buffer, |
|---|
| .. | .. |
|---|
| 404 | 387 | size_t i, len8 = len16 / sizeof(efi_char16_t); |
|---|
| 405 | 388 | char *str8; |
|---|
| 406 | 389 | |
|---|
| 407 | | - /* |
|---|
| 408 | | - * Disable the workqueue since the algorithm it uses for |
|---|
| 409 | | - * detecting new variables won't work with this buggy |
|---|
| 410 | | - * implementation of GetNextVariableName(). |
|---|
| 411 | | - */ |
|---|
| 412 | | - efivar_wq_enabled = false; |
|---|
| 413 | | - |
|---|
| 414 | 390 | str8 = kzalloc(len8, GFP_KERNEL); |
|---|
| 415 | 391 | if (!str8) |
|---|
| 416 | 392 | return; |
|---|
| .. | .. |
|---|
| 427 | 403 | * efivar_init - build the initial list of EFI variables |
|---|
| 428 | 404 | * @func: callback function to invoke for every variable |
|---|
| 429 | 405 | * @data: function-specific data to pass to @func |
|---|
| 430 | | - * @atomic: do we need to execute the @func-loop atomically? |
|---|
| 431 | 406 | * @duplicates: error if we encounter duplicates on @head? |
|---|
| 432 | 407 | * @head: initialised head of variable list |
|---|
| 433 | 408 | * |
|---|
| .. | .. |
|---|
| 509 | 484 | } |
|---|
| 510 | 485 | } |
|---|
| 511 | 486 | |
|---|
| 487 | + break; |
|---|
| 488 | + case EFI_UNSUPPORTED: |
|---|
| 489 | + err = -EOPNOTSUPP; |
|---|
| 490 | + status = EFI_NOT_FOUND; |
|---|
| 512 | 491 | break; |
|---|
| 513 | 492 | case EFI_NOT_FOUND: |
|---|
| 514 | 493 | break; |
|---|
| .. | .. |
|---|
| 763 | 742 | { |
|---|
| 764 | 743 | const struct efivar_operations *ops; |
|---|
| 765 | 744 | efi_status_t status; |
|---|
| 745 | + unsigned long varsize; |
|---|
| 766 | 746 | |
|---|
| 767 | 747 | if (!__efivars) |
|---|
| 768 | 748 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 785 | 765 | return efivar_entry_set_nonblocking(name, vendor, attributes, |
|---|
| 786 | 766 | size, data); |
|---|
| 787 | 767 | |
|---|
| 768 | + varsize = size + ucs2_strsize(name, 1024); |
|---|
| 788 | 769 | if (!block) { |
|---|
| 789 | 770 | if (down_trylock(&efivars_lock)) |
|---|
| 790 | 771 | return -EBUSY; |
|---|
| 772 | + status = check_var_size_nonblocking(attributes, varsize); |
|---|
| 791 | 773 | } else { |
|---|
| 792 | 774 | if (down_interruptible(&efivars_lock)) |
|---|
| 793 | 775 | return -EINTR; |
|---|
| 776 | + status = check_var_size(attributes, varsize); |
|---|
| 794 | 777 | } |
|---|
| 795 | 778 | |
|---|
| 796 | | - status = check_var_size(attributes, size + ucs2_strsize(name, 1024)); |
|---|
| 797 | 779 | if (status != EFI_SUCCESS) { |
|---|
| 798 | 780 | up(&efivars_lock); |
|---|
| 799 | 781 | return -ENOSPC; |
|---|
| .. | .. |
|---|
| 1084 | 1066 | * entry on the list. It is safe for @func to remove entries in the |
|---|
| 1085 | 1067 | * list via efivar_entry_delete(). |
|---|
| 1086 | 1068 | * |
|---|
| 1087 | | - * You MUST call efivar_enter_iter_begin() before this function, and |
|---|
| 1069 | + * You MUST call efivar_entry_iter_begin() before this function, and |
|---|
| 1088 | 1070 | * efivar_entry_iter_end() afterwards. |
|---|
| 1089 | 1071 | * |
|---|
| 1090 | 1072 | * It is possible to begin iteration from an arbitrary entry within |
|---|
| .. | .. |
|---|
| 1171 | 1153 | EXPORT_SYMBOL_GPL(efivars_kobject); |
|---|
| 1172 | 1154 | |
|---|
| 1173 | 1155 | /** |
|---|
| 1174 | | - * efivar_run_worker - schedule the efivar worker thread |
|---|
| 1175 | | - */ |
|---|
| 1176 | | -void efivar_run_worker(void) |
|---|
| 1177 | | -{ |
|---|
| 1178 | | - if (efivar_wq_enabled) |
|---|
| 1179 | | - schedule_work(&efivar_work); |
|---|
| 1180 | | -} |
|---|
| 1181 | | -EXPORT_SYMBOL_GPL(efivar_run_worker); |
|---|
| 1182 | | - |
|---|
| 1183 | | -/** |
|---|
| 1184 | 1156 | * efivars_register - register an efivars |
|---|
| 1185 | 1157 | * @efivars: efivars to register |
|---|
| 1186 | 1158 | * @ops: efivars operations |
|---|
| .. | .. |
|---|
| 1242 | 1214 | return rv; |
|---|
| 1243 | 1215 | } |
|---|
| 1244 | 1216 | EXPORT_SYMBOL_GPL(efivars_unregister); |
|---|
| 1217 | + |
|---|
| 1218 | +int efivar_supports_writes(void) |
|---|
| 1219 | +{ |
|---|
| 1220 | + return __efivars && __efivars->ops->set_variable; |
|---|
| 1221 | +} |
|---|
| 1222 | +EXPORT_SYMBOL_GPL(efivar_supports_writes); |
|---|