linux/drivers/xen/efi.c
<<
>>
Prefs
   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
  21#include <linux/bug.h>
  22#include <linux/efi.h>
  23#include <linux/init.h>
  24#include <linux/string.h>
  25
  26#include <xen/interface/xen.h>
  27#include <xen/interface/platform.h>
  28#include <xen/xen.h>
  29
  30#include <asm/page.h>
  31
  32#include <asm/xen/hypercall.h>
  33
  34#define INIT_EFI_OP(name) \
  35        {.cmd = XENPF_efi_runtime_call, \
  36         .u.efi_runtime_call.function = XEN_EFI_##name, \
  37         .u.efi_runtime_call.misc = 0}
  38
  39#define efi_data(op)    (op.u.efi_runtime_call)
  40
  41efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
  42{
  43        struct xen_platform_op op = INIT_EFI_OP(get_time);
  44
  45        if (HYPERVISOR_platform_op(&op) < 0)
  46                return EFI_UNSUPPORTED;
  47
  48        if (tm) {
  49                BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_time.time));
  50                memcpy(tm, &efi_data(op).u.get_time.time, sizeof(*tm));
  51        }
  52
  53        if (tc) {
  54                tc->resolution = efi_data(op).u.get_time.resolution;
  55                tc->accuracy = efi_data(op).u.get_time.accuracy;
  56                tc->sets_to_zero = !!(efi_data(op).misc &
  57                                      XEN_EFI_GET_TIME_SET_CLEARS_NS);
  58        }
  59
  60        return efi_data(op).status;
  61}
  62EXPORT_SYMBOL_GPL(xen_efi_get_time);
  63
  64efi_status_t xen_efi_set_time(efi_time_t *tm)
  65{
  66        struct xen_platform_op op = INIT_EFI_OP(set_time);
  67
  68        BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time));
  69        memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm));
  70
  71        if (HYPERVISOR_platform_op(&op) < 0)
  72                return EFI_UNSUPPORTED;
  73
  74        return efi_data(op).status;
  75}
  76EXPORT_SYMBOL_GPL(xen_efi_set_time);
  77
  78efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
  79                                     efi_time_t *tm)
  80{
  81        struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time);
  82
  83        if (HYPERVISOR_platform_op(&op) < 0)
  84                return EFI_UNSUPPORTED;
  85
  86        if (tm) {
  87                BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_wakeup_time));
  88                memcpy(tm, &efi_data(op).u.get_wakeup_time, sizeof(*tm));
  89        }
  90
  91        if (enabled)
  92                *enabled = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
  93
  94        if (pending)
  95                *pending = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
  96
  97        return efi_data(op).status;
  98}
  99EXPORT_SYMBOL_GPL(xen_efi_get_wakeup_time);
 100
 101efi_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}
 118EXPORT_SYMBOL_GPL(xen_efi_set_wakeup_time);
 119
 120efi_status_t xen_efi_get_variable(efi_char16_t *name, efi_guid_t *vendor,
 121                                  u32 *attr, unsigned long *data_size,
 122                                  void *data)
 123{
 124        struct xen_platform_op op = INIT_EFI_OP(get_variable);
 125
 126        set_xen_guest_handle(efi_data(op).u.get_variable.name, name);
 127        BUILD_BUG_ON(sizeof(*vendor) !=
 128                     sizeof(efi_data(op).u.get_variable.vendor_guid));
 129        memcpy(&efi_data(op).u.get_variable.vendor_guid, vendor, sizeof(*vendor));
 130        efi_data(op).u.get_variable.size = *data_size;
 131        set_xen_guest_handle(efi_data(op).u.get_variable.data, data);
 132
 133        if (HYPERVISOR_platform_op(&op) < 0)
 134                return EFI_UNSUPPORTED;
 135
 136        *data_size = efi_data(op).u.get_variable.size;
 137        if (attr)
 138                *attr = efi_data(op).misc;
 139
 140        return efi_data(op).status;
 141}
 142EXPORT_SYMBOL_GPL(xen_efi_get_variable);
 143
 144efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
 145                                       efi_char16_t *name,
 146                                       efi_guid_t *vendor)
 147{
 148        struct xen_platform_op op = INIT_EFI_OP(get_next_variable_name);
 149
 150        efi_data(op).u.get_next_variable_name.size = *name_size;
 151        set_xen_guest_handle(efi_data(op).u.get_next_variable_name.name, name);
 152        BUILD_BUG_ON(sizeof(*vendor) !=
 153                     sizeof(efi_data(op).u.get_next_variable_name.vendor_guid));
 154        memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor,
 155               sizeof(*vendor));
 156
 157        if (HYPERVISOR_platform_op(&op) < 0)
 158                return EFI_UNSUPPORTED;
 159
 160        *name_size = efi_data(op).u.get_next_variable_name.size;
 161        memcpy(vendor, &efi_data(op).u.get_next_variable_name.vendor_guid,
 162               sizeof(*vendor));
 163
 164        return efi_data(op).status;
 165}
 166EXPORT_SYMBOL_GPL(xen_efi_get_next_variable);
 167
 168efi_status_t xen_efi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
 169                                 u32 attr, unsigned long data_size,
 170                                 void *data)
 171{
 172        struct xen_platform_op op = INIT_EFI_OP(set_variable);
 173
 174        set_xen_guest_handle(efi_data(op).u.set_variable.name, name);
 175        efi_data(op).misc = attr;
 176        BUILD_BUG_ON(sizeof(*vendor) !=
 177                     sizeof(efi_data(op).u.set_variable.vendor_guid));
 178        memcpy(&efi_data(op).u.set_variable.vendor_guid, vendor, sizeof(*vendor));
 179        efi_data(op).u.set_variable.size = data_size;
 180        set_xen_guest_handle(efi_data(op).u.set_variable.data, data);
 181
 182        if (HYPERVISOR_platform_op(&op) < 0)
 183                return EFI_UNSUPPORTED;
 184
 185        return efi_data(op).status;
 186}
 187EXPORT_SYMBOL_GPL(xen_efi_set_variable);
 188
 189efi_status_t xen_efi_query_variable_info(u32 attr, u64 *storage_space,
 190                                         u64 *remaining_space,
 191                                         u64 *max_variable_size)
 192{
 193        struct xen_platform_op op = INIT_EFI_OP(query_variable_info);
 194
 195        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
 196                return EFI_UNSUPPORTED;
 197
 198        efi_data(op).u.query_variable_info.attr = attr;
 199
 200        if (HYPERVISOR_platform_op(&op) < 0)
 201                return EFI_UNSUPPORTED;
 202
 203        *storage_space = efi_data(op).u.query_variable_info.max_store_size;
 204        *remaining_space = efi_data(op).u.query_variable_info.remain_store_size;
 205        *max_variable_size = efi_data(op).u.query_variable_info.max_size;
 206
 207        return efi_data(op).status;
 208}
 209EXPORT_SYMBOL_GPL(xen_efi_query_variable_info);
 210
 211efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
 212{
 213        struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count);
 214
 215        if (HYPERVISOR_platform_op(&op) < 0)
 216                return EFI_UNSUPPORTED;
 217
 218        *count = efi_data(op).misc;
 219
 220        return efi_data(op).status;
 221}
 222EXPORT_SYMBOL_GPL(xen_efi_get_next_high_mono_count);
 223
 224efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
 225                                    unsigned long count, unsigned long sg_list)
 226{
 227        struct xen_platform_op op = INIT_EFI_OP(update_capsule);
 228
 229        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
 230                return EFI_UNSUPPORTED;
 231
 232        set_xen_guest_handle(efi_data(op).u.update_capsule.capsule_header_array,
 233                             capsules);
 234        efi_data(op).u.update_capsule.capsule_count = count;
 235        efi_data(op).u.update_capsule.sg_list = sg_list;
 236
 237        if (HYPERVISOR_platform_op(&op) < 0)
 238                return EFI_UNSUPPORTED;
 239
 240        return efi_data(op).status;
 241}
 242EXPORT_SYMBOL_GPL(xen_efi_update_capsule);
 243
 244efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
 245                                        unsigned long count, u64 *max_size,
 246                                        int *reset_type)
 247{
 248        struct xen_platform_op op = INIT_EFI_OP(query_capsule_capabilities);
 249
 250        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
 251                return EFI_UNSUPPORTED;
 252
 253        set_xen_guest_handle(efi_data(op).u.query_capsule_capabilities.capsule_header_array,
 254                                        capsules);
 255        efi_data(op).u.query_capsule_capabilities.capsule_count = count;
 256
 257        if (HYPERVISOR_platform_op(&op) < 0)
 258                return EFI_UNSUPPORTED;
 259
 260        *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size;
 261        *reset_type = efi_data(op).u.query_capsule_capabilities.reset_type;
 262
 263        return efi_data(op).status;
 264}
 265EXPORT_SYMBOL_GPL(xen_efi_query_capsule_caps);
 266