efi.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * EFI support for Xen.
  3. *
  4. * Copyright (C) 1999 VA Linux Systems
  5. * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  6. * Copyright (C) 1999-2002 Hewlett-Packard Co.
  7. * David Mosberger-Tang <davidm@hpl.hp.com>
  8. * Stephane Eranian <eranian@hpl.hp.com>
  9. * Copyright (C) 2005-2008 Intel Co.
  10. * Fenghua Yu <fenghua.yu@intel.com>
  11. * Bibo Mao <bibo.mao@intel.com>
  12. * Chandramouli Narayanan <mouli@linux.intel.com>
  13. * Huang Ying <ying.huang@intel.com>
  14. * Copyright (C) 2011 Novell Co.
  15. * Jan Beulich <JBeulich@suse.com>
  16. * Copyright (C) 2011-2012 Oracle Co.
  17. * Liang Tang <liang.tang@oracle.com>
  18. * Copyright (c) 2014 Oracle Co., Daniel Kiper
  19. */
  20. #include <linux/bug.h>
  21. #include <linux/efi.h>
  22. #include <linux/init.h>
  23. #include <linux/string.h>
  24. #include <xen/interface/xen.h>
  25. #include <xen/interface/platform.h>
  26. #include <xen/xen.h>
  27. #include <asm/page.h>
  28. #include <asm/xen/hypercall.h>
  29. #define INIT_EFI_OP(name) \
  30. {.cmd = XENPF_efi_runtime_call, \
  31. .u.efi_runtime_call.function = XEN_EFI_##name, \
  32. .u.efi_runtime_call.misc = 0}
  33. #define efi_data(op) (op.u.efi_runtime_call)
  34. efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
  35. {
  36. struct xen_platform_op op = INIT_EFI_OP(get_time);
  37. if (HYPERVISOR_platform_op(&op) < 0)
  38. return EFI_UNSUPPORTED;
  39. if (tm) {
  40. BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_time.time));
  41. memcpy(tm, &efi_data(op).u.get_time.time, sizeof(*tm));
  42. }
  43. if (tc) {
  44. tc->resolution = efi_data(op).u.get_time.resolution;
  45. tc->accuracy = efi_data(op).u.get_time.accuracy;
  46. tc->sets_to_zero = !!(efi_data(op).misc &
  47. XEN_EFI_GET_TIME_SET_CLEARS_NS);
  48. }
  49. return efi_data(op).status;
  50. }
  51. EXPORT_SYMBOL_GPL(xen_efi_get_time);
  52. efi_status_t xen_efi_set_time(efi_time_t *tm)
  53. {
  54. struct xen_platform_op op = INIT_EFI_OP(set_time);
  55. BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time));
  56. memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm));
  57. if (HYPERVISOR_platform_op(&op) < 0)
  58. return EFI_UNSUPPORTED;
  59. return efi_data(op).status;
  60. }
  61. EXPORT_SYMBOL_GPL(xen_efi_set_time);
  62. efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
  63. efi_time_t *tm)
  64. {
  65. struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time);
  66. if (HYPERVISOR_platform_op(&op) < 0)
  67. return EFI_UNSUPPORTED;
  68. if (tm) {
  69. BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_wakeup_time));
  70. memcpy(tm, &efi_data(op).u.get_wakeup_time, sizeof(*tm));
  71. }
  72. if (enabled)
  73. *enabled = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
  74. if (pending)
  75. *pending = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
  76. return efi_data(op).status;
  77. }
  78. EXPORT_SYMBOL_GPL(xen_efi_get_wakeup_time);
  79. efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
  80. {
  81. struct xen_platform_op op = INIT_EFI_OP(set_wakeup_time);
  82. BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_wakeup_time));
  83. if (enabled)
  84. efi_data(op).misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
  85. if (tm)
  86. memcpy(&efi_data(op).u.set_wakeup_time, tm, sizeof(*tm));
  87. else
  88. efi_data(op).misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
  89. if (HYPERVISOR_platform_op(&op) < 0)
  90. return EFI_UNSUPPORTED;
  91. return efi_data(op).status;
  92. }
  93. EXPORT_SYMBOL_GPL(xen_efi_set_wakeup_time);
  94. efi_status_t xen_efi_get_variable(efi_char16_t *name, efi_guid_t *vendor,
  95. u32 *attr, unsigned long *data_size,
  96. void *data)
  97. {
  98. struct xen_platform_op op = INIT_EFI_OP(get_variable);
  99. set_xen_guest_handle(efi_data(op).u.get_variable.name, name);
  100. BUILD_BUG_ON(sizeof(*vendor) !=
  101. sizeof(efi_data(op).u.get_variable.vendor_guid));
  102. memcpy(&efi_data(op).u.get_variable.vendor_guid, vendor, sizeof(*vendor));
  103. efi_data(op).u.get_variable.size = *data_size;
  104. set_xen_guest_handle(efi_data(op).u.get_variable.data, data);
  105. if (HYPERVISOR_platform_op(&op) < 0)
  106. return EFI_UNSUPPORTED;
  107. *data_size = efi_data(op).u.get_variable.size;
  108. if (attr)
  109. *attr = efi_data(op).misc;
  110. return efi_data(op).status;
  111. }
  112. EXPORT_SYMBOL_GPL(xen_efi_get_variable);
  113. efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
  114. efi_char16_t *name,
  115. efi_guid_t *vendor)
  116. {
  117. struct xen_platform_op op = INIT_EFI_OP(get_next_variable_name);
  118. efi_data(op).u.get_next_variable_name.size = *name_size;
  119. set_xen_guest_handle(efi_data(op).u.get_next_variable_name.name, name);
  120. BUILD_BUG_ON(sizeof(*vendor) !=
  121. sizeof(efi_data(op).u.get_next_variable_name.vendor_guid));
  122. memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor,
  123. sizeof(*vendor));
  124. if (HYPERVISOR_platform_op(&op) < 0)
  125. return EFI_UNSUPPORTED;
  126. *name_size = efi_data(op).u.get_next_variable_name.size;
  127. memcpy(vendor, &efi_data(op).u.get_next_variable_name.vendor_guid,
  128. sizeof(*vendor));
  129. return efi_data(op).status;
  130. }
  131. EXPORT_SYMBOL_GPL(xen_efi_get_next_variable);
  132. efi_status_t xen_efi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
  133. u32 attr, unsigned long data_size,
  134. void *data)
  135. {
  136. struct xen_platform_op op = INIT_EFI_OP(set_variable);
  137. set_xen_guest_handle(efi_data(op).u.set_variable.name, name);
  138. efi_data(op).misc = attr;
  139. BUILD_BUG_ON(sizeof(*vendor) !=
  140. sizeof(efi_data(op).u.set_variable.vendor_guid));
  141. memcpy(&efi_data(op).u.set_variable.vendor_guid, vendor, sizeof(*vendor));
  142. efi_data(op).u.set_variable.size = data_size;
  143. set_xen_guest_handle(efi_data(op).u.set_variable.data, data);
  144. if (HYPERVISOR_platform_op(&op) < 0)
  145. return EFI_UNSUPPORTED;
  146. return efi_data(op).status;
  147. }
  148. EXPORT_SYMBOL_GPL(xen_efi_set_variable);
  149. efi_status_t xen_efi_query_variable_info(u32 attr, u64 *storage_space,
  150. u64 *remaining_space,
  151. u64 *max_variable_size)
  152. {
  153. struct xen_platform_op op = INIT_EFI_OP(query_variable_info);
  154. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  155. return EFI_UNSUPPORTED;
  156. efi_data(op).u.query_variable_info.attr = attr;
  157. if (HYPERVISOR_platform_op(&op) < 0)
  158. return EFI_UNSUPPORTED;
  159. *storage_space = efi_data(op).u.query_variable_info.max_store_size;
  160. *remaining_space = efi_data(op).u.query_variable_info.remain_store_size;
  161. *max_variable_size = efi_data(op).u.query_variable_info.max_size;
  162. return efi_data(op).status;
  163. }
  164. EXPORT_SYMBOL_GPL(xen_efi_query_variable_info);
  165. efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
  166. {
  167. struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count);
  168. if (HYPERVISOR_platform_op(&op) < 0)
  169. return EFI_UNSUPPORTED;
  170. *count = efi_data(op).misc;
  171. return efi_data(op).status;
  172. }
  173. EXPORT_SYMBOL_GPL(xen_efi_get_next_high_mono_count);
  174. efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
  175. unsigned long count, unsigned long sg_list)
  176. {
  177. struct xen_platform_op op = INIT_EFI_OP(update_capsule);
  178. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  179. return EFI_UNSUPPORTED;
  180. set_xen_guest_handle(efi_data(op).u.update_capsule.capsule_header_array,
  181. capsules);
  182. efi_data(op).u.update_capsule.capsule_count = count;
  183. efi_data(op).u.update_capsule.sg_list = sg_list;
  184. if (HYPERVISOR_platform_op(&op) < 0)
  185. return EFI_UNSUPPORTED;
  186. return efi_data(op).status;
  187. }
  188. EXPORT_SYMBOL_GPL(xen_efi_update_capsule);
  189. efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
  190. unsigned long count, u64 *max_size,
  191. int *reset_type)
  192. {
  193. struct xen_platform_op op = INIT_EFI_OP(query_capsule_capabilities);
  194. if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
  195. return EFI_UNSUPPORTED;
  196. set_xen_guest_handle(efi_data(op).u.query_capsule_capabilities.capsule_header_array,
  197. capsules);
  198. efi_data(op).u.query_capsule_capabilities.capsule_count = count;
  199. if (HYPERVISOR_platform_op(&op) < 0)
  200. return EFI_UNSUPPORTED;
  201. *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size;
  202. *reset_type = efi_data(op).u.query_capsule_capabilities.reset_type;
  203. return efi_data(op).status;
  204. }
  205. EXPORT_SYMBOL_GPL(xen_efi_query_capsule_caps);