diff options
author | Lukas Wunner <lukas@wunner.de> | 2016-11-12 16:32:35 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-11-13 02:23:16 -0500 |
commit | 3552fdf29f01e5a889e88202dc55b67aa6766620 (patch) | |
tree | 9056eaf32ecad1662fd1cd2af9c1762e0fba1f81 | |
parent | 46cd4b75cd0edee76e0096225c2d31f8d90e92a2 (diff) |
efi: Allow bitness-agnostic protocol calls
We already have a macro to invoke boot services which on x86 adapts
automatically to the bitness of the EFI firmware: efi_call_early().
The macro allows sharing of functions across arches and bitness variants
as long as those functions only call boot services. However in practice
functions in the EFI stub contain a mix of boot services calls and
protocol calls.
Add an efi_call_proto() macro for bitness-agnostic protocol calls to
allow sharing more code across arches as well as deduplicating 32 bit
and 64 bit code paths.
On x86, implement it using a new efi_table_attr() macro for bitness-
agnostic table lookups. Refactor efi_call_early() to make use of the
same macro. (The resulting object code remains identical.)
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Andreas Noever <andreas.noever@gmail.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Jones <pjones@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-8-matt@codeblueprint.co.uk
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/arm/include/asm/efi.h | 3 | ||||
-rw-r--r-- | arch/arm64/include/asm/efi.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/efi.h | 16 |
3 files changed, 17 insertions, 5 deletions
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index 766bf9b78160..0b06f5341b45 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h | |||
@@ -57,6 +57,9 @@ void efi_virtmap_unload(void); | |||
57 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | 57 | #define __efi_call_early(f, ...) f(__VA_ARGS__) |
58 | #define efi_is_64bit() (false) | 58 | #define efi_is_64bit() (false) |
59 | 59 | ||
60 | #define efi_call_proto(protocol, f, instance, ...) \ | ||
61 | ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) | ||
62 | |||
60 | struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg); | 63 | struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg); |
61 | void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si); | 64 | void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si); |
62 | 65 | ||
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index a9e54aad15ef..771b3f0bc757 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h | |||
@@ -51,6 +51,9 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); | |||
51 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | 51 | #define __efi_call_early(f, ...) f(__VA_ARGS__) |
52 | #define efi_is_64bit() (true) | 52 | #define efi_is_64bit() (true) |
53 | 53 | ||
54 | #define efi_call_proto(protocol, f, instance, ...) \ | ||
55 | ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) | ||
56 | |||
54 | #define alloc_screen_info(x...) &screen_info | 57 | #define alloc_screen_info(x...) &screen_info |
55 | #define free_screen_info(x...) | 58 | #define free_screen_info(x...) |
56 | 59 | ||
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 389d700b961e..e99675b9c861 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -210,12 +210,18 @@ static inline bool efi_is_64bit(void) | |||
210 | return __efi_early()->is64; | 210 | return __efi_early()->is64; |
211 | } | 211 | } |
212 | 212 | ||
213 | #define efi_table_attr(table, attr, instance) \ | ||
214 | (efi_is_64bit() ? \ | ||
215 | ((table##_64_t *)(unsigned long)instance)->attr : \ | ||
216 | ((table##_32_t *)(unsigned long)instance)->attr) | ||
217 | |||
218 | #define efi_call_proto(protocol, f, instance, ...) \ | ||
219 | __efi_early()->call(efi_table_attr(protocol, f, instance), \ | ||
220 | instance, ##__VA_ARGS__) | ||
221 | |||
213 | #define efi_call_early(f, ...) \ | 222 | #define efi_call_early(f, ...) \ |
214 | __efi_early()->call(efi_is_64bit() ? \ | 223 | __efi_early()->call(efi_table_attr(efi_boot_services, f, \ |
215 | ((efi_boot_services_64_t *)(unsigned long) \ | 224 | __efi_early()->boot_services), __VA_ARGS__) |
216 | __efi_early()->boot_services)->f : \ | ||
217 | ((efi_boot_services_32_t *)(unsigned long) \ | ||
218 | __efi_early()->boot_services)->f, __VA_ARGS__) | ||
219 | 225 | ||
220 | #define __efi_call_early(f, ...) \ | 226 | #define __efi_call_early(f, ...) \ |
221 | __efi_early()->call((unsigned long)f, __VA_ARGS__); | 227 | __efi_early()->call((unsigned long)f, __VA_ARGS__); |