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