brintos

brintos / linux-shallow public Read only

0
0
Text · 16.3 KiB · 708b777 Raw
590 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * runtime-wrappers.c - Runtime Services function call wrappers4 *5 * Implementation summary:6 * -----------------------7 * 1. When user/kernel thread requests to execute efi_runtime_service(),8 * enqueue work to efi_rts_wq.9 * 2. Caller thread waits for completion until the work is finished10 * because it's dependent on the return status and execution of11 * efi_runtime_service().12 * For instance, get_variable() and get_next_variable().13 *14 * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>15 *16 * Split off from arch/x86/platform/efi/efi.c17 *18 * Copyright (C) 1999 VA Linux Systems19 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>20 * Copyright (C) 1999-2002 Hewlett-Packard Co.21 * Copyright (C) 2005-2008 Intel Co.22 * Copyright (C) 2013 SuSE Labs23 */24 25#define pr_fmt(fmt)	"efi: " fmt26 27#include <linux/bug.h>28#include <linux/efi.h>29#include <linux/irqflags.h>30#include <linux/mutex.h>31#include <linux/semaphore.h>32#include <linux/stringify.h>33#include <linux/workqueue.h>34#include <linux/completion.h>35 36#include <asm/efi.h>37 38/*39 * Wrap around the new efi_call_virt_generic() macros so that the40 * code doesn't get too cluttered:41 */42#define efi_call_virt(f, args...)   \43	arch_efi_call_virt(efi.runtime, f, args)44 45union efi_rts_args {46	struct {47		efi_time_t 	*time;48		efi_time_cap_t	*capabilities;49	} GET_TIME;50 51	struct {52		efi_time_t	*time;53	} SET_TIME;54 55	struct {56		efi_bool_t	*enabled;57		efi_bool_t	*pending;58		efi_time_t	*time;59	} GET_WAKEUP_TIME;60 61	struct {62		efi_bool_t	enable;63		efi_time_t	*time;64	} SET_WAKEUP_TIME;65 66	struct {67		efi_char16_t	*name;68		efi_guid_t	*vendor;69		u32		*attr;70		unsigned long	*data_size;71		void		*data;72	} GET_VARIABLE;73 74	struct {75		unsigned long	*name_size;76		efi_char16_t	*name;77		efi_guid_t 	*vendor;78	} GET_NEXT_VARIABLE;79 80	struct {81		efi_char16_t	*name;82		efi_guid_t	*vendor;83		u32		attr;84		unsigned long	data_size;85		void		*data;86	} SET_VARIABLE;87 88	struct {89		u32		attr;90		u64		*storage_space;91		u64		*remaining_space;92		u64		*max_variable_size;93	} QUERY_VARIABLE_INFO;94 95	struct {96		u32		*high_count;97	} GET_NEXT_HIGH_MONO_COUNT;98 99	struct {100		efi_capsule_header_t **capsules;101		unsigned long	count;102		unsigned long	sg_list;103	} UPDATE_CAPSULE;104 105	struct {106		efi_capsule_header_t **capsules;107		unsigned long	count;108		u64		*max_size;109		int		*reset_type;110	} QUERY_CAPSULE_CAPS;111 112	struct {113		efi_status_t	(__efiapi *acpi_prm_handler)(u64, void *);114		u64		param_buffer_addr;115		void		*context;116	} ACPI_PRM_HANDLER;117};118 119struct efi_runtime_work efi_rts_work;120 121/*122 * efi_queue_work:	Queue EFI runtime service call and wait for completion123 * @_rts:		EFI runtime service function identifier124 * @_args:		Arguments to pass to the EFI runtime service125 *126 * Accesses to efi_runtime_services() are serialized by a binary127 * semaphore (efi_runtime_lock) and caller waits until the work is128 * finished, hence _only_ one work is queued at a time and the caller129 * thread waits for completion.130 */131#define efi_queue_work(_rts, _args...)					\132	__efi_queue_work(EFI_ ## _rts,					\133			 &(union efi_rts_args){ ._rts = { _args }})134 135#ifndef arch_efi_save_flags136#define arch_efi_save_flags(state_flags)	local_save_flags(state_flags)137#define arch_efi_restore_flags(state_flags)	local_irq_restore(state_flags)138#endif139 140unsigned long efi_call_virt_save_flags(void)141{142	unsigned long flags;143 144	arch_efi_save_flags(flags);145	return flags;146}147 148void efi_call_virt_check_flags(unsigned long flags, const void *caller)149{150	unsigned long cur_flags, mismatch;151 152	cur_flags = efi_call_virt_save_flags();153 154	mismatch = flags ^ cur_flags;155	if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK))156		return;157 158	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE);159	pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI call from %pS\n",160			   flags, cur_flags, caller ?: __builtin_return_address(0));161	arch_efi_restore_flags(flags);162}163 164/*165 * According to section 7.1 of the UEFI spec, Runtime Services are not fully166 * reentrant, and there are particular combinations of calls that need to be167 * serialized. (source: UEFI Specification v2.4A)168 *169 * Table 31. Rules for Reentry Into Runtime Services170 * +------------------------------------+-------------------------------+171 * | If previous call is busy in	| Forbidden to call		|172 * +------------------------------------+-------------------------------+173 * | Any				| SetVirtualAddressMap()	|174 * +------------------------------------+-------------------------------+175 * | ConvertPointer()			| ConvertPointer()		|176 * +------------------------------------+-------------------------------+177 * | SetVariable()			| ResetSystem()			|178 * | UpdateCapsule()			|				|179 * | SetTime()				|				|180 * | SetWakeupTime()			|				|181 * | GetNextHighMonotonicCount()	|				|182 * +------------------------------------+-------------------------------+183 * | GetVariable()			| GetVariable()			|184 * | GetNextVariableName()		| GetNextVariableName()		|185 * | SetVariable()			| SetVariable()			|186 * | QueryVariableInfo()		| QueryVariableInfo()		|187 * | UpdateCapsule()			| UpdateCapsule()		|188 * | QueryCapsuleCapabilities()		| QueryCapsuleCapabilities()	|189 * | GetNextHighMonotonicCount()	| GetNextHighMonotonicCount()	|190 * +------------------------------------+-------------------------------+191 * | GetTime()				| GetTime()			|192 * | SetTime()				| SetTime()			|193 * | GetWakeupTime()			| GetWakeupTime()		|194 * | SetWakeupTime()			| SetWakeupTime()		|195 * +------------------------------------+-------------------------------+196 *197 * Due to the fact that the EFI pstore may write to the variable store in198 * interrupt context, we need to use a lock for at least the groups that199 * contain SetVariable() and QueryVariableInfo(). That leaves little else, as200 * none of the remaining functions are actually ever called at runtime.201 * So let's just use a single lock to serialize all Runtime Services calls.202 */203static DEFINE_SEMAPHORE(efi_runtime_lock, 1);204 205/*206 * Expose the EFI runtime lock to the UV platform207 */208#ifdef CONFIG_X86_UV209extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);210#endif211 212/*213 * Calls the appropriate efi_runtime_service() with the appropriate214 * arguments.215 */216static void __nocfi efi_call_rts(struct work_struct *work)217{218	const union efi_rts_args *args = efi_rts_work.args;219	efi_status_t status = EFI_NOT_FOUND;220	unsigned long flags;221 222	arch_efi_call_virt_setup();223	flags = efi_call_virt_save_flags();224 225	switch (efi_rts_work.efi_rts_id) {226	case EFI_GET_TIME:227		status = efi_call_virt(get_time,228				       args->GET_TIME.time,229				       args->GET_TIME.capabilities);230		break;231	case EFI_SET_TIME:232		status = efi_call_virt(set_time,233				       args->SET_TIME.time);234		break;235	case EFI_GET_WAKEUP_TIME:236		status = efi_call_virt(get_wakeup_time,237				       args->GET_WAKEUP_TIME.enabled,238				       args->GET_WAKEUP_TIME.pending,239				       args->GET_WAKEUP_TIME.time);240		break;241	case EFI_SET_WAKEUP_TIME:242		status = efi_call_virt(set_wakeup_time,243				       args->SET_WAKEUP_TIME.enable,244				       args->SET_WAKEUP_TIME.time);245		break;246	case EFI_GET_VARIABLE:247		status = efi_call_virt(get_variable,248				       args->GET_VARIABLE.name,249				       args->GET_VARIABLE.vendor,250				       args->GET_VARIABLE.attr,251				       args->GET_VARIABLE.data_size,252				       args->GET_VARIABLE.data);253		break;254	case EFI_GET_NEXT_VARIABLE:255		status = efi_call_virt(get_next_variable,256				       args->GET_NEXT_VARIABLE.name_size,257				       args->GET_NEXT_VARIABLE.name,258				       args->GET_NEXT_VARIABLE.vendor);259		break;260	case EFI_SET_VARIABLE:261		status = efi_call_virt(set_variable,262				       args->SET_VARIABLE.name,263				       args->SET_VARIABLE.vendor,264				       args->SET_VARIABLE.attr,265				       args->SET_VARIABLE.data_size,266				       args->SET_VARIABLE.data);267		break;268	case EFI_QUERY_VARIABLE_INFO:269		status = efi_call_virt(query_variable_info,270				       args->QUERY_VARIABLE_INFO.attr,271				       args->QUERY_VARIABLE_INFO.storage_space,272				       args->QUERY_VARIABLE_INFO.remaining_space,273				       args->QUERY_VARIABLE_INFO.max_variable_size);274		break;275	case EFI_GET_NEXT_HIGH_MONO_COUNT:276		status = efi_call_virt(get_next_high_mono_count,277				       args->GET_NEXT_HIGH_MONO_COUNT.high_count);278		break;279	case EFI_UPDATE_CAPSULE:280		status = efi_call_virt(update_capsule,281				       args->UPDATE_CAPSULE.capsules,282				       args->UPDATE_CAPSULE.count,283				       args->UPDATE_CAPSULE.sg_list);284		break;285	case EFI_QUERY_CAPSULE_CAPS:286		status = efi_call_virt(query_capsule_caps,287				       args->QUERY_CAPSULE_CAPS.capsules,288				       args->QUERY_CAPSULE_CAPS.count,289				       args->QUERY_CAPSULE_CAPS.max_size,290				       args->QUERY_CAPSULE_CAPS.reset_type);291		break;292	case EFI_ACPI_PRM_HANDLER:293#ifdef CONFIG_ACPI_PRMT294		status = arch_efi_call_virt(args, ACPI_PRM_HANDLER.acpi_prm_handler,295					    args->ACPI_PRM_HANDLER.param_buffer_addr,296					    args->ACPI_PRM_HANDLER.context);297		break;298#endif299	default:300		/*301		 * Ideally, we should never reach here because a caller of this302		 * function should have put the right efi_runtime_service()303		 * function identifier into efi_rts_work->efi_rts_id304		 */305		pr_err("Requested executing invalid EFI Runtime Service.\n");306	}307 308	efi_call_virt_check_flags(flags, efi_rts_work.caller);309	arch_efi_call_virt_teardown();310 311	efi_rts_work.status = status;312	complete(&efi_rts_work.efi_rts_comp);313}314 315static efi_status_t __efi_queue_work(enum efi_rts_ids id,316				     union efi_rts_args *args)317{318	efi_rts_work.efi_rts_id = id;319	efi_rts_work.args = args;320	efi_rts_work.caller = __builtin_return_address(0);321	efi_rts_work.status = EFI_ABORTED;322 323	if (!efi_enabled(EFI_RUNTIME_SERVICES)) {324		pr_warn_once("EFI Runtime Services are disabled!\n");325		efi_rts_work.status = EFI_DEVICE_ERROR;326		goto exit;327	}328 329	init_completion(&efi_rts_work.efi_rts_comp);330	INIT_WORK(&efi_rts_work.work, efi_call_rts);331 332	/*333	 * queue_work() returns 0 if work was already on queue,334	 * _ideally_ this should never happen.335	 */336	if (queue_work(efi_rts_wq, &efi_rts_work.work))337		wait_for_completion(&efi_rts_work.efi_rts_comp);338	else339		pr_err("Failed to queue work to efi_rts_wq.\n");340 341	WARN_ON_ONCE(efi_rts_work.status == EFI_ABORTED);342exit:343	efi_rts_work.efi_rts_id = EFI_NONE;344	return efi_rts_work.status;345}346 347static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)348{349	efi_status_t status;350 351	if (down_interruptible(&efi_runtime_lock))352		return EFI_ABORTED;353	status = efi_queue_work(GET_TIME, tm, tc);354	up(&efi_runtime_lock);355	return status;356}357 358static efi_status_t virt_efi_set_time(efi_time_t *tm)359{360	efi_status_t status;361 362	if (down_interruptible(&efi_runtime_lock))363		return EFI_ABORTED;364	status = efi_queue_work(SET_TIME, tm);365	up(&efi_runtime_lock);366	return status;367}368 369static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,370					     efi_bool_t *pending,371					     efi_time_t *tm)372{373	efi_status_t status;374 375	if (down_interruptible(&efi_runtime_lock))376		return EFI_ABORTED;377	status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm);378	up(&efi_runtime_lock);379	return status;380}381 382static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)383{384	efi_status_t status;385 386	if (down_interruptible(&efi_runtime_lock))387		return EFI_ABORTED;388	status = efi_queue_work(SET_WAKEUP_TIME, enabled, tm);389	up(&efi_runtime_lock);390	return status;391}392 393static efi_status_t virt_efi_get_variable(efi_char16_t *name,394					  efi_guid_t *vendor,395					  u32 *attr,396					  unsigned long *data_size,397					  void *data)398{399	efi_status_t status;400 401	if (down_interruptible(&efi_runtime_lock))402		return EFI_ABORTED;403	status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,404				data);405	up(&efi_runtime_lock);406	return status;407}408 409static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,410					       efi_char16_t *name,411					       efi_guid_t *vendor)412{413	efi_status_t status;414 415	if (down_interruptible(&efi_runtime_lock))416		return EFI_ABORTED;417	status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor);418	up(&efi_runtime_lock);419	return status;420}421 422static efi_status_t virt_efi_set_variable(efi_char16_t *name,423					  efi_guid_t *vendor,424					  u32 attr,425					  unsigned long data_size,426					  void *data)427{428	efi_status_t status;429 430	if (down_interruptible(&efi_runtime_lock))431		return EFI_ABORTED;432	status = efi_queue_work(SET_VARIABLE, name, vendor, attr, data_size,433				data);434	up(&efi_runtime_lock);435	return status;436}437 438static efi_status_t __nocfi439virt_efi_set_variable_nb(efi_char16_t *name, efi_guid_t *vendor, u32 attr,440			 unsigned long data_size, void *data)441{442	efi_status_t status;443 444	if (down_trylock(&efi_runtime_lock))445		return EFI_NOT_READY;446 447	status = efi_call_virt_pointer(efi.runtime, set_variable, name, vendor,448				       attr, data_size, data);449	up(&efi_runtime_lock);450	return status;451}452 453 454static efi_status_t virt_efi_query_variable_info(u32 attr,455						 u64 *storage_space,456						 u64 *remaining_space,457						 u64 *max_variable_size)458{459	efi_status_t status;460 461	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)462		return EFI_UNSUPPORTED;463 464	if (down_interruptible(&efi_runtime_lock))465		return EFI_ABORTED;466	status = efi_queue_work(QUERY_VARIABLE_INFO, attr, storage_space,467				remaining_space, max_variable_size);468	up(&efi_runtime_lock);469	return status;470}471 472static efi_status_t __nocfi473virt_efi_query_variable_info_nb(u32 attr, u64 *storage_space,474				u64 *remaining_space, u64 *max_variable_size)475{476	efi_status_t status;477 478	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)479		return EFI_UNSUPPORTED;480 481	if (down_trylock(&efi_runtime_lock))482		return EFI_NOT_READY;483 484	status = efi_call_virt_pointer(efi.runtime, query_variable_info, attr,485				       storage_space, remaining_space,486				       max_variable_size);487	up(&efi_runtime_lock);488	return status;489}490 491static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)492{493	efi_status_t status;494 495	if (down_interruptible(&efi_runtime_lock))496		return EFI_ABORTED;497	status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count);498	up(&efi_runtime_lock);499	return status;500}501 502static void __nocfi503virt_efi_reset_system(int reset_type, efi_status_t status,504		      unsigned long data_size, efi_char16_t *data)505{506	if (down_trylock(&efi_runtime_lock)) {507		pr_warn("failed to invoke the reset_system() runtime service:\n"508			"could not get exclusive access to the firmware\n");509		return;510	}511 512	arch_efi_call_virt_setup();513	efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM;514	arch_efi_call_virt(efi.runtime, reset_system, reset_type, status,515			   data_size, data);516	arch_efi_call_virt_teardown();517 518	up(&efi_runtime_lock);519}520 521static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,522					    unsigned long count,523					    unsigned long sg_list)524{525	efi_status_t status;526 527	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)528		return EFI_UNSUPPORTED;529 530	if (down_interruptible(&efi_runtime_lock))531		return EFI_ABORTED;532	status = efi_queue_work(UPDATE_CAPSULE, capsules, count, sg_list);533	up(&efi_runtime_lock);534	return status;535}536 537static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,538						unsigned long count,539						u64 *max_size,540						int *reset_type)541{542	efi_status_t status;543 544	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)545		return EFI_UNSUPPORTED;546 547	if (down_interruptible(&efi_runtime_lock))548		return EFI_ABORTED;549	status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, count,550				max_size, reset_type);551	up(&efi_runtime_lock);552	return status;553}554 555void __init efi_native_runtime_setup(void)556{557	efi.get_time			    = virt_efi_get_time;558	efi.set_time			    = virt_efi_set_time;559	efi.get_wakeup_time		    = virt_efi_get_wakeup_time;560	efi.set_wakeup_time		    = virt_efi_set_wakeup_time;561	efi.get_variable		    = virt_efi_get_variable;562	efi.get_next_variable		    = virt_efi_get_next_variable;563	efi.set_variable		    = virt_efi_set_variable;564	efi.set_variable_nonblocking	    = virt_efi_set_variable_nb;565	efi.get_next_high_mono_count	    = virt_efi_get_next_high_mono_count;566	efi.reset_system 		    = virt_efi_reset_system;567	efi.query_variable_info		    = virt_efi_query_variable_info;568	efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nb;569	efi.update_capsule		    = virt_efi_update_capsule;570	efi.query_capsule_caps		    = virt_efi_query_capsule_caps;571}572 573#ifdef CONFIG_ACPI_PRMT574 575efi_status_t576efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *),577			  u64 param_buffer_addr, void *context)578{579	efi_status_t status;580 581	if (down_interruptible(&efi_runtime_lock))582		return EFI_ABORTED;583	status = efi_queue_work(ACPI_PRM_HANDLER, handler_addr,584				param_buffer_addr, context);585	up(&efi_runtime_lock);586	return status;587}588 589#endif590