runtime-wrappers.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * runtime-wrappers.c - Runtime Services function call wrappers
  3. *
  4. * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
  5. *
  6. * Split off from arch/x86/platform/efi/efi.c
  7. *
  8. * Copyright (C) 1999 VA Linux Systems
  9. * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  10. * Copyright (C) 1999-2002 Hewlett-Packard Co.
  11. * Copyright (C) 2005-2008 Intel Co.
  12. * Copyright (C) 2013 SuSE Labs
  13. *
  14. * This file is released under the GPLv2.
  15. */
  16. #include <linux/bug.h>
  17. #include <linux/efi.h>
  18. #include <linux/mutex.h>
  19. #include <linux/spinlock.h>
  20. #include <asm/efi.h>
  21. /*
  22. * According to section 7.1 of the UEFI spec, Runtime Services are not fully
  23. * reentrant, and there are particular combinations of calls that need to be
  24. * serialized. (source: UEFI Specification v2.4A)
  25. *
  26. * Table 31. Rules for Reentry Into Runtime Services
  27. * +------------------------------------+-------------------------------+
  28. * | If previous call is busy in | Forbidden to call |
  29. * +------------------------------------+-------------------------------+
  30. * | Any | SetVirtualAddressMap() |
  31. * +------------------------------------+-------------------------------+
  32. * | ConvertPointer() | ConvertPointer() |
  33. * +------------------------------------+-------------------------------+
  34. * | SetVariable() | ResetSystem() |
  35. * | UpdateCapsule() | |
  36. * | SetTime() | |
  37. * | SetWakeupTime() | |
  38. * | GetNextHighMonotonicCount() | |
  39. * +------------------------------------+-------------------------------+
  40. * | GetVariable() | GetVariable() |
  41. * | GetNextVariableName() | GetNextVariableName() |
  42. * | SetVariable() | SetVariable() |
  43. * | QueryVariableInfo() | QueryVariableInfo() |
  44. * | UpdateCapsule() | UpdateCapsule() |
  45. * | QueryCapsuleCapabilities() | QueryCapsuleCapabilities() |
  46. * | GetNextHighMonotonicCount() | GetNextHighMonotonicCount() |
  47. * +------------------------------------+-------------------------------+
  48. * | GetTime() | GetTime() |
  49. * | SetTime() | SetTime() |
  50. * | GetWakeupTime() | GetWakeupTime() |
  51. * | SetWakeupTime() | SetWakeupTime() |
  52. * +------------------------------------+-------------------------------+
  53. *
  54. * Due to the fact that the EFI pstore may write to the variable store in
  55. * interrupt context, we need to use a spinlock for at least the groups that
  56. * contain SetVariable() and QueryVariableInfo(). That leaves little else, as
  57. * none of the remaining functions are actually ever called at runtime.
  58. * So let's just use a single spinlock to serialize all Runtime Services calls.
  59. */
  60. static DEFINE_SPINLOCK(efi_runtime_lock);
  61. static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
  62. {
  63. efi_status_t status;
  64. spin_lock(&efi_runtime_lock);
  65. status = efi_call_virt(get_time, tm, tc);
  66. spin_unlock(&efi_runtime_lock);
  67. return status;
  68. }
  69. static efi_status_t virt_efi_set_time(efi_time_t *tm)
  70. {
  71. efi_status_t status;
  72. spin_lock(&efi_runtime_lock);
  73. status = efi_call_virt(set_time, tm);
  74. spin_unlock(&efi_runtime_lock);
  75. return status;
  76. }
  77. static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
  78. efi_bool_t *pending,
  79. efi_time_t *tm)
  80. {
  81. efi_status_t status;
  82. spin_lock(&efi_runtime_lock);
  83. status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
  84. spin_unlock(&efi_runtime_lock);
  85. return status;
  86. }
  87. static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
  88. {
  89. efi_status_t status;
  90. spin_lock(&efi_runtime_lock);
  91. status = efi_call_virt(set_wakeup_time, enabled, tm);
  92. spin_unlock(&efi_runtime_lock);
  93. return status;
  94. }
  95. static efi_status_t virt_efi_get_variable(efi_char16_t *name,
  96. efi_guid_t *vendor,
  97. u32 *attr,
  98. unsigned long *data_size,
  99. void *data)
  100. {
  101. efi_status_t status;
  102. spin_lock(&efi_runtime_lock);
  103. status = efi_call_virt(get_variable, name, vendor, attr, data_size,
  104. data);
  105. spin_unlock(&efi_runtime_lock);
  106. return status;
  107. }
  108. static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
  109. efi_char16_t *name,
  110. efi_guid_t *vendor)
  111. {
  112. efi_status_t status;
  113. spin_lock(&efi_runtime_lock);
  114. status = efi_call_virt(get_next_variable, name_size, name, vendor);
  115. spin_unlock(&efi_runtime_lock);
  116. return status;
  117. }
  118. static efi_status_t virt_efi_set_variable(efi_char16_t *name,
  119. efi_guid_t *vendor,
  120. u32 attr,
  121. unsigned long data_size,
  122. void *data)
  123. {
  124. efi_status_t status;
  125. spin_lock(&efi_runtime_lock);
  126. status = efi_call_virt(set_variable, name, vendor, attr, data_size,
  127. data);
  128. spin_unlock(&efi_runtime_lock);
  129. return status;
  130. }
  131. static efi_status_t
  132. virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
  133. u32 attr, unsigned long data_size,
  134. void *data)
  135. {
  136. efi_status_t status;
  137. if (!spin_trylock(&efi_runtime_lock))
  138. return EFI_NOT_READY;
  139. status = efi_call_virt(set_variable, name, vendor, attr, data_size,
  140. data);
  141. spin_unlock(&efi_runtime_lock);
  142. return status;
  143. }
  144. static efi_status_t virt_efi_query_variable_info(u32 attr,
  145. u64 *storage_space,
  146. u64 *remaining_space,
  147. u64 *max_variable_size)
  148. {
  149. efi_status_t status;
  150. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  151. return EFI_UNSUPPORTED;
  152. spin_lock(&efi_runtime_lock);
  153. status = efi_call_virt(query_variable_info, attr, storage_space,
  154. remaining_space, max_variable_size);
  155. spin_unlock(&efi_runtime_lock);
  156. return status;
  157. }
  158. static efi_status_t
  159. virt_efi_query_variable_info_nonblocking(u32 attr,
  160. u64 *storage_space,
  161. u64 *remaining_space,
  162. u64 *max_variable_size)
  163. {
  164. efi_status_t status;
  165. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  166. return EFI_UNSUPPORTED;
  167. if (!spin_trylock(&efi_runtime_lock))
  168. return EFI_NOT_READY;
  169. status = efi_call_virt(query_variable_info, attr, storage_space,
  170. remaining_space, max_variable_size);
  171. spin_unlock(&efi_runtime_lock);
  172. return status;
  173. }
  174. static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
  175. {
  176. efi_status_t status;
  177. spin_lock(&efi_runtime_lock);
  178. status = efi_call_virt(get_next_high_mono_count, count);
  179. spin_unlock(&efi_runtime_lock);
  180. return status;
  181. }
  182. static void virt_efi_reset_system(int reset_type,
  183. efi_status_t status,
  184. unsigned long data_size,
  185. efi_char16_t *data)
  186. {
  187. spin_lock(&efi_runtime_lock);
  188. __efi_call_virt(reset_system, reset_type, status, data_size, data);
  189. spin_unlock(&efi_runtime_lock);
  190. }
  191. static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
  192. unsigned long count,
  193. unsigned long sg_list)
  194. {
  195. efi_status_t status;
  196. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  197. return EFI_UNSUPPORTED;
  198. spin_lock(&efi_runtime_lock);
  199. status = efi_call_virt(update_capsule, capsules, count, sg_list);
  200. spin_unlock(&efi_runtime_lock);
  201. return status;
  202. }
  203. static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
  204. unsigned long count,
  205. u64 *max_size,
  206. int *reset_type)
  207. {
  208. efi_status_t status;
  209. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  210. return EFI_UNSUPPORTED;
  211. spin_lock(&efi_runtime_lock);
  212. status = efi_call_virt(query_capsule_caps, capsules, count, max_size,
  213. reset_type);
  214. spin_unlock(&efi_runtime_lock);
  215. return status;
  216. }
  217. void efi_native_runtime_setup(void)
  218. {
  219. efi.get_time = virt_efi_get_time;
  220. efi.set_time = virt_efi_set_time;
  221. efi.get_wakeup_time = virt_efi_get_wakeup_time;
  222. efi.set_wakeup_time = virt_efi_set_wakeup_time;
  223. efi.get_variable = virt_efi_get_variable;
  224. efi.get_next_variable = virt_efi_get_next_variable;
  225. efi.set_variable = virt_efi_set_variable;
  226. efi.set_variable_nonblocking = virt_efi_set_variable_nonblocking;
  227. efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
  228. efi.reset_system = virt_efi_reset_system;
  229. efi.query_variable_info = virt_efi_query_variable_info;
  230. efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nonblocking;
  231. efi.update_capsule = virt_efi_update_capsule;
  232. efi.query_capsule_caps = virt_efi_query_capsule_caps;
  233. }