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. Note that this does not take into account that unsigned long types might exist that are not efi_status_t, but that can be addressed when it becomes an issue. Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx> --- arch/x86/boot/compressed/efi_thunk_64.S | 6 ---- arch/x86/include/asm/efi.h | 38 ++++++++------------ drivers/firmware/efi/libstub/efistub.h | 16 ++++++--- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S index 67e7edcdfea8..0c988f2a1243 100644 --- a/arch/x86/boot/compressed/efi_thunk_64.S +++ b/arch/x86/boot/compressed/efi_thunk_64.S @@ -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 diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 233ae6986d6f..8edead8568ec 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -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 */ \ @@ -344,31 +344,23 @@ 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__)) +static inline efi_status_t __efi64_widen_efi_status(u64 status) +{ + return status ? status ^ 0x8000000080000000ULL : 0; +} -#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__)) +/* The macro below handles dispatching via the thunk if needed */ -#define efi_dxe_call(func, ...) \ +#define efi_fn_call(inst, func, ...) \ (efi_is_native() \ - ? efi_dxe_table->func(__VA_ARGS__) \ - : __efi64_thunk_map(efi_dxe_table, func, __VA_ARGS__)) + ? inst->func(__VA_ARGS__) \ + : __builtin_choose_expr( \ + __builtin_types_compatible_p(efi_status_t, \ + __typeof__(inst->func(__VA_ARGS__))), \ + __efi64_widen_efi_status( \ + __efi64_thunk_map(inst, func, ##__VA_ARGS__)), \ + (__typeof__(inst->func(__VA_ARGS__))) \ + __efi64_thunk_map(inst, func, ##__VA_ARGS__))) #else /* CONFIG_EFI_MIXED */ diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index f403aebf0182..d26d3d7b99c0 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -44,15 +44,21 @@ 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_is_native() (true) #define efi_table_attr(inst, attr) (inst->attr) -#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__) +#define efi_fn_call(inst, func, ...) inst->func(__VA_ARGS__) #endif +#define efi_call_proto(inst, func, ...) \ + 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, ...) \ -- 2.35.1