cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efi.c (8708B)


      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
     43static 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
     65static 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
     78static 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
    101static 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
    119static 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
    142static 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
    165static 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
    185static 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
    206static 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
    218static 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
    237static 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
    258static 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 */
    278void __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}