aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/efi.h2
-rw-r--r--arch/arm64/include/asm/efi.h2
-rw-r--r--arch/x86/boot/compressed/eboot.c3
-rw-r--r--arch/x86/include/asm/efi.h35
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c45
-rw-r--r--include/linux/efi.h6
6 files changed, 49 insertions, 44 deletions
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 2306ed783ceb..9b0c64c28bff 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -52,7 +52,7 @@ void efi_virtmap_unload(void);
#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
#define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__)
-#define efi_is_64bit() (false)
+#define efi_is_native() (true)
#define efi_table_attr(table, attr, instance) \
((table##_t *)instance)->attr
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 7cfac5e0e310..189082c44c28 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -95,7 +95,7 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
#define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__)
-#define efi_is_64bit() (true)
+#define efi_is_native() (true)
#define efi_table_attr(table, attr, instance) \
((table##_t *)instance)->attr
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 959bcdd8c1fe..990b93379965 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -63,8 +63,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
* large romsize. The UEFI spec limits the size of option ROMs to 16
* MiB so we reject any ROMs over 16 MiB in size to catch this.
*/
- romimage = (void *)(unsigned long)efi_table_attr(efi_pci_io_protocol,
- romimage, pci);
+ romimage = efi_table_attr(efi_pci_io_protocol, romimage, pci);
romsize = efi_table_attr(efi_pci_io_protocol, romsize, pci);
if (!romimage || !romsize || romsize > SZ_16M)
return EFI_INVALID_PARAMETER;
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 6094e7f49a99..c27323cb49e5 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -222,21 +222,42 @@ static inline bool efi_is_64bit(void)
return __efi_early()->is64;
}
-#define efi_table_attr(table, attr, instance) \
- (efi_is_64bit() ? \
- ((table##_64_t *)(unsigned long)instance)->attr : \
- ((table##_32_t *)(unsigned long)instance)->attr)
+static inline bool efi_is_native(void)
+{
+ if (!IS_ENABLED(CONFIG_X86_64))
+ return true;
+ 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(table, attr, instance) ({ \
+ __typeof__(((table##_t *)0)->attr) __ret; \
+ if (efi_is_native()) { \
+ __ret = ((table##_t *)(unsigned long)instance)->attr; \
+ } else { \
+ __ret = (__typeof__(__ret))efi_mixed_mode_cast( \
+ ((table##_t *)(unsigned long)instance)->mixed_mode.attr);\
+ } \
+ __ret; \
+})
#define efi_call_proto(protocol, f, instance, ...) \
- __efi_early()->call(efi_table_attr(protocol, f, instance), \
+ __efi_early()->call((unsigned long) \
+ efi_table_attr(protocol, f, instance), \
instance, ##__VA_ARGS__)
#define efi_call_early(f, ...) \
- __efi_early()->call(efi_table_attr(efi_boot_services, f, \
+ __efi_early()->call((unsigned long) \
+ efi_table_attr(efi_boot_services, f, \
__efi_early()->boot_services), __VA_ARGS__)
#define efi_call_runtime(f, ...) \
- __efi_early()->call(efi_table_attr(efi_runtime_services, f, \
+ __efi_early()->call((unsigned long) \
+ efi_table_attr(efi_runtime_services, f, \
__efi_early()->runtime_services), __VA_ARGS__)
extern bool efi_reboot_required(void);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index e02579907f2e..1a814dc235ba 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -431,9 +431,7 @@ static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
efi_file_handle_t *fh;
efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
efi_status_t status;
- void *handle = (void *)(unsigned long)efi_table_attr(efi_loaded_image,
- device_handle,
- image);
+ void *handle = efi_table_attr(efi_loaded_image, device_handle, image);
status = efi_call_early(handle_protocol, handle,
&fs_proto, (void **)&io);
@@ -942,33 +940,20 @@ fail:
return status;
}
-#define GET_EFI_CONFIG_TABLE(bits) \
-static void *get_efi_config_table##bits(efi_system_table_t *_sys_table, \
- efi_guid_t guid) \
-{ \
- efi_system_table_##bits##_t *sys_table; \
- efi_config_table_##bits##_t *tables; \
- int i; \
- \
- sys_table = (typeof(sys_table))_sys_table; \
- tables = (typeof(tables))(unsigned long)sys_table->tables; \
- \
- for (i = 0; i < sys_table->nr_tables; i++) { \
- if (efi_guidcmp(tables[i].guid, guid) != 0) \
- continue; \
- \
- return (void *)(unsigned long)tables[i].table; \
- } \
- \
- return NULL; \
-}
-GET_EFI_CONFIG_TABLE(32)
-GET_EFI_CONFIG_TABLE(64)
-
void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
{
- if (efi_is_64bit())
- return get_efi_config_table64(sys_table, guid);
- else
- return get_efi_config_table32(sys_table, guid);
+ unsigned long tables = efi_table_attr(efi_system_table, tables, sys_table);
+ int nr_tables = efi_table_attr(efi_system_table, nr_tables, sys_table);
+ int i;
+
+ for (i = 0; i < nr_tables; i++) {
+ efi_config_table_t *t = (void *)tables;
+
+ if (efi_guidcmp(t->guid, guid) == 0)
+ return efi_table_attr(efi_config_table, table, t);
+
+ tables += efi_is_native() ? sizeof(efi_config_table_t)
+ : sizeof(efi_config_table_32_t);
+ }
+ return NULL;
}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5a220af263b1..e9d74e9667c0 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -49,11 +49,11 @@ typedef u64 efi_physical_addr_t;
typedef void *efi_handle_t;
#define efi_get_handle_at(array, idx) \
- (efi_is_64bit() ? (efi_handle_t)(unsigned long)((u64 *)(array))[idx] \
+ (efi_is_native() ? (array)[idx] \
: (efi_handle_t)(unsigned long)((u32 *)(array))[idx])
#define efi_get_handle_num(size) \
- ((size) / (efi_is_64bit() ? sizeof(u64) : sizeof(u32)))
+ ((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32)))
#define for_each_efi_handle(handle, array, size, i) \
for (i = 0; \
@@ -805,7 +805,7 @@ typedef struct {
typedef union {
struct {
efi_guid_t guid;
- unsigned long table;
+ void *table;
};
efi_config_table_32_t mixed_mode;
} efi_config_table_t;