|
8 | 8 | #include <asm/tlb.h>
|
9 | 9 | #include <asm/nospec-branch.h>
|
10 | 10 | #include <asm/mmu_context.h>
|
| 11 | +#include <linux/build_bug.h> |
11 | 12 |
|
12 | 13 | /*
|
13 | 14 | * We map the EFI regions needed for runtime services non-contiguously,
|
|
34 | 35 |
|
35 | 36 | #define ARCH_EFI_IRQ_FLAGS_MASK X86_EFLAGS_IF
|
36 | 37 |
|
| 38 | +/* |
| 39 | + * The EFI services are called through variadic functions in many cases. These |
| 40 | + * functions are implemented in assembler and support only a fixed number of |
| 41 | + * arguments. The macros below allows us to check at build time that we don't |
| 42 | + * try to call them with too many arguments. |
| 43 | + * |
| 44 | + * __efi_nargs() will return the number of arguments if it is 7 or less, and |
| 45 | + * cause a BUILD_BUG otherwise. The limitations of the C preprocessor make it |
| 46 | + * impossible to calculate the exact number of arguments beyond some |
| 47 | + * pre-defined limit. The maximum number of arguments currently supported by |
| 48 | + * any of the thunks is 7, so this is good enough for now and can be extended |
| 49 | + * in the obvious way if we ever need more. |
| 50 | + */ |
| 51 | + |
| 52 | +#define __efi_nargs(...) __efi_nargs_(__VA_ARGS__) |
| 53 | +#define __efi_nargs_(...) __efi_nargs__(0, ##__VA_ARGS__, \ |
| 54 | + __efi_arg_sentinel(7), __efi_arg_sentinel(6), \ |
| 55 | + __efi_arg_sentinel(5), __efi_arg_sentinel(4), \ |
| 56 | + __efi_arg_sentinel(3), __efi_arg_sentinel(2), \ |
| 57 | + __efi_arg_sentinel(1), __efi_arg_sentinel(0)) |
| 58 | +#define __efi_nargs__(_0, _1, _2, _3, _4, _5, _6, _7, n, ...) \ |
| 59 | + __take_second_arg(n, \ |
| 60 | + ({ BUILD_BUG_ON_MSG(1, "__efi_nargs limit exceeded"); 8; })) |
| 61 | +#define __efi_arg_sentinel(n) , n |
| 62 | + |
| 63 | +/* |
| 64 | + * __efi_nargs_check(f, n, ...) will cause a BUILD_BUG if the ellipsis |
| 65 | + * represents more than n arguments. |
| 66 | + */ |
| 67 | + |
| 68 | +#define __efi_nargs_check(f, n, ...) \ |
| 69 | + __efi_nargs_check_(f, __efi_nargs(__VA_ARGS__), n) |
| 70 | +#define __efi_nargs_check_(f, p, n) __efi_nargs_check__(f, p, n) |
| 71 | +#define __efi_nargs_check__(f, p, n) ({ \ |
| 72 | + BUILD_BUG_ON_MSG( \ |
| 73 | + (p) > (n), \ |
| 74 | + #f " called with too many arguments (" #p ">" #n ")"); \ |
| 75 | +}) |
| 76 | + |
37 | 77 | #ifdef CONFIG_X86_32
|
38 | 78 | #define arch_efi_call_virt_setup() \
|
39 | 79 | ({ \
|
|
56 | 96 |
|
57 | 97 | #define EFI_LOADER_SIGNATURE "EL64"
|
58 | 98 |
|
59 |
| -extern asmlinkage u64 efi_call(void *fp, ...); |
| 99 | +extern asmlinkage u64 __efi_call(void *fp, ...); |
| 100 | + |
| 101 | +#define efi_call(...) ({ \ |
| 102 | + __efi_nargs_check(efi_call, 7, __VA_ARGS__); \ |
| 103 | + __efi_call(__VA_ARGS__); \ |
| 104 | +}) |
60 | 105 |
|
61 | 106 | /*
|
62 | 107 | * struct efi_scratch - Scratch space used while switching to/from efi_mm
|
@@ -139,7 +184,12 @@ struct efi_setup_data {
|
139 | 184 | extern u64 efi_setup;
|
140 | 185 |
|
141 | 186 | #ifdef CONFIG_EFI
|
142 |
| -extern efi_status_t efi64_thunk(u32, ...); |
| 187 | +extern efi_status_t __efi64_thunk(u32, ...); |
| 188 | + |
| 189 | +#define efi64_thunk(...) ({ \ |
| 190 | + __efi_nargs_check(efi64_thunk, 6, __VA_ARGS__); \ |
| 191 | + __efi64_thunk(__VA_ARGS__); \ |
| 192 | +}) |
143 | 193 |
|
144 | 194 | static inline bool efi_is_mixed(void)
|
145 | 195 | {
|
|
0 commit comments