vars.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #define pr_fmt(fmt) "efivars: " fmt
  9. #include <linux/types.h>
  10. #include <linux/sizes.h>
  11. #include <linux/errno.h>
  12. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <linux/string.h>
  15. #include <linux/smp.h>
  16. #include <linux/efi.h>
  17. #include <linux/ucs2_string.h>
  18. /* Private pointer to registered efivars */
  19. static struct efivars *__efivars;
  20. static DEFINE_SEMAPHORE(efivars_lock, 1);
  21. static efi_status_t check_var_size(bool nonblocking, u32 attributes,
  22. unsigned long size)
  23. {
  24. const struct efivar_operations *fops;
  25. efi_status_t status;
  26. fops = __efivars->ops;
  27. if (!fops->query_variable_store)
  28. status = EFI_UNSUPPORTED;
  29. else
  30. status = fops->query_variable_store(attributes, size,
  31. nonblocking);
  32. if (status == EFI_UNSUPPORTED)
  33. return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
  34. return status;
  35. }
  36. /**
  37. * efivar_is_available - check if efivars is available
  38. *
  39. * @return true iff evivars is currently registered
  40. */
  41. bool efivar_is_available(void)
  42. {
  43. return __efivars != NULL;
  44. }
  45. EXPORT_SYMBOL_GPL(efivar_is_available);
  46. /**
  47. * efivars_register - register an efivars
  48. * @efivars: efivars to register
  49. * @ops: efivars operations
  50. *
  51. * Only a single efivars can be registered at any time.
  52. */
  53. int efivars_register(struct efivars *efivars,
  54. const struct efivar_operations *ops)
  55. {
  56. int rv;
  57. int event;
  58. if (down_interruptible(&efivars_lock))
  59. return -EINTR;
  60. if (__efivars) {
  61. pr_warn("efivars already registered\n");
  62. rv = -EBUSY;
  63. goto out;
  64. }
  65. efivars->ops = ops;
  66. __efivars = efivars;
  67. if (efivar_supports_writes())
  68. event = EFIVAR_OPS_RDWR;
  69. else
  70. event = EFIVAR_OPS_RDONLY;
  71. blocking_notifier_call_chain(&efivar_ops_nh, event, NULL);
  72. pr_info("Registered efivars operations\n");
  73. rv = 0;
  74. out:
  75. up(&efivars_lock);
  76. return rv;
  77. }
  78. EXPORT_SYMBOL_GPL(efivars_register);
  79. /**
  80. * efivars_unregister - unregister an efivars
  81. * @efivars: efivars to unregister
  82. *
  83. * The caller must have already removed every entry from the list,
  84. * failure to do so is an error.
  85. */
  86. int efivars_unregister(struct efivars *efivars)
  87. {
  88. int rv;
  89. if (down_interruptible(&efivars_lock))
  90. return -EINTR;
  91. if (!__efivars) {
  92. pr_err("efivars not registered\n");
  93. rv = -EINVAL;
  94. goto out;
  95. }
  96. if (__efivars != efivars) {
  97. rv = -EINVAL;
  98. goto out;
  99. }
  100. pr_info("Unregistered efivars operations\n");
  101. __efivars = NULL;
  102. rv = 0;
  103. out:
  104. up(&efivars_lock);
  105. return rv;
  106. }
  107. EXPORT_SYMBOL_GPL(efivars_unregister);
  108. bool efivar_supports_writes(void)
  109. {
  110. return __efivars && __efivars->ops->set_variable;
  111. }
  112. EXPORT_SYMBOL_GPL(efivar_supports_writes);
  113. /*
  114. * efivar_lock() - obtain the efivar lock, wait for it if needed
  115. * @return 0 on success, error code on failure
  116. */
  117. int efivar_lock(void)
  118. {
  119. if (down_interruptible(&efivars_lock))
  120. return -EINTR;
  121. if (!__efivars->ops) {
  122. up(&efivars_lock);
  123. return -ENODEV;
  124. }
  125. return 0;
  126. }
  127. EXPORT_SYMBOL_NS_GPL(efivar_lock, "EFIVAR");
  128. /*
  129. * efivar_lock() - obtain the efivar lock if it is free
  130. * @return 0 on success, error code on failure
  131. */
  132. int efivar_trylock(void)
  133. {
  134. if (down_trylock(&efivars_lock))
  135. return -EBUSY;
  136. if (!__efivars->ops) {
  137. up(&efivars_lock);
  138. return -ENODEV;
  139. }
  140. return 0;
  141. }
  142. EXPORT_SYMBOL_NS_GPL(efivar_trylock, "EFIVAR");
  143. /*
  144. * efivar_unlock() - release the efivar lock
  145. */
  146. void efivar_unlock(void)
  147. {
  148. up(&efivars_lock);
  149. }
  150. EXPORT_SYMBOL_NS_GPL(efivar_unlock, "EFIVAR");
  151. /*
  152. * efivar_get_variable() - retrieve a variable identified by name/vendor
  153. *
  154. * Must be called with efivars_lock held.
  155. */
  156. efi_status_t efivar_get_variable(efi_char16_t *name, efi_guid_t *vendor,
  157. u32 *attr, unsigned long *size, void *data)
  158. {
  159. return __efivars->ops->get_variable(name, vendor, attr, size, data);
  160. }
  161. EXPORT_SYMBOL_NS_GPL(efivar_get_variable, "EFIVAR");
  162. /*
  163. * efivar_get_next_variable() - enumerate the next name/vendor pair
  164. *
  165. * Must be called with efivars_lock held.
  166. */
  167. efi_status_t efivar_get_next_variable(unsigned long *name_size,
  168. efi_char16_t *name, efi_guid_t *vendor)
  169. {
  170. return __efivars->ops->get_next_variable(name_size, name, vendor);
  171. }
  172. EXPORT_SYMBOL_NS_GPL(efivar_get_next_variable, "EFIVAR");
  173. /*
  174. * efivar_set_variable_locked() - set a variable identified by name/vendor
  175. *
  176. * Must be called with efivars_lock held. If @nonblocking is set, it will use
  177. * non-blocking primitives so it is guaranteed not to sleep.
  178. */
  179. efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor,
  180. u32 attr, unsigned long data_size,
  181. void *data, bool nonblocking)
  182. {
  183. efi_set_variable_t *setvar;
  184. efi_status_t status;
  185. if (data_size > 0) {
  186. status = check_var_size(nonblocking, attr,
  187. data_size + ucs2_strsize(name, EFI_VAR_NAME_LEN));
  188. if (status != EFI_SUCCESS)
  189. return status;
  190. }
  191. /*
  192. * If no _nonblocking variant exists, the ordinary one
  193. * is assumed to be non-blocking.
  194. */
  195. setvar = __efivars->ops->set_variable_nonblocking;
  196. if (!setvar || !nonblocking)
  197. setvar = __efivars->ops->set_variable;
  198. return setvar(name, vendor, attr, data_size, data);
  199. }
  200. EXPORT_SYMBOL_NS_GPL(efivar_set_variable_locked, "EFIVAR");
  201. /*
  202. * efivar_set_variable() - set a variable identified by name/vendor
  203. *
  204. * Can be called without holding the efivars_lock. Will sleep on obtaining the
  205. * lock, or on obtaining other locks that are needed in order to complete the
  206. * call.
  207. */
  208. efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
  209. u32 attr, unsigned long data_size, void *data)
  210. {
  211. efi_status_t status;
  212. if (efivar_lock())
  213. return EFI_ABORTED;
  214. status = efivar_set_variable_locked(name, vendor, attr, data_size,
  215. data, false);
  216. efivar_unlock();
  217. return status;
  218. }
  219. EXPORT_SYMBOL_NS_GPL(efivar_set_variable, "EFIVAR");
  220. efi_status_t efivar_query_variable_info(u32 attr,
  221. u64 *storage_space,
  222. u64 *remaining_space,
  223. u64 *max_variable_size)
  224. {
  225. if (!__efivars->ops->query_variable_info)
  226. return EFI_UNSUPPORTED;
  227. return __efivars->ops->query_variable_info(attr, storage_space,
  228. remaining_space, max_variable_size);
  229. }
  230. EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, "EFIVAR");