Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Ard Biesheuvel <ardb@kernel.org>

+41 -44
-6
arch/x86/boot/compressed/efi_thunk_64.S
··· 93 93 movl %ebx, %fs 94 94 movl %ebx, %gs 95 95 96 - /* 97 - * Convert 32-bit status code into 64-bit. 98 - */ 99 - roll $1, %eax 100 - rorq $1, %rax 101 - 102 96 pop %rbx 103 97 pop %rbp 104 98 RET
+27 -32
arch/x86/include/asm/efi.h
··· 178 178 extern u64 efi_setup; 179 179 180 180 #ifdef CONFIG_EFI 181 - extern efi_status_t __efi64_thunk(u32, ...); 181 + extern u64 __efi64_thunk(u32, ...); 182 182 183 183 #define efi64_thunk(...) ({ \ 184 184 u64 __pad[3]; /* must have space for 3 args on the stack */ \ ··· 228 228 return efi_is_64bit(); 229 229 } 230 230 231 - #define efi_mixed_mode_cast(attr) \ 232 - __builtin_choose_expr( \ 233 - __builtin_types_compatible_p(u32, __typeof__(attr)), \ 234 - (unsigned long)(attr), (attr)) 235 - 236 231 #define efi_table_attr(inst, attr) \ 237 - (efi_is_native() \ 238 - ? inst->attr \ 239 - : (__typeof__(inst->attr)) \ 240 - efi_mixed_mode_cast(inst->mixed_mode.attr)) 232 + (efi_is_native() ? (inst)->attr \ 233 + : efi_mixed_table_attr((inst), attr)) 234 + 235 + #define efi_mixed_table_attr(inst, attr) \ 236 + (__typeof__(inst->attr)) \ 237 + _Generic(inst->mixed_mode.attr, \ 238 + u32: (unsigned long)(inst->mixed_mode.attr), \ 239 + default: (inst->mixed_mode.attr)) 241 240 242 241 /* 243 242 * The following macros allow translating arguments if necessary from native to ··· 343 344 #define __efi_eat(...) 344 345 #define __efi_eval(...) __VA_ARGS__ 345 346 346 - /* The three macros below handle dispatching via the thunk if needed */ 347 + static inline efi_status_t __efi64_widen_efi_status(u64 status) 348 + { 349 + /* use rotate to move the value of bit #31 into position #63 */ 350 + return ror64(rol32(status, 1), 1); 351 + } 347 352 348 - #define efi_call_proto(inst, func, ...) \ 349 - (efi_is_native() \ 350 - ? inst->func(inst, ##__VA_ARGS__) \ 351 - : __efi64_thunk_map(inst, func, inst, ##__VA_ARGS__)) 353 + /* The macro below handles dispatching via the thunk if needed */ 352 354 353 - #define efi_bs_call(func, ...) \ 354 - (efi_is_native() \ 355 - ? efi_system_table->boottime->func(__VA_ARGS__) \ 356 - : __efi64_thunk_map(efi_table_attr(efi_system_table, \ 357 - boottime), \ 358 - func, __VA_ARGS__)) 355 + #define efi_fn_call(inst, func, ...) \ 356 + (efi_is_native() ? (inst)->func(__VA_ARGS__) \ 357 + : efi_mixed_call((inst), func, ##__VA_ARGS__)) 359 358 360 - #define efi_rt_call(func, ...) \ 361 - (efi_is_native() \ 362 - ? efi_system_table->runtime->func(__VA_ARGS__) \ 363 - : __efi64_thunk_map(efi_table_attr(efi_system_table, \ 364 - runtime), \ 365 - func, __VA_ARGS__)) 366 - 367 - #define efi_dxe_call(func, ...) \ 368 - (efi_is_native() \ 369 - ? efi_dxe_table->func(__VA_ARGS__) \ 370 - : __efi64_thunk_map(efi_dxe_table, func, __VA_ARGS__)) 359 + #define efi_mixed_call(inst, func, ...) \ 360 + _Generic(inst->func(__VA_ARGS__), \ 361 + efi_status_t: \ 362 + __efi64_widen_efi_status( \ 363 + __efi64_thunk_map(inst, func, ##__VA_ARGS__)), \ 364 + u64: ({ BUILD_BUG(); ULONG_MAX; }), \ 365 + default: \ 366 + (__typeof__(inst->func(__VA_ARGS__))) \ 367 + __efi64_thunk_map(inst, func, ##__VA_ARGS__)) 371 368 372 369 #else /* CONFIG_EFI_MIXED */ 373 370
+14 -6
drivers/firmware/efi/libstub/efistub.h
··· 44 44 45 45 #ifndef ARCH_HAS_EFISTUB_WRAPPERS 46 46 47 - #define efi_is_native() (true) 48 - #define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__) 49 - #define efi_rt_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__) 50 - #define efi_dxe_call(func, ...) efi_dxe_table->func(__VA_ARGS__) 51 - #define efi_table_attr(inst, attr) (inst->attr) 52 - #define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__) 47 + #define efi_is_native() (true) 48 + #define efi_table_attr(inst, attr) (inst)->attr 49 + #define efi_fn_call(inst, func, ...) (inst)->func(__VA_ARGS__) 53 50 54 51 #endif 52 + 53 + #define efi_call_proto(inst, func, ...) ({ \ 54 + __typeof__(inst) __inst = (inst); \ 55 + efi_fn_call(__inst, func, __inst, ##__VA_ARGS__); \ 56 + }) 57 + #define efi_bs_call(func, ...) \ 58 + efi_fn_call(efi_table_attr(efi_system_table, boottime), func, ##__VA_ARGS__) 59 + #define efi_rt_call(func, ...) \ 60 + efi_fn_call(efi_table_attr(efi_system_table, runtime), func, ##__VA_ARGS__) 61 + #define efi_dxe_call(func, ...) \ 62 + efi_fn_call(efi_dxe_table, func, ##__VA_ARGS__) 55 63 56 64 #define efi_info(fmt, ...) \ 57 65 efi_printk(KERN_INFO fmt, ##__VA_ARGS__)