Commit a61962d8 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

efi: libstub: Permit mixed mode return types other than efi_status_t



Rework the EFI stub macro wrappers around protocol method calls and
other indirect calls in order to allow return types other than
efi_status_t. This means the widening should be conditional on whether
or not the return type is efi_status_t, and should be omitted otherwise.

Also, switch to _Generic() to implement the type based compile time
conditionals, which is more concise, and distinguishes between
efi_status_t and u64 properly.

Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 70912985
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -93,12 +93,6 @@ SYM_FUNC_START(__efi64_thunk)
	movl	%ebx, %fs
	movl	%ebx, %gs

	/*
	 * Convert 32-bit status code into 64-bit.
	 */
	roll	$1, %eax
	rorq	$1, %rax

	pop	%rbx
	pop	%rbp
	RET
+30 −35
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ struct efi_setup_data {
extern u64 efi_setup;

#ifdef CONFIG_EFI
extern efi_status_t __efi64_thunk(u32, ...);
extern u64 __efi64_thunk(u32, ...);

#define efi64_thunk(...) ({						\
	u64 __pad[3]; /* must have space for 3 args on the stack */	\
@@ -228,16 +228,15 @@ static inline bool efi_is_native(void)
	return efi_is_64bit();
}

#define efi_mixed_mode_cast(attr)					\
	__builtin_choose_expr(						\
		__builtin_types_compatible_p(u32, __typeof__(attr)),	\
			(unsigned long)(attr), (attr))

#define efi_table_attr(inst, attr)					\
	(efi_is_native()						\
		? inst->attr						\
		: (__typeof__(inst->attr))				\
			efi_mixed_mode_cast(inst->mixed_mode.attr))
	(efi_is_native() ? (inst)->attr					\
			 : efi_mixed_table_attr((inst), attr))

#define efi_mixed_table_attr(inst, attr)				\
	(__typeof__(inst->attr))					\
		_Generic(inst->mixed_mode.attr,				\
		u32:		(unsigned long)(inst->mixed_mode.attr),	\
		default:	(inst->mixed_mode.attr))

/*
 * The following macros allow translating arguments if necessary from native to
@@ -344,31 +343,27 @@ static inline u32 efi64_convert_status(efi_status_t status)
#define __efi_eat(...)
#define __efi_eval(...) __VA_ARGS__

/* The three macros below handle dispatching via the thunk if needed */

#define efi_call_proto(inst, func, ...)					\
	(efi_is_native()						\
		? inst->func(inst, ##__VA_ARGS__)			\
		: __efi64_thunk_map(inst, func, inst, ##__VA_ARGS__))

#define efi_bs_call(func, ...)						\
	(efi_is_native()						\
		? efi_system_table->boottime->func(__VA_ARGS__)		\
		: __efi64_thunk_map(efi_table_attr(efi_system_table,	\
						   boottime),		\
				    func, __VA_ARGS__))

#define efi_rt_call(func, ...)						\
	(efi_is_native()						\
		? efi_system_table->runtime->func(__VA_ARGS__)		\
		: __efi64_thunk_map(efi_table_attr(efi_system_table,	\
						   runtime),		\
				    func, __VA_ARGS__))

#define efi_dxe_call(func, ...)						\
	(efi_is_native()						\
		? efi_dxe_table->func(__VA_ARGS__)			\
		: __efi64_thunk_map(efi_dxe_table, func, __VA_ARGS__))
static inline efi_status_t __efi64_widen_efi_status(u64 status)
{
	/* use rotate to move the value of bit #31 into position #63 */
	return ror64(rol32(status, 1), 1);
}

/* The macro below handles dispatching via the thunk if needed */

#define efi_fn_call(inst, func, ...)					\
	(efi_is_native() ? (inst)->func(__VA_ARGS__)			\
			 : efi_mixed_call((inst), func, ##__VA_ARGS__))

#define efi_mixed_call(inst, func, ...)					\
	_Generic(inst->func(__VA_ARGS__),				\
	efi_status_t:							\
		__efi64_widen_efi_status(				\
			__efi64_thunk_map(inst, func, ##__VA_ARGS__)),	\
	u64: ({ BUILD_BUG(); ULONG_MAX; }),				\
	default:							\
		(__typeof__(inst->func(__VA_ARGS__)))			\
			__efi64_thunk_map(inst, func, ##__VA_ARGS__))

#else /* CONFIG_EFI_MIXED */

+14 −6
Original line number Diff line number Diff line
@@ -45,14 +45,22 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
#ifndef ARCH_HAS_EFISTUB_WRAPPERS

#define efi_is_native()			(true)
#define efi_bs_call(func, ...)	efi_system_table->boottime->func(__VA_ARGS__)
#define efi_rt_call(func, ...)	efi_system_table->runtime->func(__VA_ARGS__)
#define efi_dxe_call(func, ...)	efi_dxe_table->func(__VA_ARGS__)
#define efi_table_attr(inst, attr)	(inst->attr)
#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
#define efi_table_attr(inst, attr)	(inst)->attr
#define efi_fn_call(inst, func, ...)	(inst)->func(__VA_ARGS__)

#endif

#define efi_call_proto(inst, func, ...) ({			\
	__typeof__(inst) __inst = (inst);			\
	efi_fn_call(__inst, func, __inst, ##__VA_ARGS__);	\
})
#define efi_bs_call(func, ...) \
	efi_fn_call(efi_table_attr(efi_system_table, boottime), func, ##__VA_ARGS__)
#define efi_rt_call(func, ...) \
	efi_fn_call(efi_table_attr(efi_system_table, runtime), func, ##__VA_ARGS__)
#define efi_dxe_call(func, ...) \
	efi_fn_call(efi_dxe_table, func, ##__VA_ARGS__)

#define efi_info(fmt, ...) \
	efi_printk(KERN_INFO fmt, ##__VA_ARGS__)
#define efi_warn(fmt, ...) \