root/drivers/xen/efi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xen_efi_get_time
  2. xen_efi_set_time
  3. xen_efi_get_wakeup_time
  4. xen_efi_set_wakeup_time
  5. xen_efi_get_variable
  6. xen_efi_get_next_variable
  7. xen_efi_set_variable
  8. xen_efi_query_variable_info
  9. xen_efi_get_next_high_mono_count
  10. xen_efi_update_capsule
  11. xen_efi_query_capsule_caps
  12. xen_efi_reset_system
  13. xen_efi_runtime_setup

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * EFI support for Xen.
   4  *
   5  * Copyright (C) 1999 VA Linux Systems
   6  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
   7  * Copyright (C) 1999-2002 Hewlett-Packard Co.
   8  *      David Mosberger-Tang <davidm@hpl.hp.com>
   9  *      Stephane Eranian <eranian@hpl.hp.com>
  10  * Copyright (C) 2005-2008 Intel Co.
  11  *      Fenghua Yu <fenghua.yu@intel.com>
  12  *      Bibo Mao <bibo.mao@intel.com>
  13  *      Chandramouli Narayanan <mouli@linux.intel.com>
  14  *      Huang Ying <ying.huang@intel.com>
  15  * Copyright (C) 2011 Novell Co.
  16  *      Jan Beulich <JBeulich@suse.com>
  17  * Copyright (C) 2011-2012 Oracle Co.
  18  *      Liang Tang <liang.tang@oracle.com>
  19  * Copyright (c) 2014 Oracle Co., Daniel Kiper
  20  */
  21 
  22 #include <linux/bug.h>
  23 #include <linux/efi.h>
  24 #include <linux/init.h>
  25 #include <linux/string.h>
  26 
  27 #include <xen/interface/xen.h>
  28 #include <xen/interface/platform.h>
  29 #include <xen/xen.h>
  30 #include <xen/xen-ops.h>
  31 
  32 #include <asm/page.h>
  33 
  34 #include <asm/xen/hypercall.h>
  35 
  36 #define INIT_EFI_OP(name) \
  37         {.cmd = XENPF_efi_runtime_call, \
  38          .u.efi_runtime_call.function = XEN_EFI_##name, \
  39          .u.efi_runtime_call.misc = 0}
  40 
  41 #define efi_data(op)    (op.u.efi_runtime_call)
  42 
  43 static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
  44 {
  45         struct xen_platform_op op = INIT_EFI_OP(get_time);
  46 
  47         if (HYPERVISOR_platform_op(&op) < 0)
  48                 return EFI_UNSUPPORTED;
  49 
  50         if (tm) {
  51                 BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_time.time));
  52                 memcpy(tm, &efi_data(op).u.get_time.time, sizeof(*tm));
  53         }
  54 
  55         if (tc) {
  56                 tc->resolution = efi_data(op).u.get_time.resolution;
  57                 tc->accuracy = efi_data(op).u.get_time.accuracy;
  58                 tc->sets_to_zero = !!(efi_data(op).misc &
  59                                       XEN_EFI_GET_TIME_SET_CLEARS_NS);
  60         }
  61 
  62         return efi_data(op).status;
  63 }
  64 
  65 static efi_status_t xen_efi_set_time(efi_time_t *tm)
  66 {
  67         struct xen_platform_op op = INIT_EFI_OP(set_time);
  68 
  69         BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time));
  70         memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm));
  71 
  72         if (HYPERVISOR_platform_op(&op) < 0)
  73                 return EFI_UNSUPPORTED;
  74 
  75         return efi_data(op).status;
  76 }
  77 
  78 static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
  79                                             efi_bool_t *pending,
  80                                             efi_time_t *tm)
  81 {
  82         struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time);
  83 
  84         if (HYPERVISOR_platform_op(&op) < 0)
  85                 return EFI_UNSUPPORTED;
  86 
  87         if (tm) {
  88                 BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_wakeup_time));
  89                 memcpy(tm, &efi_data(op).u.get_wakeup_time, sizeof(*tm));
  90         }
  91 
  92         if (enabled)
  93                 *enabled = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
  94 
  95         if (pending)
  96                 *pending = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
  97 
  98         return efi_data(op).status;
  99 }
 100 
 101 static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
 102 {
 103         struct xen_platform_op op = INIT_EFI_OP(set_wakeup_time);
 104 
 105         BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_wakeup_time));
 106         if (enabled)
 107                 efi_data(op).misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
 108         if (tm)
 109                 memcpy(&efi_data(op).u.set_wakeup_time, tm, sizeof(*tm));
 110         else
 111                 efi_data(op).misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
 112 
 113         if (HYPERVISOR_platform_op(&op) < 0)
 114                 return EFI_UNSUPPORTED;
 115 
 116         return efi_data(op).status;
 117 }
 118 
 119 static efi_status_t xen_efi_get_variable(efi_char16_t *name, efi_guid_t *vendor,
 120                                          u32 *attr, unsigned long *data_size,
 121                                          void *data)
 122 {
 123         struct xen_platform_op op = INIT_EFI_OP(get_variable);
 124 
 125         set_xen_guest_handle(efi_data(op).u.get_variable.name, name);
 126         BUILD_BUG_ON(sizeof(*vendor) !=
 127                      sizeof(efi_data(op).u.get_variable.vendor_guid));
 128         memcpy(&efi_data(op).u.get_variable.vendor_guid, vendor, sizeof(*vendor));
 129         efi_data(op).u.get_variable.size = *data_size;
 130         set_xen_guest_handle(efi_data(op).u.get_variable.data, data);
 131 
 132         if (HYPERVISOR_platform_op(&op) < 0)
 133                 return EFI_UNSUPPORTED;
 134 
 135         *data_size = efi_data(op).u.get_variable.size;
 136         if (attr)
 137                 *attr = efi_data(op).misc;
 138 
 139         return efi_data(op).status;
 140 }
 141 
 142 static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
 143                                               efi_char16_t *name,
 144                                               efi_guid_t *vendor)
 145 {
 146         struct xen_platform_op op = INIT_EFI_OP(get_next_variable_name);
 147 
 148         efi_data(op).u.get_next_variable_name.size = *name_size;
 149         set_xen_guest_handle(efi_data(op).u.get_next_variable_name.name, name);
 150         BUILD_BUG_ON(sizeof(*vendor) !=
 151                      sizeof(efi_data(op).u.get_next_variable_name.vendor_guid));
 152         memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor,
 153                sizeof(*vendor));
 154 
 155         if (HYPERVISOR_platform_op(&op) < 0)
 156                 return EFI_UNSUPPORTED;
 157 
 158         *name_size = efi_data(op).u.get_next_variable_name.size;
 159         memcpy(vendor, &efi_data(op).u.get_next_variable_name.vendor_guid,
 160                sizeof(*vendor));
 161 
 162         return efi_data(op).status;
 163 }
 164 
 165 static efi_status_t xen_efi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
 166                                          u32 attr, unsigned long data_size,
 167                                          void *data)
 168 {
 169         struct xen_platform_op op = INIT_EFI_OP(set_variable);
 170 
 171         set_xen_guest_handle(efi_data(op).u.set_variable.name, name);
 172         efi_data(op).misc = attr;
 173         BUILD_BUG_ON(sizeof(*vendor) !=
 174                      sizeof(efi_data(op).u.set_variable.vendor_guid));
 175         memcpy(&efi_data(op).u.set_variable.vendor_guid, vendor, sizeof(*vendor));
 176         efi_data(op).u.set_variable.size = data_size;
 177         set_xen_guest_handle(efi_data(op).u.set_variable.data, data);
 178 
 179         if (HYPERVISOR_platform_op(&op) < 0)
 180                 return EFI_UNSUPPORTED;
 181 
 182         return efi_data(op).status;
 183 }
 184 
 185 static efi_status_t xen_efi_query_variable_info(u32 attr, u64 *storage_space,
 186                                                 u64 *remaining_space,
 187                                                 u64 *max_variable_size)
 188 {
 189         struct xen_platform_op op = INIT_EFI_OP(query_variable_info);
 190 
 191         if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
 192                 return EFI_UNSUPPORTED;
 193 
 194         efi_data(op).u.query_variable_info.attr = attr;
 195 
 196         if (HYPERVISOR_platform_op(&op) < 0)
 197                 return EFI_UNSUPPORTED;
 198 
 199         *storage_space = efi_data(op).u.query_variable_info.max_store_size;
 200         *remaining_space = efi_data(op).u.query_variable_info.remain_store_size;
 201         *max_variable_size = efi_data(op).u.query_variable_info.max_size;
 202 
 203         return efi_data(op).status;
 204 }
 205 
 206 static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
 207 {
 208         struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count);
 209 
 210         if (HYPERVISOR_platform_op(&op) < 0)
 211                 return EFI_UNSUPPORTED;
 212 
 213         *count = efi_data(op).misc;
 214 
 215         return efi_data(op).status;
 216 }
 217 
 218 static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
 219                                 unsigned long count, unsigned long sg_list)
 220 {
 221         struct xen_platform_op op = INIT_EFI_OP(update_capsule);
 222 
 223         if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
 224                 return EFI_UNSUPPORTED;
 225 
 226         set_xen_guest_handle(efi_data(op).u.update_capsule.capsule_header_array,
 227                              capsules);
 228         efi_data(op).u.update_capsule.capsule_count = count;
 229         efi_data(op).u.update_capsule.sg_list = sg_list;
 230 
 231         if (HYPERVISOR_platform_op(&op) < 0)
 232                 return EFI_UNSUPPORTED;
 233 
 234         return efi_data(op).status;
 235 }
 236 
 237 static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
 238                         unsigned long count, u64 *max_size, int *reset_type)
 239 {
 240         struct xen_platform_op op = INIT_EFI_OP(query_capsule_capabilities);
 241 
 242         if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
 243                 return EFI_UNSUPPORTED;
 244 
 245         set_xen_guest_handle(efi_data(op).u.query_capsule_capabilities.capsule_header_array,
 246                                         capsules);
 247         efi_data(op).u.query_capsule_capabilities.capsule_count = count;
 248 
 249         if (HYPERVISOR_platform_op(&op) < 0)
 250                 return EFI_UNSUPPORTED;
 251 
 252         *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size;
 253         *reset_type = efi_data(op).u.query_capsule_capabilities.reset_type;
 254 
 255         return efi_data(op).status;
 256 }
 257 
 258 static void xen_efi_reset_system(int reset_type, efi_status_t status,
 259                                  unsigned long data_size, efi_char16_t *data)
 260 {
 261         switch (reset_type) {
 262         case EFI_RESET_COLD:
 263         case EFI_RESET_WARM:
 264                 xen_reboot(SHUTDOWN_reboot);
 265                 break;
 266         case EFI_RESET_SHUTDOWN:
 267                 xen_reboot(SHUTDOWN_poweroff);
 268                 break;
 269         default:
 270                 BUG();
 271         }
 272 }
 273 
 274 /*
 275  * Set XEN EFI runtime services function pointers. Other fields of struct efi,
 276  * e.g. efi.systab, will be set like normal EFI.
 277  */
 278 void __init xen_efi_runtime_setup(void)
 279 {
 280         efi.get_time                    = xen_efi_get_time;
 281         efi.set_time                    = xen_efi_set_time;
 282         efi.get_wakeup_time             = xen_efi_get_wakeup_time;
 283         efi.set_wakeup_time             = xen_efi_set_wakeup_time;
 284         efi.get_variable                = xen_efi_get_variable;
 285         efi.get_next_variable           = xen_efi_get_next_variable;
 286         efi.set_variable                = xen_efi_set_variable;
 287         efi.set_variable_nonblocking    = xen_efi_set_variable;
 288         efi.query_variable_info         = xen_efi_query_variable_info;
 289         efi.query_variable_info_nonblocking = xen_efi_query_variable_info;
 290         efi.update_capsule              = xen_efi_update_capsule;
 291         efi.query_capsule_caps          = xen_efi_query_capsule_caps;
 292         efi.get_next_high_mono_count    = xen_efi_get_next_high_mono_count;
 293         efi.reset_system                = xen_efi_reset_system;
 294 }

/* [<][>][^][v][top][bottom][index][help] */