LCOV - code coverage report
Current view: top level - drivers/firmware/efi - vars.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 367 0.5 %
Date: 2022-03-28 15:32:58 Functions: 1 29 3.4 %
Branches: 1 233 0.4 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0+
       2                 :            : /*
       3                 :            :  * Originally from efivars.c
       4                 :            :  *
       5                 :            :  * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
       6                 :            :  * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/capability.h>
      10                 :            : #include <linux/types.h>
      11                 :            : #include <linux/errno.h>
      12                 :            : #include <linux/init.h>
      13                 :            : #include <linux/mm.h>
      14                 :            : #include <linux/module.h>
      15                 :            : #include <linux/string.h>
      16                 :            : #include <linux/smp.h>
      17                 :            : #include <linux/efi.h>
      18                 :            : #include <linux/sysfs.h>
      19                 :            : #include <linux/device.h>
      20                 :            : #include <linux/slab.h>
      21                 :            : #include <linux/ctype.h>
      22                 :            : #include <linux/ucs2_string.h>
      23                 :            : 
      24                 :            : /* Private pointer to registered efivars */
      25                 :            : static struct efivars *__efivars;
      26                 :            : 
      27                 :            : /*
      28                 :            :  * efivars_lock protects three things:
      29                 :            :  * 1) efivarfs_list and efivars_sysfs_list
      30                 :            :  * 2) ->ops calls
      31                 :            :  * 3) (un)registration of __efivars
      32                 :            :  */
      33                 :            : static DEFINE_SEMAPHORE(efivars_lock);
      34                 :            : 
      35                 :            : static bool efivar_wq_enabled = true;
      36                 :            : DECLARE_WORK(efivar_work, NULL);
      37                 :            : EXPORT_SYMBOL_GPL(efivar_work);
      38                 :            : 
      39                 :            : static bool
      40                 :          0 : validate_device_path(efi_char16_t *var_name, int match, u8 *buffer,
      41                 :            :                      unsigned long len)
      42                 :            : {
      43                 :          0 :         struct efi_generic_dev_path *node;
      44                 :          0 :         int offset = 0;
      45                 :            : 
      46                 :          0 :         node = (struct efi_generic_dev_path *)buffer;
      47                 :            : 
      48         [ #  # ]:          0 :         if (len < sizeof(*node))
      49                 :            :                 return false;
      50                 :            : 
      51         [ #  # ]:          0 :         while (offset <= len - sizeof(*node) &&
      52         [ #  # ]:          0 :                node->length >= sizeof(*node) &&
      53         [ #  # ]:          0 :                 node->length <= len - offset) {
      54                 :          0 :                 offset += node->length;
      55                 :            : 
      56         [ #  # ]:          0 :                 if ((node->type == EFI_DEV_END_PATH ||
      57                 :          0 :                      node->type == EFI_DEV_END_PATH2) &&
      58         [ #  # ]:          0 :                     node->sub_type == EFI_DEV_END_ENTIRE)
      59                 :            :                         return true;
      60                 :            : 
      61                 :          0 :                 node = (struct efi_generic_dev_path *)(buffer + offset);
      62                 :            :         }
      63                 :            : 
      64                 :            :         /*
      65                 :            :          * If we're here then either node->length pointed past the end
      66                 :            :          * of the buffer or we reached the end of the buffer without
      67                 :            :          * finding a device path end node.
      68                 :            :          */
      69                 :            :         return false;
      70                 :            : }
      71                 :            : 
      72                 :            : static bool
      73                 :          0 : validate_boot_order(efi_char16_t *var_name, int match, u8 *buffer,
      74                 :            :                     unsigned long len)
      75                 :            : {
      76                 :            :         /* An array of 16-bit integers */
      77                 :          0 :         if ((len % 2) != 0)
      78                 :            :                 return false;
      79                 :            : 
      80                 :            :         return true;
      81                 :            : }
      82                 :            : 
      83                 :            : static bool
      84                 :          0 : validate_load_option(efi_char16_t *var_name, int match, u8 *buffer,
      85                 :            :                      unsigned long len)
      86                 :            : {
      87                 :          0 :         u16 filepathlength;
      88                 :          0 :         int i, desclength = 0, namelen;
      89                 :            : 
      90                 :          0 :         namelen = ucs2_strnlen(var_name, EFI_VAR_NAME_LEN);
      91                 :            : 
      92                 :            :         /* Either "Boot" or "Driver" followed by four digits of hex */
      93         [ #  # ]:          0 :         for (i = match; i < match+4; i++) {
      94   [ #  #  #  # ]:          0 :                 if (var_name[i] > 127 ||
      95                 :          0 :                     hex_to_bin(var_name[i] & 0xff) < 0)
      96                 :          0 :                         return true;
      97                 :            :         }
      98                 :            : 
      99                 :            :         /* Reject it if there's 4 digits of hex and then further content */
     100         [ #  # ]:          0 :         if (namelen > match + 4)
     101                 :            :                 return false;
     102                 :            : 
     103                 :            :         /* A valid entry must be at least 8 bytes */
     104         [ #  # ]:          0 :         if (len < 8)
     105                 :            :                 return false;
     106                 :            : 
     107                 :          0 :         filepathlength = buffer[4] | buffer[5] << 8;
     108                 :            : 
     109                 :            :         /*
     110                 :            :          * There's no stored length for the description, so it has to be
     111                 :            :          * found by hand
     112                 :            :          */
     113                 :          0 :         desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
     114                 :            : 
     115                 :            :         /* Each boot entry must have a descriptor */
     116         [ #  # ]:          0 :         if (!desclength)
     117                 :            :                 return false;
     118                 :            : 
     119                 :            :         /*
     120                 :            :          * If the sum of the length of the description, the claimed filepath
     121                 :            :          * length and the original header are greater than the length of the
     122                 :            :          * variable, it's malformed
     123                 :            :          */
     124         [ #  # ]:          0 :         if ((desclength + filepathlength + 6) > len)
     125                 :            :                 return false;
     126                 :            : 
     127                 :            :         /*
     128                 :            :          * And, finally, check the filepath
     129                 :            :          */
     130                 :          0 :         return validate_device_path(var_name, match, buffer + desclength + 6,
     131                 :            :                                     filepathlength);
     132                 :            : }
     133                 :            : 
     134                 :            : static bool
     135                 :          0 : validate_uint16(efi_char16_t *var_name, int match, u8 *buffer,
     136                 :            :                 unsigned long len)
     137                 :            : {
     138                 :            :         /* A single 16-bit integer */
     139         [ #  # ]:          0 :         if (len != 2)
     140                 :          0 :                 return false;
     141                 :            : 
     142                 :            :         return true;
     143                 :            : }
     144                 :            : 
     145                 :            : static bool
     146                 :          0 : validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
     147                 :            :                       unsigned long len)
     148                 :            : {
     149                 :          0 :         int i;
     150                 :            : 
     151         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     152         [ #  # ]:          0 :                 if (buffer[i] > 127)
     153                 :            :                         return false;
     154                 :            : 
     155         [ #  # ]:          0 :                 if (buffer[i] == 0)
     156                 :            :                         return true;
     157                 :            :         }
     158                 :            : 
     159                 :            :         return false;
     160                 :            : }
     161                 :            : 
     162                 :            : struct variable_validate {
     163                 :            :         efi_guid_t vendor;
     164                 :            :         char *name;
     165                 :            :         bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
     166                 :            :                          unsigned long len);
     167                 :            : };
     168                 :            : 
     169                 :            : /*
     170                 :            :  * This is the list of variables we need to validate, as well as the
     171                 :            :  * whitelist for what we think is safe not to default to immutable.
     172                 :            :  *
     173                 :            :  * If it has a validate() method that's not NULL, it'll go into the
     174                 :            :  * validation routine.  If not, it is assumed valid, but still used for
     175                 :            :  * whitelisting.
     176                 :            :  *
     177                 :            :  * Note that it's sorted by {vendor,name}, but globbed names must come after
     178                 :            :  * any other name with the same prefix.
     179                 :            :  */
     180                 :            : static const struct variable_validate variable_validate[] = {
     181                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
     182                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
     183                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
     184                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
     185                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
     186                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
     187                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
     188                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
     189                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
     190                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
     191                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
     192                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
     193                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
     194                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
     195                 :            :         { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
     196                 :            :         { LINUX_EFI_CRASH_GUID, "*", NULL },
     197                 :            :         { NULL_GUID, "", NULL },
     198                 :            : };
     199                 :            : 
     200                 :            : /*
     201                 :            :  * Check if @var_name matches the pattern given in @match_name.
     202                 :            :  *
     203                 :            :  * @var_name: an array of @len non-NUL characters.
     204                 :            :  * @match_name: a NUL-terminated pattern string, optionally ending in "*". A
     205                 :            :  *              final "*" character matches any trailing characters @var_name,
     206                 :            :  *              including the case when there are none left in @var_name.
     207                 :            :  * @match: on output, the number of non-wildcard characters in @match_name
     208                 :            :  *         that @var_name matches, regardless of the return value.
     209                 :            :  * @return: whether @var_name fully matches @match_name.
     210                 :            :  */
     211                 :            : static bool
     212                 :            : variable_matches(const char *var_name, size_t len, const char *match_name,
     213                 :            :                  int *match)
     214                 :            : {
     215                 :          0 :         for (*match = 0; ; (*match)++) {
     216                 :          0 :                 char c = match_name[*match];
     217                 :            : 
     218   [ #  #  #  #  :          0 :                 switch (c) {
                   #  # ]
     219                 :            :                 case '*':
     220                 :            :                         /* Wildcard in @match_name means we've matched. */
     221                 :            :                         return true;
     222                 :            : 
     223                 :          0 :                 case '\0':
     224                 :            :                         /* @match_name has ended. Has @var_name too? */
     225                 :          0 :                         return (*match == len);
     226                 :            : 
     227                 :          0 :                 default:
     228                 :            :                         /*
     229                 :            :                          * We've reached a non-wildcard char in @match_name.
     230                 :            :                          * Continue only if there's an identical character in
     231                 :            :                          * @var_name.
     232                 :            :                          */
     233   [ #  #  #  #  :          0 :                         if (*match < len && c == var_name[*match])
             #  #  #  # ]
     234                 :          0 :                                 continue;
     235                 :            :                         return false;
     236                 :            :                 }
     237                 :            :         }
     238                 :            : }
     239                 :            : 
     240                 :            : bool
     241                 :          0 : efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
     242                 :            :                 unsigned long data_size)
     243                 :            : {
     244                 :          0 :         int i;
     245                 :          0 :         unsigned long utf8_size;
     246                 :          0 :         u8 *utf8_name;
     247                 :            : 
     248                 :          0 :         utf8_size = ucs2_utf8size(var_name);
     249         [ #  # ]:          0 :         utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
     250         [ #  # ]:          0 :         if (!utf8_name)
     251                 :            :                 return false;
     252                 :            : 
     253                 :          0 :         ucs2_as_utf8(utf8_name, var_name, utf8_size);
     254                 :          0 :         utf8_name[utf8_size] = '\0';
     255                 :            : 
     256         [ #  # ]:          0 :         for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
     257                 :          0 :                 const char *name = variable_validate[i].name;
     258                 :          0 :                 int match = 0;
     259                 :            : 
     260         [ #  # ]:          0 :                 if (efi_guidcmp(vendor, variable_validate[i].vendor))
     261                 :          0 :                         continue;
     262                 :            : 
     263         [ #  # ]:          0 :                 if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
     264         [ #  # ]:          0 :                         if (variable_validate[i].validate == NULL)
     265                 :            :                                 break;
     266                 :          0 :                         kfree(utf8_name);
     267                 :          0 :                         return variable_validate[i].validate(var_name, match,
     268                 :            :                                                              data, data_size);
     269                 :            :                 }
     270                 :            :         }
     271                 :          0 :         kfree(utf8_name);
     272                 :          0 :         return true;
     273                 :            : }
     274                 :            : EXPORT_SYMBOL_GPL(efivar_validate);
     275                 :            : 
     276                 :            : bool
     277                 :          0 : efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
     278                 :            :                              size_t len)
     279                 :            : {
     280                 :          0 :         int i;
     281                 :          0 :         bool found = false;
     282                 :          0 :         int match = 0;
     283                 :            : 
     284                 :            :         /*
     285                 :            :          * Check if our variable is in the validated variables list
     286                 :            :          */
     287         [ #  # ]:          0 :         for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
     288         [ #  # ]:          0 :                 if (efi_guidcmp(variable_validate[i].vendor, vendor))
     289                 :          0 :                         continue;
     290                 :            : 
     291         [ #  # ]:          0 :                 if (variable_matches(var_name, len,
     292                 :            :                                      variable_validate[i].name, &match)) {
     293                 :            :                         found = true;
     294                 :            :                         break;
     295                 :            :                 }
     296                 :            :         }
     297                 :            : 
     298                 :            :         /*
     299                 :            :          * If it's in our list, it is removable.
     300                 :            :          */
     301                 :          0 :         return found;
     302                 :            : }
     303                 :            : EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
     304                 :            : 
     305                 :            : static efi_status_t
     306                 :          0 : check_var_size(u32 attributes, unsigned long size)
     307                 :            : {
     308                 :          0 :         const struct efivar_operations *fops;
     309                 :            : 
     310                 :          0 :         if (!__efivars)
     311                 :            :                 return EFI_UNSUPPORTED;
     312                 :            : 
     313                 :          0 :         fops = __efivars->ops;
     314                 :            : 
     315   [ #  #  #  #  :          0 :         if (!fops->query_variable_store)
                   #  # ]
     316                 :            :                 return EFI_UNSUPPORTED;
     317                 :            : 
     318                 :          0 :         return fops->query_variable_store(attributes, size, false);
     319                 :            : }
     320                 :            : 
     321                 :            : static efi_status_t
     322                 :          0 : check_var_size_nonblocking(u32 attributes, unsigned long size)
     323                 :            : {
     324                 :          0 :         const struct efivar_operations *fops;
     325                 :            : 
     326                 :          0 :         if (!__efivars)
     327                 :            :                 return EFI_UNSUPPORTED;
     328                 :            : 
     329                 :          0 :         fops = __efivars->ops;
     330                 :            : 
     331         [ #  # ]:          0 :         if (!fops->query_variable_store)
     332                 :            :                 return EFI_UNSUPPORTED;
     333                 :            : 
     334                 :          0 :         return fops->query_variable_store(attributes, size, true);
     335                 :            : }
     336                 :            : 
     337                 :            : static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
     338                 :            :                                 struct list_head *head)
     339                 :            : {
     340                 :            :         struct efivar_entry *entry, *n;
     341                 :            :         unsigned long strsize1, strsize2;
     342                 :            :         bool found = false;
     343                 :            : 
     344                 :            :         strsize1 = ucs2_strsize(variable_name, 1024);
     345                 :            :         list_for_each_entry_safe(entry, n, head, list) {
     346                 :            :                 strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
     347                 :            :                 if (strsize1 == strsize2 &&
     348                 :            :                         !memcmp(variable_name, &(entry->var.VariableName),
     349                 :            :                                 strsize2) &&
     350                 :            :                         !efi_guidcmp(entry->var.VendorGuid,
     351                 :            :                                 *vendor)) {
     352                 :            :                         found = true;
     353                 :            :                         break;
     354                 :            :                 }
     355                 :            :         }
     356                 :            :         return found;
     357                 :            : }
     358                 :            : 
     359                 :            : /*
     360                 :            :  * Returns the size of variable_name, in bytes, including the
     361                 :            :  * terminating NULL character, or variable_name_size if no NULL
     362                 :            :  * character is found among the first variable_name_size bytes.
     363                 :            :  */
     364                 :          0 : static unsigned long var_name_strnsize(efi_char16_t *variable_name,
     365                 :            :                                        unsigned long variable_name_size)
     366                 :            : {
     367                 :          0 :         unsigned long len;
     368                 :          0 :         efi_char16_t c;
     369                 :            : 
     370                 :            :         /*
     371                 :            :          * The variable name is, by definition, a NULL-terminated
     372                 :            :          * string, so make absolutely sure that variable_name_size is
     373                 :            :          * the value we expect it to be. If not, return the real size.
     374                 :            :          */
     375         [ #  # ]:          0 :         for (len = 2; len <= variable_name_size; len += sizeof(c)) {
     376                 :          0 :                 c = variable_name[(len / sizeof(c)) - 1];
     377         [ #  # ]:          0 :                 if (!c)
     378                 :            :                         break;
     379                 :            :         }
     380                 :            : 
     381                 :          0 :         return min(len, variable_name_size);
     382                 :            : }
     383                 :            : 
     384                 :            : /*
     385                 :            :  * Print a warning when duplicate EFI variables are encountered and
     386                 :            :  * disable the sysfs workqueue since the firmware is buggy.
     387                 :            :  */
     388                 :          0 : static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
     389                 :            :                              unsigned long len16)
     390                 :            : {
     391                 :          0 :         size_t i, len8 = len16 / sizeof(efi_char16_t);
     392                 :          0 :         char *str8;
     393                 :            : 
     394                 :            :         /*
     395                 :            :          * Disable the workqueue since the algorithm it uses for
     396                 :            :          * detecting new variables won't work with this buggy
     397                 :            :          * implementation of GetNextVariableName().
     398                 :            :          */
     399                 :          0 :         efivar_wq_enabled = false;
     400                 :            : 
     401                 :          0 :         str8 = kzalloc(len8, GFP_KERNEL);
     402         [ #  # ]:          0 :         if (!str8)
     403                 :            :                 return;
     404                 :            : 
     405         [ #  # ]:          0 :         for (i = 0; i < len8; i++)
     406                 :          0 :                 str8[i] = str16[i];
     407                 :            : 
     408                 :          0 :         printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
     409                 :            :                str8, vendor_guid);
     410                 :          0 :         kfree(str8);
     411                 :            : }
     412                 :            : 
     413                 :            : /**
     414                 :            :  * efivar_init - build the initial list of EFI variables
     415                 :            :  * @func: callback function to invoke for every variable
     416                 :            :  * @data: function-specific data to pass to @func
     417                 :            :  * @atomic: do we need to execute the @func-loop atomically?
     418                 :            :  * @duplicates: error if we encounter duplicates on @head?
     419                 :            :  * @head: initialised head of variable list
     420                 :            :  *
     421                 :            :  * Get every EFI variable from the firmware and invoke @func. @func
     422                 :            :  * should call efivar_entry_add() to build the list of variables.
     423                 :            :  *
     424                 :            :  * Returns 0 on success, or a kernel error code on failure.
     425                 :            :  */
     426                 :          0 : int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
     427                 :            :                 void *data, bool duplicates, struct list_head *head)
     428                 :            : {
     429                 :          0 :         const struct efivar_operations *ops;
     430                 :          0 :         unsigned long variable_name_size = 1024;
     431                 :          0 :         efi_char16_t *variable_name;
     432                 :          0 :         efi_status_t status;
     433                 :          0 :         efi_guid_t vendor_guid;
     434                 :          0 :         int err = 0;
     435                 :            : 
     436         [ #  # ]:          0 :         if (!__efivars)
     437                 :            :                 return -EFAULT;
     438                 :            : 
     439                 :          0 :         ops = __efivars->ops;
     440                 :            : 
     441                 :          0 :         variable_name = kzalloc(variable_name_size, GFP_KERNEL);
     442         [ #  # ]:          0 :         if (!variable_name) {
     443                 :          0 :                 printk(KERN_ERR "efivars: Memory allocation failed.\n");
     444                 :          0 :                 return -ENOMEM;
     445                 :            :         }
     446                 :            : 
     447         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock)) {
     448                 :          0 :                 err = -EINTR;
     449                 :          0 :                 goto free;
     450                 :            :         }
     451                 :            : 
     452                 :            :         /*
     453                 :            :          * Per EFI spec, the maximum storage allocated for both
     454                 :            :          * the variable name and variable data is 1024 bytes.
     455                 :            :          */
     456                 :            : 
     457                 :          0 :         do {
     458                 :          0 :                 variable_name_size = 1024;
     459                 :            : 
     460                 :          0 :                 status = ops->get_next_variable(&variable_name_size,
     461                 :            :                                                 variable_name,
     462                 :            :                                                 &vendor_guid);
     463      [ #  #  # ]:          0 :                 switch (status) {
     464                 :          0 :                 case EFI_SUCCESS:
     465         [ #  # ]:          0 :                         if (duplicates)
     466                 :          0 :                                 up(&efivars_lock);
     467                 :            : 
     468                 :          0 :                         variable_name_size = var_name_strnsize(variable_name,
     469                 :            :                                                                variable_name_size);
     470                 :            : 
     471                 :            :                         /*
     472                 :            :                          * Some firmware implementations return the
     473                 :            :                          * same variable name on multiple calls to
     474                 :            :                          * get_next_variable(). Terminate the loop
     475                 :            :                          * immediately as there is no guarantee that
     476                 :            :                          * we'll ever see a different variable name,
     477                 :            :                          * and may end up looping here forever.
     478                 :            :                          */
     479   [ #  #  #  # ]:          0 :                         if (duplicates &&
     480                 :          0 :                             variable_is_present(variable_name, &vendor_guid,
     481                 :            :                                                 head)) {
     482                 :          0 :                                 dup_variable_bug(variable_name, &vendor_guid,
     483                 :            :                                                  variable_name_size);
     484                 :          0 :                                 status = EFI_NOT_FOUND;
     485                 :            :                         } else {
     486                 :          0 :                                 err = func(variable_name, vendor_guid,
     487                 :            :                                            variable_name_size, data);
     488         [ #  # ]:          0 :                                 if (err)
     489                 :          0 :                                         status = EFI_NOT_FOUND;
     490                 :            :                         }
     491                 :            : 
     492         [ #  # ]:          0 :                         if (duplicates) {
     493         [ #  # ]:          0 :                                 if (down_interruptible(&efivars_lock)) {
     494                 :          0 :                                         err = -EINTR;
     495                 :          0 :                                         goto free;
     496                 :            :                                 }
     497                 :            :                         }
     498                 :            : 
     499                 :            :                         break;
     500                 :            :                 case EFI_NOT_FOUND:
     501                 :            :                         break;
     502                 :          0 :                 default:
     503                 :          0 :                         printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
     504                 :            :                                 status);
     505                 :          0 :                         status = EFI_NOT_FOUND;
     506                 :          0 :                         break;
     507                 :            :                 }
     508                 :            : 
     509         [ #  # ]:          0 :         } while (status != EFI_NOT_FOUND);
     510                 :            : 
     511                 :          0 :         up(&efivars_lock);
     512                 :          0 : free:
     513                 :          0 :         kfree(variable_name);
     514                 :            : 
     515                 :          0 :         return err;
     516                 :            : }
     517                 :            : EXPORT_SYMBOL_GPL(efivar_init);
     518                 :            : 
     519                 :            : /**
     520                 :            :  * efivar_entry_add - add entry to variable list
     521                 :            :  * @entry: entry to add to list
     522                 :            :  * @head: list head
     523                 :            :  *
     524                 :            :  * Returns 0 on success, or a kernel error code on failure.
     525                 :            :  */
     526                 :          0 : int efivar_entry_add(struct efivar_entry *entry, struct list_head *head)
     527                 :            : {
     528         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     529                 :            :                 return -EINTR;
     530                 :          0 :         list_add(&entry->list, head);
     531                 :          0 :         up(&efivars_lock);
     532                 :            : 
     533                 :          0 :         return 0;
     534                 :            : }
     535                 :            : EXPORT_SYMBOL_GPL(efivar_entry_add);
     536                 :            : 
     537                 :            : /**
     538                 :            :  * efivar_entry_remove - remove entry from variable list
     539                 :            :  * @entry: entry to remove from list
     540                 :            :  *
     541                 :            :  * Returns 0 on success, or a kernel error code on failure.
     542                 :            :  */
     543                 :          0 : int efivar_entry_remove(struct efivar_entry *entry)
     544                 :            : {
     545         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     546                 :            :                 return -EINTR;
     547                 :          0 :         list_del(&entry->list);
     548                 :          0 :         up(&efivars_lock);
     549                 :            : 
     550                 :          0 :         return 0;
     551                 :            : }
     552                 :            : EXPORT_SYMBOL_GPL(efivar_entry_remove);
     553                 :            : 
     554                 :            : /*
     555                 :            :  * efivar_entry_list_del_unlock - remove entry from variable list
     556                 :            :  * @entry: entry to remove
     557                 :            :  *
     558                 :            :  * Remove @entry from the variable list and release the list lock.
     559                 :            :  *
     560                 :            :  * NOTE: slightly weird locking semantics here - we expect to be
     561                 :            :  * called with the efivars lock already held, and we release it before
     562                 :            :  * returning. This is because this function is usually called after
     563                 :            :  * set_variable() while the lock is still held.
     564                 :            :  */
     565                 :          0 : static void efivar_entry_list_del_unlock(struct efivar_entry *entry)
     566                 :            : {
     567                 :          0 :         list_del(&entry->list);
     568                 :          0 :         up(&efivars_lock);
     569                 :          0 : }
     570                 :            : 
     571                 :            : /**
     572                 :            :  * __efivar_entry_delete - delete an EFI variable
     573                 :            :  * @entry: entry containing EFI variable to delete
     574                 :            :  *
     575                 :            :  * Delete the variable from the firmware but leave @entry on the
     576                 :            :  * variable list.
     577                 :            :  *
     578                 :            :  * This function differs from efivar_entry_delete() because it does
     579                 :            :  * not remove @entry from the variable list. Also, it is safe to be
     580                 :            :  * called from within a efivar_entry_iter_begin() and
     581                 :            :  * efivar_entry_iter_end() region, unlike efivar_entry_delete().
     582                 :            :  *
     583                 :            :  * Returns 0 on success, or a converted EFI status code if
     584                 :            :  * set_variable() fails.
     585                 :            :  */
     586                 :          0 : int __efivar_entry_delete(struct efivar_entry *entry)
     587                 :            : {
     588                 :          0 :         efi_status_t status;
     589                 :            : 
     590         [ #  # ]:          0 :         if (!__efivars)
     591                 :            :                 return -EINVAL;
     592                 :            : 
     593                 :          0 :         status = __efivars->ops->set_variable(entry->var.VariableName,
     594                 :            :                                               &entry->var.VendorGuid,
     595                 :            :                                               0, 0, NULL);
     596                 :            : 
     597                 :          0 :         return efi_status_to_err(status);
     598                 :            : }
     599                 :            : EXPORT_SYMBOL_GPL(__efivar_entry_delete);
     600                 :            : 
     601                 :            : /**
     602                 :            :  * efivar_entry_delete - delete variable and remove entry from list
     603                 :            :  * @entry: entry containing variable to delete
     604                 :            :  *
     605                 :            :  * Delete the variable from the firmware and remove @entry from the
     606                 :            :  * variable list. It is the caller's responsibility to free @entry
     607                 :            :  * once we return.
     608                 :            :  *
     609                 :            :  * Returns 0 on success, -EINTR if we can't grab the semaphore,
     610                 :            :  * converted EFI status code if set_variable() fails.
     611                 :            :  */
     612                 :          0 : int efivar_entry_delete(struct efivar_entry *entry)
     613                 :            : {
     614                 :          0 :         const struct efivar_operations *ops;
     615                 :          0 :         efi_status_t status;
     616                 :            : 
     617         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     618                 :            :                 return -EINTR;
     619                 :            : 
     620         [ #  # ]:          0 :         if (!__efivars) {
     621                 :          0 :                 up(&efivars_lock);
     622                 :          0 :                 return -EINVAL;
     623                 :            :         }
     624                 :          0 :         ops = __efivars->ops;
     625                 :          0 :         status = ops->set_variable(entry->var.VariableName,
     626                 :            :                                    &entry->var.VendorGuid,
     627                 :            :                                    0, 0, NULL);
     628         [ #  # ]:          0 :         if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND)) {
     629                 :          0 :                 up(&efivars_lock);
     630                 :          0 :                 return efi_status_to_err(status);
     631                 :            :         }
     632                 :            : 
     633                 :          0 :         efivar_entry_list_del_unlock(entry);
     634                 :          0 :         return 0;
     635                 :            : }
     636                 :            : EXPORT_SYMBOL_GPL(efivar_entry_delete);
     637                 :            : 
     638                 :            : /**
     639                 :            :  * efivar_entry_set - call set_variable()
     640                 :            :  * @entry: entry containing the EFI variable to write
     641                 :            :  * @attributes: variable attributes
     642                 :            :  * @size: size of @data buffer
     643                 :            :  * @data: buffer containing variable data
     644                 :            :  * @head: head of variable list
     645                 :            :  *
     646                 :            :  * Calls set_variable() for an EFI variable. If creating a new EFI
     647                 :            :  * variable, this function is usually followed by efivar_entry_add().
     648                 :            :  *
     649                 :            :  * Before writing the variable, the remaining EFI variable storage
     650                 :            :  * space is checked to ensure there is enough room available.
     651                 :            :  *
     652                 :            :  * If @head is not NULL a lookup is performed to determine whether
     653                 :            :  * the entry is already on the list.
     654                 :            :  *
     655                 :            :  * Returns 0 on success, -EINTR if we can't grab the semaphore,
     656                 :            :  * -EEXIST if a lookup is performed and the entry already exists on
     657                 :            :  * the list, or a converted EFI status code if set_variable() fails.
     658                 :            :  */
     659                 :          0 : int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
     660                 :            :                      unsigned long size, void *data, struct list_head *head)
     661                 :            : {
     662                 :          0 :         const struct efivar_operations *ops;
     663                 :          0 :         efi_status_t status;
     664                 :          0 :         efi_char16_t *name = entry->var.VariableName;
     665                 :          0 :         efi_guid_t vendor = entry->var.VendorGuid;
     666                 :            : 
     667         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     668                 :            :                 return -EINTR;
     669                 :            : 
     670         [ #  # ]:          0 :         if (!__efivars) {
     671                 :          0 :                 up(&efivars_lock);
     672                 :          0 :                 return -EINVAL;
     673                 :            :         }
     674                 :          0 :         ops = __efivars->ops;
     675   [ #  #  #  # ]:          0 :         if (head && efivar_entry_find(name, vendor, head, false)) {
     676                 :          0 :                 up(&efivars_lock);
     677                 :          0 :                 return -EEXIST;
     678                 :            :         }
     679                 :            : 
     680         [ #  # ]:          0 :         status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
     681         [ #  # ]:          0 :         if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
     682                 :          0 :                 status = ops->set_variable(name, &vendor,
     683                 :            :                                            attributes, size, data);
     684                 :            : 
     685                 :          0 :         up(&efivars_lock);
     686                 :            : 
     687                 :          0 :         return efi_status_to_err(status);
     688                 :            : 
     689                 :            : }
     690                 :            : EXPORT_SYMBOL_GPL(efivar_entry_set);
     691                 :            : 
     692                 :            : /*
     693                 :            :  * efivar_entry_set_nonblocking - call set_variable_nonblocking()
     694                 :            :  *
     695                 :            :  * This function is guaranteed to not block and is suitable for calling
     696                 :            :  * from crash/panic handlers.
     697                 :            :  *
     698                 :            :  * Crucially, this function will not block if it cannot acquire
     699                 :            :  * efivars_lock. Instead, it returns -EBUSY.
     700                 :            :  */
     701                 :            : static int
     702                 :          0 : efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
     703                 :            :                              u32 attributes, unsigned long size, void *data)
     704                 :            : {
     705                 :          0 :         const struct efivar_operations *ops;
     706                 :          0 :         efi_status_t status;
     707                 :            : 
     708         [ #  # ]:          0 :         if (down_trylock(&efivars_lock))
     709                 :            :                 return -EBUSY;
     710                 :            : 
     711         [ #  # ]:          0 :         if (!__efivars) {
     712                 :          0 :                 up(&efivars_lock);
     713                 :          0 :                 return -EINVAL;
     714                 :            :         }
     715                 :            : 
     716         [ #  # ]:          0 :         status = check_var_size_nonblocking(attributes,
     717                 :          0 :                                             size + ucs2_strsize(name, 1024));
     718         [ #  # ]:          0 :         if (status != EFI_SUCCESS) {
     719                 :          0 :                 up(&efivars_lock);
     720                 :          0 :                 return -ENOSPC;
     721                 :            :         }
     722                 :            : 
     723                 :          0 :         ops = __efivars->ops;
     724                 :          0 :         status = ops->set_variable_nonblocking(name, &vendor, attributes,
     725                 :            :                                                size, data);
     726                 :            : 
     727                 :          0 :         up(&efivars_lock);
     728                 :          0 :         return efi_status_to_err(status);
     729                 :            : }
     730                 :            : 
     731                 :            : /**
     732                 :            :  * efivar_entry_set_safe - call set_variable() if enough space in firmware
     733                 :            :  * @name: buffer containing the variable name
     734                 :            :  * @vendor: variable vendor guid
     735                 :            :  * @attributes: variable attributes
     736                 :            :  * @block: can we block in this context?
     737                 :            :  * @size: size of @data buffer
     738                 :            :  * @data: buffer containing variable data
     739                 :            :  *
     740                 :            :  * Ensures there is enough free storage in the firmware for this variable, and
     741                 :            :  * if so, calls set_variable(). If creating a new EFI variable, this function
     742                 :            :  * is usually followed by efivar_entry_add().
     743                 :            :  *
     744                 :            :  * Returns 0 on success, -ENOSPC if the firmware does not have enough
     745                 :            :  * space for set_variable() to succeed, or a converted EFI status code
     746                 :            :  * if set_variable() fails.
     747                 :            :  */
     748                 :          0 : int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
     749                 :            :                           bool block, unsigned long size, void *data)
     750                 :            : {
     751                 :          0 :         const struct efivar_operations *ops;
     752                 :          0 :         efi_status_t status;
     753                 :            : 
     754         [ #  # ]:          0 :         if (!__efivars)
     755                 :            :                 return -EINVAL;
     756                 :            : 
     757                 :          0 :         ops = __efivars->ops;
     758         [ #  # ]:          0 :         if (!ops->query_variable_store)
     759                 :            :                 return -ENOSYS;
     760                 :            : 
     761                 :            :         /*
     762                 :            :          * If the EFI variable backend provides a non-blocking
     763                 :            :          * ->set_variable() operation and we're in a context where we
     764                 :            :          * cannot block, then we need to use it to avoid live-locks,
     765                 :            :          * since the implication is that the regular ->set_variable()
     766                 :            :          * will block.
     767                 :            :          *
     768                 :            :          * If no ->set_variable_nonblocking() is provided then
     769                 :            :          * ->set_variable() is assumed to be non-blocking.
     770                 :            :          */
     771   [ #  #  #  # ]:          0 :         if (!block && ops->set_variable_nonblocking)
     772                 :          0 :                 return efivar_entry_set_nonblocking(name, vendor, attributes,
     773                 :            :                                                     size, data);
     774                 :            : 
     775         [ #  # ]:          0 :         if (!block) {
     776         [ #  # ]:          0 :                 if (down_trylock(&efivars_lock))
     777                 :            :                         return -EBUSY;
     778                 :            :         } else {
     779         [ #  # ]:          0 :                 if (down_interruptible(&efivars_lock))
     780                 :            :                         return -EINTR;
     781                 :            :         }
     782                 :            : 
     783         [ #  # ]:          0 :         status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
     784         [ #  # ]:          0 :         if (status != EFI_SUCCESS) {
     785                 :          0 :                 up(&efivars_lock);
     786                 :          0 :                 return -ENOSPC;
     787                 :            :         }
     788                 :            : 
     789                 :          0 :         status = ops->set_variable(name, &vendor, attributes, size, data);
     790                 :            : 
     791                 :          0 :         up(&efivars_lock);
     792                 :            : 
     793                 :          0 :         return efi_status_to_err(status);
     794                 :            : }
     795                 :            : EXPORT_SYMBOL_GPL(efivar_entry_set_safe);
     796                 :            : 
     797                 :            : /**
     798                 :            :  * efivar_entry_find - search for an entry
     799                 :            :  * @name: the EFI variable name
     800                 :            :  * @guid: the EFI variable vendor's guid
     801                 :            :  * @head: head of the variable list
     802                 :            :  * @remove: should we remove the entry from the list?
     803                 :            :  *
     804                 :            :  * Search for an entry on the variable list that has the EFI variable
     805                 :            :  * name @name and vendor guid @guid. If an entry is found on the list
     806                 :            :  * and @remove is true, the entry is removed from the list.
     807                 :            :  *
     808                 :            :  * The caller MUST call efivar_entry_iter_begin() and
     809                 :            :  * efivar_entry_iter_end() before and after the invocation of this
     810                 :            :  * function, respectively.
     811                 :            :  *
     812                 :            :  * Returns the entry if found on the list, %NULL otherwise.
     813                 :            :  */
     814                 :          0 : struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
     815                 :            :                                        struct list_head *head, bool remove)
     816                 :            : {
     817                 :          0 :         struct efivar_entry *entry, *n;
     818                 :          0 :         int strsize1, strsize2;
     819                 :          0 :         bool found = false;
     820                 :            : 
     821         [ #  # ]:          0 :         list_for_each_entry_safe(entry, n, head, list) {
     822                 :          0 :                 strsize1 = ucs2_strsize(name, 1024);
     823                 :          0 :                 strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
     824         [ #  # ]:          0 :                 if (strsize1 == strsize2 &&
     825         [ #  # ]:          0 :                     !memcmp(name, &(entry->var.VariableName), strsize1) &&
     826         [ #  # ]:          0 :                     !efi_guidcmp(guid, entry->var.VendorGuid)) {
     827                 :            :                         found = true;
     828                 :            :                         break;
     829                 :            :                 }
     830                 :            :         }
     831                 :            : 
     832         [ #  # ]:          0 :         if (!found)
     833                 :            :                 return NULL;
     834                 :            : 
     835         [ #  # ]:          0 :         if (remove) {
     836         [ #  # ]:          0 :                 if (entry->scanning) {
     837                 :            :                         /*
     838                 :            :                          * The entry will be deleted
     839                 :            :                          * after scanning is completed.
     840                 :            :                          */
     841                 :          0 :                         entry->deleting = true;
     842                 :            :                 } else
     843                 :          0 :                         list_del(&entry->list);
     844                 :            :         }
     845                 :            : 
     846                 :            :         return entry;
     847                 :            : }
     848                 :            : EXPORT_SYMBOL_GPL(efivar_entry_find);
     849                 :            : 
     850                 :            : /**
     851                 :            :  * efivar_entry_size - obtain the size of a variable
     852                 :            :  * @entry: entry for this variable
     853                 :            :  * @size: location to store the variable's size
     854                 :            :  */
     855                 :          0 : int efivar_entry_size(struct efivar_entry *entry, unsigned long *size)
     856                 :            : {
     857                 :          0 :         const struct efivar_operations *ops;
     858                 :          0 :         efi_status_t status;
     859                 :            : 
     860                 :          0 :         *size = 0;
     861                 :            : 
     862         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     863                 :            :                 return -EINTR;
     864         [ #  # ]:          0 :         if (!__efivars) {
     865                 :          0 :                 up(&efivars_lock);
     866                 :          0 :                 return -EINVAL;
     867                 :            :         }
     868                 :          0 :         ops = __efivars->ops;
     869                 :          0 :         status = ops->get_variable(entry->var.VariableName,
     870                 :            :                                    &entry->var.VendorGuid, NULL, size, NULL);
     871                 :          0 :         up(&efivars_lock);
     872                 :            : 
     873         [ #  # ]:          0 :         if (status != EFI_BUFFER_TOO_SMALL)
     874                 :          0 :                 return efi_status_to_err(status);
     875                 :            : 
     876                 :            :         return 0;
     877                 :            : }
     878                 :            : EXPORT_SYMBOL_GPL(efivar_entry_size);
     879                 :            : 
     880                 :            : /**
     881                 :            :  * __efivar_entry_get - call get_variable()
     882                 :            :  * @entry: read data for this variable
     883                 :            :  * @attributes: variable attributes
     884                 :            :  * @size: size of @data buffer
     885                 :            :  * @data: buffer to store variable data
     886                 :            :  *
     887                 :            :  * The caller MUST call efivar_entry_iter_begin() and
     888                 :            :  * efivar_entry_iter_end() before and after the invocation of this
     889                 :            :  * function, respectively.
     890                 :            :  */
     891                 :          0 : int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
     892                 :            :                        unsigned long *size, void *data)
     893                 :            : {
     894                 :          0 :         efi_status_t status;
     895                 :            : 
     896         [ #  # ]:          0 :         if (!__efivars)
     897                 :            :                 return -EINVAL;
     898                 :            : 
     899                 :          0 :         status = __efivars->ops->get_variable(entry->var.VariableName,
     900                 :            :                                               &entry->var.VendorGuid,
     901                 :            :                                               attributes, size, data);
     902                 :            : 
     903                 :          0 :         return efi_status_to_err(status);
     904                 :            : }
     905                 :            : EXPORT_SYMBOL_GPL(__efivar_entry_get);
     906                 :            : 
     907                 :            : /**
     908                 :            :  * efivar_entry_get - call get_variable()
     909                 :            :  * @entry: read data for this variable
     910                 :            :  * @attributes: variable attributes
     911                 :            :  * @size: size of @data buffer
     912                 :            :  * @data: buffer to store variable data
     913                 :            :  */
     914                 :          0 : int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
     915                 :            :                      unsigned long *size, void *data)
     916                 :            : {
     917                 :          0 :         efi_status_t status;
     918                 :            : 
     919         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     920                 :            :                 return -EINTR;
     921                 :            : 
     922         [ #  # ]:          0 :         if (!__efivars) {
     923                 :          0 :                 up(&efivars_lock);
     924                 :          0 :                 return -EINVAL;
     925                 :            :         }
     926                 :            : 
     927                 :          0 :         status = __efivars->ops->get_variable(entry->var.VariableName,
     928                 :            :                                               &entry->var.VendorGuid,
     929                 :            :                                               attributes, size, data);
     930                 :          0 :         up(&efivars_lock);
     931                 :            : 
     932                 :          0 :         return efi_status_to_err(status);
     933                 :            : }
     934                 :            : EXPORT_SYMBOL_GPL(efivar_entry_get);
     935                 :            : 
     936                 :            : /**
     937                 :            :  * efivar_entry_set_get_size - call set_variable() and get new size (atomic)
     938                 :            :  * @entry: entry containing variable to set and get
     939                 :            :  * @attributes: attributes of variable to be written
     940                 :            :  * @size: size of data buffer
     941                 :            :  * @data: buffer containing data to write
     942                 :            :  * @set: did the set_variable() call succeed?
     943                 :            :  *
     944                 :            :  * This is a pretty special (complex) function. See efivarfs_file_write().
     945                 :            :  *
     946                 :            :  * Atomically call set_variable() for @entry and if the call is
     947                 :            :  * successful, return the new size of the variable from get_variable()
     948                 :            :  * in @size. The success of set_variable() is indicated by @set.
     949                 :            :  *
     950                 :            :  * Returns 0 on success, -EINVAL if the variable data is invalid,
     951                 :            :  * -ENOSPC if the firmware does not have enough available space, or a
     952                 :            :  * converted EFI status code if either of set_variable() or
     953                 :            :  * get_variable() fail.
     954                 :            :  *
     955                 :            :  * If the EFI variable does not exist when calling set_variable()
     956                 :            :  * (EFI_NOT_FOUND), @entry is removed from the variable list.
     957                 :            :  */
     958                 :          0 : int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
     959                 :            :                               unsigned long *size, void *data, bool *set)
     960                 :            : {
     961                 :          0 :         const struct efivar_operations *ops;
     962                 :          0 :         efi_char16_t *name = entry->var.VariableName;
     963                 :          0 :         efi_guid_t *vendor = &entry->var.VendorGuid;
     964                 :          0 :         efi_status_t status;
     965                 :          0 :         int err;
     966                 :            : 
     967                 :          0 :         *set = false;
     968                 :            : 
     969         [ #  # ]:          0 :         if (efivar_validate(*vendor, name, data, *size) == false)
     970                 :            :                 return -EINVAL;
     971                 :            : 
     972                 :            :         /*
     973                 :            :          * The lock here protects the get_variable call, the conditional
     974                 :            :          * set_variable call, and removal of the variable from the efivars
     975                 :            :          * list (in the case of an authenticated delete).
     976                 :            :          */
     977         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
     978                 :            :                 return -EINTR;
     979                 :            : 
     980         [ #  # ]:          0 :         if (!__efivars) {
     981                 :          0 :                 err = -EINVAL;
     982                 :          0 :                 goto out;
     983                 :            :         }
     984                 :            : 
     985                 :            :         /*
     986                 :            :          * Ensure that the available space hasn't shrunk below the safe level
     987                 :            :          */
     988         [ #  # ]:          0 :         status = check_var_size(attributes, *size + ucs2_strsize(name, 1024));
     989         [ #  # ]:          0 :         if (status != EFI_SUCCESS) {
     990         [ #  # ]:          0 :                 if (status != EFI_UNSUPPORTED) {
     991                 :          0 :                         err = efi_status_to_err(status);
     992                 :          0 :                         goto out;
     993                 :            :                 }
     994                 :            : 
     995         [ #  # ]:          0 :                 if (*size > 65536) {
     996                 :          0 :                         err = -ENOSPC;
     997                 :          0 :                         goto out;
     998                 :            :                 }
     999                 :            :         }
    1000                 :            : 
    1001                 :          0 :         ops = __efivars->ops;
    1002                 :            : 
    1003                 :          0 :         status = ops->set_variable(name, vendor, attributes, *size, data);
    1004         [ #  # ]:          0 :         if (status != EFI_SUCCESS) {
    1005                 :          0 :                 err = efi_status_to_err(status);
    1006                 :          0 :                 goto out;
    1007                 :            :         }
    1008                 :            : 
    1009                 :          0 :         *set = true;
    1010                 :            : 
    1011                 :            :         /*
    1012                 :            :          * Writing to the variable may have caused a change in size (which
    1013                 :            :          * could either be an append or an overwrite), or the variable to be
    1014                 :            :          * deleted. Perform a GetVariable() so we can tell what actually
    1015                 :            :          * happened.
    1016                 :            :          */
    1017                 :          0 :         *size = 0;
    1018                 :          0 :         status = ops->get_variable(entry->var.VariableName,
    1019                 :            :                                    &entry->var.VendorGuid,
    1020                 :            :                                    NULL, size, NULL);
    1021                 :            : 
    1022         [ #  # ]:          0 :         if (status == EFI_NOT_FOUND)
    1023                 :          0 :                 efivar_entry_list_del_unlock(entry);
    1024                 :            :         else
    1025                 :          0 :                 up(&efivars_lock);
    1026                 :            : 
    1027         [ #  # ]:          0 :         if (status && status != EFI_BUFFER_TOO_SMALL)
    1028                 :          0 :                 return efi_status_to_err(status);
    1029                 :            : 
    1030                 :            :         return 0;
    1031                 :            : 
    1032                 :          0 : out:
    1033                 :          0 :         up(&efivars_lock);
    1034                 :          0 :         return err;
    1035                 :            : 
    1036                 :            : }
    1037                 :            : EXPORT_SYMBOL_GPL(efivar_entry_set_get_size);
    1038                 :            : 
    1039                 :            : /**
    1040                 :            :  * efivar_entry_iter_begin - begin iterating the variable list
    1041                 :            :  *
    1042                 :            :  * Lock the variable list to prevent entry insertion and removal until
    1043                 :            :  * efivar_entry_iter_end() is called. This function is usually used in
    1044                 :            :  * conjunction with __efivar_entry_iter() or efivar_entry_iter().
    1045                 :            :  */
    1046                 :          0 : int efivar_entry_iter_begin(void)
    1047                 :            : {
    1048                 :          0 :         return down_interruptible(&efivars_lock);
    1049                 :            : }
    1050                 :            : EXPORT_SYMBOL_GPL(efivar_entry_iter_begin);
    1051                 :            : 
    1052                 :            : /**
    1053                 :            :  * efivar_entry_iter_end - finish iterating the variable list
    1054                 :            :  *
    1055                 :            :  * Unlock the variable list and allow modifications to the list again.
    1056                 :            :  */
    1057                 :          0 : void efivar_entry_iter_end(void)
    1058                 :            : {
    1059                 :          0 :         up(&efivars_lock);
    1060                 :          0 : }
    1061                 :            : EXPORT_SYMBOL_GPL(efivar_entry_iter_end);
    1062                 :            : 
    1063                 :            : /**
    1064                 :            :  * __efivar_entry_iter - iterate over variable list
    1065                 :            :  * @func: callback function
    1066                 :            :  * @head: head of the variable list
    1067                 :            :  * @data: function-specific data to pass to callback
    1068                 :            :  * @prev: entry to begin iterating from
    1069                 :            :  *
    1070                 :            :  * Iterate over the list of EFI variables and call @func with every
    1071                 :            :  * entry on the list. It is safe for @func to remove entries in the
    1072                 :            :  * list via efivar_entry_delete().
    1073                 :            :  *
    1074                 :            :  * You MUST call efivar_enter_iter_begin() before this function, and
    1075                 :            :  * efivar_entry_iter_end() afterwards.
    1076                 :            :  *
    1077                 :            :  * It is possible to begin iteration from an arbitrary entry within
    1078                 :            :  * the list by passing @prev. @prev is updated on return to point to
    1079                 :            :  * the last entry passed to @func. To begin iterating from the
    1080                 :            :  * beginning of the list @prev must be %NULL.
    1081                 :            :  *
    1082                 :            :  * The restrictions for @func are the same as documented for
    1083                 :            :  * efivar_entry_iter().
    1084                 :            :  */
    1085                 :          0 : int __efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
    1086                 :            :                         struct list_head *head, void *data,
    1087                 :            :                         struct efivar_entry **prev)
    1088                 :            : {
    1089                 :          0 :         struct efivar_entry *entry, *n;
    1090                 :          0 :         int err = 0;
    1091                 :            : 
    1092   [ #  #  #  # ]:          0 :         if (!prev || !*prev) {
    1093   [ #  #  #  # ]:          0 :                 list_for_each_entry_safe(entry, n, head, list) {
    1094                 :          0 :                         err = func(entry, data);
    1095   [ #  #  #  # ]:          0 :                         if (err)
    1096                 :            :                                 break;
    1097                 :            :                 }
    1098                 :            : 
    1099         [ #  # ]:          0 :                 if (prev)
    1100                 :          0 :                         *prev = entry;
    1101                 :            : 
    1102                 :          0 :                 return err;
    1103                 :            :         }
    1104                 :            : 
    1105                 :            : 
    1106         [ #  # ]:          0 :         list_for_each_entry_safe_continue((*prev), n, head, list) {
    1107                 :          0 :                 err = func(*prev, data);
    1108         [ #  # ]:          0 :                 if (err)
    1109                 :            :                         break;
    1110                 :            :         }
    1111                 :            : 
    1112                 :            :         return err;
    1113                 :            : }
    1114                 :            : EXPORT_SYMBOL_GPL(__efivar_entry_iter);
    1115                 :            : 
    1116                 :            : /**
    1117                 :            :  * efivar_entry_iter - iterate over variable list
    1118                 :            :  * @func: callback function
    1119                 :            :  * @head: head of variable list
    1120                 :            :  * @data: function-specific data to pass to callback
    1121                 :            :  *
    1122                 :            :  * Iterate over the list of EFI variables and call @func with every
    1123                 :            :  * entry on the list. It is safe for @func to remove entries in the
    1124                 :            :  * list via efivar_entry_delete() while iterating.
    1125                 :            :  *
    1126                 :            :  * Some notes for the callback function:
    1127                 :            :  *  - a non-zero return value indicates an error and terminates the loop
    1128                 :            :  *  - @func is called from atomic context
    1129                 :            :  */
    1130                 :          0 : int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
    1131                 :            :                       struct list_head *head, void *data)
    1132                 :            : {
    1133                 :          0 :         int err = 0;
    1134                 :            : 
    1135                 :          0 :         err = efivar_entry_iter_begin();
    1136         [ #  # ]:          0 :         if (err)
    1137                 :            :                 return err;
    1138                 :          0 :         err = __efivar_entry_iter(func, head, data, NULL);
    1139                 :          0 :         efivar_entry_iter_end();
    1140                 :            : 
    1141                 :          0 :         return err;
    1142                 :            : }
    1143                 :            : EXPORT_SYMBOL_GPL(efivar_entry_iter);
    1144                 :            : 
    1145                 :            : /**
    1146                 :            :  * efivars_kobject - get the kobject for the registered efivars
    1147                 :            :  *
    1148                 :            :  * If efivars_register() has not been called we return NULL,
    1149                 :            :  * otherwise return the kobject used at registration time.
    1150                 :            :  */
    1151                 :         28 : struct kobject *efivars_kobject(void)
    1152                 :            : {
    1153         [ -  + ]:         28 :         if (!__efivars)
    1154                 :            :                 return NULL;
    1155                 :            : 
    1156                 :          0 :         return __efivars->kobject;
    1157                 :            : }
    1158                 :            : EXPORT_SYMBOL_GPL(efivars_kobject);
    1159                 :            : 
    1160                 :            : /**
    1161                 :            :  * efivar_run_worker - schedule the efivar worker thread
    1162                 :            :  */
    1163                 :          0 : void efivar_run_worker(void)
    1164                 :            : {
    1165         [ #  # ]:          0 :         if (efivar_wq_enabled)
    1166                 :          0 :                 schedule_work(&efivar_work);
    1167                 :          0 : }
    1168                 :            : EXPORT_SYMBOL_GPL(efivar_run_worker);
    1169                 :            : 
    1170                 :            : /**
    1171                 :            :  * efivars_register - register an efivars
    1172                 :            :  * @efivars: efivars to register
    1173                 :            :  * @ops: efivars operations
    1174                 :            :  * @kobject: @efivars-specific kobject
    1175                 :            :  *
    1176                 :            :  * Only a single efivars can be registered at any time.
    1177                 :            :  */
    1178                 :          0 : int efivars_register(struct efivars *efivars,
    1179                 :            :                      const struct efivar_operations *ops,
    1180                 :            :                      struct kobject *kobject)
    1181                 :            : {
    1182         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
    1183                 :            :                 return -EINTR;
    1184                 :            : 
    1185                 :          0 :         efivars->ops = ops;
    1186                 :          0 :         efivars->kobject = kobject;
    1187                 :            : 
    1188                 :          0 :         __efivars = efivars;
    1189                 :            : 
    1190                 :          0 :         pr_info("Registered efivars operations\n");
    1191                 :            : 
    1192                 :          0 :         up(&efivars_lock);
    1193                 :            : 
    1194                 :          0 :         return 0;
    1195                 :            : }
    1196                 :            : EXPORT_SYMBOL_GPL(efivars_register);
    1197                 :            : 
    1198                 :            : /**
    1199                 :            :  * efivars_unregister - unregister an efivars
    1200                 :            :  * @efivars: efivars to unregister
    1201                 :            :  *
    1202                 :            :  * The caller must have already removed every entry from the list,
    1203                 :            :  * failure to do so is an error.
    1204                 :            :  */
    1205                 :          0 : int efivars_unregister(struct efivars *efivars)
    1206                 :            : {
    1207                 :          0 :         int rv;
    1208                 :            : 
    1209         [ #  # ]:          0 :         if (down_interruptible(&efivars_lock))
    1210                 :            :                 return -EINTR;
    1211                 :            : 
    1212         [ #  # ]:          0 :         if (!__efivars) {
    1213                 :          0 :                 printk(KERN_ERR "efivars not registered\n");
    1214                 :          0 :                 rv = -EINVAL;
    1215                 :          0 :                 goto out;
    1216                 :            :         }
    1217                 :            : 
    1218         [ #  # ]:          0 :         if (__efivars != efivars) {
    1219                 :          0 :                 rv = -EINVAL;
    1220                 :          0 :                 goto out;
    1221                 :            :         }
    1222                 :            : 
    1223                 :          0 :         pr_info("Unregistered efivars operations\n");
    1224                 :          0 :         __efivars = NULL;
    1225                 :            : 
    1226                 :          0 :         rv = 0;
    1227                 :          0 : out:
    1228                 :          0 :         up(&efivars_lock);
    1229                 :          0 :         return rv;
    1230                 :            : }
    1231                 :            : EXPORT_SYMBOL_GPL(efivars_unregister);

Generated by: LCOV version 1.14