Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * EFI support for Xen.
0004  *
0005  * Copyright (C) 1999 VA Linux Systems
0006  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
0007  * Copyright (C) 1999-2002 Hewlett-Packard Co.
0008  *  David Mosberger-Tang <davidm@hpl.hp.com>
0009  *  Stephane Eranian <eranian@hpl.hp.com>
0010  * Copyright (C) 2005-2008 Intel Co.
0011  *  Fenghua Yu <fenghua.yu@intel.com>
0012  *  Bibo Mao <bibo.mao@intel.com>
0013  *  Chandramouli Narayanan <mouli@linux.intel.com>
0014  *  Huang Ying <ying.huang@intel.com>
0015  * Copyright (C) 2011 Novell Co.
0016  *  Jan Beulich <JBeulich@suse.com>
0017  * Copyright (C) 2011-2012 Oracle Co.
0018  *  Liang Tang <liang.tang@oracle.com>
0019  * Copyright (c) 2014 Oracle Co., Daniel Kiper
0020  */
0021 
0022 #include <linux/bug.h>
0023 #include <linux/efi.h>
0024 #include <linux/init.h>
0025 #include <linux/string.h>
0026 
0027 #include <xen/interface/xen.h>
0028 #include <xen/interface/platform.h>
0029 #include <xen/xen.h>
0030 #include <xen/xen-ops.h>
0031 
0032 #include <asm/page.h>
0033 
0034 #include <asm/xen/hypercall.h>
0035 
0036 #define INIT_EFI_OP(name) \
0037     {.cmd = XENPF_efi_runtime_call, \
0038      .u.efi_runtime_call.function = XEN_EFI_##name, \
0039      .u.efi_runtime_call.misc = 0}
0040 
0041 #define efi_data(op)    (op.u.efi_runtime_call)
0042 
0043 static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
0044 {
0045     struct xen_platform_op op = INIT_EFI_OP(get_time);
0046 
0047     if (HYPERVISOR_platform_op(&op) < 0)
0048         return EFI_UNSUPPORTED;
0049 
0050     if (tm) {
0051         BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_time.time));
0052         memcpy(tm, &efi_data(op).u.get_time.time, sizeof(*tm));
0053     }
0054 
0055     if (tc) {
0056         tc->resolution = efi_data(op).u.get_time.resolution;
0057         tc->accuracy = efi_data(op).u.get_time.accuracy;
0058         tc->sets_to_zero = !!(efi_data(op).misc &
0059                       XEN_EFI_GET_TIME_SET_CLEARS_NS);
0060     }
0061 
0062     return efi_data(op).status;
0063 }
0064 
0065 static efi_status_t xen_efi_set_time(efi_time_t *tm)
0066 {
0067     struct xen_platform_op op = INIT_EFI_OP(set_time);
0068 
0069     BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time));
0070     memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm));
0071 
0072     if (HYPERVISOR_platform_op(&op) < 0)
0073         return EFI_UNSUPPORTED;
0074 
0075     return efi_data(op).status;
0076 }
0077 
0078 static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
0079                         efi_bool_t *pending,
0080                         efi_time_t *tm)
0081 {
0082     struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time);
0083 
0084     if (HYPERVISOR_platform_op(&op) < 0)
0085         return EFI_UNSUPPORTED;
0086 
0087     if (tm) {
0088         BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_wakeup_time));
0089         memcpy(tm, &efi_data(op).u.get_wakeup_time, sizeof(*tm));
0090     }
0091 
0092     if (enabled)
0093         *enabled = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
0094 
0095     if (pending)
0096         *pending = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
0097 
0098     return efi_data(op).status;
0099 }
0100 
0101 static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
0102 {
0103     struct xen_platform_op op = INIT_EFI_OP(set_wakeup_time);
0104 
0105     BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_wakeup_time));
0106     if (enabled)
0107         efi_data(op).misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
0108     if (tm)
0109         memcpy(&efi_data(op).u.set_wakeup_time, tm, sizeof(*tm));
0110     else
0111         efi_data(op).misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
0112 
0113     if (HYPERVISOR_platform_op(&op) < 0)
0114         return EFI_UNSUPPORTED;
0115 
0116     return efi_data(op).status;
0117 }
0118 
0119 static efi_status_t xen_efi_get_variable(efi_char16_t *name, efi_guid_t *vendor,
0120                      u32 *attr, unsigned long *data_size,
0121                      void *data)
0122 {
0123     struct xen_platform_op op = INIT_EFI_OP(get_variable);
0124 
0125     set_xen_guest_handle(efi_data(op).u.get_variable.name, name);
0126     BUILD_BUG_ON(sizeof(*vendor) !=
0127              sizeof(efi_data(op).u.get_variable.vendor_guid));
0128     memcpy(&efi_data(op).u.get_variable.vendor_guid, vendor, sizeof(*vendor));
0129     efi_data(op).u.get_variable.size = *data_size;
0130     set_xen_guest_handle(efi_data(op).u.get_variable.data, data);
0131 
0132     if (HYPERVISOR_platform_op(&op) < 0)
0133         return EFI_UNSUPPORTED;
0134 
0135     *data_size = efi_data(op).u.get_variable.size;
0136     if (attr)
0137         *attr = efi_data(op).misc;
0138 
0139     return efi_data(op).status;
0140 }
0141 
0142 static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
0143                           efi_char16_t *name,
0144                           efi_guid_t *vendor)
0145 {
0146     struct xen_platform_op op = INIT_EFI_OP(get_next_variable_name);
0147 
0148     efi_data(op).u.get_next_variable_name.size = *name_size;
0149     set_xen_guest_handle(efi_data(op).u.get_next_variable_name.name, name);
0150     BUILD_BUG_ON(sizeof(*vendor) !=
0151              sizeof(efi_data(op).u.get_next_variable_name.vendor_guid));
0152     memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor,
0153            sizeof(*vendor));
0154 
0155     if (HYPERVISOR_platform_op(&op) < 0)
0156         return EFI_UNSUPPORTED;
0157 
0158     *name_size = efi_data(op).u.get_next_variable_name.size;
0159     memcpy(vendor, &efi_data(op).u.get_next_variable_name.vendor_guid,
0160            sizeof(*vendor));
0161 
0162     return efi_data(op).status;
0163 }
0164 
0165 static efi_status_t xen_efi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
0166                      u32 attr, unsigned long data_size,
0167                      void *data)
0168 {
0169     struct xen_platform_op op = INIT_EFI_OP(set_variable);
0170 
0171     set_xen_guest_handle(efi_data(op).u.set_variable.name, name);
0172     efi_data(op).misc = attr;
0173     BUILD_BUG_ON(sizeof(*vendor) !=
0174              sizeof(efi_data(op).u.set_variable.vendor_guid));
0175     memcpy(&efi_data(op).u.set_variable.vendor_guid, vendor, sizeof(*vendor));
0176     efi_data(op).u.set_variable.size = data_size;
0177     set_xen_guest_handle(efi_data(op).u.set_variable.data, data);
0178 
0179     if (HYPERVISOR_platform_op(&op) < 0)
0180         return EFI_UNSUPPORTED;
0181 
0182     return efi_data(op).status;
0183 }
0184 
0185 static efi_status_t xen_efi_query_variable_info(u32 attr, u64 *storage_space,
0186                         u64 *remaining_space,
0187                         u64 *max_variable_size)
0188 {
0189     struct xen_platform_op op = INIT_EFI_OP(query_variable_info);
0190 
0191     if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
0192         return EFI_UNSUPPORTED;
0193 
0194     efi_data(op).u.query_variable_info.attr = attr;
0195 
0196     if (HYPERVISOR_platform_op(&op) < 0)
0197         return EFI_UNSUPPORTED;
0198 
0199     *storage_space = efi_data(op).u.query_variable_info.max_store_size;
0200     *remaining_space = efi_data(op).u.query_variable_info.remain_store_size;
0201     *max_variable_size = efi_data(op).u.query_variable_info.max_size;
0202 
0203     return efi_data(op).status;
0204 }
0205 
0206 static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
0207 {
0208     struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count);
0209 
0210     if (HYPERVISOR_platform_op(&op) < 0)
0211         return EFI_UNSUPPORTED;
0212 
0213     *count = efi_data(op).misc;
0214 
0215     return efi_data(op).status;
0216 }
0217 
0218 static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
0219                 unsigned long count, unsigned long sg_list)
0220 {
0221     struct xen_platform_op op = INIT_EFI_OP(update_capsule);
0222 
0223     if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
0224         return EFI_UNSUPPORTED;
0225 
0226     set_xen_guest_handle(efi_data(op).u.update_capsule.capsule_header_array,
0227                  capsules);
0228     efi_data(op).u.update_capsule.capsule_count = count;
0229     efi_data(op).u.update_capsule.sg_list = sg_list;
0230 
0231     if (HYPERVISOR_platform_op(&op) < 0)
0232         return EFI_UNSUPPORTED;
0233 
0234     return efi_data(op).status;
0235 }
0236 
0237 static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
0238             unsigned long count, u64 *max_size, int *reset_type)
0239 {
0240     struct xen_platform_op op = INIT_EFI_OP(query_capsule_capabilities);
0241 
0242     if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
0243         return EFI_UNSUPPORTED;
0244 
0245     set_xen_guest_handle(efi_data(op).u.query_capsule_capabilities.capsule_header_array,
0246                     capsules);
0247     efi_data(op).u.query_capsule_capabilities.capsule_count = count;
0248 
0249     if (HYPERVISOR_platform_op(&op) < 0)
0250         return EFI_UNSUPPORTED;
0251 
0252     *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size;
0253     *reset_type = efi_data(op).u.query_capsule_capabilities.reset_type;
0254 
0255     return efi_data(op).status;
0256 }
0257 
0258 static void xen_efi_reset_system(int reset_type, efi_status_t status,
0259                  unsigned long data_size, efi_char16_t *data)
0260 {
0261     switch (reset_type) {
0262     case EFI_RESET_COLD:
0263     case EFI_RESET_WARM:
0264         xen_reboot(SHUTDOWN_reboot);
0265         break;
0266     case EFI_RESET_SHUTDOWN:
0267         xen_reboot(SHUTDOWN_poweroff);
0268         break;
0269     default:
0270         BUG();
0271     }
0272 }
0273 
0274 /*
0275  * Set XEN EFI runtime services function pointers. Other fields of struct efi,
0276  * e.g. efi.systab, will be set like normal EFI.
0277  */
0278 void __init xen_efi_runtime_setup(void)
0279 {
0280     efi.get_time            = xen_efi_get_time;
0281     efi.set_time            = xen_efi_set_time;
0282     efi.get_wakeup_time     = xen_efi_get_wakeup_time;
0283     efi.set_wakeup_time     = xen_efi_set_wakeup_time;
0284     efi.get_variable        = xen_efi_get_variable;
0285     efi.get_next_variable       = xen_efi_get_next_variable;
0286     efi.set_variable        = xen_efi_set_variable;
0287     efi.set_variable_nonblocking    = xen_efi_set_variable;
0288     efi.query_variable_info     = xen_efi_query_variable_info;
0289     efi.query_variable_info_nonblocking = xen_efi_query_variable_info;
0290     efi.update_capsule      = xen_efi_update_capsule;
0291     efi.query_capsule_caps      = xen_efi_query_capsule_caps;
0292     efi.get_next_high_mono_count    = xen_efi_get_next_high_mono_count;
0293     efi.reset_system        = xen_efi_reset_system;
0294 }