linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode
@ 2019-12-18 17:01 Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 01/21] efi/libstub: remove unused __efi_call_early() macro Ard Biesheuvel
                   ` (21 more replies)
  0 siblings, 22 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Currently, we support mixed mode (64-bit Linux running on 32-bit firmware)
by explicitly reasoning about pointer sizes for every call into the
firmware: on x86, there are 32-bit and 64-bit versions of each protocol
interface, and each call gets routed via one of the two, depending on the
native size of the firmware.

There is a lot of casting and pointer mangling involved in this, and as
a result, we end up with much less coverage in terms of type checking by
the compiler, due to the indirection via an anonymous, variadic thunking
routine.

This peculiarity of x86 is also leaking into generic EFI code, which is
shared with ia64, arm64, ARM and likely RiscV in the future. So let's
try to clean this up a bit.

The approach taken by this series is to replace the 32/64 bit distinction
with a distinction between native calls and mixed mode calls, where the
former can be either 32 or 64 bit [depending on the platform] and use
the ordinary native protocol definitions, while mixed mode calls retain
the existing casting/thunking approach based on the 32-bit protocol
definitions.

Given that GCC now supports emitting function calls using the MS calling
convention, we can get rid of all the wrapping and casting, and emit the
indirect calls directly.

Changes since v1:
- Substantially more cleanup work to simplify and hide the mixed mode handling
  in generic EFI code.
- Get rid of all the pointless passing around of sys_table_arg
- Incorporate an updated version of Matthew's PCI DMA disable patch using EFI
  events to defer poking the busmaster bits until after all the ordinary
  ExitBootServices() callbacks have executed.

Code can be found here
https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efistub-x86-cleanup-v2

Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Matthew Garrett <matthewgarrett@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arvind Sankar <nivedita@alum.mit.edu>

Ard Biesheuvel (20):
  efi/libstub: remove unused __efi_call_early() macro
  efi/x86: rename efi_is_native() to efi_is_mixed()
  efi/libstub: use a helper to iterate over a EFI handle array
  efi/libstub: extend native protocol definitions with mixed_mode
    aliases
  efi/libstub: distinguish between native/mixed not 32/64 bit
  efi/libstub/x86: use mixed mode helpers to populate efi_config
  efi/libstub: drop explicit 32/64-bit protocol definitions
  efi/libstub: use stricter typing for firmware function pointers
  efi/libstub: annotate firmware routines as __efiapi
  efi/libstub/x86: avoid thunking for native firmware calls
  efi/libstub: get rid of 'sys_table_arg' macro parameter
  efi/libstub: unify the efi_char16_printk implementations
  efi/libstub/x86: drop __efi_early() export of efi_config struct
  efi/libstub: drop sys_table_arg from printk routines
  efi/libstub: remove 'sys_table_arg' from all function prototypes
  efi/libstub: drop protocol argument from efi_call_proto() macro
  efi/libstub: drop 'table' argument from efi_table_attr() macro
  efi/libstub: use 'func' not 'f' as macro parameter
  efi/libstub: tidy up types and names of global cmdline variables
  efi/libstub: import type definitions for creating and signalling
    events

Matthew Garrett (1):
  efi: Allow disabling PCI busmastering on bridges during boot

 .../admin-guide/kernel-parameters.txt         |   4 +
 arch/arm/include/asm/efi.h                    |  17 +-
 arch/arm64/include/asm/efi.h                  |  16 +-
 arch/x86/Kconfig                              |   1 +
 arch/x86/boot/compressed/Makefile             |   2 +-
 arch/x86/boot/compressed/eboot.c              | 180 ++--
 arch/x86/boot/compressed/eboot.h              |  30 +-
 arch/x86/boot/compressed/efi_stub_32.S        |  87 --
 arch/x86/boot/compressed/efi_stub_64.S        |   5 -
 arch/x86/boot/compressed/head_32.S            |   8 +-
 arch/x86/boot/compressed/head_64.S            |  16 +-
 arch/x86/include/asm/efi.h                    |  76 +-
 arch/x86/platform/efi/efi.c                   |  12 +-
 arch/x86/platform/efi/efi_64.c                |   6 +-
 arch/x86/platform/efi/quirks.c                |   2 +-
 drivers/firmware/efi/Kconfig                  |  22 +
 drivers/firmware/efi/libstub/Makefile         |   2 +-
 drivers/firmware/efi/libstub/arm-stub.c       |  98 ++-
 drivers/firmware/efi/libstub/arm32-stub.c     |  40 +-
 drivers/firmware/efi/libstub/arm64-stub.c     |  24 +-
 .../firmware/efi/libstub/efi-stub-helper.c    | 226 +++--
 drivers/firmware/efi/libstub/efistub.h        |  35 +-
 drivers/firmware/efi/libstub/fdt.c            |  53 +-
 drivers/firmware/efi/libstub/gop.c            |  30 +-
 drivers/firmware/efi/libstub/pci.c            | 116 +++
 drivers/firmware/efi/libstub/random.c         |  54 +-
 drivers/firmware/efi/libstub/secureboot.c     |   6 +-
 drivers/firmware/efi/libstub/tpm.c            |  23 +-
 include/linux/efi.h                           | 816 +++++++++---------
 29 files changed, 980 insertions(+), 1027 deletions(-)
 delete mode 100644 arch/x86/boot/compressed/efi_stub_32.S
 delete mode 100644 arch/x86/boot/compressed/efi_stub_64.S
 create mode 100644 drivers/firmware/efi/libstub/pci.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH v2 01/21] efi/libstub: remove unused __efi_call_early() macro
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 02/21] efi/x86: rename efi_is_native() to efi_is_mixed() Ard Biesheuvel
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

The macro __efi_call_early() is defined by various architectures but
never used. Let's get rid of it.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/efi.h   | 1 -
 arch/arm64/include/asm/efi.h | 1 -
 arch/x86/include/asm/efi.h   | 3 ---
 3 files changed, 5 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 7667826b93f1..2306ed783ceb 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -51,7 +51,6 @@ void efi_virtmap_unload(void);
 /* arch specific definitions used by the stub code */
 
 #define efi_call_early(f, ...)		sys_table_arg->boottime->f(__VA_ARGS__)
-#define __efi_call_early(f, ...)	f(__VA_ARGS__)
 #define efi_call_runtime(f, ...)	sys_table_arg->runtime->f(__VA_ARGS__)
 #define efi_is_64bit()			(false)
 
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index b54d3a86c444..7cfac5e0e310 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -94,7 +94,6 @@ 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_early(f, ...)	f(__VA_ARGS__)
 #define efi_call_runtime(f, ...)	sys_table_arg->runtime->f(__VA_ARGS__)
 #define efi_is_64bit()			(true)
 
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index d028e9acdf1c..59c19e0b6027 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -233,9 +233,6 @@ static inline bool efi_is_64bit(void)
 	__efi_early()->call(efi_table_attr(efi_boot_services, f,	\
 		__efi_early()->boot_services), __VA_ARGS__)
 
-#define __efi_call_early(f, ...)					\
-	__efi_early()->call((unsigned long)f, __VA_ARGS__);
-
 #define efi_call_runtime(f, ...)					\
 	__efi_early()->call(efi_table_attr(efi_runtime_services, f,	\
 		__efi_early()->runtime_services), __VA_ARGS__)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 02/21] efi/x86: rename efi_is_native() to efi_is_mixed()
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 01/21] efi/libstub: remove unused __efi_call_early() macro Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 03/21] efi/libstub: use a helper to iterate over a EFI handle array Ard Biesheuvel
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

The ARM architecture does not permit combining 32-bit and 64-bit code
at the same privilege level, and so EFI mixed mode is strictly a x86
concept.

In preparation of turning the 32/64 bit distinction in shared stub
code to a native vs mixed one, refactor x86's current use of the
helper function efi_is_native() into efi_is_mixed().

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/include/asm/efi.h     | 10 ++++++----
 arch/x86/platform/efi/efi.c    |  8 ++++----
 arch/x86/platform/efi/efi_64.c |  4 ++--
 arch/x86/platform/efi/quirks.c |  2 +-
 4 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 59c19e0b6027..6094e7f49a99 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -153,17 +153,19 @@ extern u64 efi_setup;
 
 #ifdef CONFIG_EFI
 
-static inline bool efi_is_native(void)
+static inline bool efi_is_mixed(void)
 {
-	return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
+	if (!IS_ENABLED(CONFIG_EFI_MIXED))
+		return false;
+	return IS_ENABLED(CONFIG_X86_64) && !efi_enabled(EFI_64BIT);
 }
 
 static inline bool efi_runtime_supported(void)
 {
-	if (efi_is_native())
+	if (!efi_is_mixed())
 		return true;
 
-	if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_enabled(EFI_OLD_MEMMAP))
+	if (!efi_enabled(EFI_OLD_MEMMAP))
 		return true;
 
 	return false;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index bb8e37a723d6..1493e964c267 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -848,7 +848,7 @@ static bool should_map_region(efi_memory_desc_t *md)
 	 * Map all of RAM so that we can access arguments in the 1:1
 	 * mapping when making EFI runtime calls.
 	 */
-	if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_native()) {
+	if (efi_is_mixed()) {
 		if (md->type == EFI_CONVENTIONAL_MEMORY ||
 		    md->type == EFI_LOADER_DATA ||
 		    md->type == EFI_LOADER_CODE)
@@ -923,7 +923,7 @@ static void __init kexec_enter_virtual_mode(void)
 	 * kexec kernel because in the initial boot something else might
 	 * have been mapped at these virtual addresses.
 	 */
-	if (!efi_is_native() || efi_enabled(EFI_OLD_MEMMAP)) {
+	if (efi_is_mixed() || efi_enabled(EFI_OLD_MEMMAP)) {
 		efi_memmap_unmap();
 		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 		return;
@@ -1060,7 +1060,7 @@ static void __init __efi_enter_virtual_mode(void)
 
 	efi_sync_low_kernel_mappings();
 
-	if (efi_is_native()) {
+	if (!efi_is_mixed()) {
 		status = phys_efi_set_virtual_address_map(
 				efi.memmap.desc_size * count,
 				efi.memmap.desc_size,
@@ -1091,7 +1091,7 @@ static void __init __efi_enter_virtual_mode(void)
 	 */
 	efi.runtime_version = efi_systab.hdr.revision;
 
-	if (efi_is_native())
+	if (!efi_is_mixed())
 		efi_native_runtime_setup();
 	else
 		efi_thunk_runtime_setup();
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 08ce8177c3af..885e50a707a6 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -388,7 +388,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	 * text and allocate a new stack because we can't rely on the
 	 * stack pointer being < 4GB.
 	 */
-	if (!IS_ENABLED(CONFIG_EFI_MIXED) || efi_is_native())
+	if (!efi_is_mixed())
 		return 0;
 
 	page = alloc_page(GFP_KERNEL|__GFP_DMA32);
@@ -449,7 +449,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
 	 * booting in EFI mixed mode, because even though we may be
 	 * running a 64-bit kernel, the firmware may only be 32-bit.
 	 */
-	if (!efi_is_native () && IS_ENABLED(CONFIG_EFI_MIXED)) {
+	if (efi_is_mixed()) {
 		md->virt_addr = md->phys_addr;
 		return;
 	}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 7675cf754d90..84d7176983d2 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -397,7 +397,7 @@ static void __init efi_unmap_pages(efi_memory_desc_t *md)
 	 * EFI runtime calls, hence don't unmap EFI boot services code/data
 	 * regions.
 	 */
-	if (!efi_is_native())
+	if (efi_is_mixed())
 		return;
 
 	if (kernel_unmap_pages_in_pgd(pgd, pa, md->num_pages))
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 03/21] efi/libstub: use a helper to iterate over a EFI handle array
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 01/21] efi/libstub: remove unused __efi_call_early() macro Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 02/21] efi/x86: rename efi_is_native() to efi_is_mixed() Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 04/21] efi/libstub: extend native protocol definitions with mixed_mode aliases Ard Biesheuvel
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Iterating over a EFI handle array is a bit finicky, since we have
to take mixed mode into account, where handles are only 32-bit
while the native efi_handle_t type is 64-bit.

So introduce a helper, and replace the various occurrences of
this pattern.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.c   | 14 +++++---------
 drivers/firmware/efi/libstub/gop.c |  9 ++-------
 include/linux/efi.h                | 13 +++++++++++++
 3 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 72b08fde6de6..959bcdd8c1fe 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -135,6 +135,7 @@ static void setup_efi_pci(struct boot_params *params)
 	unsigned long size = 0;
 	unsigned long nr_pci;
 	struct setup_data *data;
+	efi_handle_t h;
 	int i;
 
 	status = efi_call_early(locate_handle,
@@ -164,14 +165,11 @@ static void setup_efi_pci(struct boot_params *params)
 	while (data && data->next)
 		data = (struct setup_data *)(unsigned long)data->next;
 
-	nr_pci = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32));
-	for (i = 0; i < nr_pci; i++) {
+	for_each_efi_handle(h, pci_handle, size, i) {
 		efi_pci_io_protocol_t *pci = NULL;
 		struct pci_setup_rom *rom;
 
-		status = efi_call_early(handle_protocol,
-					efi_is_64bit() ? ((u64 *)pci_handle)[i]
-						       : ((u32 *)pci_handle)[i],
+		status = efi_call_early(handle_protocol, h,
 					&pci_proto, (void **)&pci);
 		if (status != EFI_SUCCESS || !pci)
 			continue;
@@ -266,6 +264,7 @@ setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
 	void **uga_handle = NULL;
 	efi_uga_draw_protocol_t *uga = NULL, *first_uga;
 	unsigned long nr_ugas;
+	efi_handle_t handle;
 	int i;
 
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
@@ -283,13 +282,10 @@ setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
 	width = 0;
 
 	first_uga = NULL;
-	nr_ugas = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32));
-	for (i = 0; i < nr_ugas; i++) {
+	for_each_efi_handle(handle, uga_handle, size, i) {
 		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
 		u32 w, h, depth, refresh;
 		void *pciio;
-		unsigned long handle = efi_is_64bit() ? ((u64 *)uga_handle)[i]
-						      : ((u32 *)uga_handle)[i];
 
 		status = efi_call_early(handle_protocol, handle,
 					uga_proto, (void **)&uga);
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 94045ab7dd3d..5f4fbc2ac687 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -91,7 +91,6 @@ setup_gop(efi_system_table_t *sys_table_arg, struct screen_info *si,
 	  efi_guid_t *proto, unsigned long size, void **handles)
 {
 	efi_graphics_output_protocol_t *gop, *first_gop;
-	unsigned long nr_gops;
 	u16 width, height;
 	u32 pixels_per_scan_line;
 	u32 ext_lfb_base;
@@ -99,22 +98,18 @@ setup_gop(efi_system_table_t *sys_table_arg, struct screen_info *si,
 	efi_pixel_bitmask_t pixel_info;
 	int pixel_format;
 	efi_status_t status;
+	efi_handle_t h;
 	int i;
-	bool is64 = efi_is_64bit();
 
 	first_gop = NULL;
 	gop = NULL;
 
-	nr_gops = size / (is64 ? sizeof(u64) : sizeof(u32));
-	for (i = 0; i < nr_gops; i++) {
+	for_each_efi_handle(h, handles, size, i) {
 		efi_graphics_output_protocol_mode_t *mode;
 		efi_graphics_output_mode_info_t *info = NULL;
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
 		bool conout_found = false;
 		void *dummy = NULL;
-		efi_handle_t h = (efi_handle_t)(unsigned long)
-				 (is64 ? ((u64 *)handles)[i]
-				       : ((u32 *)handles)[i]);
 		efi_physical_addr_t current_fb_base;
 
 		status = efi_call_early(handle_protocol, h,
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ea0b43878c59..3e3d9602647a 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -48,6 +48,19 @@ typedef u16 efi_char16_t;		/* UNICODE character */
 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_handle_t)(unsigned long)((u32 *)(array))[idx])
+
+#define efi_get_handle_num(size)					\
+	((size) / (efi_is_64bit() ? sizeof(u64) : sizeof(u32)))
+
+#define for_each_efi_handle(handle, array, size, i)			\
+	for (i = 0;							\
+	     i < efi_get_handle_num(size) &&				\
+		((handle = efi_get_handle_at((array), i)) || true);	\
+	     i++)
+
 /*
  * The UEFI spec and EDK2 reference implementation both define EFI_GUID as
  * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 04/21] efi/libstub: extend native protocol definitions with mixed_mode aliases
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 03/21] efi/libstub: use a helper to iterate over a EFI handle array Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 05/21] efi/libstub: distinguish between native/mixed not 32/64 bit Ard Biesheuvel
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

In preparation of moving to a native vs. mixed mode split rather than a
32 vs. 64 bit split when it comes to invoking EFI firmware services,
update all the native protocol definitions and redefine them as unions
containing an anonymous struct for the native view and a struct called
'mixed_mode' describing the 32-bit view of the protocol when called from
64-bit code.

While at it, flesh out some PCI I/O member definitions that we will be
needing shortly.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.h        |  15 +-
 drivers/firmware/efi/libstub/arm-stub.c |   4 +-
 drivers/firmware/efi/libstub/random.c   |  22 +-
 include/linux/efi.h                     | 506 +++++++++++++-------
 4 files changed, 365 insertions(+), 182 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index 8297387c4676..26f1f2635f64 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -24,10 +24,17 @@ typedef struct {
 	u64 blt;
 } efi_uga_draw_protocol_64_t;
 
-typedef struct {
-	void *get_mode;
-	void *set_mode;
-	void *blt;
+typedef union {
+	struct {
+		void *get_mode;
+		void *set_mode;
+		void *blt;
+	};
+	struct {
+		u32 get_mode;
+		u32 set_mode;
+		u32 blt;
+	} mixed_mode;
 } efi_uga_draw_protocol_t;
 
 #endif /* BOOT_COMPRESSED_EBOOT_H */
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 817237ce2420..60a301e1c072 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -40,9 +40,9 @@ static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 void efi_char16_printk(efi_system_table_t *sys_table_arg,
 			      efi_char16_t *str)
 {
-	struct efi_simple_text_output_protocol *out;
+	efi_simple_text_output_protocol_t *out;
 
-	out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
+	out = (efi_simple_text_output_protocol_t *)sys_table_arg->con_out;
 	out->output_string(out, str);
 }
 
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 97378cf96a2e..d92cd640c73d 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -9,7 +9,7 @@
 
 #include "efistub.h"
 
-typedef struct efi_rng_protocol efi_rng_protocol_t;
+typedef union efi_rng_protocol efi_rng_protocol_t;
 
 typedef struct {
 	u32 get_info;
@@ -21,11 +21,17 @@ typedef struct {
 	u64 get_rng;
 } efi_rng_protocol_64_t;
 
-struct efi_rng_protocol {
-	efi_status_t (*get_info)(struct efi_rng_protocol *,
-				 unsigned long *, efi_guid_t *);
-	efi_status_t (*get_rng)(struct efi_rng_protocol *,
-				efi_guid_t *, unsigned long, u8 *out);
+union efi_rng_protocol {
+	struct {
+		efi_status_t (*get_info)(efi_rng_protocol_t *,
+					 unsigned long *, efi_guid_t *);
+		efi_status_t (*get_rng)(efi_rng_protocol_t *,
+					efi_guid_t *, unsigned long, u8 *out);
+	};
+	struct {
+		u32 get_info;
+		u32 get_rng;
+	} mixed_mode;
 };
 
 efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
@@ -33,7 +39,7 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
 {
 	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
 	efi_status_t status;
-	struct efi_rng_protocol *rng = NULL;
+	efi_rng_protocol_t *rng = NULL;
 
 	status = efi_call_early(locate_protocol, &rng_proto, NULL,
 				(void **)&rng);
@@ -162,7 +168,7 @@ efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
 	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
 	efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
 	efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
-	struct efi_rng_protocol *rng = NULL;
+	efi_rng_protocol_t *rng = NULL;
 	struct linux_efi_random_seed *seed = NULL;
 	efi_status_t status;
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 3e3d9602647a..048cdc9bc96d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -315,55 +315,58 @@ typedef struct {
 /*
  * EFI Boot Services table
  */
-typedef struct {
-	efi_table_hdr_t hdr;
-	void *raise_tpl;
-	void *restore_tpl;
-	efi_status_t (*allocate_pages)(int, int, unsigned long,
-				       efi_physical_addr_t *);
-	efi_status_t (*free_pages)(efi_physical_addr_t, unsigned long);
-	efi_status_t (*get_memory_map)(unsigned long *, void *, unsigned long *,
-				       unsigned long *, u32 *);
-	efi_status_t (*allocate_pool)(int, unsigned long, void **);
-	efi_status_t (*free_pool)(void *);
-	void *create_event;
-	void *set_timer;
-	void *wait_for_event;
-	void *signal_event;
-	void *close_event;
-	void *check_event;
-	void *install_protocol_interface;
-	void *reinstall_protocol_interface;
-	void *uninstall_protocol_interface;
-	efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **);
-	void *__reserved;
-	void *register_protocol_notify;
-	efi_status_t (*locate_handle)(int, efi_guid_t *, void *,
-				      unsigned long *, efi_handle_t *);
-	void *locate_device_path;
-	efi_status_t (*install_configuration_table)(efi_guid_t *, void *);
-	void *load_image;
-	void *start_image;
-	void *exit;
-	void *unload_image;
-	efi_status_t (*exit_boot_services)(efi_handle_t, unsigned long);
-	void *get_next_monotonic_count;
-	void *stall;
-	void *set_watchdog_timer;
-	void *connect_controller;
-	void *disconnect_controller;
-	void *open_protocol;
-	void *close_protocol;
-	void *open_protocol_information;
-	void *protocols_per_handle;
-	void *locate_handle_buffer;
-	efi_status_t (*locate_protocol)(efi_guid_t *, void *, void **);
-	void *install_multiple_protocol_interfaces;
-	void *uninstall_multiple_protocol_interfaces;
-	void *calculate_crc32;
-	void *copy_mem;
-	void *set_mem;
-	void *create_event_ex;
+typedef union {
+	struct {
+		efi_table_hdr_t hdr;
+		void *raise_tpl;
+		void *restore_tpl;
+		efi_status_t (*allocate_pages)(int, int, unsigned long,
+					       efi_physical_addr_t *);
+		efi_status_t (*free_pages)(efi_physical_addr_t, unsigned long);
+		efi_status_t (*get_memory_map)(unsigned long *, void *, unsigned long *,
+					       unsigned long *, u32 *);
+		efi_status_t (*allocate_pool)(int, unsigned long, void **);
+		efi_status_t (*free_pool)(void *);
+		void *create_event;
+		void *set_timer;
+		void *wait_for_event;
+		void *signal_event;
+		void *close_event;
+		void *check_event;
+		void *install_protocol_interface;
+		void *reinstall_protocol_interface;
+		void *uninstall_protocol_interface;
+		efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **);
+		void *__reserved;
+		void *register_protocol_notify;
+		efi_status_t (*locate_handle)(int, efi_guid_t *, void *,
+					      unsigned long *, efi_handle_t *);
+		void *locate_device_path;
+		efi_status_t (*install_configuration_table)(efi_guid_t *, void *);
+		void *load_image;
+		void *start_image;
+		void *exit;
+		void *unload_image;
+		efi_status_t (*exit_boot_services)(efi_handle_t, unsigned long);
+		void *get_next_monotonic_count;
+		void *stall;
+		void *set_watchdog_timer;
+		void *connect_controller;
+		void *disconnect_controller;
+		void *open_protocol;
+		void *close_protocol;
+		void *open_protocol_information;
+		void *protocols_per_handle;
+		void *locate_handle_buffer;
+		efi_status_t (*locate_protocol)(efi_guid_t *, void *, void **);
+		void *install_multiple_protocol_interfaces;
+		void *uninstall_multiple_protocol_interfaces;
+		void *calculate_crc32;
+		void *copy_mem;
+		void *set_mem;
+		void *create_event_ex;
+	};
+	efi_boot_services_32_t mixed_mode;
 } efi_boot_services_t;
 
 typedef enum {
@@ -401,11 +404,30 @@ typedef struct {
 	u64 write;
 } efi_pci_io_protocol_access_64_t;
 
+typedef union efi_pci_io_protocol efi_pci_io_protocol_t;
+
+typedef
+efi_status_t (*efi_pci_io_protocol_mem_t)(efi_pci_io_protocol_t *,
+					  EFI_PCI_IO_PROTOCOL_WIDTH,
+					  u8 bar_index, u64 offset,
+					  unsigned long count, void *buffer);
+
+typedef
+efi_status_t (*efi_pci_io_protocol_cfg_t)(efi_pci_io_protocol_t *,
+					  EFI_PCI_IO_PROTOCOL_WIDTH,
+					  u32 offset, unsigned long count,
+					  void *buffer);
+
 typedef struct {
-	void *read;
-	void *write;
+	efi_pci_io_protocol_mem_t read;
+	efi_pci_io_protocol_mem_t write;
 } efi_pci_io_protocol_access_t;
 
+typedef struct {
+	efi_pci_io_protocol_cfg_t read;
+	efi_pci_io_protocol_cfg_t write;
+} efi_pci_io_protocol_config_access_t;
+
 typedef struct {
 	u32 poll_mem;
 	u32 poll_io;
@@ -446,25 +468,46 @@ typedef struct {
 	u64 romimage;
 } efi_pci_io_protocol_64_t;
 
-typedef struct {
-	void *poll_mem;
-	void *poll_io;
-	efi_pci_io_protocol_access_t mem;
-	efi_pci_io_protocol_access_t io;
-	efi_pci_io_protocol_access_t pci;
-	void *copy_mem;
-	void *map;
-	void *unmap;
-	void *allocate_buffer;
-	void *free_buffer;
-	void *flush;
-	void *get_location;
-	void *attributes;
-	void *get_bar_attributes;
-	void *set_bar_attributes;
-	uint64_t romsize;
-	void *romimage;
-} efi_pci_io_protocol_t;
+union efi_pci_io_protocol {
+	struct {
+		void *poll_mem;
+		void *poll_io;
+		efi_pci_io_protocol_access_t mem;
+		efi_pci_io_protocol_access_t io;
+		efi_pci_io_protocol_config_access_t pci;
+		void *copy_mem;
+		void *map;
+		void *unmap;
+		void *allocate_buffer;
+		void *free_buffer;
+		void *flush;
+		void *get_location;
+		void *attributes;
+		void *get_bar_attributes;
+		void *set_bar_attributes;
+		uint64_t romsize;
+		void *romimage;
+	};
+	struct {
+		u32 poll_mem;
+		u32 poll_io;
+		efi_pci_io_protocol_access_32_t mem;
+		efi_pci_io_protocol_access_32_t io;
+		efi_pci_io_protocol_access_32_t pci;
+		u32 copy_mem;
+		u32 map;
+		u32 unmap;
+		u32 allocate_buffer;
+		u32 free_buffer;
+		u32 flush;
+		u32 get_location;
+		u32 attributes;
+		u32 get_bar_attributes;
+		u32 set_bar_attributes;
+		u64 romsize;
+		u32 romimage;
+	} mixed_mode;
+};
 
 #define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
 #define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
@@ -502,6 +545,33 @@ typedef struct {
 	u64 get_all;
 } apple_properties_protocol_64_t;
 
+struct efi_dev_path;
+
+typedef union apple_properties_protocol apple_properties_protocol_t;
+
+union apple_properties_protocol {
+	struct {
+		unsigned long version;
+		efi_status_t (*get)(apple_properties_protocol_t *,
+				    struct efi_dev_path *, efi_char16_t *,
+				    void *, u32 *);
+		efi_status_t (*set)(apple_properties_protocol_t *,
+				    struct efi_dev_path *, efi_char16_t *,
+				    void *, u32);
+		efi_status_t (*del)(apple_properties_protocol_t *,
+				    struct efi_dev_path *, efi_char16_t *);
+		efi_status_t (*get_all)(apple_properties_protocol_t *,
+					void *buffer, u32 *);
+	};
+	struct {
+		u32 version;
+		u32 get;
+		u32 set;
+		u32 del;
+		u32 get_all;
+	} mixed_mode;
+};
+
 typedef struct {
 	u32 get_capability;
 	u32 get_event_log;
@@ -524,16 +594,32 @@ typedef struct {
 
 typedef u32 efi_tcg2_event_log_format;
 
-typedef struct {
-	void *get_capability;
-	efi_status_t (*get_event_log)(efi_handle_t, efi_tcg2_event_log_format,
-		efi_physical_addr_t *, efi_physical_addr_t *, efi_bool_t *);
-	void *hash_log_extend_event;
-	void *submit_command;
-	void *get_active_pcr_banks;
-	void *set_active_pcr_banks;
-	void *get_result_of_set_active_pcr_banks;
-} efi_tcg2_protocol_t;
+typedef union efi_tcg2_protocol efi_tcg2_protocol_t;
+
+union efi_tcg2_protocol {
+	struct {
+		void *get_capability;
+		efi_status_t (*get_event_log)(efi_handle_t,
+					      efi_tcg2_event_log_format,
+					      efi_physical_addr_t *,
+					      efi_physical_addr_t *,
+					      efi_bool_t *);
+		void *hash_log_extend_event;
+		void *submit_command;
+		void *get_active_pcr_banks;
+		void *set_active_pcr_banks;
+		void *get_result_of_set_active_pcr_banks;
+	};
+	struct {
+		u32 get_capability;
+		u32 get_event_log;
+		u32 hash_log_extend_event;
+		u32 submit_command;
+		u32 get_active_pcr_banks;
+		u32 set_active_pcr_banks;
+		u32 get_result_of_set_active_pcr_banks;
+	} mixed_mode;
+};
 
 /*
  * Types and defines for EFI ResetSystem
@@ -618,22 +704,25 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes,
 						unsigned long size,
 						bool nonblocking);
 
-typedef struct {
-	efi_table_hdr_t			hdr;
-	efi_get_time_t			*get_time;
-	efi_set_time_t			*set_time;
-	efi_get_wakeup_time_t		*get_wakeup_time;
-	efi_set_wakeup_time_t		*set_wakeup_time;
-	efi_set_virtual_address_map_t	*set_virtual_address_map;
-	void				*convert_pointer;
-	efi_get_variable_t		*get_variable;
-	efi_get_next_variable_t		*get_next_variable;
-	efi_set_variable_t		*set_variable;
-	efi_get_next_high_mono_count_t	*get_next_high_mono_count;
-	efi_reset_system_t		*reset_system;
-	efi_update_capsule_t		*update_capsule;
-	efi_query_capsule_caps_t	*query_capsule_caps;
-	efi_query_variable_info_t	*query_variable_info;
+typedef union {
+	struct {
+		efi_table_hdr_t			hdr;
+		efi_get_time_t			*get_time;
+		efi_set_time_t			*set_time;
+		efi_get_wakeup_time_t		*get_wakeup_time;
+		efi_set_wakeup_time_t		*set_wakeup_time;
+		efi_set_virtual_address_map_t	*set_virtual_address_map;
+		void				*convert_pointer;
+		efi_get_variable_t		*get_variable;
+		efi_get_next_variable_t		*get_next_variable;
+		efi_set_variable_t		*set_variable;
+		efi_get_next_high_mono_count_t	*get_next_high_mono_count;
+		efi_reset_system_t		*reset_system;
+		efi_update_capsule_t		*update_capsule;
+		efi_query_capsule_caps_t	*query_capsule_caps;
+		efi_query_variable_info_t	*query_variable_info;
+	};
+	efi_runtime_services_32_t mixed_mode;
 } efi_runtime_services_t;
 
 void efi_native_runtime_setup(void);
@@ -719,9 +808,12 @@ typedef struct {
 	u32 table;
 } efi_config_table_32_t;
 
-typedef struct {
-	efi_guid_t guid;
-	unsigned long table;
+typedef union {
+	struct {
+		efi_guid_t guid;
+		unsigned long table;
+	};
+	efi_config_table_32_t mixed_mode;
 } efi_config_table_t;
 
 typedef struct {
@@ -773,20 +865,23 @@ typedef struct {
 	u32 tables;
 } efi_system_table_32_t;
 
-typedef struct {
-	efi_table_hdr_t hdr;
-	unsigned long fw_vendor;	/* physical addr of CHAR16 vendor string */
-	u32 fw_revision;
-	unsigned long con_in_handle;
-	unsigned long con_in;
-	unsigned long con_out_handle;
-	unsigned long con_out;
-	unsigned long stderr_handle;
-	unsigned long stderr;
-	efi_runtime_services_t *runtime;
-	efi_boot_services_t *boottime;
-	unsigned long nr_tables;
-	unsigned long tables;
+typedef union {
+	struct {
+		efi_table_hdr_t hdr;
+		unsigned long fw_vendor;	/* physical addr of CHAR16 vendor string */
+		u32 fw_revision;
+		unsigned long con_in_handle;
+		unsigned long con_in;
+		unsigned long con_out_handle;
+		unsigned long con_out;
+		unsigned long stderr_handle;
+		unsigned long stderr;
+		efi_runtime_services_t *runtime;
+		efi_boot_services_t *boottime;
+		unsigned long nr_tables;
+		unsigned long tables;
+	};
+	efi_system_table_32_t mixed_mode;
 } efi_system_table_t;
 
 /*
@@ -856,22 +951,40 @@ typedef struct {
 	u64 unload;
 } efi_loaded_image_64_t;
 
-typedef struct {
-	u32 revision;
-	efi_handle_t parent_handle;
-	efi_system_table_t *system_table;
-	efi_handle_t device_handle;
-	void *file_path;
-	void *reserved;
-	u32 load_options_size;
-	void *load_options;
-	void *image_base;
-	__aligned_u64 image_size;
-	unsigned int image_code_type;
-	unsigned int image_data_type;
-	efi_status_t (*unload)(efi_handle_t image_handle);
-} efi_loaded_image_t;
+typedef union efi_loaded_image efi_loaded_image_t;
 
+union efi_loaded_image {
+	struct {
+		u32 revision;
+		efi_handle_t parent_handle;
+		efi_system_table_t *system_table;
+		efi_handle_t device_handle;
+		void *file_path;
+		void *reserved;
+		u32 load_options_size;
+		void *load_options;
+		void *image_base;
+		__aligned_u64 image_size;
+		unsigned int image_code_type;
+		unsigned int image_data_type;
+		efi_status_t (*unload)(efi_handle_t image_handle);
+	};
+	struct {
+		u32 revision;
+		u32 parent_handle;
+		u32 system_table;
+		u32 device_handle;
+		u32 file_path;
+		u32 reserved;
+		u32 load_options_size;
+		u32 load_options;
+		u32 image_base;
+		__aligned_u64 image_size;
+		unsigned int image_code_type;
+		unsigned int image_data_type;
+		u32 unload;
+	} mixed_mode;
+};
 
 typedef struct {
 	u64 size;
@@ -912,23 +1025,40 @@ typedef struct {
 	u64 flush;
 } efi_file_handle_64_t;
 
-typedef struct _efi_file_handle {
-	u64 revision;
-	efi_status_t (*open)(struct _efi_file_handle *,
-			     struct _efi_file_handle **,
-			     efi_char16_t *, u64, u64);
-	efi_status_t (*close)(struct _efi_file_handle *);
-	void *delete;
-	efi_status_t (*read)(struct _efi_file_handle *, unsigned long *,
-			     void *);
-	void *write;
-	void *get_position;
-	void *set_position;
-	efi_status_t (*get_info)(struct _efi_file_handle *, efi_guid_t *,
-			unsigned long *, void *);
-	void *set_info;
-	void *flush;
-} efi_file_handle_t;
+typedef union efi_file_handle efi_file_handle_t;
+
+union efi_file_handle {
+	struct {
+		u64 revision;
+		efi_status_t (*open)(efi_file_handle_t *,
+				     efi_file_handle_t **,
+				     efi_char16_t *, u64, u64);
+		efi_status_t (*close)(efi_file_handle_t *);
+		void *delete;
+		efi_status_t (*read)(efi_file_handle_t *, unsigned long *,
+				     void *);
+		void *write;
+		void *get_position;
+		void *set_position;
+		efi_status_t (*get_info)(efi_file_handle_t *, efi_guid_t *,
+				unsigned long *, void *);
+		void *set_info;
+		void *flush;
+	};
+	struct {
+		u64 revision;
+		u32 open;
+		u32 close;
+		u32 delete;
+		u32 read;
+		u32 write;
+		u32 get_position;
+		u32 set_position;
+		u32 get_info;
+		u32 set_info;
+		u32 flush;
+	} mixed_mode;
+};
 
 typedef struct {
 	u64 revision;
@@ -940,11 +1070,19 @@ typedef struct {
 	u64 open_volume;
 } efi_file_io_interface_64_t;
 
-typedef struct _efi_file_io_interface {
-	u64 revision;
-	int (*open_volume)(struct _efi_file_io_interface *,
-			   efi_file_handle_t **);
-} efi_file_io_interface_t;
+typedef union efi_file_io_interface efi_file_io_interface_t;
+
+union efi_file_io_interface {
+	struct {
+		u64 revision;
+		int (*open_volume)(efi_file_io_interface_t *,
+				   efi_file_handle_t **);
+	};
+	struct {
+		u64 revision;
+		u32 open_volume;
+	} mixed_mode;
+} ;
 
 #define EFI_FILE_MODE_READ	0x0000000000000001
 #define EFI_FILE_MODE_WRITE	0x0000000000000002
@@ -1415,10 +1553,20 @@ typedef struct {
 	u64 test_string;
 } efi_simple_text_output_protocol_64_t;
 
-struct efi_simple_text_output_protocol {
-	void *reset;
-	efi_status_t (*output_string)(void *, void *);
-	void *test_string;
+typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
+
+union efi_simple_text_output_protocol {
+	struct {
+		void *reset;
+		efi_status_t (*output_string)(efi_simple_text_output_protocol_t *,
+					      efi_char16_t *);
+		void *test_string;
+	};
+	struct {
+		u32 reset;
+		u32 output_string;
+		u32 test_string;
+	} mixed_mode;
 };
 
 #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR		0
@@ -1461,14 +1609,26 @@ typedef struct {
 	u64 frame_buffer_size;
 } efi_graphics_output_protocol_mode_64_t;
 
-typedef struct {
-	u32 max_mode;
-	u32 mode;
-	efi_graphics_output_mode_info_t *info;
-	unsigned long size_of_info;
-	efi_physical_addr_t frame_buffer_base;
-	unsigned long frame_buffer_size;
-} efi_graphics_output_protocol_mode_t;
+typedef union efi_graphics_output_protocol_mode efi_graphics_output_protocol_mode_t;
+
+union efi_graphics_output_protocol_mode {
+	struct {
+		u32 max_mode;
+		u32 mode;
+		efi_graphics_output_mode_info_t *info;
+		unsigned long size_of_info;
+		efi_physical_addr_t frame_buffer_base;
+		unsigned long frame_buffer_size;
+	};
+	struct {
+		u32 max_mode;
+		u32 mode;
+		u32 info;
+		u32 size_of_info;
+		u64 frame_buffer_base;
+		u32 frame_buffer_size;
+	} mixed_mode;
+};
 
 typedef struct {
 	u32 query_mode;
@@ -1484,12 +1644,22 @@ typedef struct {
 	u64 mode;
 } efi_graphics_output_protocol_64_t;
 
-typedef struct {
-	void *query_mode;
-	void *set_mode;
-	void *blt;
-	efi_graphics_output_protocol_mode_t *mode;
-} efi_graphics_output_protocol_t;
+typedef union efi_graphics_output_protocol efi_graphics_output_protocol_t;
+
+union efi_graphics_output_protocol {
+	struct {
+		void *query_mode;
+		void *set_mode;
+		void *blt;
+		efi_graphics_output_protocol_mode_t *mode;
+	};
+	struct {
+		u32 query_mode;
+		u32 set_mode;
+		u32 blt;
+		u32 mode;
+	} mixed_mode;
+};
 
 extern struct list_head efivar_sysfs_list;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 05/21] efi/libstub: distinguish between native/mixed not 32/64 bit
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 04/21] efi/libstub: extend native protocol definitions with mixed_mode aliases Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 06/21] efi/libstub/x86: use mixed mode helpers to populate efi_config Ard Biesheuvel
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Currently, we support mixed mode by casting all boot time firmware
calls to 64-bit explicitly on native 64-bit systems, and to 32-bit
on 32-bit systems or 64-bit systems running with 32-bit firmware.

Due to this explicit awareness of the bitness in the code, we do a
lot of casting even on generic code that is shared with other
architectures, where mixed mode does not even exist. This casting
leads to loss of coverage of type checking by the compiler, which
we should try to avoid.

So instead of distinguishing between 32-bit vs 64-bit, distinguish
between native vs mixed, and limit all the nasty casting and
pointer mangling to the code that actually deals with mixed mode.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/efi.h                     |  2 +-
 arch/arm64/include/asm/efi.h                   |  2 +-
 arch/x86/boot/compressed/eboot.c               |  3 +-
 arch/x86/include/asm/efi.h                     | 35 +++++++++++---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 49 +++++++-------------
 include/linux/efi.h                            |  6 +--
 6 files changed, 51 insertions(+), 46 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 6c714b4ef59e..489c4febc185 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -358,7 +358,7 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
 	 * explicit 64-bit wide arguments. So all we can do is leak the
 	 * allocation.
 	 */
-	if (!size || (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_64bit()))
+	if (!size || !efi_is_native())
 		return;
 
 	nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
@@ -436,9 +436,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);
@@ -547,7 +545,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 	 * parameters in their prototypes, which are not marshalled correctly
 	 * by the thunking code.
 	 */
-	if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_64bit()) {
+	if (!efi_is_native()) {
 		pr_efi(sys_table_arg,
 		       "Ignoring file= arguments on mixed mode system\n");
 		return EFI_SUCCESS;
@@ -959,33 +957,20 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
 	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 048cdc9bc96d..1dbda78d2823 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;							\
@@ -811,7 +811,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;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 06/21] efi/libstub/x86: use mixed mode helpers to populate efi_config
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (4 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 05/21] efi/libstub: distinguish between native/mixed not 32/64 bit Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 07/21] efi/libstub: drop explicit 32/64-bit protocol definitions Ard Biesheuvel
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

The efi_config struct returned by __efi_early() contains a couple
of pointers that are obtained from the EFI system table, which
could be 32-bit on a 64-bit system. For this reason, there are
two versions of the setup_boot_services() routine, one for 32-bit
and one for 64-bit.

We have helpers now that hide all this nastiness, so let's use
those instead.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.c   | 27 +++++---------------
 arch/x86/boot/compressed/head_32.S |  6 ++---
 arch/x86/include/asm/efi.h         |  6 ++---
 arch/x86/platform/efi/efi.c        |  4 +--
 include/linux/efi.h                |  6 ++---
 5 files changed, 18 insertions(+), 31 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 990b93379965..f9074f12e89f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -27,19 +27,12 @@ __pure const struct efi_config *__efi_early(void)
 	return efi_early;
 }
 
-#define BOOT_SERVICES(bits)						\
-static void setup_boot_services##bits(struct efi_config *c)		\
-{									\
-	efi_system_table_##bits##_t *table;				\
-									\
-	table = (typeof(table))sys_table;				\
-									\
-	c->runtime_services	= table->runtime;			\
-	c->boot_services	= table->boottime;			\
-	c->text_output		= table->con_out;			\
+static void setup_boot_services(struct efi_config *c)
+{
+	c->runtime_services	= efi_table_attr(efi_system_table, runtime, sys_table);
+	c->boot_services	= efi_table_attr(efi_system_table, boottime, sys_table);
+	c->text_output		= efi_table_attr(efi_system_table, con_out, sys_table);
 }
-BOOT_SERVICES(32);
-BOOT_SERVICES(64);
 
 void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
 {
@@ -396,10 +389,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		return NULL;
 
-	if (efi_is_64bit())
-		setup_boot_services64(efi_early);
-	else
-		setup_boot_services32(efi_early);
+	setup_boot_services(efi_early);
 
 	status = efi_call_early(handle_protocol, handle,
 				&proto, (void *)&image);
@@ -758,10 +748,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		goto fail;
 
-	if (efi_is_64bit())
-		setup_boot_services64(efi_early);
-	else
-		setup_boot_services32(efi_early);
+	setup_boot_services(efi_early);
 
 	/*
 	 * make_boot_params() may have been called before efi_main(), in which
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index f2dfd6d083ef..40468ab49b9b 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -163,7 +163,7 @@ SYM_FUNC_START(efi_pe_entry)
 
 	/* Relocate efi_config->call() */
 	leal	efi32_config(%esi), %eax
-	add	%esi, 40(%eax)
+	add	%esi, 28(%eax)
 	pushl	%eax
 
 	call	make_boot_params
@@ -190,7 +190,7 @@ SYM_FUNC_START(efi32_stub_entry)
 
 	/* Relocate efi_config->call() */
 	leal	efi32_config(%esi), %eax
-	add	%esi, 40(%eax)
+	add	%esi, 28(%eax)
 	pushl	%eax
 2:
 	call	efi_main
@@ -265,7 +265,7 @@ SYM_FUNC_END(.Lrelocated)
 #ifdef CONFIG_EFI_STUB
 	.data
 efi32_config:
-	.fill 5,8,0
+	.fill 7,4,0
 	.long efi_call_phys
 	.long 0
 	.byte 0
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index c27323cb49e5..183cd49e0495 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -202,9 +202,9 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
 struct efi_config {
 	u64 image_handle;
 	u64 table;
-	u64 runtime_services;
-	u64 boot_services;
-	u64 text_output;
+	efi_runtime_services_t *runtime_services;
+	efi_boot_services_t *boot_services;
+	efi_simple_text_output_protocol_t *text_output;
 	efi_status_t (*call)(unsigned long, ...);
 	bool is64;
 } __packed;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1493e964c267..27700268ed4a 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -388,7 +388,7 @@ static int __init efi_systab_init(void *phys)
 		tmp |= systab64->con_in;
 		efi_systab.con_out_handle = systab64->con_out_handle;
 		tmp |= systab64->con_out_handle;
-		efi_systab.con_out = systab64->con_out;
+		efi_systab.con_out = (void *)(unsigned long)systab64->con_out;
 		tmp |= systab64->con_out;
 		efi_systab.stderr_handle = systab64->stderr_handle;
 		tmp |= systab64->stderr_handle;
@@ -430,7 +430,7 @@ static int __init efi_systab_init(void *phys)
 		efi_systab.con_in_handle = systab32->con_in_handle;
 		efi_systab.con_in = systab32->con_in;
 		efi_systab.con_out_handle = systab32->con_out_handle;
-		efi_systab.con_out = systab32->con_out;
+		efi_systab.con_out = (void *)(unsigned long)systab32->con_out;
 		efi_systab.stderr_handle = systab32->stderr_handle;
 		efi_systab.stderr = systab32->stderr;
 		efi_systab.runtime = (void *)(unsigned long)systab32->runtime;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 1dbda78d2823..2c33841d0d4a 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -822,6 +822,8 @@ typedef struct {
 	unsigned long *ptr;
 } efi_config_table_type_t;
 
+typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
+
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
 
 #define EFI_2_30_SYSTEM_TABLE_REVISION  ((2 << 16) | (30))
@@ -873,7 +875,7 @@ typedef union {
 		unsigned long con_in_handle;
 		unsigned long con_in;
 		unsigned long con_out_handle;
-		unsigned long con_out;
+		efi_simple_text_output_protocol_t *con_out;
 		unsigned long stderr_handle;
 		unsigned long stderr;
 		efi_runtime_services_t *runtime;
@@ -1553,8 +1555,6 @@ typedef struct {
 	u64 test_string;
 } efi_simple_text_output_protocol_64_t;
 
-typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
-
 union efi_simple_text_output_protocol {
 	struct {
 		void *reset;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 07/21] efi/libstub: drop explicit 32/64-bit protocol definitions
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (5 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 06/21] efi/libstub/x86: use mixed mode helpers to populate efi_config Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 08/21] efi/libstub: use stricter typing for firmware function pointers Ard Biesheuvel
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Now that we have incorporated the mixed mode protocol definitions
into the native ones using unions, we no longer need the separate
32/64 bit struct definitions, with the exception of the EFI system
table definition and the boot services, runtime services and
configuration table definitions. So drop the unused ones.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.h      |  12 -
 drivers/firmware/efi/libstub/random.c |  10 -
 include/linux/efi.h                   | 233 +-------------------
 3 files changed, 1 insertion(+), 254 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index 26f1f2635f64..de13865dc7d2 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -12,18 +12,6 @@
 
 #define DESC_TYPE_CODE_DATA	(1 << 0)
 
-typedef struct {
-	u32 get_mode;
-	u32 set_mode;
-	u32 blt;
-} efi_uga_draw_protocol_32_t;
-
-typedef struct {
-	u64 get_mode;
-	u64 set_mode;
-	u64 blt;
-} efi_uga_draw_protocol_64_t;
-
 typedef union {
 	struct {
 		void *get_mode;
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index d92cd640c73d..1a5a4a9db2a7 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -11,16 +11,6 @@
 
 typedef union efi_rng_protocol efi_rng_protocol_t;
 
-typedef struct {
-	u32 get_info;
-	u32 get_rng;
-} efi_rng_protocol_32_t;
-
-typedef struct {
-	u64 get_info;
-	u64 get_rng;
-} efi_rng_protocol_64_t;
-
 union efi_rng_protocol {
 	struct {
 		efi_status_t (*get_info)(efi_rng_protocol_t *,
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2c33841d0d4a..d09ce1cea130 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -264,54 +264,6 @@ typedef struct {
 	u32 create_event_ex;
 } __packed efi_boot_services_32_t;
 
-typedef struct {
-	efi_table_hdr_t hdr;
-	u64 raise_tpl;
-	u64 restore_tpl;
-	u64 allocate_pages;
-	u64 free_pages;
-	u64 get_memory_map;
-	u64 allocate_pool;
-	u64 free_pool;
-	u64 create_event;
-	u64 set_timer;
-	u64 wait_for_event;
-	u64 signal_event;
-	u64 close_event;
-	u64 check_event;
-	u64 install_protocol_interface;
-	u64 reinstall_protocol_interface;
-	u64 uninstall_protocol_interface;
-	u64 handle_protocol;
-	u64 __reserved;
-	u64 register_protocol_notify;
-	u64 locate_handle;
-	u64 locate_device_path;
-	u64 install_configuration_table;
-	u64 load_image;
-	u64 start_image;
-	u64 exit;
-	u64 unload_image;
-	u64 exit_boot_services;
-	u64 get_next_monotonic_count;
-	u64 stall;
-	u64 set_watchdog_timer;
-	u64 connect_controller;
-	u64 disconnect_controller;
-	u64 open_protocol;
-	u64 close_protocol;
-	u64 open_protocol_information;
-	u64 protocols_per_handle;
-	u64 locate_handle_buffer;
-	u64 locate_protocol;
-	u64 install_multiple_protocol_interfaces;
-	u64 uninstall_multiple_protocol_interfaces;
-	u64 calculate_crc32;
-	u64 copy_mem;
-	u64 set_mem;
-	u64 create_event_ex;
-} __packed efi_boot_services_64_t;
-
 /*
  * EFI Boot Services table
  */
@@ -399,11 +351,6 @@ typedef struct {
 	u32 write;
 } efi_pci_io_protocol_access_32_t;
 
-typedef struct {
-	u64 read;
-	u64 write;
-} efi_pci_io_protocol_access_64_t;
-
 typedef union efi_pci_io_protocol efi_pci_io_protocol_t;
 
 typedef
@@ -428,46 +375,6 @@ typedef struct {
 	efi_pci_io_protocol_cfg_t write;
 } efi_pci_io_protocol_config_access_t;
 
-typedef struct {
-	u32 poll_mem;
-	u32 poll_io;
-	efi_pci_io_protocol_access_32_t mem;
-	efi_pci_io_protocol_access_32_t io;
-	efi_pci_io_protocol_access_32_t pci;
-	u32 copy_mem;
-	u32 map;
-	u32 unmap;
-	u32 allocate_buffer;
-	u32 free_buffer;
-	u32 flush;
-	u32 get_location;
-	u32 attributes;
-	u32 get_bar_attributes;
-	u32 set_bar_attributes;
-	u64 romsize;
-	u32 romimage;
-} efi_pci_io_protocol_32_t;
-
-typedef struct {
-	u64 poll_mem;
-	u64 poll_io;
-	efi_pci_io_protocol_access_64_t mem;
-	efi_pci_io_protocol_access_64_t io;
-	efi_pci_io_protocol_access_64_t pci;
-	u64 copy_mem;
-	u64 map;
-	u64 unmap;
-	u64 allocate_buffer;
-	u64 free_buffer;
-	u64 flush;
-	u64 get_location;
-	u64 attributes;
-	u64 get_bar_attributes;
-	u64 set_bar_attributes;
-	u64 romsize;
-	u64 romimage;
-} efi_pci_io_protocol_64_t;
-
 union efi_pci_io_protocol {
 	struct {
 		void *poll_mem;
@@ -529,22 +436,6 @@ union efi_pci_io_protocol {
 #define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
 #define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
 
-typedef struct {
-	u32 version;
-	u32 get;
-	u32 set;
-	u32 del;
-	u32 get_all;
-} apple_properties_protocol_32_t;
-
-typedef struct {
-	u64 version;
-	u64 get;
-	u64 set;
-	u64 del;
-	u64 get_all;
-} apple_properties_protocol_64_t;
-
 struct efi_dev_path;
 
 typedef union apple_properties_protocol apple_properties_protocol_t;
@@ -572,26 +463,6 @@ union apple_properties_protocol {
 	} mixed_mode;
 };
 
-typedef struct {
-	u32 get_capability;
-	u32 get_event_log;
-	u32 hash_log_extend_event;
-	u32 submit_command;
-	u32 get_active_pcr_banks;
-	u32 set_active_pcr_banks;
-	u32 get_result_of_set_active_pcr_banks;
-} efi_tcg2_protocol_32_t;
-
-typedef struct {
-	u64 get_capability;
-	u64 get_event_log;
-	u64 hash_log_extend_event;
-	u64 submit_command;
-	u64 get_active_pcr_banks;
-	u64 set_active_pcr_banks;
-	u64 get_result_of_set_active_pcr_banks;
-} efi_tcg2_protocol_64_t;
-
 typedef u32 efi_tcg2_event_log_format;
 
 typedef union efi_tcg2_protocol efi_tcg2_protocol_t;
@@ -921,38 +792,6 @@ struct efi_fdt_params {
 	u32 desc_ver;
 };
 
-typedef struct {
-	u32 revision;
-	u32 parent_handle;
-	u32 system_table;
-	u32 device_handle;
-	u32 file_path;
-	u32 reserved;
-	u32 load_options_size;
-	u32 load_options;
-	u32 image_base;
-	__aligned_u64 image_size;
-	unsigned int image_code_type;
-	unsigned int image_data_type;
-	u32 unload;
-} efi_loaded_image_32_t;
-
-typedef struct {
-	u32 revision;
-	u64 parent_handle;
-	u64 system_table;
-	u64 device_handle;
-	u64 file_path;
-	u64 reserved;
-	u32 load_options_size;
-	u64 load_options;
-	u64 image_base;
-	__aligned_u64 image_size;
-	unsigned int image_code_type;
-	unsigned int image_data_type;
-	u64 unload;
-} efi_loaded_image_64_t;
-
 typedef union efi_loaded_image efi_loaded_image_t;
 
 union efi_loaded_image {
@@ -999,34 +838,6 @@ typedef struct {
 	efi_char16_t filename[1];
 } efi_file_info_t;
 
-typedef struct {
-	u64 revision;
-	u32 open;
-	u32 close;
-	u32 delete;
-	u32 read;
-	u32 write;
-	u32 get_position;
-	u32 set_position;
-	u32 get_info;
-	u32 set_info;
-	u32 flush;
-} efi_file_handle_32_t;
-
-typedef struct {
-	u64 revision;
-	u64 open;
-	u64 close;
-	u64 delete;
-	u64 read;
-	u64 write;
-	u64 get_position;
-	u64 set_position;
-	u64 get_info;
-	u64 set_info;
-	u64 flush;
-} efi_file_handle_64_t;
-
 typedef union efi_file_handle efi_file_handle_t;
 
 union efi_file_handle {
@@ -1062,16 +873,6 @@ union efi_file_handle {
 	} mixed_mode;
 };
 
-typedef struct {
-	u64 revision;
-	u32 open_volume;
-} efi_file_io_interface_32_t;
-
-typedef struct {
-	u64 revision;
-	u64 open_volume;
-} efi_file_io_interface_64_t;
-
 typedef union efi_file_io_interface efi_file_io_interface_t;
 
 union efi_file_io_interface {
@@ -1084,7 +885,7 @@ union efi_file_io_interface {
 		u64 revision;
 		u32 open_volume;
 	} mixed_mode;
-} ;
+};
 
 #define EFI_FILE_MODE_READ	0x0000000000000001
 #define EFI_FILE_MODE_WRITE	0x0000000000000002
@@ -1591,24 +1392,6 @@ typedef struct {
 	u32 pixels_per_scan_line;
 } efi_graphics_output_mode_info_t;
 
-typedef struct {
-	u32 max_mode;
-	u32 mode;
-	u32 info;
-	u32 size_of_info;
-	u64 frame_buffer_base;
-	u32 frame_buffer_size;
-} efi_graphics_output_protocol_mode_32_t;
-
-typedef struct {
-	u32 max_mode;
-	u32 mode;
-	u64 info;
-	u64 size_of_info;
-	u64 frame_buffer_base;
-	u64 frame_buffer_size;
-} efi_graphics_output_protocol_mode_64_t;
-
 typedef union efi_graphics_output_protocol_mode efi_graphics_output_protocol_mode_t;
 
 union efi_graphics_output_protocol_mode {
@@ -1630,20 +1413,6 @@ union efi_graphics_output_protocol_mode {
 	} mixed_mode;
 };
 
-typedef struct {
-	u32 query_mode;
-	u32 set_mode;
-	u32 blt;
-	u32 mode;
-} efi_graphics_output_protocol_32_t;
-
-typedef struct {
-	u64 query_mode;
-	u64 set_mode;
-	u64 blt;
-	u64 mode;
-} efi_graphics_output_protocol_64_t;
-
 typedef union efi_graphics_output_protocol efi_graphics_output_protocol_t;
 
 union efi_graphics_output_protocol {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 08/21] efi/libstub: use stricter typing for firmware function pointers
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (6 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 07/21] efi/libstub: drop explicit 32/64-bit protocol definitions Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 09/21] efi/libstub: annotate firmware routines as __efiapi Ard Biesheuvel
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

We will soon remove another level of pointer casting, so let's make
sure all type handling involving firmware calls at boot time is correct.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.c               | 10 ++++++----
 arch/x86/boot/compressed/eboot.h               |  9 ++++++---
 drivers/firmware/efi/libstub/efi-stub-helper.c |  5 +++--
 drivers/firmware/efi/libstub/tpm.c             |  4 ++--
 include/linux/efi.h                            |  6 +++++-
 5 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index f9074f12e89f..4a965212ee64 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -63,7 +63,8 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 
 	size = romsize + sizeof(*rom);
 
-	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
+	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size,
+				(void **)&rom);
 	if (status != EFI_SUCCESS) {
 		efi_printk(sys_table, "Failed to allocate memory for 'rom'\n");
 		return status;
@@ -188,9 +189,9 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 	struct setup_data *data, *new;
 	efi_status_t status;
 	u32 size = 0;
-	void *p;
+	apple_properties_protocol_t *p;
 
-	status = efi_call_early(locate_protocol, &guid, NULL, &p);
+	status = efi_call_early(locate_protocol, &guid, NULL, (void **)&p);
 	if (status != EFI_SUCCESS)
 		return;
 
@@ -205,7 +206,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 
 	do {
 		status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
-					size + sizeof(struct setup_data), &new);
+					size + sizeof(struct setup_data),
+					(void **)&new);
 		if (status != EFI_SUCCESS) {
 			efi_printk(sys_table, "Failed to allocate memory for 'properties'\n");
 			return;
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index de13865dc7d2..b8d11928f528 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -12,9 +12,12 @@
 
 #define DESC_TYPE_CODE_DATA	(1 << 0)
 
-typedef union {
+typedef union efi_uga_draw_protocol efi_uga_draw_protocol_t;
+
+union efi_uga_draw_protocol {
 	struct {
-		void *get_mode;
+		efi_status_t (*get_mode)(efi_uga_draw_protocol_t *,
+					 u32*, u32*, u32*, u32*);
 		void *set_mode;
 		void *blt;
 	};
@@ -23,6 +26,6 @@ typedef union {
 		u32 set_mode;
 		u32 blt;
 	} mixed_mode;
-} efi_uga_draw_protocol_t;
+};
 
 #endif /* BOOT_COMPRESSED_EBOOT_H */
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 489c4febc185..5eaf6ada960f 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -418,12 +418,13 @@ static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
 	return status;
 }
 
-static efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr)
+static efi_status_t efi_file_read(efi_file_handle_t *handle,
+				  unsigned long *size, void *addr)
 {
 	return efi_call_proto(efi_file_handle, read, handle, size, addr);
 }
 
-static efi_status_t efi_file_close(void *handle)
+static efi_status_t efi_file_close(efi_file_handle_t *handle)
 {
 	return efi_call_proto(efi_file_handle, close, handle);
 }
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index eb9af83e4d59..d270acd43de8 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -69,11 +69,11 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
 	size_t log_size, last_entry_size;
 	efi_bool_t truncated;
 	int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
-	void *tcg2_protocol = NULL;
+	efi_tcg2_protocol_t *tcg2_protocol = NULL;
 	int final_events_size = 0;
 
 	status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
-				&tcg2_protocol);
+				(void **)&tcg2_protocol);
 	if (status != EFI_SUCCESS)
 		return;
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index d09ce1cea130..969eb06e780a 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -388,7 +388,11 @@ union efi_pci_io_protocol {
 		void *allocate_buffer;
 		void *free_buffer;
 		void *flush;
-		void *get_location;
+		efi_status_t (*get_location)(efi_pci_io_protocol_t *,
+					     unsigned long *segment_nr,
+					     unsigned long *bus_nr,
+					     unsigned long *device_nr,
+					     unsigned long *function_nr);
 		void *attributes;
 		void *get_bar_attributes;
 		void *set_bar_attributes;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 09/21] efi/libstub: annotate firmware routines as __efiapi
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (7 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 08/21] efi/libstub: use stricter typing for firmware function pointers Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls Ard Biesheuvel
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Annotate all the firmware routines (boot services, runtime services and
protocol methods) called in the boot context as __efiapi, and make
it expand to __attribute__((ms_abi)) on 64-bit x86. This allows us
to use the compiler to generate the calls into firmware that use the
MS calling convention instead of the SysV one.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/Kconfig                      |   1 +
 arch/x86/boot/compressed/eboot.h      |   4 +-
 drivers/firmware/efi/libstub/random.c |  10 +-
 include/linux/efi.h                   | 156 +++++++++++---------
 4 files changed, 96 insertions(+), 75 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5e8949953660..8ba81036a7ef 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1993,6 +1993,7 @@ config EFI
 config EFI_STUB
        bool "EFI stub support"
        depends on EFI && !X86_USE_3DNOW
+       depends on $(cc-option,-mabi=ms)
        select RELOCATABLE
        ---help---
           This kernel feature allows a bzImage to be loaded directly
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index b8d11928f528..99f35343d443 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -16,8 +16,8 @@ typedef union efi_uga_draw_protocol efi_uga_draw_protocol_t;
 
 union efi_uga_draw_protocol {
 	struct {
-		efi_status_t (*get_mode)(efi_uga_draw_protocol_t *,
-					 u32*, u32*, u32*, u32*);
+		efi_status_t (__efiapi *get_mode)(efi_uga_draw_protocol_t *,
+						  u32*, u32*, u32*, u32*);
 		void *set_mode;
 		void *blt;
 	};
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 1a5a4a9db2a7..4f5c249c62dc 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -13,10 +13,12 @@ typedef union efi_rng_protocol efi_rng_protocol_t;
 
 union efi_rng_protocol {
 	struct {
-		efi_status_t (*get_info)(efi_rng_protocol_t *,
-					 unsigned long *, efi_guid_t *);
-		efi_status_t (*get_rng)(efi_rng_protocol_t *,
-					efi_guid_t *, unsigned long, u8 *out);
+		efi_status_t (__efiapi *get_info)(efi_rng_protocol_t *,
+						  unsigned long *,
+						  efi_guid_t *);
+		efi_status_t (__efiapi *get_rng)(efi_rng_protocol_t *,
+						 efi_guid_t *, unsigned long,
+						 u8 *out);
 	};
 	struct {
 		u32 get_info;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 969eb06e780a..6ae582a31738 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -48,6 +48,12 @@ typedef u16 efi_char16_t;		/* UNICODE character */
 typedef u64 efi_physical_addr_t;
 typedef void *efi_handle_t;
 
+#ifdef CONFIG_X86_64
+#define __efiapi __attribute__((ms_abi))
+#else
+#define __efiapi
+#endif
+
 #define efi_get_handle_at(array, idx)					\
 	(efi_is_native() ? (array)[idx] 				\
 		: (efi_handle_t)(unsigned long)((u32 *)(array))[idx])
@@ -272,13 +278,16 @@ typedef union {
 		efi_table_hdr_t hdr;
 		void *raise_tpl;
 		void *restore_tpl;
-		efi_status_t (*allocate_pages)(int, int, unsigned long,
-					       efi_physical_addr_t *);
-		efi_status_t (*free_pages)(efi_physical_addr_t, unsigned long);
-		efi_status_t (*get_memory_map)(unsigned long *, void *, unsigned long *,
-					       unsigned long *, u32 *);
-		efi_status_t (*allocate_pool)(int, unsigned long, void **);
-		efi_status_t (*free_pool)(void *);
+		efi_status_t (__efiapi *allocate_pages)(int, int, unsigned long,
+							efi_physical_addr_t *);
+		efi_status_t (__efiapi *free_pages)(efi_physical_addr_t,
+						    unsigned long);
+		efi_status_t (__efiapi *get_memory_map)(unsigned long *, void *,
+							unsigned long *,
+							unsigned long *, u32 *);
+		efi_status_t (__efiapi *allocate_pool)(int, unsigned long,
+						       void **);
+		efi_status_t (__efiapi *free_pool)(void *);
 		void *create_event;
 		void *set_timer;
 		void *wait_for_event;
@@ -288,18 +297,22 @@ typedef union {
 		void *install_protocol_interface;
 		void *reinstall_protocol_interface;
 		void *uninstall_protocol_interface;
-		efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **);
+		efi_status_t (__efiapi *handle_protocol)(efi_handle_t,
+							 efi_guid_t *, void **);
 		void *__reserved;
 		void *register_protocol_notify;
-		efi_status_t (*locate_handle)(int, efi_guid_t *, void *,
-					      unsigned long *, efi_handle_t *);
+		efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *,
+						       void *, unsigned long *,
+						       efi_handle_t *);
 		void *locate_device_path;
-		efi_status_t (*install_configuration_table)(efi_guid_t *, void *);
+		efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *,
+								     void *);
 		void *load_image;
 		void *start_image;
 		void *exit;
 		void *unload_image;
-		efi_status_t (*exit_boot_services)(efi_handle_t, unsigned long);
+		efi_status_t (__efiapi *exit_boot_services)(efi_handle_t,
+							    unsigned long);
 		void *get_next_monotonic_count;
 		void *stall;
 		void *set_watchdog_timer;
@@ -310,7 +323,8 @@ typedef union {
 		void *open_protocol_information;
 		void *protocols_per_handle;
 		void *locate_handle_buffer;
-		efi_status_t (*locate_protocol)(efi_guid_t *, void *, void **);
+		efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *,
+							 void **);
 		void *install_multiple_protocol_interfaces;
 		void *uninstall_multiple_protocol_interfaces;
 		void *calculate_crc32;
@@ -354,16 +368,18 @@ typedef struct {
 typedef union efi_pci_io_protocol efi_pci_io_protocol_t;
 
 typedef
-efi_status_t (*efi_pci_io_protocol_mem_t)(efi_pci_io_protocol_t *,
-					  EFI_PCI_IO_PROTOCOL_WIDTH,
-					  u8 bar_index, u64 offset,
-					  unsigned long count, void *buffer);
+efi_status_t (__efiapi *efi_pci_io_protocol_mem_t)(efi_pci_io_protocol_t *,
+						   EFI_PCI_IO_PROTOCOL_WIDTH,
+						   u8 bar_index, u64 offset,
+						   unsigned long count,
+						   void *buffer);
 
 typedef
-efi_status_t (*efi_pci_io_protocol_cfg_t)(efi_pci_io_protocol_t *,
-					  EFI_PCI_IO_PROTOCOL_WIDTH,
-					  u32 offset, unsigned long count,
-					  void *buffer);
+efi_status_t (__efiapi *efi_pci_io_protocol_cfg_t)(efi_pci_io_protocol_t *,
+						   EFI_PCI_IO_PROTOCOL_WIDTH,
+						   u32 offset,
+						   unsigned long count,
+						   void *buffer);
 
 typedef struct {
 	efi_pci_io_protocol_mem_t read;
@@ -388,11 +404,11 @@ union efi_pci_io_protocol {
 		void *allocate_buffer;
 		void *free_buffer;
 		void *flush;
-		efi_status_t (*get_location)(efi_pci_io_protocol_t *,
-					     unsigned long *segment_nr,
-					     unsigned long *bus_nr,
-					     unsigned long *device_nr,
-					     unsigned long *function_nr);
+		efi_status_t (__efiapi *get_location)(efi_pci_io_protocol_t *,
+						      unsigned long *segment_nr,
+						      unsigned long *bus_nr,
+						      unsigned long *device_nr,
+						      unsigned long *func_nr);
 		void *attributes;
 		void *get_bar_attributes;
 		void *set_bar_attributes;
@@ -447,16 +463,17 @@ typedef union apple_properties_protocol apple_properties_protocol_t;
 union apple_properties_protocol {
 	struct {
 		unsigned long version;
-		efi_status_t (*get)(apple_properties_protocol_t *,
-				    struct efi_dev_path *, efi_char16_t *,
-				    void *, u32 *);
-		efi_status_t (*set)(apple_properties_protocol_t *,
-				    struct efi_dev_path *, efi_char16_t *,
-				    void *, u32);
-		efi_status_t (*del)(apple_properties_protocol_t *,
-				    struct efi_dev_path *, efi_char16_t *);
-		efi_status_t (*get_all)(apple_properties_protocol_t *,
-					void *buffer, u32 *);
+		efi_status_t (__efiapi *get)(apple_properties_protocol_t *,
+					     struct efi_dev_path *,
+					     efi_char16_t *, void *, u32 *);
+		efi_status_t (__efiapi *set)(apple_properties_protocol_t *,
+					     struct efi_dev_path *,
+					     efi_char16_t *, void *, u32);
+		efi_status_t (__efiapi *del)(apple_properties_protocol_t *,
+					     struct efi_dev_path *,
+					     efi_char16_t *);
+		efi_status_t (__efiapi *get_all)(apple_properties_protocol_t *,
+						 void *buffer, u32 *);
 	};
 	struct {
 		u32 version;
@@ -474,11 +491,11 @@ typedef union efi_tcg2_protocol efi_tcg2_protocol_t;
 union efi_tcg2_protocol {
 	struct {
 		void *get_capability;
-		efi_status_t (*get_event_log)(efi_handle_t,
-					      efi_tcg2_event_log_format,
-					      efi_physical_addr_t *,
-					      efi_physical_addr_t *,
-					      efi_bool_t *);
+		efi_status_t (__efiapi *get_event_log)(efi_handle_t,
+						       efi_tcg2_event_log_format,
+						       efi_physical_addr_t *,
+						       efi_physical_addr_t *,
+						       efi_bool_t *);
 		void *hash_log_extend_event;
 		void *submit_command;
 		void *get_active_pcr_banks;
@@ -581,21 +598,21 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes,
 
 typedef union {
 	struct {
-		efi_table_hdr_t			hdr;
-		efi_get_time_t			*get_time;
-		efi_set_time_t			*set_time;
-		efi_get_wakeup_time_t		*get_wakeup_time;
-		efi_set_wakeup_time_t		*set_wakeup_time;
-		efi_set_virtual_address_map_t	*set_virtual_address_map;
-		void				*convert_pointer;
-		efi_get_variable_t		*get_variable;
-		efi_get_next_variable_t		*get_next_variable;
-		efi_set_variable_t		*set_variable;
-		efi_get_next_high_mono_count_t	*get_next_high_mono_count;
-		efi_reset_system_t		*reset_system;
-		efi_update_capsule_t		*update_capsule;
-		efi_query_capsule_caps_t	*query_capsule_caps;
-		efi_query_variable_info_t	*query_variable_info;
+		efi_table_hdr_t				hdr;
+		efi_get_time_t __efiapi			*get_time;
+		efi_set_time_t __efiapi			*set_time;
+		efi_get_wakeup_time_t __efiapi		*get_wakeup_time;
+		efi_set_wakeup_time_t __efiapi		*set_wakeup_time;
+		efi_set_virtual_address_map_t __efiapi	*set_virtual_address_map;
+		void					*convert_pointer;
+		efi_get_variable_t __efiapi		*get_variable;
+		efi_get_next_variable_t __efiapi	*get_next_variable;
+		efi_set_variable_t __efiapi		*set_variable;
+		efi_get_next_high_mono_count_t __efiapi	*get_next_high_mono_count;
+		efi_reset_system_t __efiapi		*reset_system;
+		efi_update_capsule_t __efiapi		*update_capsule;
+		efi_query_capsule_caps_t __efiapi	*query_capsule_caps;
+		efi_query_variable_info_t __efiapi	*query_variable_info;
 	};
 	efi_runtime_services_32_t mixed_mode;
 } efi_runtime_services_t;
@@ -812,7 +829,7 @@ union efi_loaded_image {
 		__aligned_u64 image_size;
 		unsigned int image_code_type;
 		unsigned int image_data_type;
-		efi_status_t (*unload)(efi_handle_t image_handle);
+		efi_status_t ( __efiapi *unload)(efi_handle_t image_handle);
 	};
 	struct {
 		u32 revision;
@@ -847,18 +864,19 @@ typedef union efi_file_handle efi_file_handle_t;
 union efi_file_handle {
 	struct {
 		u64 revision;
-		efi_status_t (*open)(efi_file_handle_t *,
-				     efi_file_handle_t **,
-				     efi_char16_t *, u64, u64);
-		efi_status_t (*close)(efi_file_handle_t *);
+		efi_status_t (__efiapi *open)(efi_file_handle_t *,
+					      efi_file_handle_t **,
+					      efi_char16_t *, u64, u64);
+		efi_status_t (__efiapi *close)(efi_file_handle_t *);
 		void *delete;
-		efi_status_t (*read)(efi_file_handle_t *, unsigned long *,
-				     void *);
+		efi_status_t (__efiapi *read)(efi_file_handle_t *,
+					      unsigned long *, void *);
 		void *write;
 		void *get_position;
 		void *set_position;
-		efi_status_t (*get_info)(efi_file_handle_t *, efi_guid_t *,
-				unsigned long *, void *);
+		efi_status_t (__efiapi *get_info)(efi_file_handle_t *,
+						  efi_guid_t *, unsigned long *,
+						  void *);
 		void *set_info;
 		void *flush;
 	};
@@ -882,8 +900,8 @@ typedef union efi_file_io_interface efi_file_io_interface_t;
 union efi_file_io_interface {
 	struct {
 		u64 revision;
-		int (*open_volume)(efi_file_io_interface_t *,
-				   efi_file_handle_t **);
+		int (__efiapi *open_volume)(efi_file_io_interface_t *,
+					    efi_file_handle_t **);
 	};
 	struct {
 		u64 revision;
@@ -1363,8 +1381,8 @@ typedef struct {
 union efi_simple_text_output_protocol {
 	struct {
 		void *reset;
-		efi_status_t (*output_string)(efi_simple_text_output_protocol_t *,
-					      efi_char16_t *);
+		efi_status_t (__efiapi *output_string)(efi_simple_text_output_protocol_t *,
+						       efi_char16_t *);
 		void *test_string;
 	};
 	struct {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (8 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 09/21] efi/libstub: annotate firmware routines as __efiapi Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-21 21:22   ` Hans de Goede
  2019-12-18 17:01 ` [PATCH v2 11/21] efi/libstub: get rid of 'sys_table_arg' macro parameter Ard Biesheuvel
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

We use special wrapper routines to invoke firmware services in the
native case as well as the mixed mode case. For mixed mode, the need
is obvious, but for the native cases, we can simply rely on the
compiler to generate the indirect call, given that GCC now has
support for the MS calling convention (and has had it for quite some
time now). Note that on i386, the decompressor and the EFI stub are not
built with -mregparm=3 like the rest of the i386 kernel, so we can
safely allow the compiler to emit the indirect calls here as well.

So drop all the wrappers and indirection, and switch to either native
calls, or direct calls into the thunk routine for mixed mode.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/Makefile      |  2 +-
 arch/x86/boot/compressed/efi_stub_32.S | 87 --------------------
 arch/x86/boot/compressed/efi_stub_64.S |  5 --
 arch/x86/boot/compressed/head_32.S     |  6 --
 arch/x86/boot/compressed/head_64.S     | 12 ---
 arch/x86/include/asm/efi.h             | 30 +++----
 arch/x86/platform/efi/efi_64.c         |  2 -
 7 files changed, 17 insertions(+), 127 deletions(-)

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index aa976adb7094..a20f55c59753 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -89,7 +89,7 @@ vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
-vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
+vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o \
 	$(objtree)/drivers/firmware/efi/libstub/lib.a
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
 
diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S
deleted file mode 100644
index ed6c351d34ed..000000000000
--- a/arch/x86/boot/compressed/efi_stub_32.S
+++ /dev/null
@@ -1,87 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * EFI call stub for IA32.
- *
- * This stub allows us to make EFI calls in physical mode with interrupts
- * turned off. Note that this implementation is different from the one in
- * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical
- * mode at this point.
- */
-
-#include <linux/linkage.h>
-#include <asm/page_types.h>
-
-/*
- * efi_call_phys(void *, ...) is a function with variable parameters.
- * All the callers of this function assure that all the parameters are 4-bytes.
- */
-
-/*
- * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save.
- * So we'd better save all of them at the beginning of this function and restore
- * at the end no matter how many we use, because we can not assure EFI runtime
- * service functions will comply with gcc calling convention, too.
- */
-
-.text
-SYM_FUNC_START(efi_call_phys)
-	/*
-	 * 0. The function can only be called in Linux kernel. So CS has been
-	 * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
-	 * the values of these registers are the same. And, the corresponding
-	 * GDT entries are identical. So I will do nothing about segment reg
-	 * and GDT, but change GDT base register in prelog and epilog.
-	 */
-
-	/*
-	 * 1. Because we haven't been relocated by this point we need to
-	 * use relative addressing.
-	 */
-	call	1f
-1:	popl	%edx
-	subl	$1b, %edx
-
-	/*
-	 * 2. Now on the top of stack is the return
-	 * address in the caller of efi_call_phys(), then parameter 1,
-	 * parameter 2, ..., param n. To make things easy, we save the return
-	 * address of efi_call_phys in a global variable.
-	 */
-	popl	%ecx
-	movl	%ecx, saved_return_addr(%edx)
-	/* get the function pointer into ECX*/
-	popl	%ecx
-	movl	%ecx, efi_rt_function_ptr(%edx)
-
-	/*
-	 * 3. Call the physical function.
-	 */
-	call	*%ecx
-
-	/*
-	 * 4. Balance the stack. And because EAX contain the return value,
-	 * we'd better not clobber it. We need to calculate our address
-	 * again because %ecx and %edx are not preserved across EFI function
-	 * calls.
-	 */
-	call	1f
-1:	popl	%edx
-	subl	$1b, %edx
-
-	movl	efi_rt_function_ptr(%edx), %ecx
-	pushl	%ecx
-
-	/*
-	 * 10. Push the saved return address onto the stack and return.
-	 */
-	movl	saved_return_addr(%edx), %ecx
-	pushl	%ecx
-	ret
-SYM_FUNC_END(efi_call_phys)
-.previous
-
-.data
-saved_return_addr:
-	.long 0
-efi_rt_function_ptr:
-	.long 0
diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S
deleted file mode 100644
index 99494dff2113..000000000000
--- a/arch/x86/boot/compressed/efi_stub_64.S
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <asm/segment.h>
-#include <asm/msr.h>
-#include <asm/processor-flags.h>
-
-#include "../../platform/efi/efi_stub_64.S"
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 40468ab49b9b..7da4dfc53df6 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -161,9 +161,7 @@ SYM_FUNC_START(efi_pe_entry)
 	popl	%ecx
 	movl	%ecx, efi32_config+8(%esi)	/* EFI System table pointer */
 
-	/* Relocate efi_config->call() */
 	leal	efi32_config(%esi), %eax
-	add	%esi, 28(%eax)
 	pushl	%eax
 
 	call	make_boot_params
@@ -188,9 +186,7 @@ SYM_FUNC_START(efi32_stub_entry)
 	movl	%ecx, efi32_config(%esi)	/* Handle */
 	movl	%edx, efi32_config+8(%esi)	/* EFI System table pointer */
 
-	/* Relocate efi_config->call() */
 	leal	efi32_config(%esi), %eax
-	add	%esi, 28(%eax)
 	pushl	%eax
 2:
 	call	efi_main
@@ -266,8 +262,6 @@ SYM_FUNC_END(.Lrelocated)
 	.data
 efi32_config:
 	.fill 7,4,0
-	.long efi_call_phys
-	.long 0
 	.byte 0
 #endif
 
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 58a512e33d8d..6dc6a7ebb9e1 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -458,11 +458,6 @@ SYM_FUNC_START(efi_pe_entry)
 1:	popq	%rbp
 	subq	$1b, %rbp
 
-	/*
-	 * Relocate efi_config->call().
-	 */
-	addq	%rbp, efi64_config+40(%rip)
-
 	movq	%rax, %rdi
 	call	make_boot_params
 	cmpq	$0,%rax
@@ -477,11 +472,6 @@ handover_entry:
 1:	popq	%rbp
 	subq	$1b, %rbp
 
-	/*
-	 * Relocate efi_config->call().
-	 */
-	movq	efi_config(%rip), %rax
-	addq	%rbp, 40(%rax)
 2:
 	movq	efi_config(%rip), %rdi
 	call	efi_main
@@ -683,14 +673,12 @@ SYM_DATA_LOCAL(efi_config, .quad 0)
 #ifdef CONFIG_EFI_MIXED
 SYM_DATA_START(efi32_config)
 	.fill	5,8,0
-	.quad	efi64_thunk
 	.byte	0
 SYM_DATA_END(efi32_config)
 #endif
 
 SYM_DATA_START(efi64_config)
 	.fill	5,8,0
-	.quad	efi_call
 	.byte	1
 SYM_DATA_END(efi64_config)
 #endif /* CONFIG_EFI_STUB */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 183cd49e0495..e0789ec5c9f6 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -152,6 +152,7 @@ struct efi_setup_data {
 extern u64 efi_setup;
 
 #ifdef CONFIG_EFI
+extern efi_status_t efi64_thunk(u32, ...);
 
 static inline bool efi_is_mixed(void)
 {
@@ -205,7 +206,6 @@ struct efi_config {
 	efi_runtime_services_t *runtime_services;
 	efi_boot_services_t *boot_services;
 	efi_simple_text_output_protocol_t *text_output;
-	efi_status_t (*call)(unsigned long, ...);
 	bool is64;
 } __packed;
 
@@ -235,30 +235,32 @@ static inline bool efi_is_native(void)
 			(unsigned long)(attr), (attr))
 
 #define efi_table_attr(table, attr, instance) ({			\
-	__typeof__(((table##_t *)0)->attr) __ret;			\
+	__typeof__(instance->attr) __ret;				\
 	if (efi_is_native()) {						\
-		__ret = ((table##_t *)(unsigned long)instance)->attr;	\
+		__ret = instance->attr;					\
 	} else {							\
-		__ret = (__typeof__(__ret))efi_mixed_mode_cast(		\
-		((table##_t *)(unsigned long)instance)->mixed_mode.attr);\
+		__ret = (__typeof__(__ret))				\
+			efi_mixed_mode_cast(instance->mixed_mode.attr);	\
 	}								\
 	__ret;								\
 })
 
 #define efi_call_proto(protocol, f, instance, ...)			\
-	__efi_early()->call((unsigned long)				\
-				efi_table_attr(protocol, f, instance),	\
-		instance, ##__VA_ARGS__)
+	(efi_is_native()						\
+		? instance->f(instance, ##__VA_ARGS__)			\
+		: efi64_thunk(instance->mixed_mode.f, instance,	##__VA_ARGS__))
 
 #define efi_call_early(f, ...)						\
-	__efi_early()->call((unsigned long)				\
-				efi_table_attr(efi_boot_services, f,	\
-		__efi_early()->boot_services), __VA_ARGS__)
+	(efi_is_native()						\
+		? __efi_early()->boot_services->f(__VA_ARGS__)		\
+		: efi64_thunk(__efi_early()->boot_services->mixed_mode.f,\
+			__VA_ARGS__))
 
 #define efi_call_runtime(f, ...)					\
-	__efi_early()->call((unsigned long)				\
-				efi_table_attr(efi_runtime_services, f,	\
-		__efi_early()->runtime_services), __VA_ARGS__)
+	(efi_is_native()						\
+		? __efi_early()->runtime_services->f(__VA_ARGS__)	\
+		: efi64_thunk(__efi_early()->runtime_services->mixed_mode.f,\
+			__VA_ARGS__))
 
 extern bool efi_reboot_required(void);
 extern bool efi_is_table_address(unsigned long phys_addr);
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 885e50a707a6..03c2ed3c645c 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -635,8 +635,6 @@ void efi_switch_mm(struct mm_struct *mm)
 }
 
 #ifdef CONFIG_EFI_MIXED
-extern efi_status_t efi64_thunk(u32, ...);
-
 static DEFINE_SPINLOCK(efi_runtime_lock);
 
 #define runtime_service32(func)						 \
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 11/21] efi/libstub: get rid of 'sys_table_arg' macro parameter
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (9 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 12/21] efi/libstub: unify the efi_char16_printk implementations Ard Biesheuvel
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

The efi_call macros on ARM have a dependency on a variable 'sys_table_arg'
existing in the scope of the macro instantiation. Since this variable
always points to the same data structure, let's create a global getter
for it and use that instead.

Note that the use of a global variable with external linkage is avoided,
given the problems we had in the past with early processing of the GOT
tables.

While at it, drop the redundant casts in the efi_table_attr and
efi_call_proto macros.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/efi.h              |  8 ++++----
 arch/arm64/include/asm/efi.h            |  8 ++++----
 arch/x86/boot/compressed/eboot.c        |  5 +++++
 drivers/firmware/efi/libstub/arm-stub.c | 11 ++++++++++-
 drivers/firmware/efi/libstub/efistub.h  |  2 ++
 drivers/firmware/efi/libstub/gop.c      |  2 ++
 6 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 9b0c64c28bff..555364b7bd2a 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -50,15 +50,15 @@ void efi_virtmap_unload(void);
 
 /* arch specific definitions used by the stub code */
 
-#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_call_early(f, ...)		efi_system_table()->boottime->f(__VA_ARGS__)
+#define efi_call_runtime(f, ...)	efi_system_table()->runtime->f(__VA_ARGS__)
 #define efi_is_native()			(true)
 
 #define efi_table_attr(table, attr, instance)				\
-	((table##_t *)instance)->attr
+	instance->attr
 
 #define efi_call_proto(protocol, f, instance, ...)			\
-	((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
+	instance->f(instance, ##__VA_ARGS__)
 
 struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
 void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 189082c44c28..9aa518d67588 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -93,15 +93,15 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
 	return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
 }
 
-#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_call_early(f, ...)		efi_system_table()->boottime->f(__VA_ARGS__)
+#define efi_call_runtime(f, ...)	efi_system_table()->runtime->f(__VA_ARGS__)
 #define efi_is_native()			(true)
 
 #define efi_table_attr(table, attr, instance)				\
-	((table##_t *)instance)->attr
+	instance->attr
 
 #define efi_call_proto(protocol, f, instance, ...)			\
-	((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
+	instance->f(instance, ##__VA_ARGS__)
 
 #define alloc_screen_info(x...)		&screen_info
 
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 4a965212ee64..bed78679e10b 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -27,6 +27,11 @@ __pure const struct efi_config *__efi_early(void)
 	return efi_early;
 }
 
+__pure efi_system_table_t *efi_system_table(void)
+{
+	return sys_table;
+}
+
 static void setup_boot_services(struct efi_config *c)
 {
 	c->runtime_services	= efi_table_attr(efi_system_table, runtime, sys_table);
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 60a301e1c072..47f072ac3f30 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -37,6 +37,13 @@
 
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 
+static efi_system_table_t *__section(.data) sys_table;
+
+__pure efi_system_table_t *efi_system_table(void)
+{
+	return sys_table;
+}
+
 void efi_char16_printk(efi_system_table_t *sys_table_arg,
 			      efi_char16_t *str)
 {
@@ -110,7 +117,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
  * for both archictectures, with the arch-specific code provided in the
  * handle_kernel_image() function.
  */
-unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
+unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 			       unsigned long *image_addr)
 {
 	efi_loaded_image_t *image;
@@ -131,6 +138,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
 	enum efi_secureboot_mode secure_boot;
 	struct screen_info *si;
 
+	sys_table = sys_table_arg;
+
 	/* Check if we were booted by the EFI firmware */
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		goto fail;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 05739ae013c8..e6775c16a97d 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -29,6 +29,8 @@ extern int __pure nokaslr(void);
 extern int __pure is_quiet(void);
 extern int __pure novamap(void);
 
+extern __pure efi_system_table_t  *efi_system_table(void);
+
 #define pr_efi(sys_table, msg)		do {				\
 	if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg);	\
 } while (0)
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 5f4fbc2ac687..6c49d0a9aa3f 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -10,6 +10,8 @@
 #include <asm/efi.h>
 #include <asm/setup.h>
 
+#include "efistub.h"
+
 static void find_bits(unsigned long mask, u8 *pos, u8 *size)
 {
 	u8 first, len;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 12/21] efi/libstub: unify the efi_char16_printk implementations
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (10 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 11/21] efi/libstub: get rid of 'sys_table_arg' macro parameter Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct Ard Biesheuvel
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Use a single implementation for efi_char16_printk() across all
architectures.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.c               | 6 ------
 drivers/firmware/efi/libstub/arm-stub.c        | 9 ---------
 drivers/firmware/efi/libstub/efi-stub-helper.c | 9 +++++++++
 3 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index bed78679e10b..2bcab1ef5a56 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -39,12 +39,6 @@ static void setup_boot_services(struct efi_config *c)
 	c->text_output		= efi_table_attr(efi_system_table, con_out, sys_table);
 }
 
-void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
-{
-	efi_call_proto(efi_simple_text_output_protocol, output_string,
-		       efi_early->text_output, str);
-}
-
 static efi_status_t
 preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 {
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 47f072ac3f30..b44b1bd4d480 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -44,15 +44,6 @@ __pure efi_system_table_t *efi_system_table(void)
 	return sys_table;
 }
 
-void efi_char16_printk(efi_system_table_t *sys_table_arg,
-			      efi_char16_t *str)
-{
-	efi_simple_text_output_protocol_t *out;
-
-	out = (efi_simple_text_output_protocol_t *)sys_table_arg->con_out;
-	out->output_string(out, str);
-}
-
 static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg)
 {
 	efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 5eaf6ada960f..3b89317f4c80 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -975,3 +975,12 @@ void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 	}
 	return NULL;
 }
+
+void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
+{
+	efi_call_proto(efi_simple_text_output_protocol,
+		       output_string,
+		       efi_table_attr(efi_system_table, con_out,
+				      efi_system_table()),
+		       str);
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (11 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 12/21] efi/libstub: unify the efi_char16_printk implementations Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-24 19:34   ` Hans de Goede
  2019-12-31 23:04   ` Arvind Sankar
  2019-12-18 17:01 ` [PATCH v2 14/21] efi/libstub: drop sys_table_arg from printk routines Ard Biesheuvel
                   ` (8 subsequent siblings)
  21 siblings, 2 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

The various pointers we stash in the efi_config struct which we
retrieve using __efi_early() are simply copies of the ones in
the EFI system table, which we have started accessing directly
in the previous patch. So drop all the __efi_early() related
plumbing, except for the access to a boolean which tells us
whether the firmware is 64-bit or not.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.c   | 36 ++++++++------------
 arch/x86/boot/compressed/head_32.S |  2 +-
 arch/x86/boot/compressed/head_64.S |  4 +--
 arch/x86/include/asm/efi.h         | 23 +++++--------
 4 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 2bcab1ef5a56..53e67334c4c3 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -20,11 +20,17 @@
 
 static efi_system_table_t *sys_table;
 
-static struct efi_config *efi_early;
+struct efi_config {
+	u64 image_handle;
+	u64 table;
+	bool is64;
+} __packed;
 
-__pure const struct efi_config *__efi_early(void)
+static bool is64;
+
+__pure bool __efi_early_is64(void)
 {
-	return efi_early;
+	return is64;
 }
 
 __pure efi_system_table_t *efi_system_table(void)
@@ -32,13 +38,6 @@ __pure efi_system_table_t *efi_system_table(void)
 	return sys_table;
 }
 
-static void setup_boot_services(struct efi_config *c)
-{
-	c->runtime_services	= efi_table_attr(efi_system_table, runtime, sys_table);
-	c->boot_services	= efi_table_attr(efi_system_table, boottime, sys_table);
-	c->text_output		= efi_table_attr(efi_system_table, con_out, sys_table);
-}
-
 static efi_status_t
 preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 {
@@ -382,16 +381,14 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	unsigned long ramdisk_addr;
 	unsigned long ramdisk_size;
 
-	efi_early = c;
-	sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
-	handle = (void *)(unsigned long)efi_early->image_handle;
+	sys_table = (efi_system_table_t *)(unsigned long)c->table;
+	handle = (void *)(unsigned long)c->image_handle;
+	is64 = c->is64;
 
 	/* Check if we were booted by the EFI firmware */
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		return NULL;
 
-	setup_boot_services(efi_early);
-
 	status = efi_call_early(handle_protocol, handle,
 				&proto, (void *)&image);
 	if (status != EFI_SUCCESS) {
@@ -738,10 +735,9 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	efi_system_table_t *_table;
 	unsigned long cmdline_paddr;
 
-	efi_early = c;
-
-	_table = (efi_system_table_t *)(unsigned long)efi_early->table;
-	handle = (void *)(unsigned long)efi_early->image_handle;
+	_table = (efi_system_table_t *)(unsigned long)c->table;
+	handle = (void *)(unsigned long)c->image_handle;
+	is64 = c->is64;
 
 	sys_table = _table;
 
@@ -749,8 +745,6 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		goto fail;
 
-	setup_boot_services(efi_early);
-
 	/*
 	 * make_boot_params() may have been called before efi_main(), in which
 	 * case this is the second time we parse the cmdline. This is ok,
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 7da4dfc53df6..c026ab881405 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -261,7 +261,7 @@ SYM_FUNC_END(.Lrelocated)
 #ifdef CONFIG_EFI_STUB
 	.data
 efi32_config:
-	.fill 7,4,0
+	.fill 4,4,0
 	.byte 0
 #endif
 
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 6dc6a7ebb9e1..72065735abc1 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -672,13 +672,13 @@ SYM_DATA_LOCAL(efi_config, .quad 0)
 
 #ifdef CONFIG_EFI_MIXED
 SYM_DATA_START(efi32_config)
-	.fill	5,8,0
+	.fill	2,8,0
 	.byte	0
 SYM_DATA_END(efi32_config)
 #endif
 
 SYM_DATA_START(efi64_config)
-	.fill	5,8,0
+	.fill	2,8,0
 	.byte	1
 SYM_DATA_END(efi64_config)
 #endif /* CONFIG_EFI_STUB */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index e0789ec5c9f6..8137d4f5c104 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -200,16 +200,7 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
 
 /* arch specific definitions used by the stub code */
 
-struct efi_config {
-	u64 image_handle;
-	u64 table;
-	efi_runtime_services_t *runtime_services;
-	efi_boot_services_t *boot_services;
-	efi_simple_text_output_protocol_t *text_output;
-	bool is64;
-} __packed;
-
-__pure const struct efi_config *__efi_early(void);
+__pure bool __efi_early_is64(void);
 
 static inline bool efi_is_64bit(void)
 {
@@ -219,7 +210,7 @@ static inline bool efi_is_64bit(void)
 	if (!IS_ENABLED(CONFIG_EFI_MIXED))
 		return true;
 
-	return __efi_early()->is64;
+	return __efi_early_is64();
 }
 
 static inline bool efi_is_native(void)
@@ -252,14 +243,16 @@ static inline bool efi_is_native(void)
 
 #define efi_call_early(f, ...)						\
 	(efi_is_native()						\
-		? __efi_early()->boot_services->f(__VA_ARGS__)		\
-		: efi64_thunk(__efi_early()->boot_services->mixed_mode.f,\
+		? efi_system_table()->boottime->f(__VA_ARGS__)		\
+		: efi64_thunk(efi_table_attr(efi_boot_services,		\
+			boottime, efi_system_table())->mixed_mode.f,	\
 			__VA_ARGS__))
 
 #define efi_call_runtime(f, ...)					\
 	(efi_is_native()						\
-		? __efi_early()->runtime_services->f(__VA_ARGS__)	\
-		: efi64_thunk(__efi_early()->runtime_services->mixed_mode.f,\
+		? efi_system_table()->runtime->f(__VA_ARGS__)		\
+		: efi64_thunk(efi_table_attr(efi_runtime_services,	\
+			runtime, efi_system_table())->mixed_mode.f,	\
 			__VA_ARGS__))
 
 extern bool efi_reboot_required(void);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 14/21] efi/libstub: drop sys_table_arg from printk routines
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (12 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 15/21] efi/libstub: remove 'sys_table_arg' from all function prototypes Ard Biesheuvel
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

As a first step towards getting rid of the need to pass around a function
parameter 'sys_table_arg' pointing to the EFI system table, remove the
references to it in the printing code, which is represents the majority
of the use cases.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/x86/boot/compressed/eboot.c               | 28 +++++++--------
 drivers/firmware/efi/libstub/arm-stub.c        | 28 +++++++--------
 drivers/firmware/efi/libstub/arm32-stub.c      | 14 ++++----
 drivers/firmware/efi/libstub/arm64-stub.c      | 12 +++----
 drivers/firmware/efi/libstub/efi-stub-helper.c | 37 ++++++++++----------
 drivers/firmware/efi/libstub/efistub.h         |  9 ++---
 drivers/firmware/efi/libstub/fdt.c             | 16 ++++-----
 drivers/firmware/efi/libstub/secureboot.c      |  4 +--
 drivers/firmware/efi/libstub/tpm.c             |  3 +-
 include/linux/efi.h                            |  2 +-
 10 files changed, 75 insertions(+), 78 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 53e67334c4c3..92fbd455f496 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -64,7 +64,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size,
 				(void **)&rom);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to allocate memory for 'rom'\n");
+		efi_printk("Failed to allocate memory for 'rom'\n");
 		return status;
 	}
 
@@ -81,7 +81,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 				&rom->vendor);
 
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to read rom->vendor\n");
+		efi_printk("Failed to read rom->vendor\n");
 		goto free_struct;
 	}
 
@@ -90,7 +90,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 				&rom->devid);
 
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to read rom->devid\n");
+		efi_printk("Failed to read rom->devid\n");
 		goto free_struct;
 	}
 
@@ -139,7 +139,7 @@ static void setup_efi_pci(struct boot_params *params)
 					size, (void **)&pci_handle);
 
 		if (status != EFI_SUCCESS) {
-			efi_printk(sys_table, "Failed to allocate memory for 'pci_handle'\n");
+			efi_printk("Failed to allocate memory for 'pci_handle'\n");
 			return;
 		}
 
@@ -194,7 +194,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 		return;
 
 	if (efi_table_attr(apple_properties_protocol, version, p) != 0x10000) {
-		efi_printk(sys_table, "Unsupported properties proto version\n");
+		efi_printk("Unsupported properties proto version\n");
 		return;
 	}
 
@@ -207,7 +207,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 					size + sizeof(struct setup_data),
 					(void **)&new);
 		if (status != EFI_SUCCESS) {
-			efi_printk(sys_table, "Failed to allocate memory for 'properties'\n");
+			efi_printk("Failed to allocate memory for 'properties'\n");
 			return;
 		}
 
@@ -392,14 +392,14 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	status = efi_call_early(handle_protocol, handle,
 				&proto, (void *)&image);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
+		efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
 		return NULL;
 	}
 
 	status = efi_low_alloc(sys_table, 0x4000, 1,
 			       (unsigned long *)&boot_params);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to allocate lowmem for boot params\n");
+		efi_printk("Failed to allocate lowmem for boot params\n");
 		return NULL;
 	}
 
@@ -447,7 +447,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
 
 	if (status != EFI_SUCCESS &&
 	    hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) {
-		efi_printk(sys_table, "Trying to load files to higher address\n");
+		efi_printk("Trying to load files to higher address\n");
 		status = handle_cmdline_files(sys_table, image,
 				      (char *)(unsigned long)hdr->cmd_line_ptr,
 				      "initrd=", -1UL,
@@ -777,7 +777,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
 				sizeof(*gdt), (void **)&gdt);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to allocate memory for 'gdt' structure\n");
+		efi_printk("Failed to allocate memory for 'gdt' structure\n");
 		goto fail;
 	}
 
@@ -785,7 +785,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	status = efi_low_alloc(sys_table, gdt->size, 8,
 			   (unsigned long *)&gdt->address);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "Failed to allocate memory for 'gdt'\n");
+		efi_printk("Failed to allocate memory for 'gdt'\n");
 		goto fail;
 	}
 
@@ -801,7 +801,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 					     hdr->kernel_alignment,
 					     LOAD_PHYSICAL_ADDR);
 		if (status != EFI_SUCCESS) {
-			efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
+			efi_printk("efi_relocate_kernel() failed!\n");
 			goto fail;
 		}
 
@@ -811,7 +811,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 
 	status = exit_boot(boot_params, handle);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table, "exit_boot() failed!\n");
+		efi_printk("exit_boot() failed!\n");
 		goto fail;
 	}
 
@@ -904,7 +904,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 
 	return boot_params;
 fail:
-	efi_printk(sys_table, "efi_main() failed!\n");
+	efi_printk("efi_main() failed!\n");
 
 	return NULL;
 }
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index b44b1bd4d480..2ed4bd457e66 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -73,7 +73,7 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
 				(void **)&rsv);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table_arg, "Failed to allocate memreserve entry!\n");
+		pr_efi_err("Failed to allocate memreserve entry!\n");
 		return;
 	}
 
@@ -85,7 +85,7 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
 				&memreserve_table_guid,
 				rsv);
 	if (status != EFI_SUCCESS)
-		pr_efi_err(sys_table_arg, "Failed to install memreserve config table!\n");
+		pr_efi_err("Failed to install memreserve config table!\n");
 }
 
 
@@ -147,13 +147,13 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	status = sys_table->boottime->handle_protocol(handle,
 					&loaded_image_proto, (void *)&image);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Failed to get loaded image protocol\n");
+		pr_efi_err("Failed to get loaded image protocol\n");
 		goto fail;
 	}
 
 	dram_base = get_dram_base(sys_table);
 	if (dram_base == EFI_ERROR) {
-		pr_efi_err(sys_table, "Failed to find DRAM base\n");
+		pr_efi_err("Failed to find DRAM base\n");
 		goto fail;
 	}
 
@@ -164,7 +164,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	 */
 	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
 	if (!cmdline_ptr) {
-		pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
+		pr_efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
 		goto fail;
 	}
 
@@ -176,7 +176,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
 		efi_parse_options(cmdline_ptr);
 
-	pr_efi(sys_table, "Booting Linux Kernel...\n");
+	pr_efi("Booting Linux Kernel...\n");
 
 	si = setup_graphics(sys_table);
 
@@ -185,7 +185,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 				     &reserve_size,
 				     dram_base, image);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Failed to relocate kernel\n");
+		pr_efi_err("Failed to relocate kernel\n");
 		goto fail_free_cmdline;
 	}
 
@@ -204,29 +204,29 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
 	     secure_boot != efi_secureboot_mode_disabled) {
 		if (strstr(cmdline_ptr, "dtb="))
-			pr_efi(sys_table, "Ignoring DTB from command line.\n");
+			pr_efi("Ignoring DTB from command line.\n");
 	} else {
 		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
 					      "dtb=",
 					      ~0UL, &fdt_addr, &fdt_size);
 
 		if (status != EFI_SUCCESS) {
-			pr_efi_err(sys_table, "Failed to load device tree!\n");
+			pr_efi_err("Failed to load device tree!\n");
 			goto fail_free_image;
 		}
 	}
 
 	if (fdt_addr) {
-		pr_efi(sys_table, "Using DTB from command line\n");
+		pr_efi("Using DTB from command line\n");
 	} else {
 		/* Look for a device tree configuration table entry. */
 		fdt_addr = (uintptr_t)get_fdt(sys_table, &fdt_size);
 		if (fdt_addr)
-			pr_efi(sys_table, "Using DTB from configuration table\n");
+			pr_efi("Using DTB from configuration table\n");
 	}
 
 	if (!fdt_addr)
-		pr_efi(sys_table, "Generating empty DTB\n");
+		pr_efi("Generating empty DTB\n");
 
 	status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
 				      efi_get_max_initrd_addr(dram_base,
@@ -234,7 +234,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 				      (unsigned long *)&initrd_addr,
 				      (unsigned long *)&initrd_size);
 	if (status != EFI_SUCCESS)
-		pr_efi_err(sys_table, "Failed initrd from command line!\n");
+		pr_efi_err("Failed initrd from command line!\n");
 
 	efi_random_get_seed(sys_table);
 
@@ -275,7 +275,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	if (status == EFI_SUCCESS)
 		return new_fdt_addr;
 
-	pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n");
+	pr_efi_err("Failed to update FDT and exit boot services\n");
 
 	efi_free(sys_table, initrd_size, initrd_addr);
 	efi_free(sys_table, fdt_size, fdt_addr);
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index 4566640de650..7b5c717ddfac 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -18,7 +18,7 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 	/* LPAE kernels need compatible hardware */
 	block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
 	if (block < 5) {
-		pr_efi_err(sys_table_arg, "This LPAE kernel is not supported by your CPU\n");
+		pr_efi_err("This LPAE kernel is not supported by your CPU\n");
 		return EFI_UNSUPPORTED;
 	}
 	return EFI_SUCCESS;
@@ -121,8 +121,7 @@ static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
 	 */
 	status = efi_get_memory_map(sys_table_arg, &map);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table_arg,
-			   "reserve_kernel_base(): Unable to retrieve memory map.\n");
+		pr_efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
 		return status;
 	}
 
@@ -164,8 +163,7 @@ static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
 						(end - start) / EFI_PAGE_SIZE,
 						&start);
 			if (status != EFI_SUCCESS) {
-				pr_efi_err(sys_table_arg,
-					"reserve_kernel_base(): alloc failed.\n");
+				pr_efi_err("reserve_kernel_base(): alloc failed.\n");
 				goto out;
 			}
 			break;
@@ -224,7 +222,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 	status = reserve_kernel_base(sys_table, kernel_base, reserve_addr,
 				     reserve_size);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
+		pr_efi_err("Unable to allocate memory for uncompressed kernel.\n");
 		return status;
 	}
 
@@ -237,7 +235,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 				     *image_size,
 				     kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Failed to relocate kernel.\n");
+		pr_efi_err("Failed to relocate kernel.\n");
 		efi_free(sys_table, *reserve_size, *reserve_addr);
 		*reserve_size = 0;
 		return status;
@@ -249,7 +247,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 	 * address at which the zImage is loaded.
 	 */
 	if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
-		pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n");
+		pr_efi_err("Failed to relocate kernel, no low memory available.\n");
 		efi_free(sys_table, *reserve_size, *reserve_addr);
 		*reserve_size = 0;
 		efi_free(sys_table, *image_size, *image_addr);
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 1550d244e996..b09dda600c78 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -32,9 +32,9 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 	tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
 	if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
 		if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
-			pr_efi_err(sys_table_arg, "This 64 KB granular kernel is not supported by your CPU\n");
+			pr_efi_err("This 64 KB granular kernel is not supported by your CPU\n");
 		else
-			pr_efi_err(sys_table_arg, "This 16 KB granular kernel is not supported by your CPU\n");
+			pr_efi_err("This 16 KB granular kernel is not supported by your CPU\n");
 		return EFI_UNSUPPORTED;
 	}
 	return EFI_SUCCESS;
@@ -60,13 +60,13 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 						      sizeof(phys_seed),
 						      (u8 *)&phys_seed);
 			if (status == EFI_NOT_FOUND) {
-				pr_efi(sys_table_arg, "EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
+				pr_efi("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
 			} else if (status != EFI_SUCCESS) {
-				pr_efi_err(sys_table_arg, "efi_get_random_bytes() failed\n");
+				pr_efi_err("efi_get_random_bytes() failed\n");
 				return status;
 			}
 		} else {
-			pr_efi(sys_table_arg, "KASLR disabled on kernel command line\n");
+			pr_efi("KASLR disabled on kernel command line\n");
 		}
 	}
 
@@ -143,7 +143,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 				       MIN_KIMG_ALIGN, reserve_addr);
 
 		if (status != EFI_SUCCESS) {
-			pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
+			pr_efi_err("Failed to relocate kernel\n");
 			*reserve_size = 0;
 			return status;
 		}
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3b89317f4c80..ebe792f2ed27 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -58,7 +58,7 @@ struct file_info {
 	u64 size;
 };
 
-void efi_printk(efi_system_table_t *sys_table_arg, char *str)
+void efi_printk(char *str)
 {
 	char *s8;
 
@@ -68,10 +68,10 @@ void efi_printk(efi_system_table_t *sys_table_arg, char *str)
 		ch[0] = *s8;
 		if (*s8 == '\n') {
 			efi_char16_t nl[2] = { '\r', 0 };
-			efi_char16_printk(sys_table_arg, nl);
+			efi_char16_printk(nl);
 		}
 
-		efi_char16_printk(sys_table_arg, ch);
+		efi_char16_printk(ch);
 	}
 }
 
@@ -378,9 +378,9 @@ static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
 	status = efi_call_proto(efi_file_handle, open, fh, &h, filename_16,
 				EFI_FILE_MODE_READ, (u64)0);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg, "Failed to open file: ");
-		efi_char16_printk(sys_table_arg, filename_16);
-		efi_printk(sys_table_arg, "\n");
+		efi_printk("Failed to open file: ");
+		efi_char16_printk(filename_16);
+		efi_printk("\n");
 		return status;
 	}
 
@@ -390,7 +390,7 @@ static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
 	status = efi_call_proto(efi_file_handle, get_info, h, &info_guid,
 				&info_sz, NULL);
 	if (status != EFI_BUFFER_TOO_SMALL) {
-		efi_printk(sys_table_arg, "Failed to get file info size\n");
+		efi_printk("Failed to get file info size\n");
 		return status;
 	}
 
@@ -398,7 +398,7 @@ static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
 				info_sz, (void **)&info);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
+		efi_printk("Failed to alloc mem for file info\n");
 		return status;
 	}
 
@@ -413,7 +413,7 @@ static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
 	efi_call_early(free_pool, info);
 
 	if (status != EFI_SUCCESS)
-		efi_printk(sys_table_arg, "Failed to get initrd info\n");
+		efi_printk("Failed to get initrd info\n");
 
 	return status;
 }
@@ -442,13 +442,13 @@ static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
 	status = efi_call_early(handle_protocol, handle,
 				&fs_proto, (void **)&io);
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
+		efi_printk("Failed to handle fs_proto\n");
 		return status;
 	}
 
 	status = efi_call_proto(efi_file_io_interface, open_volume, io, &fh);
 	if (status != EFI_SUCCESS)
-		efi_printk(sys_table_arg, "Failed to open volume\n");
+		efi_printk("Failed to open volume\n");
 	else
 		*__fh = fh;
 
@@ -547,8 +547,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 	 * by the thunking code.
 	 */
 	if (!efi_is_native()) {
-		pr_efi(sys_table_arg,
-		       "Ignoring file= arguments on mixed mode system\n");
+		pr_efi("Ignoring file= arguments on mixed mode system\n");
 		return EFI_SUCCESS;
 	}
 
@@ -589,7 +588,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
 				nr_files * sizeof(*files), (void **)&files);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table_arg, "Failed to alloc mem for file handle list\n");
+		pr_efi_err("Failed to alloc mem for file handle list\n");
 		goto fail;
 	}
 
@@ -652,13 +651,13 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 		status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000,
 				    &file_addr, max_addr);
 		if (status != EFI_SUCCESS) {
-			pr_efi_err(sys_table_arg, "Failed to alloc highmem for files\n");
+			pr_efi_err("Failed to alloc highmem for files\n");
 			goto close_handles;
 		}
 
 		/* We've run out of free low memory. */
 		if (file_addr > max_addr) {
-			pr_efi_err(sys_table_arg, "We've run out of free low memory\n");
+			pr_efi_err("We've run out of free low memory\n");
 			status = EFI_INVALID_PARAMETER;
 			goto free_file_total;
 		}
@@ -680,7 +679,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 						       &chunksize,
 						       (void *)addr);
 				if (status != EFI_SUCCESS) {
-					pr_efi_err(sys_table_arg, "Failed to read file\n");
+					pr_efi_err("Failed to read file\n");
 					goto free_file_total;
 				}
 				addr += chunksize;
@@ -766,7 +765,7 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
 					     alignment, &new_addr, min_addr);
 	}
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table_arg, "Failed to allocate usable memory for kernel.\n");
+		pr_efi_err("Failed to allocate usable memory for kernel.\n");
 		return status;
 	}
 
@@ -976,7 +975,7 @@ void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 	return NULL;
 }
 
-void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
+void efi_char16_printk(efi_char16_t *str)
 {
 	efi_call_proto(efi_simple_text_output_protocol,
 		       output_string,
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index e6775c16a97d..4a6acd28ce65 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -31,13 +31,14 @@ extern int __pure novamap(void);
 
 extern __pure efi_system_table_t  *efi_system_table(void);
 
-#define pr_efi(sys_table, msg)		do {				\
-	if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg);	\
+#define pr_efi(msg)		do {			\
+	if (!is_quiet()) efi_printk("EFI stub: "msg);	\
 } while (0)
 
-#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
+#define pr_efi_err(msg) efi_printk("EFI stub: ERROR: "msg)
 
-void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+void efi_char16_printk(efi_char16_t *);
+void efi_char16_printk(efi_char16_t *);
 
 unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
 
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 0bf0190917e0..1bf7edfd81ec 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -40,7 +40,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
 	/* Do some checks on provided FDT, if it exists: */
 	if (orig_fdt) {
 		if (fdt_check_header(orig_fdt)) {
-			pr_efi_err(sys_table, "Device Tree header not valid!\n");
+			pr_efi_err("Device Tree header not valid!\n");
 			return EFI_LOAD_ERROR;
 		}
 		/*
@@ -48,7 +48,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
 		 * configuration table:
 		 */
 		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
-			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
+			pr_efi_err("Truncated device tree! foo!\n");
 			return EFI_LOAD_ERROR;
 		}
 	}
@@ -277,17 +277,17 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	 */
 	status = efi_get_memory_map(sys_table, &map);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n");
+		pr_efi_err("Unable to retrieve UEFI memory map.\n");
 		return status;
 	}
 
-	pr_efi(sys_table, "Exiting boot services and installing virtual address map...\n");
+	pr_efi("Exiting boot services and installing virtual address map...\n");
 
 	map.map = &memory_map;
 	status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
 				new_fdt_addr, max_addr);
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
+		pr_efi_err("Unable to allocate memory for new device tree.\n");
 		goto fail;
 	}
 
@@ -304,7 +304,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 			    initrd_addr, initrd_size);
 
 	if (status != EFI_SUCCESS) {
-		pr_efi_err(sys_table, "Unable to construct new device tree.\n");
+		pr_efi_err("Unable to construct new device tree.\n");
 		goto fail_free_new_fdt;
 	}
 
@@ -350,7 +350,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 		return EFI_SUCCESS;
 	}
 
-	pr_efi_err(sys_table, "Exit boot services failed.\n");
+	pr_efi_err("Exit boot services failed.\n");
 
 fail_free_new_fdt:
 	efi_free(sys_table, MAX_FDT_SIZE, *new_fdt_addr);
@@ -371,7 +371,7 @@ void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
 		return NULL;
 
 	if (fdt_check_header(fdt) != 0) {
-		pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n");
+		pr_efi_err("Invalid header detected on UEFI supplied FDT, ignoring ...\n");
 		return NULL;
 	}
 	*fdt_size = fdt_totalsize(fdt);
diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c
index edba5e7a3743..9071b57da8fe 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -72,10 +72,10 @@ enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg)
 		return efi_secureboot_mode_disabled;
 
 secure_boot_enabled:
-	pr_efi(sys_table_arg, "UEFI Secure Boot is enabled.\n");
+	pr_efi("UEFI Secure Boot is enabled.\n");
 	return efi_secureboot_mode_enabled;
 
 out_efi_err:
-	pr_efi_err(sys_table_arg, "Could not determine UEFI Secure Boot status.\n");
+	pr_efi_err("Could not determine UEFI Secure Boot status.\n");
 	return efi_secureboot_mode_unknown;
 }
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index d270acd43de8..86658b005e85 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -131,8 +131,7 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
 				(void **) &log_tbl);
 
 	if (status != EFI_SUCCESS) {
-		efi_printk(sys_table_arg,
-			   "Unable to allocate memory for event log\n");
+		efi_printk("Unable to allocate memory for event log\n");
 		return;
 	}
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 6ae582a31738..1cddf3337471 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1551,7 +1551,7 @@ static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
 
 /* prototypes shared between arch specific and generic stub code */
 
-void efi_printk(efi_system_table_t *sys_table_arg, char *str);
+void efi_printk(char *str);
 
 void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
 	      unsigned long addr);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 15/21] efi/libstub: remove 'sys_table_arg' from all function prototypes
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (13 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 14/21] efi/libstub: drop sys_table_arg from printk routines Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 16/21] efi/libstub: drop protocol argument from efi_call_proto() macro Ard Biesheuvel
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

We have a helper efi_system_table() that gives us the address of the
EFI system table in memory, so there is no longer point in passing
it around from each function to the next.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/efi.h                     |  4 +-
 arch/arm64/include/asm/efi.h                   |  3 +-
 arch/x86/boot/compressed/eboot.c               | 40 +++++------
 drivers/firmware/efi/libstub/arm-stub.c        | 55 +++++++--------
 drivers/firmware/efi/libstub/arm32-stub.c      | 26 +++----
 drivers/firmware/efi/libstub/arm64-stub.c      | 12 ++--
 drivers/firmware/efi/libstub/efi-stub-helper.c | 74 +++++++++-----------
 drivers/firmware/efi/libstub/efistub.h         | 17 ++---
 drivers/firmware/efi/libstub/fdt.c             | 37 +++++-----
 drivers/firmware/efi/libstub/gop.c             | 10 ++-
 drivers/firmware/efi/libstub/random.c          | 10 ++-
 drivers/firmware/efi/libstub/secureboot.c      |  2 +-
 drivers/firmware/efi/libstub/tpm.c             |  5 +-
 include/linux/efi.h                            | 43 +++++-------
 14 files changed, 147 insertions(+), 191 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 555364b7bd2a..58e5acc424a0 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -60,8 +60,8 @@ void efi_virtmap_unload(void);
 #define efi_call_proto(protocol, f, instance, ...)			\
 	instance->f(instance, ##__VA_ARGS__)
 
-struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
-void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
+struct screen_info *alloc_screen_info(void);
+void free_screen_info(struct screen_info *si);
 
 static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
 {
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 9aa518d67588..d73693177f31 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -105,8 +105,7 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
 
 #define alloc_screen_info(x...)		&screen_info
 
-static inline void free_screen_info(efi_system_table_t *sys_table_arg,
-				    struct screen_info *si)
+static inline void free_screen_info(struct screen_info *si)
 {
 }
 
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 92fbd455f496..b4e859399451 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -347,7 +347,7 @@ void setup_graphics(struct boot_params *boot_params)
 				EFI_LOCATE_BY_PROTOCOL,
 				&graphics_proto, NULL, &size, gop_handle);
 	if (status == EFI_BUFFER_TOO_SMALL)
-		status = efi_setup_gop(NULL, si, &graphics_proto, size);
+		status = efi_setup_gop(si, &graphics_proto, size);
 
 	if (status != EFI_SUCCESS) {
 		size = 0;
@@ -396,8 +396,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
 		return NULL;
 	}
 
-	status = efi_low_alloc(sys_table, 0x4000, 1,
-			       (unsigned long *)&boot_params);
+	status = efi_low_alloc(0x4000, 1, (unsigned long *)&boot_params);
 	if (status != EFI_SUCCESS) {
 		efi_printk("Failed to allocate lowmem for boot params\n");
 		return NULL;
@@ -422,7 +421,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	hdr->type_of_loader = 0x21;
 
 	/* Convert unicode cmdline to ascii */
-	cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size);
+	cmdline_ptr = efi_convert_cmdline(image, &options_size);
 	if (!cmdline_ptr)
 		goto fail;
 
@@ -440,7 +439,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	if (status != EFI_SUCCESS)
 		goto fail2;
 
-	status = handle_cmdline_files(sys_table, image,
+	status = handle_cmdline_files(image,
 				      (char *)(unsigned long)hdr->cmd_line_ptr,
 				      "initrd=", hdr->initrd_addr_max,
 				      &ramdisk_addr, &ramdisk_size);
@@ -448,7 +447,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	if (status != EFI_SUCCESS &&
 	    hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) {
 		efi_printk("Trying to load files to higher address\n");
-		status = handle_cmdline_files(sys_table, image,
+		status = handle_cmdline_files(image,
 				      (char *)(unsigned long)hdr->cmd_line_ptr,
 				      "initrd=", -1UL,
 				      &ramdisk_addr, &ramdisk_size);
@@ -464,9 +463,9 @@ struct boot_params *make_boot_params(struct efi_config *c)
 	return boot_params;
 
 fail2:
-	efi_free(sys_table, options_size, hdr->cmd_line_ptr);
+	efi_free(options_size, hdr->cmd_line_ptr);
 fail:
-	efi_free(sys_table, 0x4000, (unsigned long)boot_params);
+	efi_free(0x4000, (unsigned long)boot_params);
 
 	return NULL;
 }
@@ -633,7 +632,7 @@ static efi_status_t allocate_e820(struct boot_params *params,
 	boot_map.key_ptr	= NULL;
 	boot_map.buff_size	= &buff_size;
 
-	status = efi_get_memory_map(sys_table, &boot_map);
+	status = efi_get_memory_map(&boot_map);
 	if (status != EFI_SUCCESS)
 		return status;
 
@@ -655,8 +654,7 @@ struct exit_boot_struct {
 	struct efi_info		*efi;
 };
 
-static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
-				   struct efi_boot_memmap *map,
+static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
 				   void *priv)
 {
 	const char *signature;
@@ -666,14 +664,14 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
 				   : EFI32_LOADER_SIGNATURE;
 	memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
 
-	p->efi->efi_systab		= (unsigned long)sys_table_arg;
+	p->efi->efi_systab		= (unsigned long)efi_system_table();
 	p->efi->efi_memdesc_size	= *map->desc_size;
 	p->efi->efi_memdesc_version	= *map->desc_ver;
 	p->efi->efi_memmap		= (unsigned long)*map->map;
 	p->efi->efi_memmap_size		= *map->map_size;
 
 #ifdef CONFIG_X86_64
-	p->efi->efi_systab_hi		= (unsigned long)sys_table_arg >> 32;
+	p->efi->efi_systab_hi		= (unsigned long)efi_system_table() >> 32;
 	p->efi->efi_memmap_hi		= (unsigned long)*map->map >> 32;
 #endif
 
@@ -705,8 +703,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 		return status;
 
 	/* Might as well exit boot services now */
-	status = efi_exit_boot_services(sys_table, handle, &map, &priv,
-					exit_boot_func);
+	status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
 	if (status != EFI_SUCCESS)
 		return status;
 
@@ -759,14 +756,14 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	 * otherwise we ask the BIOS.
 	 */
 	if (boot_params->secure_boot == efi_secureboot_mode_unset)
-		boot_params->secure_boot = efi_get_secureboot(sys_table);
+		boot_params->secure_boot = efi_get_secureboot();
 
 	/* Ask the firmware to clear memory on unclean shutdown */
-	efi_enable_reset_attack_mitigation(sys_table);
+	efi_enable_reset_attack_mitigation();
 
-	efi_random_get_seed(sys_table);
+	efi_random_get_seed();
 
-	efi_retrieve_tpm2_eventlog(sys_table);
+	efi_retrieve_tpm2_eventlog();
 
 	setup_graphics(boot_params);
 
@@ -782,8 +779,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	}
 
 	gdt->size = 0x800;
-	status = efi_low_alloc(sys_table, gdt->size, 8,
-			   (unsigned long *)&gdt->address);
+	status = efi_low_alloc(gdt->size, 8, (unsigned long *)&gdt->address);
 	if (status != EFI_SUCCESS) {
 		efi_printk("Failed to allocate memory for 'gdt'\n");
 		goto fail;
@@ -795,7 +791,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
 	 */
 	if (hdr->pref_address != hdr->code32_start) {
 		unsigned long bzimage_addr = hdr->code32_start;
-		status = efi_relocate_kernel(sys_table, &bzimage_addr,
+		status = efi_relocate_kernel(&bzimage_addr,
 					     hdr->init_size, hdr->init_size,
 					     hdr->pref_address,
 					     hdr->kernel_alignment,
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 2ed4bd457e66..e1ec0b2cde29 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -44,7 +44,7 @@ __pure efi_system_table_t *efi_system_table(void)
 	return sys_table;
 }
 
-static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg)
+static struct screen_info *setup_graphics(void)
 {
 	efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
 	efi_status_t status;
@@ -56,15 +56,15 @@ static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg)
 	status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL,
 				&gop_proto, NULL, &size, gop_handle);
 	if (status == EFI_BUFFER_TOO_SMALL) {
-		si = alloc_screen_info(sys_table_arg);
+		si = alloc_screen_info();
 		if (!si)
 			return NULL;
-		efi_setup_gop(sys_table_arg, si, &gop_proto, size);
+		efi_setup_gop(si, &gop_proto, size);
 	}
 	return si;
 }
 
-void install_memreserve_table(efi_system_table_t *sys_table_arg)
+void install_memreserve_table(void)
 {
 	struct linux_efi_memreserve *rsv;
 	efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
@@ -95,8 +95,7 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
  * must be reserved. On failure it is required to free all
  * all allocations it has made.
  */
-efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
-				 unsigned long *image_addr,
+efi_status_t handle_kernel_image(unsigned long *image_addr,
 				 unsigned long *image_size,
 				 unsigned long *reserve_addr,
 				 unsigned long *reserve_size,
@@ -135,7 +134,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		goto fail;
 
-	status = check_platform_features(sys_table);
+	status = check_platform_features();
 	if (status != EFI_SUCCESS)
 		goto fail;
 
@@ -151,7 +150,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 		goto fail;
 	}
 
-	dram_base = get_dram_base(sys_table);
+	dram_base = get_dram_base();
 	if (dram_base == EFI_ERROR) {
 		pr_efi_err("Failed to find DRAM base\n");
 		goto fail;
@@ -162,7 +161,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	 * protocol. We are going to copy the command line into the
 	 * device tree, so this can be allocated anywhere.
 	 */
-	cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
+	cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
 	if (!cmdline_ptr) {
 		pr_efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
 		goto fail;
@@ -178,9 +177,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 
 	pr_efi("Booting Linux Kernel...\n");
 
-	si = setup_graphics(sys_table);
+	si = setup_graphics();
 
-	status = handle_kernel_image(sys_table, image_addr, &image_size,
+	status = handle_kernel_image(image_addr, &image_size,
 				     &reserve_addr,
 				     &reserve_size,
 				     dram_base, image);
@@ -189,12 +188,12 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 		goto fail_free_cmdline;
 	}
 
-	efi_retrieve_tpm2_eventlog(sys_table);
+	efi_retrieve_tpm2_eventlog();
 
 	/* Ask the firmware to clear memory on unclean shutdown */
-	efi_enable_reset_attack_mitigation(sys_table);
+	efi_enable_reset_attack_mitigation();
 
-	secure_boot = efi_get_secureboot(sys_table);
+	secure_boot = efi_get_secureboot();
 
 	/*
 	 * Unauthenticated device tree data is a security hazard, so ignore
@@ -206,8 +205,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 		if (strstr(cmdline_ptr, "dtb="))
 			pr_efi("Ignoring DTB from command line.\n");
 	} else {
-		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
-					      "dtb=",
+		status = handle_cmdline_files(image, cmdline_ptr, "dtb=",
 					      ~0UL, &fdt_addr, &fdt_size);
 
 		if (status != EFI_SUCCESS) {
@@ -220,7 +218,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 		pr_efi("Using DTB from command line\n");
 	} else {
 		/* Look for a device tree configuration table entry. */
-		fdt_addr = (uintptr_t)get_fdt(sys_table, &fdt_size);
+		fdt_addr = (uintptr_t)get_fdt(&fdt_size);
 		if (fdt_addr)
 			pr_efi("Using DTB from configuration table\n");
 	}
@@ -228,7 +226,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	if (!fdt_addr)
 		pr_efi("Generating empty DTB\n");
 
-	status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
+	status = handle_cmdline_files(image, cmdline_ptr, "initrd=",
 				      efi_get_max_initrd_addr(dram_base,
 							      *image_addr),
 				      (unsigned long *)&initrd_addr,
@@ -236,7 +234,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	if (status != EFI_SUCCESS)
 		pr_efi_err("Failed initrd from command line!\n");
 
-	efi_random_get_seed(sys_table);
+	efi_random_get_seed();
 
 	/* hibernation expects the runtime regions to stay in the same place */
 	if (!IS_ENABLED(CONFIG_HIBERNATION) && !nokaslr()) {
@@ -251,18 +249,17 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 					    EFI_RT_VIRTUAL_SIZE;
 		u32 rnd;
 
-		status = efi_get_random_bytes(sys_table, sizeof(rnd),
-					      (u8 *)&rnd);
+		status = efi_get_random_bytes(sizeof(rnd), (u8 *)&rnd);
 		if (status == EFI_SUCCESS) {
 			virtmap_base = EFI_RT_VIRTUAL_BASE +
 				       (((headroom >> 21) * rnd) >> (32 - 21));
 		}
 	}
 
-	install_memreserve_table(sys_table);
+	install_memreserve_table();
 
 	new_fdt_addr = fdt_addr;
-	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
+	status = allocate_new_fdt_and_exit_boot(handle,
 				&new_fdt_addr, efi_get_max_fdt_addr(dram_base),
 				initrd_addr, initrd_size, cmdline_ptr,
 				fdt_addr, fdt_size);
@@ -277,15 +274,15 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 
 	pr_efi_err("Failed to update FDT and exit boot services\n");
 
-	efi_free(sys_table, initrd_size, initrd_addr);
-	efi_free(sys_table, fdt_size, fdt_addr);
+	efi_free(initrd_size, initrd_addr);
+	efi_free(fdt_size, fdt_addr);
 
 fail_free_image:
-	efi_free(sys_table, image_size, *image_addr);
-	efi_free(sys_table, reserve_size, reserve_addr);
+	efi_free(image_size, *image_addr);
+	efi_free(reserve_size, reserve_addr);
 fail_free_cmdline:
-	free_screen_info(sys_table, si);
-	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
+	free_screen_info(si);
+	efi_free(cmdline_size, (unsigned long)cmdline_ptr);
 fail:
 	return EFI_ERROR;
 }
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index 7b5c717ddfac..e7a38d912749 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -7,7 +7,7 @@
 
 #include "efistub.h"
 
-efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
+efi_status_t check_platform_features(void)
 {
 	int block;
 
@@ -26,7 +26,7 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 
 static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
 
-struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg)
+struct screen_info *alloc_screen_info(void)
 {
 	struct screen_info *si;
 	efi_status_t status;
@@ -52,7 +52,7 @@ struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg)
 	return NULL;
 }
 
-void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si)
+void free_screen_info(struct screen_info *si)
 {
 	if (!si)
 		return;
@@ -61,8 +61,7 @@ void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si)
 	efi_call_early(free_pool, si);
 }
 
-static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
-					unsigned long dram_base,
+static efi_status_t reserve_kernel_base(unsigned long dram_base,
 					unsigned long *reserve_addr,
 					unsigned long *reserve_size)
 {
@@ -119,7 +118,7 @@ static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
 	 * released to the OS after ExitBootServices(), the decompressor can
 	 * safely overwrite them.
 	 */
-	status = efi_get_memory_map(sys_table_arg, &map);
+	status = efi_get_memory_map(&map);
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
 		return status;
@@ -190,8 +189,7 @@ static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
 	return status;
 }
 
-efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
-				 unsigned long *image_addr,
+efi_status_t handle_kernel_image(unsigned long *image_addr,
 				 unsigned long *image_size,
 				 unsigned long *reserve_addr,
 				 unsigned long *reserve_size,
@@ -219,8 +217,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 	 */
 	kernel_base += TEXT_OFFSET - 5 * PAGE_SIZE;
 
-	status = reserve_kernel_base(sys_table, kernel_base, reserve_addr,
-				     reserve_size);
+	status = reserve_kernel_base(kernel_base, reserve_addr, reserve_size);
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("Unable to allocate memory for uncompressed kernel.\n");
 		return status;
@@ -231,12 +228,11 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 	 * memory window.
 	 */
 	*image_size = image->image_size;
-	status = efi_relocate_kernel(sys_table, image_addr, *image_size,
-				     *image_size,
+	status = efi_relocate_kernel(image_addr, *image_size, *image_size,
 				     kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0);
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("Failed to relocate kernel.\n");
-		efi_free(sys_table, *reserve_size, *reserve_addr);
+		efi_free(*reserve_size, *reserve_addr);
 		*reserve_size = 0;
 		return status;
 	}
@@ -248,9 +244,9 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 	 */
 	if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
 		pr_efi_err("Failed to relocate kernel, no low memory available.\n");
-		efi_free(sys_table, *reserve_size, *reserve_addr);
+		efi_free(*reserve_size, *reserve_addr);
 		*reserve_size = 0;
-		efi_free(sys_table, *image_size, *image_addr);
+		efi_free(*image_size, *image_addr);
 		*image_size = 0;
 		return EFI_LOAD_ERROR;
 	}
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index b09dda600c78..beba45e478c7 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -21,7 +21,7 @@
 
 #include "efistub.h"
 
-efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
+efi_status_t check_platform_features(void)
 {
 	u64 tg;
 
@@ -40,8 +40,7 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
 	return EFI_SUCCESS;
 }
 
-efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
-				 unsigned long *image_addr,
+efi_status_t handle_kernel_image(unsigned long *image_addr,
 				 unsigned long *image_size,
 				 unsigned long *reserve_addr,
 				 unsigned long *reserve_size,
@@ -56,8 +55,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
 		if (!nokaslr()) {
-			status = efi_get_random_bytes(sys_table_arg,
-						      sizeof(phys_seed),
+			status = efi_get_random_bytes(sizeof(phys_seed),
 						      (u8 *)&phys_seed);
 			if (status == EFI_NOT_FOUND) {
 				pr_efi("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
@@ -108,7 +106,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 		 * locate the kernel at a randomized offset in physical memory.
 		 */
 		*reserve_size = kernel_memsize + offset;
-		status = efi_random_alloc(sys_table_arg, *reserve_size,
+		status = efi_random_alloc(*reserve_size,
 					  MIN_KIMG_ALIGN, reserve_addr,
 					  (u32)phys_seed);
 
@@ -139,7 +137,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
 
 	if (status != EFI_SUCCESS) {
 		*reserve_size = kernel_memsize + TEXT_OFFSET;
-		status = efi_low_alloc(sys_table_arg, *reserve_size,
+		status = efi_low_alloc(*reserve_size,
 				       MIN_KIMG_ALIGN, reserve_addr);
 
 		if (status != EFI_SUCCESS) {
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index ebe792f2ed27..2ddeb312e8e5 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -84,8 +84,7 @@ static inline bool mmap_has_headroom(unsigned long buff_size,
 	return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
 }
 
-efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
-				struct efi_boot_memmap *map)
+efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
 {
 	efi_memory_desc_t *m = NULL;
 	efi_status_t status;
@@ -135,7 +134,7 @@ efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
 }
 
 
-unsigned long get_dram_base(efi_system_table_t *sys_table_arg)
+unsigned long get_dram_base(void)
 {
 	efi_status_t status;
 	unsigned long map_size, buff_size;
@@ -151,7 +150,7 @@ unsigned long get_dram_base(efi_system_table_t *sys_table_arg)
 	boot_map.key_ptr =	NULL;
 	boot_map.buff_size =	&buff_size;
 
-	status = efi_get_memory_map(sys_table_arg, &boot_map);
+	status = efi_get_memory_map(&boot_map);
 	if (status != EFI_SUCCESS)
 		return membase;
 
@@ -172,8 +171,7 @@ unsigned long get_dram_base(efi_system_table_t *sys_table_arg)
 /*
  * Allocate at the highest possible address that is not above 'max'.
  */
-efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
-			    unsigned long size, unsigned long align,
+efi_status_t efi_high_alloc(unsigned long size, unsigned long align,
 			    unsigned long *addr, unsigned long max)
 {
 	unsigned long map_size, desc_size, buff_size;
@@ -191,7 +189,7 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
 	boot_map.key_ptr =	NULL;
 	boot_map.buff_size =	&buff_size;
 
-	status = efi_get_memory_map(sys_table_arg, &boot_map);
+	status = efi_get_memory_map(&boot_map);
 	if (status != EFI_SUCCESS)
 		goto fail;
 
@@ -271,8 +269,7 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
 /*
  * Allocate at the lowest possible address that is not below 'min'.
  */
-efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg,
-				 unsigned long size, unsigned long align,
+efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
 				 unsigned long *addr, unsigned long min)
 {
 	unsigned long map_size, desc_size, buff_size;
@@ -289,7 +286,7 @@ efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg,
 	boot_map.key_ptr =	NULL;
 	boot_map.buff_size =	&buff_size;
 
-	status = efi_get_memory_map(sys_table_arg, &boot_map);
+	status = efi_get_memory_map(&boot_map);
 	if (status != EFI_SUCCESS)
 		goto fail;
 
@@ -348,8 +345,7 @@ efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg,
 	return status;
 }
 
-void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
-	      unsigned long addr)
+void efi_free(unsigned long size, unsigned long addr)
 {
 	unsigned long nr_pages;
 
@@ -365,9 +361,8 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
 	efi_call_early(free_pages, addr, nr_pages);
 }
 
-static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
-				  efi_char16_t *filename_16, void **handle,
-				  u64 *file_sz)
+static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,
+				  void **handle, u64 *file_sz)
 {
 	efi_file_handle_t *h, *fh = __fh;
 	efi_file_info_t *info;
@@ -429,8 +424,7 @@ static efi_status_t efi_file_close(efi_file_handle_t *handle)
 	return efi_call_proto(efi_file_handle, close, handle);
 }
 
-static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
-				    efi_loaded_image_t *image,
+static efi_status_t efi_open_volume(efi_loaded_image_t *image,
 				    efi_file_handle_t **__fh)
 {
 	efi_file_io_interface_t *io;
@@ -524,8 +518,7 @@ efi_status_t efi_parse_options(char const *cmdline)
  * We only support loading a file from the same filesystem as
  * the kernel image.
  */
-efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
-				  efi_loaded_image_t *image,
+efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 				  char *cmd_line, char *option_string,
 				  unsigned long max_addr,
 				  unsigned long *load_addr,
@@ -627,13 +620,13 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 
 		/* Only open the volume once. */
 		if (!i) {
-			status = efi_open_volume(sys_table_arg, image, &fh);
+			status = efi_open_volume(image, &fh);
 			if (status != EFI_SUCCESS)
 				goto free_files;
 		}
 
-		status = efi_file_size(sys_table_arg, fh, filename_16,
-				       (void **)&file->handle, &file->size);
+		status = efi_file_size(fh, filename_16, (void **)&file->handle,
+				       &file->size);
 		if (status != EFI_SUCCESS)
 			goto close_handles;
 
@@ -648,8 +641,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 		 * so allocate enough memory for all the files.  This is used
 		 * for loading multiple files.
 		 */
-		status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000,
-				    &file_addr, max_addr);
+		status = efi_high_alloc(file_size_total, 0x1000, &file_addr,
+					max_addr);
 		if (status != EFI_SUCCESS) {
 			pr_efi_err("Failed to alloc highmem for files\n");
 			goto close_handles;
@@ -699,7 +692,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 	return status;
 
 free_file_total:
-	efi_free(sys_table_arg, file_size_total, file_addr);
+	efi_free(file_size_total, file_addr);
 
 close_handles:
 	for (k = j; k < i; k++)
@@ -722,8 +715,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
  * address is not available the lowest available address will
  * be used.
  */
-efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
-				 unsigned long *image_addr,
+efi_status_t efi_relocate_kernel(unsigned long *image_addr,
 				 unsigned long image_size,
 				 unsigned long alloc_size,
 				 unsigned long preferred_addr,
@@ -761,8 +753,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
 	 * possible.
 	 */
 	if (status != EFI_SUCCESS) {
-		status = efi_low_alloc_above(sys_table_arg, alloc_size,
-					     alignment, &new_addr, min_addr);
+		status = efi_low_alloc_above(alloc_size, alignment, &new_addr,
+					     min_addr);
 	}
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("Failed to allocate usable memory for kernel.\n");
@@ -839,8 +831,7 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
  * Size of memory allocated return in *cmd_line_len.
  * Returns NULL on error.
  */
-char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
-			  efi_loaded_image_t *image,
+char *efi_convert_cmdline(efi_loaded_image_t *image,
 			  int *cmd_line_len)
 {
 	const u16 *s2;
@@ -869,8 +860,8 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
 
 	options_bytes++;	/* NUL termination */
 
-	status = efi_high_alloc(sys_table_arg, options_bytes, 0,
-				&cmdline_addr, MAX_CMDLINE_ADDRESS);
+	status = efi_high_alloc(options_bytes, 0, &cmdline_addr,
+				MAX_CMDLINE_ADDRESS);
 	if (status != EFI_SUCCESS)
 		return NULL;
 
@@ -892,20 +883,19 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
  * specific structure may be passed to the function via priv.  The client
  * function may be called multiple times.
  */
-efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
-				    void *handle,
+efi_status_t efi_exit_boot_services(void *handle,
 				    struct efi_boot_memmap *map,
 				    void *priv,
 				    efi_exit_boot_map_processing priv_func)
 {
 	efi_status_t status;
 
-	status = efi_get_memory_map(sys_table_arg, map);
+	status = efi_get_memory_map(map);
 
 	if (status != EFI_SUCCESS)
 		goto fail;
 
-	status = priv_func(sys_table_arg, map, priv);
+	status = priv_func(map, priv);
 	if (status != EFI_SUCCESS)
 		goto free_map;
 
@@ -937,7 +927,7 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
 		if (status != EFI_SUCCESS)
 			goto fail;
 
-		status = priv_func(sys_table_arg, map, priv);
+		status = priv_func(map, priv);
 		/* exit_boot_services() was called, thus cannot free */
 		if (status != EFI_SUCCESS)
 			goto fail;
@@ -957,10 +947,12 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
 	return status;
 }
 
-void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
+void *get_efi_config_table(efi_guid_t 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);
+	unsigned long tables = efi_table_attr(efi_system_table, tables,
+					      efi_system_table());
+	int nr_tables = efi_table_attr(efi_system_table, nr_tables,
+				       efi_system_table());
 	int i;
 
 	for (i = 0; i < nr_tables; i++) {
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 4a6acd28ce65..b5d9c9e65213 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -40,10 +40,9 @@ extern __pure efi_system_table_t  *efi_system_table(void);
 void efi_char16_printk(efi_char16_t *);
 void efi_char16_printk(efi_char16_t *);
 
-unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
+unsigned long get_dram_base(void);
 
-efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
-					    void *handle,
+efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
 					    unsigned long *new_fdt_addr,
 					    unsigned long max_addr,
 					    u64 initrd_addr, u64 initrd_size,
@@ -51,22 +50,20 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 					    unsigned long fdt_addr,
 					    unsigned long fdt_size);
 
-void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size);
+void *get_fdt(unsigned long *fdt_size);
 
 void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
 		     unsigned long desc_size, efi_memory_desc_t *runtime_map,
 		     int *count);
 
-efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table,
-				  unsigned long size, u8 *out);
+efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
 
-efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
-			      unsigned long size, unsigned long align,
+efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
 			      unsigned long *addr, unsigned long random_seed);
 
-efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
+efi_status_t check_platform_features(void);
 
-void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid);
+void *get_efi_config_table(efi_guid_t guid);
 
 /* Helper macros for the usual case of using simple C variables: */
 #ifndef fdt_setprop_inplace_var
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 1bf7edfd81ec..0a91e5232127 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -16,7 +16,7 @@
 #define EFI_DT_ADDR_CELLS_DEFAULT 2
 #define EFI_DT_SIZE_CELLS_DEFAULT 2
 
-static void fdt_update_cell_size(efi_system_table_t *sys_table, void *fdt)
+static void fdt_update_cell_size(void *fdt)
 {
 	int offset;
 
@@ -27,8 +27,7 @@ static void fdt_update_cell_size(efi_system_table_t *sys_table, void *fdt)
 	fdt_setprop_u32(fdt, offset, "#size-cells",    EFI_DT_SIZE_CELLS_DEFAULT);
 }
 
-static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-			       unsigned long orig_fdt_size,
+static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
 			       void *fdt, int new_fdt_size, char *cmdline_ptr,
 			       u64 initrd_addr, u64 initrd_size)
 {
@@ -62,7 +61,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
 			 * Any failure from the following function is
 			 * non-critical:
 			 */
-			fdt_update_cell_size(sys_table, fdt);
+			fdt_update_cell_size(fdt);
 		}
 	}
 
@@ -111,7 +110,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
 
 	/* Add FDT entries for EFI runtime services in chosen node. */
 	node = fdt_subnode_offset(fdt, 0, "chosen");
-	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
+	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)efi_system_table());
 
 	status = fdt_setprop_var(fdt, node, "linux,uefi-system-table", fdt_val64);
 	if (status)
@@ -140,7 +139,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
 		efi_status_t efi_status;
 
-		efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64),
+		efi_status = efi_get_random_bytes(sizeof(fdt_val64),
 						  (u8 *)&fdt_val64);
 		if (efi_status == EFI_SUCCESS) {
 			status = fdt_setprop_var(fdt, node, "kaslr-seed", fdt_val64);
@@ -210,8 +209,7 @@ struct exit_boot_struct {
 	void			*new_fdt_addr;
 };
 
-static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
-				   struct efi_boot_memmap *map,
+static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
 				   void *priv)
 {
 	struct exit_boot_struct *p = priv;
@@ -244,8 +242,7 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
  * with the final memory map in it.
  */
 
-efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
-					    void *handle,
+efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
 					    unsigned long *new_fdt_addr,
 					    unsigned long max_addr,
 					    u64 initrd_addr, u64 initrd_size,
@@ -275,7 +272,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	 * subsequent allocations adding entries, since they could not affect
 	 * the number of EFI_MEMORY_RUNTIME regions.
 	 */
-	status = efi_get_memory_map(sys_table, &map);
+	status = efi_get_memory_map(&map);
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("Unable to retrieve UEFI memory map.\n");
 		return status;
@@ -284,7 +281,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	pr_efi("Exiting boot services and installing virtual address map...\n");
 
 	map.map = &memory_map;
-	status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
+	status = efi_high_alloc(MAX_FDT_SIZE, EFI_FDT_ALIGN,
 				new_fdt_addr, max_addr);
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("Unable to allocate memory for new device tree.\n");
@@ -295,11 +292,11 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	 * Now that we have done our final memory allocation (and free)
 	 * we can get the memory map key needed for exit_boot_services().
 	 */
-	status = efi_get_memory_map(sys_table, &map);
+	status = efi_get_memory_map(&map);
 	if (status != EFI_SUCCESS)
 		goto fail_free_new_fdt;
 
-	status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
+	status = update_fdt((void *)fdt_addr, fdt_size,
 			    (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
 			    initrd_addr, initrd_size);
 
@@ -313,7 +310,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	priv.runtime_entry_count	= &runtime_entry_count;
 	priv.new_fdt_addr		= (void *)*new_fdt_addr;
 
-	status = efi_exit_boot_services(sys_table, handle, &map, &priv, exit_boot_func);
+	status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
 
 	if (status == EFI_SUCCESS) {
 		efi_set_virtual_address_map_t *svam;
@@ -322,7 +319,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 			return EFI_SUCCESS;
 
 		/* Install the new virtual address map */
-		svam = sys_table->runtime->set_virtual_address_map;
+		svam = efi_system_table()->runtime->set_virtual_address_map;
 		status = svam(runtime_entry_count * desc_size, desc_size,
 			      desc_ver, runtime_map);
 
@@ -353,19 +350,19 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 	pr_efi_err("Exit boot services failed.\n");
 
 fail_free_new_fdt:
-	efi_free(sys_table, MAX_FDT_SIZE, *new_fdt_addr);
+	efi_free(MAX_FDT_SIZE, *new_fdt_addr);
 
 fail:
-	sys_table->boottime->free_pool(runtime_map);
+	efi_system_table()->boottime->free_pool(runtime_map);
 
 	return EFI_LOAD_ERROR;
 }
 
-void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
+void *get_fdt(unsigned long *fdt_size)
 {
 	void *fdt;
 
-	fdt = get_efi_config_table(sys_table, DEVICE_TREE_GUID);
+	fdt = get_efi_config_table(DEVICE_TREE_GUID);
 
 	if (!fdt)
 		return NULL;
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 6c49d0a9aa3f..c3afe8d4a688 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -88,9 +88,8 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 #define efi_gop_attr(table, attr, instance) \
 	(efi_table_attr(efi_graphics_output_protocol##table, attr, instance))
 
-static efi_status_t
-setup_gop(efi_system_table_t *sys_table_arg, struct screen_info *si,
-	  efi_guid_t *proto, unsigned long size, void **handles)
+static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
+			      unsigned long size, void **handles)
 {
 	efi_graphics_output_protocol_t *gop, *first_gop;
 	u16 width, height;
@@ -185,8 +184,7 @@ setup_gop(efi_system_table_t *sys_table_arg, struct screen_info *si,
 /*
  * See if we have Graphics Output Protocol
  */
-efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
-			   struct screen_info *si, efi_guid_t *proto,
+efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
 			   unsigned long size)
 {
 	efi_status_t status;
@@ -203,7 +201,7 @@ efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
 	if (status != EFI_SUCCESS)
 		goto free_handle;
 
-	status = setup_gop(sys_table_arg, si, proto, size, gop_handle);
+	status = setup_gop(si, proto, size, gop_handle);
 
 free_handle:
 	efi_call_early(free_pool, gop_handle);
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 4f5c249c62dc..9b30d953d13b 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -26,8 +26,7 @@ union efi_rng_protocol {
 	} mixed_mode;
 };
 
-efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
-				  unsigned long size, u8 *out)
+efi_status_t efi_get_random_bytes(unsigned long size, u8 *out)
 {
 	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
 	efi_status_t status;
@@ -79,8 +78,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
  */
 #define MD_NUM_SLOTS(md)	((md)->virt_addr)
 
-efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
-			      unsigned long size,
+efi_status_t efi_random_alloc(unsigned long size,
 			      unsigned long align,
 			      unsigned long *addr,
 			      unsigned long random_seed)
@@ -99,7 +97,7 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 	map.key_ptr =	NULL;
 	map.buff_size =	&buff_size;
 
-	status = efi_get_memory_map(sys_table_arg, &map);
+	status = efi_get_memory_map(&map);
 	if (status != EFI_SUCCESS)
 		return status;
 
@@ -155,7 +153,7 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 	return status;
 }
 
-efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+efi_status_t efi_random_get_seed(void)
 {
 	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
 	efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c
index 9071b57da8fe..0935d824a6ab 100644
--- a/drivers/firmware/efi/libstub/secureboot.c
+++ b/drivers/firmware/efi/libstub/secureboot.c
@@ -32,7 +32,7 @@ static const efi_char16_t shim_MokSBState_name[] = L"MokSBState";
  * Please keep the logic in sync with
  * arch/x86/xen/efi.c:xen_efi_get_secureboot().
  */
-enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg)
+enum efi_secureboot_mode efi_get_secureboot(void)
 {
 	u32 attr;
 	u8 secboot, setupmode, moksbstate;
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 86658b005e85..9fae0850e2ac 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -57,7 +57,7 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg)
 
 #endif
 
-void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
+void efi_retrieve_tpm2_eventlog(void)
 {
 	efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
 	efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
@@ -139,8 +139,7 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
 	 * Figure out whether any events have already been logged to the
 	 * final events structure, and if so how much space they take up
 	 */
-	final_events_table = get_efi_config_table(sys_table_arg,
-						LINUX_EFI_TPM_FINAL_LOG_GUID);
+	final_events_table = get_efi_config_table(LINUX_EFI_TPM_FINAL_LOG_GUID);
 	if (final_events_table && final_events_table->nr_events) {
 		struct tcg_pcr_event2_head *header;
 		int offset;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 1cddf3337471..f97f48a3dc81 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1553,22 +1553,17 @@ static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
 
 void efi_printk(char *str);
 
-void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
-	      unsigned long addr);
+void efi_free(unsigned long size, unsigned long addr);
 
-char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
-			  efi_loaded_image_t *image, int *cmd_line_len);
+char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
 
-efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
-				struct efi_boot_memmap *map);
+efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
 
-efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg,
-				 unsigned long size, unsigned long align,
+efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
 				 unsigned long *addr, unsigned long min);
 
 static inline
-efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
-			   unsigned long size, unsigned long align,
+efi_status_t efi_low_alloc(unsigned long size, unsigned long align,
 			   unsigned long *addr)
 {
 	/*
@@ -1576,23 +1571,20 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
 	 * checks pointers against NULL. Skip the first 8
 	 * bytes so we start at a nice even number.
 	 */
-	return efi_low_alloc_above(sys_table_arg, size, align, addr, 0x8);
+	return efi_low_alloc_above(size, align, addr, 0x8);
 }
 
-efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
-			    unsigned long size, unsigned long align,
+efi_status_t efi_high_alloc(unsigned long size, unsigned long align,
 			    unsigned long *addr, unsigned long max);
 
-efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
-				 unsigned long *image_addr,
+efi_status_t efi_relocate_kernel(unsigned long *image_addr,
 				 unsigned long image_size,
 				 unsigned long alloc_size,
 				 unsigned long preferred_addr,
 				 unsigned long alignment,
 				 unsigned long min_addr);
 
-efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
-				  efi_loaded_image_t *image,
+efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 				  char *cmd_line, char *option_string,
 				  unsigned long max_addr,
 				  unsigned long *load_addr,
@@ -1600,8 +1592,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 
 efi_status_t efi_parse_options(char const *cmdline);
 
-efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
-			   struct screen_info *si, efi_guid_t *proto,
+efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
 			   unsigned long size);
 
 #ifdef CONFIG_EFI
@@ -1619,18 +1610,18 @@ enum efi_secureboot_mode {
 	efi_secureboot_mode_disabled,
 	efi_secureboot_mode_enabled,
 };
-enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table);
+enum efi_secureboot_mode efi_get_secureboot(void);
 
 #ifdef CONFIG_RESET_ATTACK_MITIGATION
-void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg);
+void efi_enable_reset_attack_mitigation(void);
 #else
 static inline void
-efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { }
+efi_enable_reset_attack_mitigation(void) { }
 #endif
 
-efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+efi_status_t efi_random_get_seed(void);
 
-void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table);
+void efi_retrieve_tpm2_eventlog(void);
 
 /*
  * Arch code can implement the following three template macros, avoiding
@@ -1682,12 +1673,10 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table);
 })
 
 typedef efi_status_t (*efi_exit_boot_map_processing)(
-	efi_system_table_t *sys_table_arg,
 	struct efi_boot_memmap *map,
 	void *priv);
 
-efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
-				    void *handle,
+efi_status_t efi_exit_boot_services(void *handle,
 				    struct efi_boot_memmap *map,
 				    void *priv,
 				    efi_exit_boot_map_processing priv_func);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 16/21] efi/libstub: drop protocol argument from efi_call_proto() macro
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (14 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 15/21] efi/libstub: remove 'sys_table_arg' from all function prototypes Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 17/21] efi/libstub: drop 'table' argument from efi_table_attr() macro Ard Biesheuvel
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

After refactoring the mixed mode support code, efi_call_proto()
no longer uses its protocol argument in any of its implementation,
so let's remove it altogether.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/efi.h                     |  3 +--
 arch/arm64/include/asm/efi.h                   |  3 +--
 arch/x86/boot/compressed/eboot.c               | 23 ++++++++------------
 arch/x86/include/asm/efi.h                     |  6 ++---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 22 ++++++++-----------
 drivers/firmware/efi/libstub/random.c          |  8 +++----
 drivers/firmware/efi/libstub/tpm.c             | 11 +++++-----
 7 files changed, 32 insertions(+), 44 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 58e5acc424a0..bdc5288cc643 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -57,8 +57,7 @@ void efi_virtmap_unload(void);
 #define efi_table_attr(table, attr, instance)				\
 	instance->attr
 
-#define efi_call_proto(protocol, f, instance, ...)			\
-	instance->f(instance, ##__VA_ARGS__)
+#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
 
 struct screen_info *alloc_screen_info(void);
 void free_screen_info(struct screen_info *si);
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index d73693177f31..4bc1e89671ab 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -100,8 +100,7 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
 #define efi_table_attr(table, attr, instance)				\
 	instance->attr
 
-#define efi_call_proto(protocol, f, instance, ...)			\
-	instance->f(instance, ##__VA_ARGS__)
+#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
 
 #define alloc_screen_info(x...)		&screen_info
 
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b4e859399451..da3e7509bbe7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -76,27 +76,24 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 	rom->pcilen	= pci->romsize;
 	*__rom = rom;
 
-	status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
-				EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
-				&rom->vendor);
+	status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
+				PCI_VENDOR_ID, 1, &rom->vendor);
 
 	if (status != EFI_SUCCESS) {
 		efi_printk("Failed to read rom->vendor\n");
 		goto free_struct;
 	}
 
-	status = efi_call_proto(efi_pci_io_protocol, pci.read, pci,
-				EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
-				&rom->devid);
+	status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
+				PCI_DEVICE_ID, 1, &rom->devid);
 
 	if (status != EFI_SUCCESS) {
 		efi_printk("Failed to read rom->devid\n");
 		goto free_struct;
 	}
 
-	status = efi_call_proto(efi_pci_io_protocol, get_location, pci,
-				&rom->segment, &rom->bus, &rom->device,
-				&rom->function);
+	status = efi_call_proto(pci, get_location, &rom->segment, &rom->bus,
+				&rom->device, &rom->function);
 
 	if (status != EFI_SUCCESS)
 		goto free_struct;
@@ -198,7 +195,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 		return;
 	}
 
-	efi_call_proto(apple_properties_protocol, get_all, p, NULL, &size);
+	efi_call_proto(p, get_all, NULL, &size);
 	if (!size)
 		return;
 
@@ -211,8 +208,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 			return;
 		}
 
-		status = efi_call_proto(apple_properties_protocol, get_all, p,
-					new->data, &size);
+		status = efi_call_proto(p, get_all, new->data, &size);
 
 		if (status == EFI_BUFFER_TOO_SMALL)
 			efi_call_early(free_pool, new);
@@ -287,8 +283,7 @@ setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
 		pciio = NULL;
 		efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
 
-		status = efi_call_proto(efi_uga_draw_protocol, get_mode, uga,
-					&w, &h, &depth, &refresh);
+		status = efi_call_proto(uga, get_mode, &w, &h, &depth, &refresh);
 		if (status == EFI_SUCCESS && (!first_uga || pciio)) {
 			width = w;
 			height = h;
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 8137d4f5c104..7bdd2fb11e7c 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -236,10 +236,10 @@ static inline bool efi_is_native(void)
 	__ret;								\
 })
 
-#define efi_call_proto(protocol, f, instance, ...)			\
+#define efi_call_proto(inst, func, ...)					\
 	(efi_is_native()						\
-		? instance->f(instance, ##__VA_ARGS__)			\
-		: efi64_thunk(instance->mixed_mode.f, instance,	##__VA_ARGS__))
+		? inst->func(inst, ##__VA_ARGS__)			\
+		: efi64_thunk(inst->mixed_mode.func, inst, ##__VA_ARGS__))
 
 #define efi_call_early(f, ...)						\
 	(efi_is_native()						\
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 2ddeb312e8e5..4117813a1707 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -370,8 +370,8 @@ static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,
 	efi_guid_t info_guid = EFI_FILE_INFO_ID;
 	unsigned long info_sz;
 
-	status = efi_call_proto(efi_file_handle, open, fh, &h, filename_16,
-				EFI_FILE_MODE_READ, (u64)0);
+	status = efi_call_proto(fh, open, &h, filename_16, EFI_FILE_MODE_READ,
+				(u64)0);
 	if (status != EFI_SUCCESS) {
 		efi_printk("Failed to open file: ");
 		efi_char16_printk(filename_16);
@@ -382,8 +382,7 @@ static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,
 	*handle = h;
 
 	info_sz = 0;
-	status = efi_call_proto(efi_file_handle, get_info, h, &info_guid,
-				&info_sz, NULL);
+	status = efi_call_proto(h, get_info, &info_guid, &info_sz, NULL);
 	if (status != EFI_BUFFER_TOO_SMALL) {
 		efi_printk("Failed to get file info size\n");
 		return status;
@@ -397,8 +396,7 @@ static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,
 		return status;
 	}
 
-	status = efi_call_proto(efi_file_handle, get_info, h, &info_guid,
-				&info_sz, info);
+	status = efi_call_proto(h, get_info, &info_guid, &info_sz, info);
 	if (status == EFI_BUFFER_TOO_SMALL) {
 		efi_call_early(free_pool, info);
 		goto grow;
@@ -416,12 +414,12 @@ static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16,
 static efi_status_t efi_file_read(efi_file_handle_t *handle,
 				  unsigned long *size, void *addr)
 {
-	return efi_call_proto(efi_file_handle, read, handle, size, addr);
+	return efi_call_proto(handle, read, size, addr);
 }
 
 static efi_status_t efi_file_close(efi_file_handle_t *handle)
 {
-	return efi_call_proto(efi_file_handle, close, handle);
+	return efi_call_proto(handle, close);
 }
 
 static efi_status_t efi_open_volume(efi_loaded_image_t *image,
@@ -440,7 +438,7 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image,
 		return status;
 	}
 
-	status = efi_call_proto(efi_file_io_interface, open_volume, io, &fh);
+	status = efi_call_proto(io, open_volume, &fh);
 	if (status != EFI_SUCCESS)
 		efi_printk("Failed to open volume\n");
 	else
@@ -969,9 +967,7 @@ void *get_efi_config_table(efi_guid_t guid)
 
 void efi_char16_printk(efi_char16_t *str)
 {
-	efi_call_proto(efi_simple_text_output_protocol,
-		       output_string,
-		       efi_table_attr(efi_system_table, con_out,
+	efi_call_proto(efi_table_attr(efi_system_table, con_out,
 				      efi_system_table()),
-		       str);
+		       output_string, str);
 }
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 9b30d953d13b..fbd5b5724b19 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -37,7 +37,7 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out)
 	if (status != EFI_SUCCESS)
 		return status;
 
-	return efi_call_proto(efi_rng_protocol, get_rng, rng, NULL, size, out);
+	return efi_call_proto(rng, get_rng, NULL, size, out);
 }
 
 /*
@@ -173,7 +173,7 @@ efi_status_t efi_random_get_seed(void)
 	if (status != EFI_SUCCESS)
 		return status;
 
-	status = efi_call_proto(efi_rng_protocol, get_rng, rng, &rng_algo_raw,
+	status = efi_call_proto(rng, get_rng, &rng_algo_raw,
 				 EFI_RANDOM_SEED_SIZE, seed->bits);
 
 	if (status == EFI_UNSUPPORTED)
@@ -181,8 +181,8 @@ efi_status_t efi_random_get_seed(void)
 		 * Use whatever algorithm we have available if the raw algorithm
 		 * is not implemented.
 		 */
-		status = efi_call_proto(efi_rng_protocol, get_rng, rng, NULL,
-					 EFI_RANDOM_SEED_SIZE, seed->bits);
+		status = efi_call_proto(rng, get_rng, NULL,
+					EFI_RANDOM_SEED_SIZE, seed->bits);
 
 	if (status != EFI_SUCCESS)
 		goto err_freepool;
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 9fae0850e2ac..dbb4b3cfc4e8 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -77,15 +77,14 @@ void efi_retrieve_tpm2_eventlog(void)
 	if (status != EFI_SUCCESS)
 		return;
 
-	status = efi_call_proto(efi_tcg2_protocol, get_event_log,
-				tcg2_protocol, version, &log_location,
-				&log_last_entry, &truncated);
+	status = efi_call_proto(tcg2_protocol, get_event_log, version,
+				&log_location, &log_last_entry, &truncated);
 
 	if (status != EFI_SUCCESS || !log_location) {
 		version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
-		status = efi_call_proto(efi_tcg2_protocol, get_event_log,
-					tcg2_protocol, version, &log_location,
-					&log_last_entry, &truncated);
+		status = efi_call_proto(tcg2_protocol, get_event_log, version,
+					&log_location, &log_last_entry,
+					&truncated);
 		if (status != EFI_SUCCESS || !log_location)
 			return;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 17/21] efi/libstub: drop 'table' argument from efi_table_attr() macro
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (15 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 16/21] efi/libstub: drop protocol argument from efi_call_proto() macro Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter Ard Biesheuvel
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

None of the definitions of the efi_table_attr() still refer to
their 'table' argument so let's get rid of it entirely.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/efi.h                     |  3 +--
 arch/arm64/include/asm/efi.h                   |  3 +--
 arch/x86/boot/compressed/eboot.c               |  8 +++----
 arch/x86/include/asm/efi.h                     | 25 +++++++-------------
 drivers/firmware/efi/libstub/efi-stub-helper.c | 13 ++++------
 drivers/firmware/efi/libstub/gop.c             |  9 +++----
 6 files changed, 23 insertions(+), 38 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index bdc5288cc643..bc720024a260 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -54,8 +54,7 @@ void efi_virtmap_unload(void);
 #define efi_call_runtime(f, ...)	efi_system_table()->runtime->f(__VA_ARGS__)
 #define efi_is_native()			(true)
 
-#define efi_table_attr(table, attr, instance)				\
-	instance->attr
+#define efi_table_attr(inst, attr)	(inst->attr)
 
 #define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
 
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 4bc1e89671ab..6f041ae446d2 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -97,8 +97,7 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
 #define efi_call_runtime(f, ...)	efi_system_table()->runtime->f(__VA_ARGS__)
 #define efi_is_native()			(true)
 
-#define efi_table_attr(table, attr, instance)				\
-	instance->attr
+#define efi_table_attr(inst, attr)	(inst->attr)
 
 #define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
 
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index da3e7509bbe7..a3000283dc7a 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -54,8 +54,8 @@ 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 = efi_table_attr(efi_pci_io_protocol, romimage, pci);
-	romsize = efi_table_attr(efi_pci_io_protocol, romsize, pci);
+	romimage = efi_table_attr(pci, romimage);
+	romsize = efi_table_attr(pci, romsize);
 	if (!romimage || !romsize || romsize > SZ_16M)
 		return EFI_INVALID_PARAMETER;
 
@@ -190,7 +190,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
 	if (status != EFI_SUCCESS)
 		return;
 
-	if (efi_table_attr(apple_properties_protocol, version, p) != 0x10000) {
+	if (efi_table_attr(p, version) != 0x10000) {
 		efi_printk("Unsupported properties proto version\n");
 		return;
 	}
@@ -233,7 +233,7 @@ static const efi_char16_t apple[] = L"Apple";
 static void setup_quirks(struct boot_params *boot_params)
 {
 	efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
-		efi_table_attr(efi_system_table, fw_vendor, sys_table);
+		efi_table_attr(efi_system_table(), fw_vendor);
 
 	if (!memcmp(fw_vendor, apple, sizeof(apple))) {
 		if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 7bdd2fb11e7c..593a8cda8361 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -225,16 +225,11 @@ static inline bool efi_is_native(void)
 		__builtin_types_compatible_p(u32, __typeof__(attr)),	\
 			(unsigned long)(attr), (attr))
 
-#define efi_table_attr(table, attr, instance) ({			\
-	__typeof__(instance->attr) __ret;				\
-	if (efi_is_native()) {						\
-		__ret = instance->attr;					\
-	} else {							\
-		__ret = (__typeof__(__ret))				\
-			efi_mixed_mode_cast(instance->mixed_mode.attr);	\
-	}								\
-	__ret;								\
-})
+#define efi_table_attr(inst, attr)					\
+	(efi_is_native()						\
+		? inst->attr						\
+		: (__typeof__(inst->attr))				\
+			efi_mixed_mode_cast(inst->mixed_mode.attr))
 
 #define efi_call_proto(inst, func, ...)					\
 	(efi_is_native()						\
@@ -244,16 +239,14 @@ static inline bool efi_is_native(void)
 #define efi_call_early(f, ...)						\
 	(efi_is_native()						\
 		? efi_system_table()->boottime->f(__VA_ARGS__)		\
-		: efi64_thunk(efi_table_attr(efi_boot_services,		\
-			boottime, efi_system_table())->mixed_mode.f,	\
-			__VA_ARGS__))
+		: efi64_thunk(efi_table_attr(efi_system_table(),	\
+				boottime)->mixed_mode.f, __VA_ARGS__))
 
 #define efi_call_runtime(f, ...)					\
 	(efi_is_native()						\
 		? efi_system_table()->runtime->f(__VA_ARGS__)		\
-		: efi64_thunk(efi_table_attr(efi_runtime_services,	\
-			runtime, efi_system_table())->mixed_mode.f,	\
-			__VA_ARGS__))
+		: efi64_thunk(efi_table_attr(efi_system_table(),	\
+				runtime)->mixed_mode.f, __VA_ARGS__))
 
 extern bool efi_reboot_required(void);
 extern bool efi_is_table_address(unsigned long phys_addr);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 4117813a1707..59c273cb7a92 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -429,7 +429,7 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image,
 	efi_file_handle_t *fh;
 	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
 	efi_status_t status;
-	void *handle = efi_table_attr(efi_loaded_image, device_handle, image);
+	void *handle = efi_table_attr(image, device_handle);
 
 	status = efi_call_early(handle_protocol, handle,
 				&fs_proto, (void **)&io);
@@ -947,17 +947,15 @@ efi_status_t efi_exit_boot_services(void *handle,
 
 void *get_efi_config_table(efi_guid_t guid)
 {
-	unsigned long tables = efi_table_attr(efi_system_table, tables,
-					      efi_system_table());
-	int nr_tables = efi_table_attr(efi_system_table, nr_tables,
-				       efi_system_table());
+	unsigned long tables = efi_table_attr(efi_system_table(), tables);
+	int nr_tables = efi_table_attr(efi_system_table(), nr_tables);
 	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);
+			return efi_table_attr(t, table);
 
 		tables += efi_is_native() ? sizeof(efi_config_table_t)
 					  : sizeof(efi_config_table_32_t);
@@ -967,7 +965,6 @@ void *get_efi_config_table(efi_guid_t guid)
 
 void efi_char16_printk(efi_char16_t *str)
 {
-	efi_call_proto(efi_table_attr(efi_system_table, con_out,
-				      efi_system_table()),
+	efi_call_proto(efi_table_attr(efi_system_table(), con_out),
 		       output_string, str);
 }
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index c3afe8d4a688..8f746282c219 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -85,9 +85,6 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 	}
 }
 
-#define efi_gop_attr(table, attr, instance) \
-	(efi_table_attr(efi_graphics_output_protocol##table, attr, instance))
-
 static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 			      unsigned long size, void **handles)
 {
@@ -123,9 +120,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 
-		mode = (void *)(unsigned long)efi_gop_attr(, mode, gop);
-		info = (void *)(unsigned long)efi_gop_attr(_mode, info, mode);
-		current_fb_base = efi_gop_attr(_mode, frame_buffer_base, mode);
+		mode = efi_table_attr(gop, mode);
+		info = efi_table_attr(mode, info);
+		current_fb_base = efi_table_attr(mode, frame_buffer_base);
 
 		if ((!first_gop || conout_found) &&
 		    info->pixel_format != PIXEL_BLT_ONLY) {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (16 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 17/21] efi/libstub: drop 'table' argument from efi_table_attr() macro Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-31 16:51   ` Arvind Sankar
  2019-12-18 17:01 ` [PATCH v2 19/21] efi/libstub: tidy up types and names of global cmdline variables Ard Biesheuvel
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Use 'func' as the macro parameter name for the efi_call() macros
which is less likely to collide and cause weird build errors.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/efi.h |  4 ++--
 arch/x86/include/asm/efi.h   | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 6f041ae446d2..d06305590ac5 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -93,8 +93,8 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
 	return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
 }
 
-#define efi_call_early(f, ...)		efi_system_table()->boottime->f(__VA_ARGS__)
-#define efi_call_runtime(f, ...)	efi_system_table()->runtime->f(__VA_ARGS__)
+#define efi_call_early(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
+#define efi_call_runtime(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
 #define efi_is_native()			(true)
 
 #define efi_table_attr(inst, attr)	(inst->attr)
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 593a8cda8361..ba3f8a98e156 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -236,17 +236,17 @@ static inline bool efi_is_native(void)
 		? inst->func(inst, ##__VA_ARGS__)			\
 		: efi64_thunk(inst->mixed_mode.func, inst, ##__VA_ARGS__))
 
-#define efi_call_early(f, ...)						\
+#define efi_call_early(func, ...)					\
 	(efi_is_native()						\
-		? efi_system_table()->boottime->f(__VA_ARGS__)		\
+		? efi_system_table()->boottime->func(__VA_ARGS__)	\
 		: efi64_thunk(efi_table_attr(efi_system_table(),	\
-				boottime)->mixed_mode.f, __VA_ARGS__))
+				boottime)->mixed_mode.func, __VA_ARGS__))
 
-#define efi_call_runtime(f, ...)					\
+#define efi_call_runtime(func, ...)					\
 	(efi_is_native()						\
-		? efi_system_table()->runtime->f(__VA_ARGS__)		\
+		? efi_system_table()->runtime->func(__VA_ARGS__)	\
 		: efi64_thunk(efi_table_attr(efi_system_table(),	\
-				runtime)->mixed_mode.f, __VA_ARGS__))
+				runtime)->mixed_mode.func, __VA_ARGS__))
 
 extern bool efi_reboot_required(void);
 extern bool efi_is_table_address(unsigned long phys_addr);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 19/21] efi/libstub: tidy up types and names of global cmdline variables
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (17 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 20/21] efi/libstub: import type definitions for creating and signalling events Ard Biesheuvel
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Drop leading underscores and use bool not int for true/false
variables set on the command line.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 34 ++++++++++----------
 drivers/firmware/efi/libstub/efistub.h         |  6 ++--
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 59c273cb7a92..8b0d59f5c8cd 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -27,24 +27,24 @@
  */
 #define EFI_READ_CHUNK_SIZE	(1024 * 1024)
 
-static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
+static unsigned long efi_chunk_size = EFI_READ_CHUNK_SIZE;
 
-static int __section(.data) __nokaslr;
-static int __section(.data) __quiet;
-static int __section(.data) __novamap;
+static bool __section(.data) efi_nokaslr;
+static bool __section(.data) efi_quiet;
+static bool __section(.data) efi_novamap;
 static bool __section(.data) efi_nosoftreserve;
 
-int __pure nokaslr(void)
+bool __pure nokaslr(void)
 {
-	return __nokaslr;
+	return efi_nokaslr;
 }
-int __pure is_quiet(void)
+bool __pure is_quiet(void)
 {
-	return __quiet;
+	return efi_quiet;
 }
-int __pure novamap(void)
+bool __pure novamap(void)
 {
-	return __novamap;
+	return efi_novamap;
 }
 bool __pure __efi_soft_reserve_enabled(void)
 {
@@ -461,11 +461,11 @@ efi_status_t efi_parse_options(char const *cmdline)
 
 	str = strstr(cmdline, "nokaslr");
 	if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
-		__nokaslr = 1;
+		efi_nokaslr = true;
 
 	str = strstr(cmdline, "quiet");
 	if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
-		__quiet = 1;
+		efi_quiet = true;
 
 	/*
 	 * If no EFI parameters were specified on the cmdline we've got
@@ -485,18 +485,18 @@ efi_status_t efi_parse_options(char const *cmdline)
 	while (*str && *str != ' ') {
 		if (!strncmp(str, "nochunk", 7)) {
 			str += strlen("nochunk");
-			__chunk_size = -1UL;
+			efi_chunk_size = -1UL;
 		}
 
 		if (!strncmp(str, "novamap", 7)) {
 			str += strlen("novamap");
-			__novamap = 1;
+			efi_novamap = true;
 		}
 
 		if (IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&
 		    !strncmp(str, "nosoftreserve", 7)) {
 			str += strlen("nosoftreserve");
-			efi_nosoftreserve = 1;
+			efi_nosoftreserve = true;
 		}
 
 		/* Group words together, delimited by "," */
@@ -661,8 +661,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 			while (size) {
 				unsigned long chunksize;
 
-				if (IS_ENABLED(CONFIG_X86) && size > __chunk_size)
-					chunksize = __chunk_size;
+				if (IS_ENABLED(CONFIG_X86) && size > efi_chunk_size)
+					chunksize = efi_chunk_size;
 				else
 					chunksize = size;
 
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index b5d9c9e65213..72e60b6afbf8 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -25,9 +25,9 @@
 #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
 #endif
 
-extern int __pure nokaslr(void);
-extern int __pure is_quiet(void);
-extern int __pure novamap(void);
+extern bool __pure nokaslr(void);
+extern bool __pure is_quiet(void);
+extern bool __pure novamap(void);
 
 extern __pure efi_system_table_t  *efi_system_table(void);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 20/21] efi/libstub: import type definitions for creating and signalling events
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (18 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 19/21] efi/libstub: tidy up types and names of global cmdline variables Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
  2019-12-19 11:12 ` [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Hans de Goede
  21 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

We will use the EFI event handling infrastructure in a future patch to
register a notification function that executes at the very end of
ExitBootServices() to disable DMA on all PCI bridges in the system.

So import the missing macros and typedefs from the UEFI spec.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 include/linux/efi.h | 23 ++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index f97f48a3dc81..81bd1e8c201f 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -270,6 +270,23 @@ typedef struct {
 	u32 create_event_ex;
 } __packed efi_boot_services_32_t;
 
+typedef unsigned long efi_tpl_t;
+
+#define TPL_APPLICATION				4
+#define TPL_CALLBACK				8
+#define TPL_NOTIFY				16
+#define TPL_HIGH_LEVEL				31
+
+typedef void *efi_event_t;
+typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
+
+#define EVT_TIMER				0x80000000
+#define EVT_RUNTIME				0x40000000
+#define EVT_NOTIFY_WAIT				0x00000100
+#define EVT_NOTIFY_SIGNAL			0x00000200
+#define EVT_SIGNAL_EXIT_BOOT_SERVICES		0x00000201
+#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE	0x60000202
+
 /*
  * EFI Boot Services table
  */
@@ -288,10 +305,12 @@ typedef union {
 		efi_status_t (__efiapi *allocate_pool)(int, unsigned long,
 						       void **);
 		efi_status_t (__efiapi *free_pool)(void *);
-		void *create_event;
+		efi_status_t (__efiapi *create_event)(u32 type, efi_tpl_t,
+						      efi_event_notify_t,
+						      void *, efi_event_t *);
 		void *set_timer;
 		void *wait_for_event;
-		void *signal_event;
+		efi_status_t (__efiapi *signal_event)(efi_event_t);
 		void *close_event;
 		void *check_event;
 		void *install_protocol_interface;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (19 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 20/21] efi/libstub: import type definitions for creating and signalling events Ard Biesheuvel
@ 2019-12-18 17:01 ` Ard Biesheuvel
  2019-12-19  2:50   ` Andy Lutomirski
                     ` (2 more replies)
  2019-12-19 11:12 ` [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Hans de Goede
  21 siblings, 3 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-18 17:01 UTC (permalink / raw)
  To: linux-efi
  Cc: Ard Biesheuvel, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar, Matthew Garrett

From: Matthew Garrett <matthewgarrett@google.com>

Add an option to disable the busmaster bit in the control register on
all PCI bridges during the invocation of ExitBootServices() and passing
control to the runtime kernel. System firmware may configure the IOMMU
to prevent malicious PCI devices from being able to attack the OS via DMA.
However, since firmware can't guarantee that the OS is IOMMU-aware, it
will tear down IOMMU configuration when ExitBootServices() is called.
This leaves a window between where a hostile device could still cause
damage before Linux configures the IOMMU again.

If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
command line argument is passed, the EFI stub will clear the busmaster
bit on all PCI bridges before ExitBootServices() completes. This will
prevent any malicious PCI devices from being able to perform DMA until
the kernel reenables busmastering after configuring the IOMMU.

This option is disabled when in EFI mixed mode environments (ie, 64-bit
kernels with a 32-bit EFI implementation), given that the use of EFI
events is not supported in this case.

This option may cause failures with some poorly behaved hardware and
should not be enabled without testing. The kernel commandline options
"efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
override the default.

Co-developed-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: Matthew Garrett <mjg59@google.com>
[ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 Documentation/admin-guide/kernel-parameters.txt |   4 +
 arch/x86/boot/compressed/eboot.c                |   2 +
 drivers/firmware/efi/Kconfig                    |  22 ++++
 drivers/firmware/efi/libstub/Makefile           |   2 +-
 drivers/firmware/efi/libstub/arm-stub.c         |   1 +
 drivers/firmware/efi/libstub/efi-stub-helper.c  |  17 +++
 drivers/firmware/efi/libstub/efistub.h          |   1 +
 drivers/firmware/efi/libstub/pci.c              | 116 ++++++++++++++++++++
 include/linux/efi.h                             |   2 +
 9 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 5a92d89a1bd4..06fd8d2c9a2c 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1180,6 +1180,10 @@
 			claim. Specify efi=nosoftreserve to disable this
 			reservation and treat the memory by its base type
 			(i.e. EFI_CONVENTIONAL_MEMORY / "System RAM").
+			disable_pci_dma: Disable the busmaster bit on all
+			PCI bridges while in the EFI boot stub
+			no_disable_pci_dma: Leave the busmaster bit set on all
+			PCI bridges while in the EFI boot stub
 
 	efi_no_storage_paranoia [EFI; X86]
 			Using this parameter you can use more than 50% of
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a3000283dc7a..79c3c3308195 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -126,6 +126,8 @@ static void setup_efi_pci(struct boot_params *params)
 	efi_handle_t h;
 	int i;
 
+	efi_pci_disable_bridge_busmaster();
+
 	status = efi_call_early(locate_handle,
 				EFI_LOCATE_BY_PROTOCOL,
 				&pci_proto, NULL, &size, pci_handle);
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index bcc378c19ebe..da2f5fc862aa 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -215,6 +215,28 @@ config EFI_RCI2_TABLE
 
 	  Say Y here for Dell EMC PowerEdge systems.
 
+config EFI_DISABLE_PCI_DMA
+       bool "Clear Busmaster bit on PCI bridges during ExitBootServices()"
+       help
+	  Disable the busmaster bit in the control register on all PCI bridges
+	  while calling ExitBootServices() and passing control to the runtime
+	  kernel. System firmware may configure the IOMMU to prevent malicious
+	  PCI devices from being able to attack the OS via DMA. However, since
+	  firmware can't guarantee that the OS is IOMMU-aware, it will tear
+	  down IOMMU configuration when ExitBootServices() is called. This
+	  leaves a window between where a hostile device could still cause
+	  damage before Linux configures the IOMMU again.
+
+	  If you say Y here, the EFI stub will clear the busmaster bit on all
+	  PCI bridges before ExitBootServices() completes. This will prevent
+	  any malicious PCI devices from being able to perform DMA until the
+	  kernel reenables busmastering after configuring the IOMMU.
+
+	  This option will cause failures with some poorly behaved hardware
+	  and should not be enabled without testing. The kernel commandline
+	  options "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be
+	  used to override this option.
+
 endmenu
 
 config UEFI_CPER
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index c35f893897e1..98a81576213d 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -39,7 +39,7 @@ OBJECT_FILES_NON_STANDARD	:= y
 KCOV_INSTRUMENT			:= n
 
 lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
-				   random.o
+				   random.o pci.o
 
 # include the stub's generic dependencies from lib/ when building for ARM/arm64
 arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index e1ec0b2cde29..aa2929098d60 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -257,6 +257,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
 	}
 
 	install_memreserve_table();
+	efi_pci_disable_bridge_busmaster();
 
 	new_fdt_addr = fdt_addr;
 	status = allocate_new_fdt_and_exit_boot(handle,
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 8b0d59f5c8cd..4b79bfff1fd4 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -33,6 +33,8 @@ static bool __section(.data) efi_nokaslr;
 static bool __section(.data) efi_quiet;
 static bool __section(.data) efi_novamap;
 static bool __section(.data) efi_nosoftreserve;
+static bool __section(.data) efi_disable_pci_dma =
+					IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
 
 bool __pure nokaslr(void)
 {
@@ -51,6 +53,11 @@ bool __pure __efi_soft_reserve_enabled(void)
 	return !efi_nosoftreserve;
 }
 
+bool __pure disable_pci_dma(void)
+{
+	return efi_disable_pci_dma;
+}
+
 #define EFI_MMAP_NR_SLACK_SLOTS	8
 
 struct file_info {
@@ -499,6 +506,16 @@ efi_status_t efi_parse_options(char const *cmdline)
 			efi_nosoftreserve = true;
 		}
 
+		if (!strncmp(str, "disable_pci_dma", 15)) {
+			str += strlen("disable_pci_dma");
+			efi_disable_pci_dma = true;
+		}
+
+		if (!strncmp(str, "no_disable_pci_dma", 18)) {
+			str += strlen("no_disable_pci_dma");
+			efi_disable_pci_dma = false;
+		}
+
 		/* Group words together, delimited by "," */
 		while (*str && *str != ' ' && *str != ',')
 			str++;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 72e60b6afbf8..679268f67521 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -28,6 +28,7 @@
 extern bool __pure nokaslr(void);
 extern bool __pure is_quiet(void);
 extern bool __pure novamap(void);
+extern bool __pure disable_pci_dma(void);
 
 extern __pure efi_system_table_t  *efi_system_table(void);
 
diff --git a/drivers/firmware/efi/libstub/pci.c b/drivers/firmware/efi/libstub/pci.c
new file mode 100644
index 000000000000..e2f71f890dd1
--- /dev/null
+++ b/drivers/firmware/efi/libstub/pci.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCI-related functions used by the EFI stub on multiple
+ * architectures.
+ *
+ * Copyright 2019 Google, LLC
+ */
+
+#include <linux/efi.h>
+#include <linux/pci.h>
+
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+static efi_event_t __section(.data) exit_boot_services_event;
+static efi_event_t __section(.data) disable_pci_dma_event;
+
+static efi_handle_t *__section(.data) pci_handle;
+static unsigned long __section(.data) pci_handle_size;
+
+static efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+
+static void __efiapi handle_exit_boot_services_event(efi_event_t event,
+						     void *context)
+{
+	efi_call_early(signal_event, disable_pci_dma_event);
+}
+
+static void __efiapi handle_disable_pci_dma_event(efi_event_t event,
+						  void *context)
+{
+	efi_handle_t handle;
+	efi_status_t status;
+	u16 class, command;
+	int i;
+
+	for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
+		efi_pci_io_protocol_t *pci = NULL;
+
+		status = efi_call_early(handle_protocol, handle,
+					&pci_proto, (void **)&pci);
+		if (status != EFI_SUCCESS || !pci)
+			continue;
+
+		status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
+					PCI_CLASS_DEVICE, 1, &class);
+
+		if (status != EFI_SUCCESS || class != PCI_CLASS_BRIDGE_PCI)
+			continue;
+
+		/* Disable busmastering */
+		status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
+					PCI_COMMAND, 1, &command);
+		if (status != EFI_SUCCESS || !(command & PCI_COMMAND_MASTER))
+			continue;
+
+		command &= ~PCI_COMMAND_MASTER;
+		status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16,
+					PCI_COMMAND, 1, &command);
+		if (status != EFI_SUCCESS)
+			pr_efi_err("Failed to disable PCI busmastering\n");
+	}
+}
+
+void efi_pci_disable_bridge_busmaster(void)
+{
+	efi_status_t status;
+
+	if (!disable_pci_dma() || !efi_is_native())
+		return;
+
+	status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL,
+				&pci_proto, NULL, &pci_handle_size, pci_handle);
+
+	if (status != EFI_BUFFER_TOO_SMALL) {
+		if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
+			pr_efi_err("Failed to locate PCI I/O handles'\n");
+		return;
+	}
+
+	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+				pci_handle_size, (void **)&pci_handle);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err("Failed to allocate memory for 'pci_handle'\n");
+		return;
+	}
+
+	status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL,
+				&pci_proto, NULL, &pci_handle_size, pci_handle);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err("Failed to locate PCI I/O handles'\n");
+		goto free_handle;
+	}
+
+	status = efi_call_early(create_event, EVT_NOTIFY_SIGNAL,
+				TPL_CALLBACK, handle_disable_pci_dma_event,
+				NULL, &disable_pci_dma_event);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err("Failed to create event to disable PCI DMA\n");
+		goto free_handle;
+	}
+
+	status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
+				TPL_CALLBACK, handle_exit_boot_services_event,
+				NULL, &exit_boot_services_event);
+	if (status != EFI_SUCCESS) {
+		pr_efi_err("Failed to register for EBS() event\n");
+		goto free_handle;
+	}
+
+	return;
+
+free_handle:
+	efi_call_early(free_pool, pci_handle);
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 81bd1e8c201f..2864633abff0 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1786,4 +1786,6 @@ struct linux_efi_memreserve {
 #define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \
 	/ sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
 
+void efi_pci_disable_bridge_busmaster(void);
+
 #endif /* _LINUX_EFI_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
@ 2019-12-19  2:50   ` Andy Lutomirski
  2019-12-19 13:17     ` Ard Biesheuvel
  2019-12-19 20:04   ` Matthew Garrett
  2020-02-06 14:30   ` Hans de Goede
  2 siblings, 1 reply; 87+ messages in thread
From: Andy Lutomirski @ 2019-12-19  2:50 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar, Matthew Garrett

On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> From: Matthew Garrett <matthewgarrett@google.com>
>
> Add an option to disable the busmaster bit in the control register on
> all PCI bridges during the invocation of ExitBootServices() and passing
> control to the runtime kernel. System firmware may configure the IOMMU
> to prevent malicious PCI devices from being able to attack the OS via DMA.
> However, since firmware can't guarantee that the OS is IOMMU-aware, it
> will tear down IOMMU configuration when ExitBootServices() is called.
> This leaves a window between where a hostile device could still cause
> damage before Linux configures the IOMMU again.
>
> If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
> command line argument is passed, the EFI stub will clear the busmaster
> bit on all PCI bridges before ExitBootServices() completes. This will
> prevent any malicious PCI devices from being able to perform DMA until
> the kernel reenables busmastering after configuring the IOMMU.
>
> This option is disabled when in EFI mixed mode environments (ie, 64-bit
> kernels with a 32-bit EFI implementation), given that the use of EFI
> events is not supported in this case.
>
> This option may cause failures with some poorly behaved hardware and
> should not be enabled without testing. The kernel commandline options
> "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
> override the default.

Could this maybe be efi=disable_early_pci_dma?

As it stands, it reads like busmastering is turned off and stays off,
which is not the case.  I'm dreading the silly forum posts saying
"your system is slow, and busmastering is leet, so use
efi=no_disable_pci_dma to allow busmastering and make it OMG fast".

--Andy

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode
  2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
                   ` (20 preceding siblings ...)
  2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
@ 2019-12-19 11:12 ` Hans de Goede
  2019-12-19 13:22   ` Ard Biesheuvel
  21 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2019-12-19 11:12 UTC (permalink / raw)
  To: Ard Biesheuvel, linux-efi
  Cc: Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner,
	Arvind Sankar

Hi,

On 18-12-2019 18:01, Ard Biesheuvel wrote:
> Currently, we support mixed mode (64-bit Linux running on 32-bit firmware)
> by explicitly reasoning about pointer sizes for every call into the
> firmware: on x86, there are 32-bit and 64-bit versions of each protocol
> interface, and each call gets routed via one of the two, depending on the
> native size of the firmware.
> 
> There is a lot of casting and pointer mangling involved in this, and as
> a result, we end up with much less coverage in terms of type checking by
> the compiler, due to the indirection via an anonymous, variadic thunking
> routine.
> 
> This peculiarity of x86 is also leaking into generic EFI code, which is
> shared with ia64, arm64, ARM and likely RiscV in the future. So let's
> try to clean this up a bit.
> 
> The approach taken by this series is to replace the 32/64 bit distinction
> with a distinction between native calls and mixed mode calls, where the
> former can be either 32 or 64 bit [depending on the platform] and use
> the ordinary native protocol definitions, while mixed mode calls retain
> the existing casting/thunking approach based on the 32-bit protocol
> definitions.
> 
> Given that GCC now supports emitting function calls using the MS calling
> convention, we can get rid of all the wrapping and casting, and emit the
> indirect calls directly.
> 
> Changes since v1:
> - Substantially more cleanup work to simplify and hide the mixed mode handling
>    in generic EFI code.
> - Get rid of all the pointless passing around of sys_table_arg
> - Incorporate an updated version of Matthew's PCI DMA disable patch using EFI
>    events to defer poking the busmaster bits until after all the ordinary
>    ExitBootServices() callbacks have executed.
> 
> Code can be found here
> https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efistub-x86-cleanup-v2
> 
> Cc: Hans de Goede <hdegoede@redhat.com>
> Cc: Matthew Garrett <matthewgarrett@google.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Arvind Sankar <nivedita@alum.mit.edu>

I've merged ardb/efistub-x86-cleanup-v3 into my local tree for testing I will let
you know if I see any unexpected side-effects. I've set CONFIG_EFI_DISABLE_PCI_DMA=n
for now.

I did notice one small cosmetic issue with the last patch:

 > diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
 > index bcc378c19ebe..da2f5fc862aa 100644
 > --- a/drivers/firmware/efi/Kconfig
 > +++ b/drivers/firmware/efi/Kconfig
 > @@ -215,6 +215,28 @@ config EFI_RCI2_TABLE
 >
 >   	  Say Y here for Dell EMC PowerEdge systems.
 >
 > +config EFI_DISABLE_PCI_DMA
 > +       bool "Clear Busmaster bit on PCI bridges during ExitBootServices()"
 > +       help

The bool and help here seem to be indented by 7 spaces rather then by a tab.

Regards,

Hans



^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-19  2:50   ` Andy Lutomirski
@ 2019-12-19 13:17     ` Ard Biesheuvel
  2019-12-19 20:04       ` Matthew Garrett
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-19 13:17 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Thomas Gleixner, Arvind Sankar, Matthew Garrett

On Thu, 19 Dec 2019 at 04:50, Andy Lutomirski <luto@kernel.org> wrote:
>
> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> >
> > From: Matthew Garrett <matthewgarrett@google.com>
> >
> > Add an option to disable the busmaster bit in the control register on
> > all PCI bridges during the invocation of ExitBootServices() and passing
> > control to the runtime kernel. System firmware may configure the IOMMU
> > to prevent malicious PCI devices from being able to attack the OS via DMA.
> > However, since firmware can't guarantee that the OS is IOMMU-aware, it
> > will tear down IOMMU configuration when ExitBootServices() is called.
> > This leaves a window between where a hostile device could still cause
> > damage before Linux configures the IOMMU again.
> >
> > If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
> > command line argument is passed, the EFI stub will clear the busmaster
> > bit on all PCI bridges before ExitBootServices() completes. This will
> > prevent any malicious PCI devices from being able to perform DMA until
> > the kernel reenables busmastering after configuring the IOMMU.
> >
> > This option is disabled when in EFI mixed mode environments (ie, 64-bit
> > kernels with a 32-bit EFI implementation), given that the use of EFI
> > events is not supported in this case.
> >
> > This option may cause failures with some poorly behaved hardware and
> > should not be enabled without testing. The kernel commandline options
> > "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
> > override the default.
>
> Could this maybe be efi=disable_early_pci_dma?
>
> As it stands, it reads like busmastering is turned off and stays off,
> which is not the case.  I'm dreading the silly forum posts saying
> "your system is slow, and busmastering is leet, so use
> efi=no_disable_pci_dma to allow busmastering and make it OMG fast".
>

Fair enough. I'll change this to [no_]disable_early_pci_dma (assuming
Matthew doesn't object to the exact shade of this bikeshed)

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode
  2019-12-19 11:12 ` [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Hans de Goede
@ 2019-12-19 13:22   ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-19 13:22 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Thu, 19 Dec 2019 at 13:12, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 18-12-2019 18:01, Ard Biesheuvel wrote:
> > Currently, we support mixed mode (64-bit Linux running on 32-bit firmware)
> > by explicitly reasoning about pointer sizes for every call into the
> > firmware: on x86, there are 32-bit and 64-bit versions of each protocol
> > interface, and each call gets routed via one of the two, depending on the
> > native size of the firmware.
> >
> > There is a lot of casting and pointer mangling involved in this, and as
> > a result, we end up with much less coverage in terms of type checking by
> > the compiler, due to the indirection via an anonymous, variadic thunking
> > routine.
> >
> > This peculiarity of x86 is also leaking into generic EFI code, which is
> > shared with ia64, arm64, ARM and likely RiscV in the future. So let's
> > try to clean this up a bit.
> >
> > The approach taken by this series is to replace the 32/64 bit distinction
> > with a distinction between native calls and mixed mode calls, where the
> > former can be either 32 or 64 bit [depending on the platform] and use
> > the ordinary native protocol definitions, while mixed mode calls retain
> > the existing casting/thunking approach based on the 32-bit protocol
> > definitions.
> >
> > Given that GCC now supports emitting function calls using the MS calling
> > convention, we can get rid of all the wrapping and casting, and emit the
> > indirect calls directly.
> >
> > Changes since v1:
> > - Substantially more cleanup work to simplify and hide the mixed mode handling
> >    in generic EFI code.
> > - Get rid of all the pointless passing around of sys_table_arg
> > - Incorporate an updated version of Matthew's PCI DMA disable patch using EFI
> >    events to defer poking the busmaster bits until after all the ordinary
> >    ExitBootServices() callbacks have executed.
> >
> > Code can be found here
> > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efistub-x86-cleanup-v2
> >
> > Cc: Hans de Goede <hdegoede@redhat.com>
> > Cc: Matthew Garrett <matthewgarrett@google.com>
> > Cc: Ingo Molnar <mingo@kernel.org>
> > Cc: Andy Lutomirski <luto@kernel.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Arvind Sankar <nivedita@alum.mit.edu>
>
> I've merged ardb/efistub-x86-cleanup-v3 into my local tree for testing I will let
> you know if I see any unexpected side-effects. I've set CONFIG_EFI_DISABLE_PCI_DMA=n
> for now.
>

Thanks Hans.

The CONFIG should not make a difference on mixed-mode - all the code
is there anyway, and only the default value changes, but it is
overridden to 'false' on mixed mode systems. The reason is that my
version of this patch uses an event callback, which would mean 32-bit
firmware calling back into the 64-bit kernel in the mixed mode case,
which we don't support.



> I did notice one small cosmetic issue with the last patch:
>
>  > diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
>  > index bcc378c19ebe..da2f5fc862aa 100644
>  > --- a/drivers/firmware/efi/Kconfig
>  > +++ b/drivers/firmware/efi/Kconfig
>  > @@ -215,6 +215,28 @@ config EFI_RCI2_TABLE
>  >
>  >        Say Y here for Dell EMC PowerEdge systems.
>  >
>  > +config EFI_DISABLE_PCI_DMA
>  > +       bool "Clear Busmaster bit on PCI bridges during ExitBootServices()"
>  > +       help
>
> The bool and help here seem to be indented by 7 spaces rather then by a tab.
>
> Regards,
>
> Hans
>
>

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-19 13:17     ` Ard Biesheuvel
@ 2019-12-19 20:04       ` Matthew Garrett
  0 siblings, 0 replies; 87+ messages in thread
From: Matthew Garrett @ 2019-12-19 20:04 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Andy Lutomirski, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Thomas Gleixner, Arvind Sankar

On Thu, Dec 19, 2019 at 5:17 AM Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:

> Fair enough. I'll change this to [no_]disable_early_pci_dma (assuming
> Matthew doesn't object to the exact shade of this bikeshed)

I'm fine with that.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
  2019-12-19  2:50   ` Andy Lutomirski
@ 2019-12-19 20:04   ` Matthew Garrett
  2019-12-20  7:06     ` Ard Biesheuvel
  2020-02-06 14:30   ` Hans de Goede
  2 siblings, 1 reply; 87+ messages in thread
From: Matthew Garrett @ 2019-12-19 20:04 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, Hans de Goede, Ingo Molnar, Andy Lutomirski,
	Thomas Gleixner, Arvind Sankar

On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> +                               TPL_CALLBACK, handle_exit_boot_services_event,
> +                               NULL, &exit_boot_services_event);
> +       if (status != EFI_SUCCESS) {
> +               pr_efi_err("Failed to register for EBS() event\n");
> +               goto free_handle;
> +       }

OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
first?

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-19 20:04   ` Matthew Garrett
@ 2019-12-20  7:06     ` Ard Biesheuvel
  2019-12-20  7:17       ` Andy Lutomirski
  2019-12-20 20:43       ` Matthew Garrett
  0 siblings, 2 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-20  7:06 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
>
> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> > +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> > +                               TPL_CALLBACK, handle_exit_boot_services_event,
> > +                               NULL, &exit_boot_services_event);
> > +       if (status != EFI_SUCCESS) {
> > +               pr_efi_err("Failed to register for EBS() event\n");
> > +               goto free_handle;
> > +       }
>
> OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
> EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
> first?

It doesn't, and that is kind of the point. The only guarantee you have
is that this runs before ExitBootServices() returns, but after any
other callbacks that have been registered. I know this is not 100%
what you're after, but it is the only way we can avoid poking devices
behind the backs of their drivers.

So this approach is what i am willing to accept for mainline, and I
would even start out by enabling it by default to get the most
coverage. If you need something stronger, I understand but I don't
think it belongs in mainline.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-20  7:06     ` Ard Biesheuvel
@ 2019-12-20  7:17       ` Andy Lutomirski
  2019-12-20  8:11         ` Ard Biesheuvel
  2019-12-20 20:43       ` Matthew Garrett
  1 sibling, 1 reply; 87+ messages in thread
From: Andy Lutomirski @ 2019-12-20  7:17 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Matthew Garrett, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner, Arvind Sankar



> On Dec 20, 2019, at 3:07 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 
> On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
>> 
>>> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>>> +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
>>> +                               TPL_CALLBACK, handle_exit_boot_services_event,
>>> +                               NULL, &exit_boot_services_event);
>>> +       if (status != EFI_SUCCESS) {
>>> +               pr_efi_err("Failed to register for EBS() event\n");
>>> +               goto free_handle;
>>> +       }
>> 
>> OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
>> EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
>> first?
> 
> It doesn't, and that is kind of the point. The only guarantee you have
> is that this runs before ExitBootServices() returns, but after any
> other callbacks that have been registered. I know this is not 100%
> what you're after, but it is the only way we can avoid poking devices
> behind the backs of their drivers.
> 

Can you clarify (in the changelog or a comment perhaps) why you’re doing this instead of turning off busmastering before calling ExitBootServices()?  Maybe this was covered in this thread, but I missed it.

Also, surely this whole mess is a a design error in EFI, at least when SEV is involved, and there should be an EFI extension to keep IOMMU enabled.  Or a specified way to *guarantee* that DMA is off when we exit boot services without hackery.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-20  7:17       ` Andy Lutomirski
@ 2019-12-20  8:11         ` Ard Biesheuvel
  2019-12-20 19:41           ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-20  8:11 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Matthew Garrett, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Fri, 20 Dec 2019 at 09:17, Andy Lutomirski <luto@amacapital.net> wrote:
>
>
>
> > On Dec 20, 2019, at 3:07 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >
> > On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
> >>
> >>> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> >>> +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> >>> +                               TPL_CALLBACK, handle_exit_boot_services_event,
> >>> +                               NULL, &exit_boot_services_event);
> >>> +       if (status != EFI_SUCCESS) {
> >>> +               pr_efi_err("Failed to register for EBS() event\n");
> >>> +               goto free_handle;
> >>> +       }
> >>
> >> OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
> >> EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
> >> first?
> >
> > It doesn't, and that is kind of the point. The only guarantee you have
> > is that this runs before ExitBootServices() returns, but after any
> > other callbacks that have been registered. I know this is not 100%
> > what you're after, but it is the only way we can avoid poking devices
> > behind the backs of their drivers.
> >
>
> Can you clarify (in the changelog or a comment perhaps) why you’re doing this instead of turning off busmastering before calling ExitBootServices()?  Maybe this was covered in this thread, but I missed it.
>

Sure. The problem is that EBS() is the place where drivers tear down
rings etc and gracefully take down the device. So killing DMA for all
of them by clearing the BM bit of every bridge is likely to cause
problems, because the teardown code wasn't written with the idea in
mind that DMA is no longer possible. On arm64 at least, it may result
in the kernel being entered with a pending SError which will kill the
OS as soon as they are unmasked. But the UEFI drivers themselves may
simply hang or timeout on some DMA access.

> Also, surely this whole mess is a a design error in EFI, at least when SEV is involved, and there should be an EFI extension to keep IOMMU enabled.  Or a specified way to *guarantee* that DMA is off when we exit boot services without hackery.

The UEFI spec requires that all devices stop doing DMA at
ExitBootServices() time, which is why they register for this event and
disable DMA in their drivers. So from this pov, the state of the IOMMU
is irrelevant since no device should be doing DMA anyway. The UEFI
spec does not reason at all about IOMMUs.

But indeed, the whole idea that the IOMMU is a 'feature' that you can
ignore if you want since it will be in passthrough mode otherwise is
misguided, but I'm not sure this is a firmware problem. The desire to
be able to run yesterday's OS on today's hardware, especially in the
Windows world, resulted in a situation where many security and
hardening features are opt-in rather than opt-out, with the adoption
you might expect.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-20  8:11         ` Ard Biesheuvel
@ 2019-12-20 19:41           ` Arvind Sankar
  2020-01-02 14:46             ` Laszlo Ersek
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2019-12-20 19:41 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Andy Lutomirski, Matthew Garrett, Ard Biesheuvel, linux-efi,
	Hans de Goede, Ingo Molnar, Andy Lutomirski, Thomas Gleixner,
	Arvind Sankar, Laszlo Ersek

On Fri, Dec 20, 2019 at 10:11:00AM +0200, Ard Biesheuvel wrote:
> On Fri, 20 Dec 2019 at 09:17, Andy Lutomirski <luto@amacapital.net> wrote:
> >
> >
> >
> > > On Dec 20, 2019, at 3:07 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > >
> > > On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
> > >>
> > >>> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> > >>> +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> > >>> +                               TPL_CALLBACK, handle_exit_boot_services_event,
> > >>> +                               NULL, &exit_boot_services_event);
> > >>> +       if (status != EFI_SUCCESS) {
> > >>> +               pr_efi_err("Failed to register for EBS() event\n");
> > >>> +               goto free_handle;
> > >>> +       }
> > >>
> > >> OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
> > >> EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
> > >> first?
> > >
> > > It doesn't, and that is kind of the point. The only guarantee you have
> > > is that this runs before ExitBootServices() returns, but after any
> > > other callbacks that have been registered. I know this is not 100%
> > > what you're after, but it is the only way we can avoid poking devices
> > > behind the backs of their drivers.
> > >

Could we add a comment to describe why we have the two-step event
notification, i.e. to ensure the ordering?

Regarding SEV, from what Laszlo had said [1] I had understood that the
SEV driver left everything blacklisted -- is this necessary at all for
SEV or did I misunderstand his comment?

[1] https://lore.kernel.org/lkml/9c58f2d2-5712-0972-6ea7-092500f37cf9@redhat.com/

> >
> > Can you clarify (in the changelog or a comment perhaps) why you’re doing this instead of turning off busmastering before calling ExitBootServices()?  Maybe this was covered in this thread, but I missed it.
> >
> 
> Sure. The problem is that EBS() is the place where drivers tear down
> rings etc and gracefully take down the device. So killing DMA for all
> of them by clearing the BM bit of every bridge is likely to cause
> problems, because the teardown code wasn't written with the idea in
> mind that DMA is no longer possible. On arm64 at least, it may result
> in the kernel being entered with a pending SError which will kill the
> OS as soon as they are unmasked. But the UEFI drivers themselves may
> simply hang or timeout on some DMA access.
> 

As I understand it, the order in which we want the bus-mastering
disable to happen is
- all PCI device drivers are stopped
- bus mastering is disabled
- depending on firmware, iommu might get disabled (probably out of our
  control)

Instead of using the event notifier, could we not explicitly call
DisconnectController() for all the PCI devices, then disable
bus-mastering, and only then call ExitBootServices()?

> > Also, surely this whole mess is a a design error in EFI, at least when SEV is involved, and there should be an EFI extension to keep IOMMU enabled.  Or a specified way to *guarantee* that DMA is off when we exit boot services without hackery.
> 
> The UEFI spec requires that all devices stop doing DMA at
> ExitBootServices() time, which is why they register for this event and
> disable DMA in their drivers. So from this pov, the state of the IOMMU
> is irrelevant since no device should be doing DMA anyway. The UEFI
> spec does not reason at all about IOMMUs.
> 
> But indeed, the whole idea that the IOMMU is a 'feature' that you can
> ignore if you want since it will be in passthrough mode otherwise is
> misguided, but I'm not sure this is a firmware problem. The desire to
> be able to run yesterday's OS on today's hardware, especially in the
> Windows world, resulted in a situation where many security and
> hardening features are opt-in rather than opt-out, with the adoption
> you might expect.

Looking at the intel iommu driver [2] there is a PCD entry to control
whether to leave the IOMMU enabled. Is it possible to check its value to
see whether the bus-master disabling is necessary -- ie IOMMU was
enabled during boot and its going to get turned off during
ExitBootServices, or even check whether it's settable and if so set it
to leave the IOMMU enabled?

[2] https://github.com/tianocore/edk2-platforms/blob/0d4d661b5a7cf3114a7d81e1c59e5cb57ceaf139/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c#L601


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-20  7:06     ` Ard Biesheuvel
  2019-12-20  7:17       ` Andy Lutomirski
@ 2019-12-20 20:43       ` Matthew Garrett
  2019-12-21 16:44         ` Ard Biesheuvel
  1 sibling, 1 reply; 87+ messages in thread
From: Matthew Garrett @ 2019-12-20 20:43 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Thu, Dec 19, 2019 at 11:07 PM Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
>
> On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
> >
> > On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> > > +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> > > +                               TPL_CALLBACK, handle_exit_boot_services_event,
> > > +                               NULL, &exit_boot_services_event);
> > > +       if (status != EFI_SUCCESS) {
> > > +               pr_efi_err("Failed to register for EBS() event\n");
> > > +               goto free_handle;
> > > +       }
> >
> > OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
> > EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
> > first?
>
> It doesn't, and that is kind of the point. The only guarantee you have
> is that this runs before ExitBootServices() returns, but after any
> other callbacks that have been registered. I know this is not 100%
> what you're after, but it is the only way we can avoid poking devices
> behind the backs of their drivers.

Hm. In that case, I think this version fails to match the patch
description - there's potentially still a window where DMA-capable PCI
devices can attack the kernel, it's just smaller. If disconnecting
drivers from the device would give us the same expectations then that
seems like a better approach, but I think I probably wouldn't add my
signed-off-by to this version.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-20 20:43       ` Matthew Garrett
@ 2019-12-21 16:44         ` Ard Biesheuvel
  2019-12-21 21:24           ` Matthew Garrett
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-21 16:44 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Fri, 20 Dec 2019 at 22:43, Matthew Garrett <mjg59@google.com> wrote:
>
> On Thu, Dec 19, 2019 at 11:07 PM Ard Biesheuvel
> <ard.biesheuvel@linaro.org> wrote:
> >
> > On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
> > >
> > > On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> > > > +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> > > > +                               TPL_CALLBACK, handle_exit_boot_services_event,
> > > > +                               NULL, &exit_boot_services_event);
> > > > +       if (status != EFI_SUCCESS) {
> > > > +               pr_efi_err("Failed to register for EBS() event\n");
> > > > +               goto free_handle;
> > > > +       }
> > >
> > > OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
> > > EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
> > > first?
> >
> > It doesn't, and that is kind of the point. The only guarantee you have
> > is that this runs before ExitBootServices() returns, but after any
> > other callbacks that have been registered. I know this is not 100%
> > what you're after, but it is the only way we can avoid poking devices
> > behind the backs of their drivers.
>
> Hm. In that case, I think this version fails to match the patch
> description - there's potentially still a window where DMA-capable PCI
> devices can attack the kernel, it's just smaller. If disconnecting
> drivers from the device would give us the same expectations then that
> seems like a better approach, but I think I probably wouldn't add my
> signed-off-by to this version.

Point taken. I like Arvind's suggestion but we need to take care not
to disable the device producing the GOP. Beyond that, it should be
possible to disable all devices that are behind PCI bridges. It does
mean we need to decode the secondary/subordinate bus values from the
config space and take them into account when iterating over the PCI
handle list.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-18 17:01 ` [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls Ard Biesheuvel
@ 2019-12-21 21:22   ` Hans de Goede
  2019-12-22 12:02     ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2019-12-21 21:22 UTC (permalink / raw)
  To: Ard Biesheuvel, linux-efi
  Cc: Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner,
	Arvind Sankar

Hi Ard,

On 18-12-2019 18:01, Ard Biesheuvel wrote:
> We use special wrapper routines to invoke firmware services in the
> native case as well as the mixed mode case. For mixed mode, the need
> is obvious, but for the native cases, we can simply rely on the
> compiler to generate the indirect call, given that GCC now has
> support for the MS calling convention (and has had it for quite some
> time now). Note that on i386, the decompressor and the EFI stub are not
> built with -mregparm=3 like the rest of the i386 kernel, so we can
> safely allow the compiler to emit the indirect calls here as well.
> 
> So drop all the wrappers and indirection, and switch to either native
> calls, or direct calls into the thunk routine for mixed mode.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

I'm afraid that this patch breaks the boot on one of my machines.

Specifically this patch breaks my GDP pocket machine. This is a Cherry
Trail device with a 64 UEFI running a 64 bit kernel build.

As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
tree, the GPD pocket stops booting and it stop so early on that I get 0
debug output. I guess I could try adding a few pr_efi_err calls
and see if those still do something.

I noticed that you have made some changes to this patch, I've
tried updating it to the version from your efistub-x86-cleanup-v3
branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
and I have also cherry-picked the latest version of all preceding
commits, unfortunately even with the new version, the GPD pocket
still hangs at boot.

Unfortunately the nature of this patch makes it hard to figure
out the root cause of this issue...

I've also tried another Cherry Trail device with 64 bit UEFI and
that does not suffer from this problem.

Regards,

Hans



> ---
>   arch/x86/boot/compressed/Makefile      |  2 +-
>   arch/x86/boot/compressed/efi_stub_32.S | 87 --------------------
>   arch/x86/boot/compressed/efi_stub_64.S |  5 --
>   arch/x86/boot/compressed/head_32.S     |  6 --
>   arch/x86/boot/compressed/head_64.S     | 12 ---
>   arch/x86/include/asm/efi.h             | 30 +++----
>   arch/x86/platform/efi/efi_64.c         |  2 -
>   7 files changed, 17 insertions(+), 127 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index aa976adb7094..a20f55c59753 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -89,7 +89,7 @@ vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
>   
>   $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
>   
> -vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
> +vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o \
>   	$(objtree)/drivers/firmware/efi/libstub/lib.a
>   vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
>   
> diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S
> deleted file mode 100644
> index ed6c351d34ed..000000000000
> --- a/arch/x86/boot/compressed/efi_stub_32.S
> +++ /dev/null
> @@ -1,87 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/*
> - * EFI call stub for IA32.
> - *
> - * This stub allows us to make EFI calls in physical mode with interrupts
> - * turned off. Note that this implementation is different from the one in
> - * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical
> - * mode at this point.
> - */
> -
> -#include <linux/linkage.h>
> -#include <asm/page_types.h>
> -
> -/*
> - * efi_call_phys(void *, ...) is a function with variable parameters.
> - * All the callers of this function assure that all the parameters are 4-bytes.
> - */
> -
> -/*
> - * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save.
> - * So we'd better save all of them at the beginning of this function and restore
> - * at the end no matter how many we use, because we can not assure EFI runtime
> - * service functions will comply with gcc calling convention, too.
> - */
> -
> -.text
> -SYM_FUNC_START(efi_call_phys)
> -	/*
> -	 * 0. The function can only be called in Linux kernel. So CS has been
> -	 * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
> -	 * the values of these registers are the same. And, the corresponding
> -	 * GDT entries are identical. So I will do nothing about segment reg
> -	 * and GDT, but change GDT base register in prelog and epilog.
> -	 */
> -
> -	/*
> -	 * 1. Because we haven't been relocated by this point we need to
> -	 * use relative addressing.
> -	 */
> -	call	1f
> -1:	popl	%edx
> -	subl	$1b, %edx
> -
> -	/*
> -	 * 2. Now on the top of stack is the return
> -	 * address in the caller of efi_call_phys(), then parameter 1,
> -	 * parameter 2, ..., param n. To make things easy, we save the return
> -	 * address of efi_call_phys in a global variable.
> -	 */
> -	popl	%ecx
> -	movl	%ecx, saved_return_addr(%edx)
> -	/* get the function pointer into ECX*/
> -	popl	%ecx
> -	movl	%ecx, efi_rt_function_ptr(%edx)
> -
> -	/*
> -	 * 3. Call the physical function.
> -	 */
> -	call	*%ecx
> -
> -	/*
> -	 * 4. Balance the stack. And because EAX contain the return value,
> -	 * we'd better not clobber it. We need to calculate our address
> -	 * again because %ecx and %edx are not preserved across EFI function
> -	 * calls.
> -	 */
> -	call	1f
> -1:	popl	%edx
> -	subl	$1b, %edx
> -
> -	movl	efi_rt_function_ptr(%edx), %ecx
> -	pushl	%ecx
> -
> -	/*
> -	 * 10. Push the saved return address onto the stack and return.
> -	 */
> -	movl	saved_return_addr(%edx), %ecx
> -	pushl	%ecx
> -	ret
> -SYM_FUNC_END(efi_call_phys)
> -.previous
> -
> -.data
> -saved_return_addr:
> -	.long 0
> -efi_rt_function_ptr:
> -	.long 0
> diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S
> deleted file mode 100644
> index 99494dff2113..000000000000
> --- a/arch/x86/boot/compressed/efi_stub_64.S
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -#include <asm/segment.h>
> -#include <asm/msr.h>
> -#include <asm/processor-flags.h>
> -
> -#include "../../platform/efi/efi_stub_64.S"
> diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
> index 40468ab49b9b..7da4dfc53df6 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -161,9 +161,7 @@ SYM_FUNC_START(efi_pe_entry)
>   	popl	%ecx
>   	movl	%ecx, efi32_config+8(%esi)	/* EFI System table pointer */
>   
> -	/* Relocate efi_config->call() */
>   	leal	efi32_config(%esi), %eax
> -	add	%esi, 28(%eax)
>   	pushl	%eax
>   
>   	call	make_boot_params
> @@ -188,9 +186,7 @@ SYM_FUNC_START(efi32_stub_entry)
>   	movl	%ecx, efi32_config(%esi)	/* Handle */
>   	movl	%edx, efi32_config+8(%esi)	/* EFI System table pointer */
>   
> -	/* Relocate efi_config->call() */
>   	leal	efi32_config(%esi), %eax
> -	add	%esi, 28(%eax)
>   	pushl	%eax
>   2:
>   	call	efi_main
> @@ -266,8 +262,6 @@ SYM_FUNC_END(.Lrelocated)
>   	.data
>   efi32_config:
>   	.fill 7,4,0
> -	.long efi_call_phys
> -	.long 0
>   	.byte 0
>   #endif
>   
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index 58a512e33d8d..6dc6a7ebb9e1 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -458,11 +458,6 @@ SYM_FUNC_START(efi_pe_entry)
>   1:	popq	%rbp
>   	subq	$1b, %rbp
>   
> -	/*
> -	 * Relocate efi_config->call().
> -	 */
> -	addq	%rbp, efi64_config+40(%rip)
> -
>   	movq	%rax, %rdi
>   	call	make_boot_params
>   	cmpq	$0,%rax
> @@ -477,11 +472,6 @@ handover_entry:
>   1:	popq	%rbp
>   	subq	$1b, %rbp
>   
> -	/*
> -	 * Relocate efi_config->call().
> -	 */
> -	movq	efi_config(%rip), %rax
> -	addq	%rbp, 40(%rax)
>   2:
>   	movq	efi_config(%rip), %rdi
>   	call	efi_main
> @@ -683,14 +673,12 @@ SYM_DATA_LOCAL(efi_config, .quad 0)
>   #ifdef CONFIG_EFI_MIXED
>   SYM_DATA_START(efi32_config)
>   	.fill	5,8,0
> -	.quad	efi64_thunk
>   	.byte	0
>   SYM_DATA_END(efi32_config)
>   #endif
>   
>   SYM_DATA_START(efi64_config)
>   	.fill	5,8,0
> -	.quad	efi_call
>   	.byte	1
>   SYM_DATA_END(efi64_config)
>   #endif /* CONFIG_EFI_STUB */
> diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
> index 183cd49e0495..e0789ec5c9f6 100644
> --- a/arch/x86/include/asm/efi.h
> +++ b/arch/x86/include/asm/efi.h
> @@ -152,6 +152,7 @@ struct efi_setup_data {
>   extern u64 efi_setup;
>   
>   #ifdef CONFIG_EFI
> +extern efi_status_t efi64_thunk(u32, ...);
>   
>   static inline bool efi_is_mixed(void)
>   {
> @@ -205,7 +206,6 @@ struct efi_config {
>   	efi_runtime_services_t *runtime_services;
>   	efi_boot_services_t *boot_services;
>   	efi_simple_text_output_protocol_t *text_output;
> -	efi_status_t (*call)(unsigned long, ...);
>   	bool is64;
>   } __packed;
>   
> @@ -235,30 +235,32 @@ static inline bool efi_is_native(void)
>   			(unsigned long)(attr), (attr))
>   
>   #define efi_table_attr(table, attr, instance) ({			\
> -	__typeof__(((table##_t *)0)->attr) __ret;			\
> +	__typeof__(instance->attr) __ret;				\
>   	if (efi_is_native()) {						\
> -		__ret = ((table##_t *)(unsigned long)instance)->attr;	\
> +		__ret = instance->attr;					\
>   	} else {							\
> -		__ret = (__typeof__(__ret))efi_mixed_mode_cast(		\
> -		((table##_t *)(unsigned long)instance)->mixed_mode.attr);\
> +		__ret = (__typeof__(__ret))				\
> +			efi_mixed_mode_cast(instance->mixed_mode.attr);	\
>   	}								\
>   	__ret;								\
>   })
>   
>   #define efi_call_proto(protocol, f, instance, ...)			\
> -	__efi_early()->call((unsigned long)				\
> -				efi_table_attr(protocol, f, instance),	\
> -		instance, ##__VA_ARGS__)
> +	(efi_is_native()						\
> +		? instance->f(instance, ##__VA_ARGS__)			\
> +		: efi64_thunk(instance->mixed_mode.f, instance,	##__VA_ARGS__))
>   
>   #define efi_call_early(f, ...)						\
> -	__efi_early()->call((unsigned long)				\
> -				efi_table_attr(efi_boot_services, f,	\
> -		__efi_early()->boot_services), __VA_ARGS__)
> +	(efi_is_native()						\
> +		? __efi_early()->boot_services->f(__VA_ARGS__)		\
> +		: efi64_thunk(__efi_early()->boot_services->mixed_mode.f,\
> +			__VA_ARGS__))
>   
>   #define efi_call_runtime(f, ...)					\
> -	__efi_early()->call((unsigned long)				\
> -				efi_table_attr(efi_runtime_services, f,	\
> -		__efi_early()->runtime_services), __VA_ARGS__)
> +	(efi_is_native()						\
> +		? __efi_early()->runtime_services->f(__VA_ARGS__)	\
> +		: efi64_thunk(__efi_early()->runtime_services->mixed_mode.f,\
> +			__VA_ARGS__))
>   
>   extern bool efi_reboot_required(void);
>   extern bool efi_is_table_address(unsigned long phys_addr);
> diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
> index 885e50a707a6..03c2ed3c645c 100644
> --- a/arch/x86/platform/efi/efi_64.c
> +++ b/arch/x86/platform/efi/efi_64.c
> @@ -635,8 +635,6 @@ void efi_switch_mm(struct mm_struct *mm)
>   }
>   
>   #ifdef CONFIG_EFI_MIXED
> -extern efi_status_t efi64_thunk(u32, ...);
> -
>   static DEFINE_SPINLOCK(efi_runtime_lock);
>   
>   #define runtime_service32(func)						 \
> 


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-21 16:44         ` Ard Biesheuvel
@ 2019-12-21 21:24           ` Matthew Garrett
  2019-12-21 22:54             ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Matthew Garrett @ 2019-12-21 21:24 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Sat, Dec 21, 2019 at 8:44 AM Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> Point taken. I like Arvind's suggestion but we need to take care not
> to disable the device producing the GOP. Beyond that, it should be
> possible to disable all devices that are behind PCI bridges. It does
> mean we need to decode the secondary/subordinate bus values from the
> config space and take them into account when iterating over the PCI
> handle list.

The device producing the GOP is the device that I'm most afraid of, to
be honest.I'd naively expect that anything presenting a linear
framebuffer will probably leave it up at disconnect time, and we're
definitely not using DMA to access that framebuffer.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-21 21:24           ` Matthew Garrett
@ 2019-12-21 22:54             ` Arvind Sankar
  2019-12-23 14:02               ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2019-12-21 22:54 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Ard Biesheuvel, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Sat, Dec 21, 2019 at 01:24:16PM -0800, Matthew Garrett wrote:
> On Sat, Dec 21, 2019 at 8:44 AM Ard Biesheuvel
> <ard.biesheuvel@linaro.org> wrote:
> > Point taken. I like Arvind's suggestion but we need to take care not
> > to disable the device producing the GOP. Beyond that, it should be
> > possible to disable all devices that are behind PCI bridges. It does
> > mean we need to decode the secondary/subordinate bus values from the
> > config space and take them into account when iterating over the PCI
> > handle list.

Why do we need to look at the bus numbers? Shouldn't it be just looping
and disabling everything that's a regular device in the first pass
(possibly excluding devices that are producing GOP/UGA), and then going
over it again to disable the bus-master settings on bridges?

Also, why do we restrict the bus-master disable to only PCI/PCI bridges?
Shouldn't we also disable bus-mastering on all the other PCI-xxx
bridges?

> 
> The device producing the GOP is the device that I'm most afraid of, to
> be honest.I'd naively expect that anything presenting a linear
> framebuffer will probably leave it up at disconnect time, and we're
> definitely not using DMA to access that framebuffer.

At least on my system, disconnecting the GOP device does leave the
display up, and the framebuffer remains active (ie writing to it updates
the display). It wouldn't be surprising if this doesn't work for all
GPUs though.


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-21 21:22   ` Hans de Goede
@ 2019-12-22 12:02     ` Ard Biesheuvel
  2019-12-22 12:37       ` Ard Biesheuvel
                         ` (2 more replies)
  0 siblings, 3 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-22 12:02 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Sat, 21 Dec 2019 at 22:22, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi Ard,
>
> On 18-12-2019 18:01, Ard Biesheuvel wrote:
> > We use special wrapper routines to invoke firmware services in the
> > native case as well as the mixed mode case. For mixed mode, the need
> > is obvious, but for the native cases, we can simply rely on the
> > compiler to generate the indirect call, given that GCC now has
> > support for the MS calling convention (and has had it for quite some
> > time now). Note that on i386, the decompressor and the EFI stub are not
> > built with -mregparm=3 like the rest of the i386 kernel, so we can
> > safely allow the compiler to emit the indirect calls here as well.
> >
> > So drop all the wrappers and indirection, and switch to either native
> > calls, or direct calls into the thunk routine for mixed mode.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> I'm afraid that this patch breaks the boot on one of my machines.
>
> Specifically this patch breaks my GDP pocket machine. This is a Cherry
> Trail device with a 64 UEFI running a 64 bit kernel build.
>
> As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
> tree, the GPD pocket stops booting and it stop so early on that I get 0
> debug output. I guess I could try adding a few pr_efi_err calls
> and see if those still do something.
>
> I noticed that you have made some changes to this patch, I've
> tried updating it to the version from your efistub-x86-cleanup-v3
> branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
> and I have also cherry-picked the latest version of all preceding
> commits, unfortunately even with the new version, the GPD pocket
> still hangs at boot.
>
> Unfortunately the nature of this patch makes it hard to figure
> out the root cause of this issue...
>
> I've also tried another Cherry Trail device with 64 bit UEFI and
> that does not suffer from this problem.
>

Thanks Hans.

There are a number of things that change in the way the calls are
made, but the most obvious thing to check is whether the stack needs
to be aligned, since that is no longer being done.

If you have time to experiment a bit more, could you check whether
doing 'and $~0xf %rsp' before 'call efi_main' in the .S stub code for
x86_64 makes a difference?

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-22 12:02     ` Ard Biesheuvel
@ 2019-12-22 12:37       ` Ard Biesheuvel
  2019-12-22 12:46       ` Andy Lutomirski
  2019-12-23 11:49       ` Hans de Goede
  2 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-22 12:37 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Sun, 22 Dec 2019 at 13:02, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> On Sat, 21 Dec 2019 at 22:22, Hans de Goede <hdegoede@redhat.com> wrote:
> >
> > Hi Ard,
> >
> > On 18-12-2019 18:01, Ard Biesheuvel wrote:
> > > We use special wrapper routines to invoke firmware services in the
> > > native case as well as the mixed mode case. For mixed mode, the need
> > > is obvious, but for the native cases, we can simply rely on the
> > > compiler to generate the indirect call, given that GCC now has
> > > support for the MS calling convention (and has had it for quite some
> > > time now). Note that on i386, the decompressor and the EFI stub are not
> > > built with -mregparm=3 like the rest of the i386 kernel, so we can
> > > safely allow the compiler to emit the indirect calls here as well.
> > >
> > > So drop all the wrappers and indirection, and switch to either native
> > > calls, or direct calls into the thunk routine for mixed mode.
> > >
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >
> > I'm afraid that this patch breaks the boot on one of my machines.
> >
> > Specifically this patch breaks my GDP pocket machine. This is a Cherry
> > Trail device with a 64 UEFI running a 64 bit kernel build.
> >
> > As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
> > tree, the GPD pocket stops booting and it stop so early on that I get 0
> > debug output. I guess I could try adding a few pr_efi_err calls
> > and see if those still do something.
> >
> > I noticed that you have made some changes to this patch, I've
> > tried updating it to the version from your efistub-x86-cleanup-v3
> > branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
> > and I have also cherry-picked the latest version of all preceding
> > commits, unfortunately even with the new version, the GPD pocket
> > still hangs at boot.
> >
> > Unfortunately the nature of this patch makes it hard to figure
> > out the root cause of this issue...
> >
> > I've also tried another Cherry Trail device with 64 bit UEFI and
> > that does not suffer from this problem.
> >
>
> Thanks Hans.
>
> There are a number of things that change in the way the calls are
> made, but the most obvious thing to check is whether the stack needs
> to be aligned, since that is no longer being done.
>
> If you have time to experiment a bit more, could you check whether
> doing 'and $~0xf %rsp' before 'call efi_main' in the .S stub code for
> x86_64 makes a difference?

... or in case that does not help, I have updated my -v3 branch to
split the removal of the thunking sequence for x86_64 in several
discrete steps.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-22 12:02     ` Ard Biesheuvel
  2019-12-22 12:37       ` Ard Biesheuvel
@ 2019-12-22 12:46       ` Andy Lutomirski
  2019-12-22 15:29         ` Ard Biesheuvel
  2019-12-23 11:49       ` Hans de Goede
  2 siblings, 1 reply; 87+ messages in thread
From: Andy Lutomirski @ 2019-12-22 12:46 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Hans de Goede, Ard Biesheuvel, linux-efi, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner, Arvind Sankar



> On Dec 22, 2019, at 8:02 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 
> On Sat, 21 Dec 2019 at 22:22, Hans de Goede <hdegoede@redhat.com> wrote:
>> 
>> Hi Ard,
>> 
>>> On 18-12-2019 18:01, Ard Biesheuvel wrote:
>>> We use special wrapper routines to invoke firmware services in the
>>> native case as well as the mixed mode case. For mixed mode, the need
>>> is obvious, but for the native cases, we can simply rely on the
>>> compiler to generate the indirect call, given that GCC now has
>>> support for the MS calling convention (and has had it for quite some
>>> time now). Note that on i386, the decompressor and the EFI stub are not
>>> built with -mregparm=3 like the rest of the i386 kernel, so we can
>>> safely allow the compiler to emit the indirect calls here as well.
>>> 
>>> So drop all the wrappers and indirection, and switch to either native
>>> calls, or direct calls into the thunk routine for mixed mode.
>>> 
>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>> 
>> I'm afraid that this patch breaks the boot on one of my machines.
>> 
>> Specifically this patch breaks my GDP pocket machine. This is a Cherry
>> Trail device with a 64 UEFI running a 64 bit kernel build.
>> 
>> As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
>> tree, the GPD pocket stops booting and it stop so early on that I get 0
>> debug output. I guess I could try adding a few pr_efi_err calls
>> and see if those still do something.
>> 
>> I noticed that you have made some changes to this patch, I've
>> tried updating it to the version from your efistub-x86-cleanup-v3
>> branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
>> and I have also cherry-picked the latest version of all preceding
>> commits, unfortunately even with the new version, the GPD pocket
>> still hangs at boot.
>> 
>> Unfortunately the nature of this patch makes it hard to figure
>> out the root cause of this issue...
>> 
>> I've also tried another Cherry Trail device with 64 bit UEFI and
>> that does not suffer from this problem.
>> 
> 
> Thanks Hans.
> 
> There are a number of things that change in the way the calls are
> made, but the most obvious thing to check is whether the stack needs
> to be aligned, since that is no longer being done.
> 
> If you have time to experiment a bit more, could you check whether
> doing 'and $~0xf %rsp' before 'call efi_main' in the .S stub code for
> x86_64 makes a difference?

Hmm. Most of the kernel is compiled with the stack alignment set to 8, and there a lot of asm that makes no effort to preserve alignment beyond 8 bytes.  So if EFI calls need 16 byte alignment, you may need to do something special.

On new enough gcc (the versions that actually support the flags to set the alignment to 8), maybe you can use function attributes, or maybe you can stick a 16-byte-aligned local variable in functions that call EFI functions?  The latter would be rather fragile.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-22 12:46       ` Andy Lutomirski
@ 2019-12-22 15:29         ` Ard Biesheuvel
  2019-12-22 21:12           ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-22 15:29 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Hans de Goede, Ard Biesheuvel, linux-efi, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Sun, 22 Dec 2019 at 13:46, Andy Lutomirski <luto@amacapital.net> wrote:
>
>
>
> > On Dec 22, 2019, at 8:02 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >
> > On Sat, 21 Dec 2019 at 22:22, Hans de Goede <hdegoede@redhat.com> wrote:
> >>
> >> Hi Ard,
> >>
> >>> On 18-12-2019 18:01, Ard Biesheuvel wrote:
> >>> We use special wrapper routines to invoke firmware services in the
> >>> native case as well as the mixed mode case. For mixed mode, the need
> >>> is obvious, but for the native cases, we can simply rely on the
> >>> compiler to generate the indirect call, given that GCC now has
> >>> support for the MS calling convention (and has had it for quite some
> >>> time now). Note that on i386, the decompressor and the EFI stub are not
> >>> built with -mregparm=3 like the rest of the i386 kernel, so we can
> >>> safely allow the compiler to emit the indirect calls here as well.
> >>>
> >>> So drop all the wrappers and indirection, and switch to either native
> >>> calls, or direct calls into the thunk routine for mixed mode.
> >>>
> >>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >>
> >> I'm afraid that this patch breaks the boot on one of my machines.
> >>
> >> Specifically this patch breaks my GDP pocket machine. This is a Cherry
> >> Trail device with a 64 UEFI running a 64 bit kernel build.
> >>
> >> As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
> >> tree, the GPD pocket stops booting and it stop so early on that I get 0
> >> debug output. I guess I could try adding a few pr_efi_err calls
> >> and see if those still do something.
> >>
> >> I noticed that you have made some changes to this patch, I've
> >> tried updating it to the version from your efistub-x86-cleanup-v3
> >> branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
> >> and I have also cherry-picked the latest version of all preceding
> >> commits, unfortunately even with the new version, the GPD pocket
> >> still hangs at boot.
> >>
> >> Unfortunately the nature of this patch makes it hard to figure
> >> out the root cause of this issue...
> >>
> >> I've also tried another Cherry Trail device with 64 bit UEFI and
> >> that does not suffer from this problem.
> >>
> >
> > Thanks Hans.
> >
> > There are a number of things that change in the way the calls are
> > made, but the most obvious thing to check is whether the stack needs
> > to be aligned, since that is no longer being done.
> >
> > If you have time to experiment a bit more, could you check whether
> > doing 'and $~0xf %rsp' before 'call efi_main' in the .S stub code for
> > x86_64 makes a difference?
>
> Hmm. Most of the kernel is compiled with the stack alignment set to 8, and there a lot of asm that makes no effort to preserve alignment beyond 8 bytes.  So if EFI calls need 16 byte alignment, you may need to do something special.
>
> On new enough gcc (the versions that actually support the flags to set the alignment to 8), maybe you can use function attributes, or maybe you can stick a 16-byte-aligned local variable in functions that call EFI functions?  The latter would be rather fragile.

This patch replaces open coded SysV to MS calling convention
translation to GCC generated code (using __attribute__((ms_abi)) which
we have been using for a long time in EDK2), because the former relies
on a wrapper function

efi_call(fn, ...)

which is type unsafe and relies on a lot of nasty casting, especially
combined with the mixed mode support. efi_call() is implemented as
below, and as Hans reports, omitting this sequence causes a boot
regression on one of the platforms he has tested this on.

So the question is which of the pieces below this UEFI implementation
is actually relying on, and the stack pointer alignment is my first
guess, but it could be any of the other things as well. Once we
identify what it is we are missing, I can simply stick it back in, but
without reverting to using the efi_call() thunk.

Note that the decompressor/stub are built with the default stack
alignment of 16 afaict, but if GRUB enters the decompressor with a
misaligned stack, we probably wouldn't notice until we hit something
like a movaps, right?

Thanks,
Ard.



#define SAVE_XMM \
    mov %rsp, %rax; \
    subq $0x70, %rsp; \
    and $~0xf, %rsp; \
    mov %rax, (%rsp); \
    mov %cr0, %rax; \
    clts; \
    mov %rax, 0x8(%rsp); \
    movaps %xmm0, 0x60(%rsp); \
    movaps %xmm1, 0x50(%rsp); \
    movaps %xmm2, 0x40(%rsp); \
    movaps %xmm3, 0x30(%rsp); \
    movaps %xmm4, 0x20(%rsp); \
    movaps %xmm5, 0x10(%rsp)

#define RESTORE_XMM \
    movaps 0x60(%rsp), %xmm0; \
    movaps 0x50(%rsp), %xmm1; \
    movaps 0x40(%rsp), %xmm2; \
    movaps 0x30(%rsp), %xmm3; \
    movaps 0x20(%rsp), %xmm4; \
    movaps 0x10(%rsp), %xmm5; \
    mov 0x8(%rsp), %rsi; \
    mov %rsi, %cr0; \
    mov (%rsp), %rsp

SYM_FUNC_START(efi_call)
    pushq %rbp
    movq %rsp, %rbp
    SAVE_XMM
    mov 16(%rbp), %rax
    subq $48, %rsp
    mov %r9, 32(%rsp)
    mov %rax, 40(%rsp)
    mov %r8, %r9
    mov %rcx, %r8
    mov %rsi, %rcx
    call *%rdi
    addq $48, %rsp
    RESTORE_XMM
    popq %rbp
    ret
SYM_FUNC_END(efi_call)

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-22 15:29         ` Ard Biesheuvel
@ 2019-12-22 21:12           ` Arvind Sankar
  2019-12-22 21:25             ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2019-12-22 21:12 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Andy Lutomirski, Hans de Goede, Ard Biesheuvel, linux-efi,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner,
	Arvind Sankar

On Sun, Dec 22, 2019 at 04:29:48PM +0100, Ard Biesheuvel wrote:
> On Sun, 22 Dec 2019 at 13:46, Andy Lutomirski <luto@amacapital.net> wrote:
> >
> > Hmm. Most of the kernel is compiled with the stack alignment set to 8, and there a lot of asm that makes no effort to preserve alignment beyond 8 bytes.  So if EFI calls need 16 byte alignment, you may need to do something special.
> >
> > On new enough gcc (the versions that actually support the flags to set the alignment to 8), maybe you can use function attributes, or maybe you can stick a 16-byte-aligned local variable in functions that call EFI functions?  The latter would be rather fragile.
> 
> This patch replaces open coded SysV to MS calling convention
> translation to GCC generated code (using __attribute__((ms_abi)) which
> we have been using for a long time in EDK2), because the former relies
> on a wrapper function
> 
> efi_call(fn, ...)
> 
> which is type unsafe and relies on a lot of nasty casting, especially
> combined with the mixed mode support. efi_call() is implemented as
> below, and as Hans reports, omitting this sequence causes a boot
> regression on one of the platforms he has tested this on.
> 
> So the question is which of the pieces below this UEFI implementation
> is actually relying on, and the stack pointer alignment is my first
> guess, but it could be any of the other things as well. Once we
> identify what it is we are missing, I can simply stick it back in, but
> without reverting to using the efi_call() thunk.
> 
> Note that the decompressor/stub are built with the default stack
> alignment of 16 afaict, but if GRUB enters the decompressor with a
> misaligned stack, we probably wouldn't notice until we hit something
> like a movaps, right?
> 
> Thanks,
> Ard.
> 

Won't the entry code misalign the stack when efi_main is called,
assuming the stack was properly aligned at efi_stub_entry? There needs
to be a sub $8, %rsp in there, no?

arch/x86/boot/compressed/head_64.S:

#ifdef CONFIG_EFI_STUB
        .org 0x390
SYM_FUNC_START(efi64_stub_entry)
SYM_FUNC_START_ALIAS(efi_stub_entry)
        movq    $1, %rcx
handover_entry:
        call    efi_main	<--- this will enter efi_main with a misaligned stack?
        movq    %rax,%rsi
        movl    BP_code32_start(%esi), %eax
        leaq    startup_64(%rax), %rax
        jmp     *%rax
SYM_FUNC_END(efi64_stub_entry)
SYM_FUNC_END_ALIAS(efi_stub_entry)
#endif


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-22 21:12           ` Arvind Sankar
@ 2019-12-22 21:25             ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-22 21:25 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Andy Lutomirski, Hans de Goede, Ard Biesheuvel, linux-efi,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Sun, 22 Dec 2019 at 22:13, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Sun, Dec 22, 2019 at 04:29:48PM +0100, Ard Biesheuvel wrote:
> > On Sun, 22 Dec 2019 at 13:46, Andy Lutomirski <luto@amacapital.net> wrote:
> > >
> > > Hmm. Most of the kernel is compiled with the stack alignment set to 8, and there a lot of asm that makes no effort to preserve alignment beyond 8 bytes.  So if EFI calls need 16 byte alignment, you may need to do something special.
> > >
> > > On new enough gcc (the versions that actually support the flags to set the alignment to 8), maybe you can use function attributes, or maybe you can stick a 16-byte-aligned local variable in functions that call EFI functions?  The latter would be rather fragile.
> >
> > This patch replaces open coded SysV to MS calling convention
> > translation to GCC generated code (using __attribute__((ms_abi)) which
> > we have been using for a long time in EDK2), because the former relies
> > on a wrapper function
> >
> > efi_call(fn, ...)
> >
> > which is type unsafe and relies on a lot of nasty casting, especially
> > combined with the mixed mode support. efi_call() is implemented as
> > below, and as Hans reports, omitting this sequence causes a boot
> > regression on one of the platforms he has tested this on.
> >
> > So the question is which of the pieces below this UEFI implementation
> > is actually relying on, and the stack pointer alignment is my first
> > guess, but it could be any of the other things as well. Once we
> > identify what it is we are missing, I can simply stick it back in, but
> > without reverting to using the efi_call() thunk.
> >
> > Note that the decompressor/stub are built with the default stack
> > alignment of 16 afaict, but if GRUB enters the decompressor with a
> > misaligned stack, we probably wouldn't notice until we hit something
> > like a movaps, right?
> >
> > Thanks,
> > Ard.
> >
>
> Won't the entry code misalign the stack when efi_main is called,
> assuming the stack was properly aligned at efi_stub_entry? There needs
> to be a sub $8, %rsp in there, no?
>
> arch/x86/boot/compressed/head_64.S:
>
> #ifdef CONFIG_EFI_STUB
>         .org 0x390
> SYM_FUNC_START(efi64_stub_entry)
> SYM_FUNC_START_ALIAS(efi_stub_entry)
>         movq    $1, %rcx
> handover_entry:
>         call    efi_main        <--- this will enter efi_main with a misaligned stack?
>         movq    %rax,%rsi
>         movl    BP_code32_start(%esi), %eax
>         leaq    startup_64(%rax), %rax
>         jmp     *%rax
> SYM_FUNC_END(efi64_stub_entry)
> SYM_FUNC_END_ALIAS(efi_stub_entry)
> #endif
>

Indeed, well spotted. Note that the above is the version from the top
of that branch, but the version that Hans tested isn't any different.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-22 12:02     ` Ard Biesheuvel
  2019-12-22 12:37       ` Ard Biesheuvel
  2019-12-22 12:46       ` Andy Lutomirski
@ 2019-12-23 11:49       ` Hans de Goede
  2019-12-23 12:00         ` Ard Biesheuvel
  2 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2019-12-23 11:49 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Hi Ard,

On 22-12-2019 13:02, Ard Biesheuvel wrote:
> On Sat, 21 Dec 2019 at 22:22, Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi Ard,
>>
>> On 18-12-2019 18:01, Ard Biesheuvel wrote:
>>> We use special wrapper routines to invoke firmware services in the
>>> native case as well as the mixed mode case. For mixed mode, the need
>>> is obvious, but for the native cases, we can simply rely on the
>>> compiler to generate the indirect call, given that GCC now has
>>> support for the MS calling convention (and has had it for quite some
>>> time now). Note that on i386, the decompressor and the EFI stub are not
>>> built with -mregparm=3 like the rest of the i386 kernel, so we can
>>> safely allow the compiler to emit the indirect calls here as well.
>>>
>>> So drop all the wrappers and indirection, and switch to either native
>>> calls, or direct calls into the thunk routine for mixed mode.
>>>
>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>>
>> I'm afraid that this patch breaks the boot on one of my machines.
>>
>> Specifically this patch breaks my GDP pocket machine. This is a Cherry
>> Trail device with a 64 UEFI running a 64 bit kernel build.
>>
>> As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
>> tree, the GPD pocket stops booting and it stop so early on that I get 0
>> debug output. I guess I could try adding a few pr_efi_err calls
>> and see if those still do something.
>>
>> I noticed that you have made some changes to this patch, I've
>> tried updating it to the version from your efistub-x86-cleanup-v3
>> branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
>> and I have also cherry-picked the latest version of all preceding
>> commits, unfortunately even with the new version, the GPD pocket
>> still hangs at boot.
>>
>> Unfortunately the nature of this patch makes it hard to figure
>> out the root cause of this issue...
>>
>> I've also tried another Cherry Trail device with 64 bit UEFI and
>> that does not suffer from this problem.
>>
> 
> Thanks Hans.
> 
> There are a number of things that change in the way the calls are
> made, but the most obvious thing to check is whether the stack needs
> to be aligned, since that is no longer being done.
> 
> If you have time to experiment a bit more, could you check whether
> doing 'and $~0xf %rsp' before 'call efi_main' in the .S stub code for
> x86_64 makes a difference?

Ok, so I made this change on top of a37d90a2c570a25926fd1645482cb9f3c1d042a0
(the last "efi/libstub/x86: avoid thunking for native firmware calls" version
I tried before reporting this problem) :

--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -464,6 +464,7 @@ SYM_FUNC_START(efi_pe_entry)

  handover_entry:
         movq    efi_config(%rip), %rdi
+       and     $~0xf, %rsp
         call    efi_main
         movq    %rax,%rsi
         cmpq    $0,%rax

And that does the trick, the GPD pocket boots successfully with commit
a37d90a2c570a25926fd1645482cb9f3c1d042a0 + the above change.

So it looks like your first hunch on how to fix this is correct :)

Regards,

Hans


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
  2019-12-23 11:49       ` Hans de Goede
@ 2019-12-23 12:00         ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-23 12:00 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Mon, 23 Dec 2019 at 12:49, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi Ard,
>
> On 22-12-2019 13:02, Ard Biesheuvel wrote:
> > On Sat, 21 Dec 2019 at 22:22, Hans de Goede <hdegoede@redhat.com> wrote:
> >>
> >> Hi Ard,
> >>
> >> On 18-12-2019 18:01, Ard Biesheuvel wrote:
> >>> We use special wrapper routines to invoke firmware services in the
> >>> native case as well as the mixed mode case. For mixed mode, the need
> >>> is obvious, but for the native cases, we can simply rely on the
> >>> compiler to generate the indirect call, given that GCC now has
> >>> support for the MS calling convention (and has had it for quite some
> >>> time now). Note that on i386, the decompressor and the EFI stub are not
> >>> built with -mregparm=3 like the rest of the i386 kernel, so we can
> >>> safely allow the compiler to emit the indirect calls here as well.
> >>>
> >>> So drop all the wrappers and indirection, and switch to either native
> >>> calls, or direct calls into the thunk routine for mixed mode.
> >>>
> >>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >>
> >> I'm afraid that this patch breaks the boot on one of my machines.
> >>
> >> Specifically this patch breaks my GDP pocket machine. This is a Cherry
> >> Trail device with a 64 UEFI running a 64 bit kernel build.
> >>
> >> As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
> >> tree, the GPD pocket stops booting and it stop so early on that I get 0
> >> debug output. I guess I could try adding a few pr_efi_err calls
> >> and see if those still do something.
> >>
> >> I noticed that you have made some changes to this patch, I've
> >> tried updating it to the version from your efistub-x86-cleanup-v3
> >> branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
> >> and I have also cherry-picked the latest version of all preceding
> >> commits, unfortunately even with the new version, the GPD pocket
> >> still hangs at boot.
> >>
> >> Unfortunately the nature of this patch makes it hard to figure
> >> out the root cause of this issue...
> >>
> >> I've also tried another Cherry Trail device with 64 bit UEFI and
> >> that does not suffer from this problem.
> >>
> >
> > Thanks Hans.
> >
> > There are a number of things that change in the way the calls are
> > made, but the most obvious thing to check is whether the stack needs
> > to be aligned, since that is no longer being done.
> >
> > If you have time to experiment a bit more, could you check whether
> > doing 'and $~0xf %rsp' before 'call efi_main' in the .S stub code for
> > x86_64 makes a difference?
>
> Ok, so I made this change on top of a37d90a2c570a25926fd1645482cb9f3c1d042a0
> (the last "efi/libstub/x86: avoid thunking for native firmware calls" version
> I tried before reporting this problem) :
>
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -464,6 +464,7 @@ SYM_FUNC_START(efi_pe_entry)
>
>   handover_entry:
>          movq    efi_config(%rip), %rdi
> +       and     $~0xf, %rsp
>          call    efi_main
>          movq    %rax,%rsi
>          cmpq    $0,%rax
>
> And that does the trick, the GPD pocket boots successfully with commit
> a37d90a2c570a25926fd1645482cb9f3c1d042a0 + the above change.
>
> So it looks like your first hunch on how to fix this is correct :)
>

Excellent! Thanks for testing.

I'll fold this in.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-21 22:54             ` Arvind Sankar
@ 2019-12-23 14:02               ` Ard Biesheuvel
  2019-12-23 15:46                 ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-23 14:02 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Matthew Garrett, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Sat, 21 Dec 2019 at 23:54, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Sat, Dec 21, 2019 at 01:24:16PM -0800, Matthew Garrett wrote:
> > On Sat, Dec 21, 2019 at 8:44 AM Ard Biesheuvel
> > <ard.biesheuvel@linaro.org> wrote:
> > > Point taken. I like Arvind's suggestion but we need to take care not
> > > to disable the device producing the GOP. Beyond that, it should be
> > > possible to disable all devices that are behind PCI bridges. It does
> > > mean we need to decode the secondary/subordinate bus values from the
> > > config space and take them into account when iterating over the PCI
> > > handle list.
>
> Why do we need to look at the bus numbers? Shouldn't it be just looping
> and disabling everything that's a regular device in the first pass
> (possibly excluding devices that are producing GOP/UGA), and then going
> over it again to disable the bus-master settings on bridges?
>

Yeah, that would work I guess

> Also, why do we restrict the bus-master disable to only PCI/PCI bridges?
> Shouldn't we also disable bus-mastering on all the other PCI-xxx
> bridges?
>

Practically, on PCIe systems, PCI/PCI bridges are the only thing we
need to care about, since that is how PCIe root ports are modelled.


> >
> > The device producing the GOP is the device that I'm most afraid of, to
> > be honest.I'd naively expect that anything presenting a linear
> > framebuffer will probably leave it up at disconnect time, and we're
> > definitely not using DMA to access that framebuffer.
>
> At least on my system, disconnecting the GOP device does leave the
> display up, and the framebuffer remains active (ie writing to it updates
> the display). It wouldn't be surprising if this doesn't work for all
> GPUs though.
>

Disconnecting a device should result in the protocols installed by the
driver to be removed again, and this also applies to the GOP protocol.
Whether or not the framebuffer is still live after that point is not
entirely relevant.

But if the GOP it produces is not BltOnly and its framebuffer address
doesn't intersect system memory, it should be safe to disable DMA on
such devices.

So in summary, we'll need to do

for each PCI I/O handle {
  if (bus == 0 || // not behind a bridge
      type == bridge)
    ignore;
  else
    disconnect();
}

for each PCI I/O handle {
  if (type == bridge)
    disable BM bit;
}

Disregarding bus 0 means all the 'special' devices integrated into the
root complex are disregarded as well, which seems safer to me.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-23 14:02               ` Ard Biesheuvel
@ 2019-12-23 15:46                 ` Arvind Sankar
  2019-12-23 15:58                   ` Ard Biesheuvel
  2019-12-23 20:57                   ` Matthew Garrett
  0 siblings, 2 replies; 87+ messages in thread
From: Arvind Sankar @ 2019-12-23 15:46 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Matthew Garrett, Ard Biesheuvel, linux-efi,
	Hans de Goede, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Mon, Dec 23, 2019 at 03:02:40PM +0100, Ard Biesheuvel wrote:
> 
> Practically, on PCIe systems, PCI/PCI bridges are the only thing we
> need to care about, since that is how PCIe root ports are modelled.

If I'm interpreting my lspci output correctly, I have a PCI/ISA bridge
on bus 0 that's not behind a PCI/PCI bridge. Device 1f.0 below is the
PCI/ISA bridge. Devices 1-3 are the CPU root ports and 1c.* are the
chipset root ports.

Also, what about for eg, the USB or SATA controllers? I know that
someone had said earlier that disabling BM on endpoints is pointless as
malicious endpoints could just re-enable it, but is it not possible for
malicious USB devices/SATA devices to try to use DMA through those
controllers? ie if we trust the controllers since they're on-board, but
not necessarily the devices behind them, wouldn't it still be worth it
to disable BM on the controllers too?

$ lspci -tv -s 0:0:
-[0000:00]-+-00.0  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2
           +-01.0-[01]--
           +-01.1-[02]--
           +-02.0-[03]--
           +-02.2-[04]--
           +-03.0-[05]--
           +-03.2-[06-09]--
           +-05.0  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management
           +-05.1  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug
           +-05.2  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors
           +-05.4  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC
           +-11.0  Intel Corporation C610/X99 series chipset SPSR
           +-11.4  Intel Corporation C610/X99 series chipset sSATA Controller [AHCI mode]
           +-14.0  Intel Corporation C610/X99 series chipset USB xHCI Host Controller
           +-16.0  Intel Corporation C610/X99 series chipset MEI Controller #1
           +-16.1  Intel Corporation C610/X99 series chipset MEI Controller #2
           +-1a.0  Intel Corporation C610/X99 series chipset USB Enhanced Host Controller #2
           +-1b.0  Intel Corporation C610/X99 series chipset HD Audio Controller
           +-1c.0-[0a]--
           +-1c.2-[0b]--
           +-1c.3-[0c]--
           +-1c.4-[0d]--
           +-1c.7-[0e-0f]--
           +-1d.0  Intel Corporation C610/X99 series chipset USB Enhanced Host Controller #1
           +-1f.0  Intel Corporation C610/X99 series chipset LPC Controller
           +-1f.2  Intel Corporation C610/X99 series chipset 6-Port SATA Controller [AHCI mode]
           \-1f.3  Intel Corporation C610/X99 series chipset SMBus Controller


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-23 15:46                 ` Arvind Sankar
@ 2019-12-23 15:58                   ` Ard Biesheuvel
  2019-12-23 16:12                     ` Arvind Sankar
  2019-12-23 20:57                   ` Matthew Garrett
  1 sibling, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-23 15:58 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Matthew Garrett, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Mon, 23 Dec 2019 at 16:46, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Mon, Dec 23, 2019 at 03:02:40PM +0100, Ard Biesheuvel wrote:
> >
> > Practically, on PCIe systems, PCI/PCI bridges are the only thing we
> > need to care about, since that is how PCIe root ports are modelled.
>
> If I'm interpreting my lspci output correctly, I have a PCI/ISA bridge
> on bus 0 that's not behind a PCI/PCI bridge. Device 1f.0 below is the
> PCI/ISA bridge.

Yeah, this is the LPC controller, right? What devices are actually on
that bus that are not closely tied to the chipset?

> Devices 1-3 are the CPU root ports and 1c.* are the
> chipset root ports.
>

Right.

> Also, what about for eg, the USB or SATA controllers? I know that
> someone had said earlier that disabling BM on endpoints is pointless as
> malicious endpoints could just re-enable it, but is it not possible for
> malicious USB devices/SATA devices to try to use DMA through those
> controllers? ie if we trust the controllers since they're on-board, but
> not necessarily the devices behind them, wouldn't it still be worth it
> to disable BM on the controllers too?
>

At this point, it probably makes sense to clarify what the threat
model is. I have been assuming (but Matthew should confirm) that we're
primarily concerned with DMA attacks over, e.g., Thunderbolt ports, in
which case managing the BM bit at the root port level should be
sufficient.

If there are other things we want to address (or if my assumption was
incorrect), we should clarify this first, before deciding what the
right mitigation would be.

> $ lspci -tv -s 0:0:
> -[0000:00]-+-00.0  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2
>            +-01.0-[01]--
>            +-01.1-[02]--
>            +-02.0-[03]--
>            +-02.2-[04]--
>            +-03.0-[05]--
>            +-03.2-[06-09]--
>            +-05.0  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management
>            +-05.1  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug
>            +-05.2  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors
>            +-05.4  Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC
>            +-11.0  Intel Corporation C610/X99 series chipset SPSR
>            +-11.4  Intel Corporation C610/X99 series chipset sSATA Controller [AHCI mode]
>            +-14.0  Intel Corporation C610/X99 series chipset USB xHCI Host Controller
>            +-16.0  Intel Corporation C610/X99 series chipset MEI Controller #1
>            +-16.1  Intel Corporation C610/X99 series chipset MEI Controller #2
>            +-1a.0  Intel Corporation C610/X99 series chipset USB Enhanced Host Controller #2
>            +-1b.0  Intel Corporation C610/X99 series chipset HD Audio Controller
>            +-1c.0-[0a]--
>            +-1c.2-[0b]--
>            +-1c.3-[0c]--
>            +-1c.4-[0d]--
>            +-1c.7-[0e-0f]--
>            +-1d.0  Intel Corporation C610/X99 series chipset USB Enhanced Host Controller #1
>            +-1f.0  Intel Corporation C610/X99 series chipset LPC Controller
>            +-1f.2  Intel Corporation C610/X99 series chipset 6-Port SATA Controller [AHCI mode]
>            \-1f.3  Intel Corporation C610/X99 series chipset SMBus Controller
>

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-23 15:58                   ` Ard Biesheuvel
@ 2019-12-23 16:12                     ` Arvind Sankar
  0 siblings, 0 replies; 87+ messages in thread
From: Arvind Sankar @ 2019-12-23 16:12 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Matthew Garrett, Ard Biesheuvel, linux-efi,
	Hans de Goede, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Mon, Dec 23, 2019 at 04:58:26PM +0100, Ard Biesheuvel wrote:
> On Mon, 23 Dec 2019 at 16:46, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Mon, Dec 23, 2019 at 03:02:40PM +0100, Ard Biesheuvel wrote:
> > >
> > > Practically, on PCIe systems, PCI/PCI bridges are the only thing we
> > > need to care about, since that is how PCIe root ports are modelled.
> >
> > If I'm interpreting my lspci output correctly, I have a PCI/ISA bridge
> > on bus 0 that's not behind a PCI/PCI bridge. Device 1f.0 below is the
> > PCI/ISA bridge.
> 
> Yeah, this is the LPC controller, right? What devices are actually on
> that bus that are not closely tied to the chipset?
> 

AFAICT it's my BMC's IPMI interface and some sort of watchdog I think --
don't have drivers but there are three other ACPI PNP* nodes under there
as well.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-23 15:46                 ` Arvind Sankar
  2019-12-23 15:58                   ` Ard Biesheuvel
@ 2019-12-23 20:57                   ` Matthew Garrett
  1 sibling, 0 replies; 87+ messages in thread
From: Matthew Garrett @ 2019-12-23 20:57 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, Ard Biesheuvel, linux-efi, Hans de Goede,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Mon, Dec 23, 2019 at 7:46 AM Arvind Sankar <nivedita@alum.mit.edu> wrote:
> Also, what about for eg, the USB or SATA controllers? I know that
> someone had said earlier that disabling BM on endpoints is pointless as
> malicious endpoints could just re-enable it, but is it not possible for
> malicious USB devices/SATA devices to try to use DMA through those
> controllers? ie if we trust the controllers since they're on-board, but
> not necessarily the devices behind them, wouldn't it still be worth it
> to disable BM on the controllers too?

The concern is DMA initiated by a hostile device. SATA and USB don't
permit the devices themselves to initiate DMA, whereas PCI does.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-18 17:01 ` [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct Ard Biesheuvel
@ 2019-12-24 19:34   ` Hans de Goede
  2019-12-25 14:42     ` Ard Biesheuvel
  2019-12-31 23:04   ` Arvind Sankar
  1 sibling, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2019-12-24 19:34 UTC (permalink / raw)
  To: Ard Biesheuvel, linux-efi
  Cc: Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner,
	Arvind Sankar

Hi Ard,

On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> The various pointers we stash in the efi_config struct which we
> retrieve using __efi_early() are simply copies of the ones in
> the EFI system table, which we have started accessing directly
> in the previous patch. So drop all the __efi_early() related
> plumbing, except for the access to a boolean which tells us
> whether the firmware is 64-bit or not.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

I synced my personal tree yesterday to 5.5-rc3 + the most
recent version (as of yesterday afternoon) of your
efistub-x86-cleanup-v3 branch on top.

This has been working fine on a bunch of devices, but it fails
on a Teclast X89 Bay Trail (mixed mode) device. When reverting all
the commits from your efistub-x86-cleanup-v3 branch one by one, things
start working again after reverting this one.

Regards,

Hans


> ---
>   arch/x86/boot/compressed/eboot.c   | 36 ++++++++------------
>   arch/x86/boot/compressed/head_32.S |  2 +-
>   arch/x86/boot/compressed/head_64.S |  4 +--
>   arch/x86/include/asm/efi.h         | 23 +++++--------
>   4 files changed, 26 insertions(+), 39 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
> index 2bcab1ef5a56..53e67334c4c3 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -20,11 +20,17 @@
>   
>   static efi_system_table_t *sys_table;
>   
> -static struct efi_config *efi_early;
> +struct efi_config {
> +	u64 image_handle;
> +	u64 table;
> +	bool is64;
> +} __packed;
>   
> -__pure const struct efi_config *__efi_early(void)
> +static bool is64;
> +
> +__pure bool __efi_early_is64(void)
>   {
> -	return efi_early;
> +	return is64;
>   }
>   
>   __pure efi_system_table_t *efi_system_table(void)
> @@ -32,13 +38,6 @@ __pure efi_system_table_t *efi_system_table(void)
>   	return sys_table;
>   }
>   
> -static void setup_boot_services(struct efi_config *c)
> -{
> -	c->runtime_services	= efi_table_attr(efi_system_table, runtime, sys_table);
> -	c->boot_services	= efi_table_attr(efi_system_table, boottime, sys_table);
> -	c->text_output		= efi_table_attr(efi_system_table, con_out, sys_table);
> -}
> -
>   static efi_status_t
>   preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
>   {
> @@ -382,16 +381,14 @@ struct boot_params *make_boot_params(struct efi_config *c)
>   	unsigned long ramdisk_addr;
>   	unsigned long ramdisk_size;
>   
> -	efi_early = c;
> -	sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
> -	handle = (void *)(unsigned long)efi_early->image_handle;
> +	sys_table = (efi_system_table_t *)(unsigned long)c->table;
> +	handle = (void *)(unsigned long)c->image_handle;
> +	is64 = c->is64;
>   
>   	/* Check if we were booted by the EFI firmware */
>   	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
>   		return NULL;
>   
> -	setup_boot_services(efi_early);
> -
>   	status = efi_call_early(handle_protocol, handle,
>   				&proto, (void *)&image);
>   	if (status != EFI_SUCCESS) {
> @@ -738,10 +735,9 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
>   	efi_system_table_t *_table;
>   	unsigned long cmdline_paddr;
>   
> -	efi_early = c;
> -
> -	_table = (efi_system_table_t *)(unsigned long)efi_early->table;
> -	handle = (void *)(unsigned long)efi_early->image_handle;
> +	_table = (efi_system_table_t *)(unsigned long)c->table;
> +	handle = (void *)(unsigned long)c->image_handle;
> +	is64 = c->is64;
>   
>   	sys_table = _table;
>   
> @@ -749,8 +745,6 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
>   	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
>   		goto fail;
>   
> -	setup_boot_services(efi_early);
> -
>   	/*
>   	 * make_boot_params() may have been called before efi_main(), in which
>   	 * case this is the second time we parse the cmdline. This is ok,
> diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
> index 7da4dfc53df6..c026ab881405 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -261,7 +261,7 @@ SYM_FUNC_END(.Lrelocated)
>   #ifdef CONFIG_EFI_STUB
>   	.data
>   efi32_config:
> -	.fill 7,4,0
> +	.fill 4,4,0
>   	.byte 0
>   #endif
>   
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index 6dc6a7ebb9e1..72065735abc1 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -672,13 +672,13 @@ SYM_DATA_LOCAL(efi_config, .quad 0)
>   
>   #ifdef CONFIG_EFI_MIXED
>   SYM_DATA_START(efi32_config)
> -	.fill	5,8,0
> +	.fill	2,8,0
>   	.byte	0
>   SYM_DATA_END(efi32_config)
>   #endif
>   
>   SYM_DATA_START(efi64_config)
> -	.fill	5,8,0
> +	.fill	2,8,0
>   	.byte	1
>   SYM_DATA_END(efi64_config)
>   #endif /* CONFIG_EFI_STUB */
> diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
> index e0789ec5c9f6..8137d4f5c104 100644
> --- a/arch/x86/include/asm/efi.h
> +++ b/arch/x86/include/asm/efi.h
> @@ -200,16 +200,7 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
>   
>   /* arch specific definitions used by the stub code */
>   
> -struct efi_config {
> -	u64 image_handle;
> -	u64 table;
> -	efi_runtime_services_t *runtime_services;
> -	efi_boot_services_t *boot_services;
> -	efi_simple_text_output_protocol_t *text_output;
> -	bool is64;
> -} __packed;
> -
> -__pure const struct efi_config *__efi_early(void);
> +__pure bool __efi_early_is64(void);
>   
>   static inline bool efi_is_64bit(void)
>   {
> @@ -219,7 +210,7 @@ static inline bool efi_is_64bit(void)
>   	if (!IS_ENABLED(CONFIG_EFI_MIXED))
>   		return true;
>   
> -	return __efi_early()->is64;
> +	return __efi_early_is64();
>   }
>   
>   static inline bool efi_is_native(void)
> @@ -252,14 +243,16 @@ static inline bool efi_is_native(void)
>   
>   #define efi_call_early(f, ...)						\
>   	(efi_is_native()						\
> -		? __efi_early()->boot_services->f(__VA_ARGS__)		\
> -		: efi64_thunk(__efi_early()->boot_services->mixed_mode.f,\
> +		? efi_system_table()->boottime->f(__VA_ARGS__)		\
> +		: efi64_thunk(efi_table_attr(efi_boot_services,		\
> +			boottime, efi_system_table())->mixed_mode.f,	\
>   			__VA_ARGS__))
>   
>   #define efi_call_runtime(f, ...)					\
>   	(efi_is_native()						\
> -		? __efi_early()->runtime_services->f(__VA_ARGS__)	\
> -		: efi64_thunk(__efi_early()->runtime_services->mixed_mode.f,\
> +		? efi_system_table()->runtime->f(__VA_ARGS__)		\
> +		: efi64_thunk(efi_table_attr(efi_runtime_services,	\
> +			runtime, efi_system_table())->mixed_mode.f,	\
>   			__VA_ARGS__))
>   
>   extern bool efi_reboot_required(void);
> 


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-24 19:34   ` Hans de Goede
@ 2019-12-25 14:42     ` Ard Biesheuvel
  2019-12-27 22:44       ` Hans de Goede
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-25 14:42 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Tue, 24 Dec 2019 at 20:34, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi Ard,
>
> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> > The various pointers we stash in the efi_config struct which we
> > retrieve using __efi_early() are simply copies of the ones in
> > the EFI system table, which we have started accessing directly
> > in the previous patch. So drop all the __efi_early() related
> > plumbing, except for the access to a boolean which tells us
> > whether the firmware is 64-bit or not.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> I synced my personal tree yesterday to 5.5-rc3 + the most
> recent version (as of yesterday afternoon) of your
> efistub-x86-cleanup-v3 branch on top.
>
> This has been working fine on a bunch of devices, but it fails
> on a Teclast X89 Bay Trail (mixed mode) device. When reverting all
> the commits from your efistub-x86-cleanup-v3 branch one by one, things
> start working again after reverting this one.
>

Oops again. And thanks again for taking the time to test this stuff.

Could you please try the branch below and check whether it fixes it?

https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-core-mm-fix

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-25 14:42     ` Ard Biesheuvel
@ 2019-12-27 22:44       ` Hans de Goede
  2019-12-27 22:51         ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2019-12-27 22:44 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

Hi,

On 25-12-2019 15:42, Ard Biesheuvel wrote:
> On Tue, 24 Dec 2019 at 20:34, Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi Ard,
>>
>> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
>>> The various pointers we stash in the efi_config struct which we
>>> retrieve using __efi_early() are simply copies of the ones in
>>> the EFI system table, which we have started accessing directly
>>> in the previous patch. So drop all the __efi_early() related
>>> plumbing, except for the access to a boolean which tells us
>>> whether the firmware is 64-bit or not.
>>>
>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>>
>> I synced my personal tree yesterday to 5.5-rc3 + the most
>> recent version (as of yesterday afternoon) of your
>> efistub-x86-cleanup-v3 branch on top.
>>
>> This has been working fine on a bunch of devices, but it fails
>> on a Teclast X89 Bay Trail (mixed mode) device. When reverting all
>> the commits from your efistub-x86-cleanup-v3 branch one by one, things
>> start working again after reverting this one.
>>
> 
> Oops again. And thanks again for taking the time to test this stuff.
> 
> Could you please try the branch below and check whether it fixes it?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-core-mm-fix

This seems to fix the issue, the Teclast X89 boots again and I've
also tested this on 2 other devices (one mixed mode Bay Trail one 64 bit
Cherry Trail device).

If I want to also test them, how do the 2 new series you've just posted come
into the mix here? :

"[PATCH 0/3] efi/x86: clean up and simplify runtime call wrappers"
"[PATCH 0/3] efi/x86: righten memory protections at runtime"

Regards,

Hans


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-27 22:44       ` Hans de Goede
@ 2019-12-27 22:51         ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-27 22:51 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Fri, 27 Dec 2019 at 23:44, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 25-12-2019 15:42, Ard Biesheuvel wrote:
> > On Tue, 24 Dec 2019 at 20:34, Hans de Goede <hdegoede@redhat.com> wrote:
> >>
> >> Hi Ard,
> >>
> >> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> >>> The various pointers we stash in the efi_config struct which we
> >>> retrieve using __efi_early() are simply copies of the ones in
> >>> the EFI system table, which we have started accessing directly
> >>> in the previous patch. So drop all the __efi_early() related
> >>> plumbing, except for the access to a boolean which tells us
> >>> whether the firmware is 64-bit or not.
> >>>
> >>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >>
> >> I synced my personal tree yesterday to 5.5-rc3 + the most
> >> recent version (as of yesterday afternoon) of your
> >> efistub-x86-cleanup-v3 branch on top.
> >>
> >> This has been working fine on a bunch of devices, but it fails
> >> on a Teclast X89 Bay Trail (mixed mode) device. When reverting all
> >> the commits from your efistub-x86-cleanup-v3 branch one by one, things
> >> start working again after reverting this one.
> >>
> >
> > Oops again. And thanks again for taking the time to test this stuff.
> >
> > Could you please try the branch below and check whether it fixes it?
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-core-mm-fix
>
> This seems to fix the issue, the Teclast X89 boots again and I've
> also tested this on 2 other devices (one mixed mode Bay Trail one 64 bit
> Cherry Trail device).
>

Great, thanks.

> If I want to also test them, how do the 2 new series you've just posted come
> into the mix here? :
>
> "[PATCH 0/3] efi/x86: clean up and simplify runtime call wrappers"
> "[PATCH 0/3] efi/x86: righten memory protections at runtime"
>

I have accumulated a couple of more fixes in addition, and a patch
that I haven't sent out yet.
Easiest to grab them from

https://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git/log/?h=next

-- 
Ard.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter
  2019-12-18 17:01 ` [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter Ard Biesheuvel
@ 2019-12-31 16:51   ` Arvind Sankar
  2019-12-31 17:06     ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2019-12-31 16:51 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Wed, Dec 18, 2019 at 07:01:36PM +0200, Ard Biesheuvel wrote:
> Use 'func' as the macro parameter name for the efi_call() macros
> which is less likely to collide and cause weird build errors.
> 

For my education, what are the possible collisions/build errors that might happen?

Thanks

> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/arm64/include/asm/efi.h |  4 ++--
>  arch/x86/include/asm/efi.h   | 12 ++++++------
>  2 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
> index 6f041ae446d2..d06305590ac5 100644
> --- a/arch/arm64/include/asm/efi.h
> +++ b/arch/arm64/include/asm/efi.h
> @@ -93,8 +93,8 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
>  	return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
>  }
>  
> -#define efi_call_early(f, ...)		efi_system_table()->boottime->f(__VA_ARGS__)
> -#define efi_call_runtime(f, ...)	efi_system_table()->runtime->f(__VA_ARGS__)
> +#define efi_call_early(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
> +#define efi_call_runtime(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
>  #define efi_is_native()			(true)
>  
>  #define efi_table_attr(inst, attr)	(inst->attr)
> diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
> index 593a8cda8361..ba3f8a98e156 100644
> --- a/arch/x86/include/asm/efi.h
> +++ b/arch/x86/include/asm/efi.h
> @@ -236,17 +236,17 @@ static inline bool efi_is_native(void)
>  		? inst->func(inst, ##__VA_ARGS__)			\
>  		: efi64_thunk(inst->mixed_mode.func, inst, ##__VA_ARGS__))
>  
> -#define efi_call_early(f, ...)						\
> +#define efi_call_early(func, ...)					\
>  	(efi_is_native()						\
> -		? efi_system_table()->boottime->f(__VA_ARGS__)		\
> +		? efi_system_table()->boottime->func(__VA_ARGS__)	\
>  		: efi64_thunk(efi_table_attr(efi_system_table(),	\
> -				boottime)->mixed_mode.f, __VA_ARGS__))
> +				boottime)->mixed_mode.func, __VA_ARGS__))
>  
> -#define efi_call_runtime(f, ...)					\
> +#define efi_call_runtime(func, ...)					\
>  	(efi_is_native()						\
> -		? efi_system_table()->runtime->f(__VA_ARGS__)		\
> +		? efi_system_table()->runtime->func(__VA_ARGS__)	\
>  		: efi64_thunk(efi_table_attr(efi_system_table(),	\
> -				runtime)->mixed_mode.f, __VA_ARGS__))
> +				runtime)->mixed_mode.func, __VA_ARGS__))
>  
>  extern bool efi_reboot_required(void);
>  extern bool efi_is_table_address(unsigned long phys_addr);
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter
  2019-12-31 16:51   ` Arvind Sankar
@ 2019-12-31 17:06     ` Ard Biesheuvel
  2019-12-31 17:36       ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2019-12-31 17:06 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Tue, 31 Dec 2019 at 17:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Wed, Dec 18, 2019 at 07:01:36PM +0200, Ard Biesheuvel wrote:
> > Use 'func' as the macro parameter name for the efi_call() macros
> > which is less likely to collide and cause weird build errors.
> >
>
> For my education, what are the possible collisions/build errors that might happen?
>

I was concerned about variables called 'f' being passed as one of the
arguments, but now that I think of it, I'm not sure how that could
break.

In any case, I'd like to keep this patch since it also increases legibility.

> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > ---
> >  arch/arm64/include/asm/efi.h |  4 ++--
> >  arch/x86/include/asm/efi.h   | 12 ++++++------
> >  2 files changed, 8 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
> > index 6f041ae446d2..d06305590ac5 100644
> > --- a/arch/arm64/include/asm/efi.h
> > +++ b/arch/arm64/include/asm/efi.h
> > @@ -93,8 +93,8 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
> >       return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
> >  }
> >
> > -#define efi_call_early(f, ...)               efi_system_table()->boottime->f(__VA_ARGS__)
> > -#define efi_call_runtime(f, ...)     efi_system_table()->runtime->f(__VA_ARGS__)
> > +#define efi_call_early(func, ...)    efi_system_table()->boottime->func(__VA_ARGS__)
> > +#define efi_call_runtime(func, ...)  efi_system_table()->runtime->func(__VA_ARGS__)
> >  #define efi_is_native()                      (true)
> >
> >  #define efi_table_attr(inst, attr)   (inst->attr)
> > diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
> > index 593a8cda8361..ba3f8a98e156 100644
> > --- a/arch/x86/include/asm/efi.h
> > +++ b/arch/x86/include/asm/efi.h
> > @@ -236,17 +236,17 @@ static inline bool efi_is_native(void)
> >               ? inst->func(inst, ##__VA_ARGS__)                       \
> >               : efi64_thunk(inst->mixed_mode.func, inst, ##__VA_ARGS__))
> >
> > -#define efi_call_early(f, ...)                                               \
> > +#define efi_call_early(func, ...)                                    \
> >       (efi_is_native()                                                \
> > -             ? efi_system_table()->boottime->f(__VA_ARGS__)          \
> > +             ? efi_system_table()->boottime->func(__VA_ARGS__)       \
> >               : efi64_thunk(efi_table_attr(efi_system_table(),        \
> > -                             boottime)->mixed_mode.f, __VA_ARGS__))
> > +                             boottime)->mixed_mode.func, __VA_ARGS__))
> >
> > -#define efi_call_runtime(f, ...)                                     \
> > +#define efi_call_runtime(func, ...)                                  \
> >       (efi_is_native()                                                \
> > -             ? efi_system_table()->runtime->f(__VA_ARGS__)           \
> > +             ? efi_system_table()->runtime->func(__VA_ARGS__)        \
> >               : efi64_thunk(efi_table_attr(efi_system_table(),        \
> > -                             runtime)->mixed_mode.f, __VA_ARGS__))
> > +                             runtime)->mixed_mode.func, __VA_ARGS__))
> >
> >  extern bool efi_reboot_required(void);
> >  extern bool efi_is_table_address(unsigned long phys_addr);
> > --
> > 2.17.1
> >

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter
  2019-12-31 17:06     ` Ard Biesheuvel
@ 2019-12-31 17:36       ` Arvind Sankar
  0 siblings, 0 replies; 87+ messages in thread
From: Arvind Sankar @ 2019-12-31 17:36 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Tue, Dec 31, 2019 at 06:06:33PM +0100, Ard Biesheuvel wrote:
> On Tue, 31 Dec 2019 at 17:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Wed, Dec 18, 2019 at 07:01:36PM +0200, Ard Biesheuvel wrote:
> > > Use 'func' as the macro parameter name for the efi_call() macros
> > > which is less likely to collide and cause weird build errors.
> > >
> >
> > For my education, what are the possible collisions/build errors that might happen?
> >
> 
> I was concerned about variables called 'f' being passed as one of the
> arguments, but now that I think of it, I'm not sure how that could
> break.
> 
> In any case, I'd like to keep this patch since it also increases legibility.
> 

No objections to the patch, I just wanted to check if I was missing
something. Probably update the commit message though.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-18 17:01 ` [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct Ard Biesheuvel
  2019-12-24 19:34   ` Hans de Goede
@ 2019-12-31 23:04   ` Arvind Sankar
  2020-01-01 18:13     ` Ard Biesheuvel
  1 sibling, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2019-12-31 23:04 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, Hans de Goede, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar

On Wed, Dec 18, 2019 at 07:01:31PM +0200, Ard Biesheuvel wrote:
> The various pointers we stash in the efi_config struct which we
> retrieve using __efi_early() are simply copies of the ones in
> the EFI system table, which we have started accessing directly
> in the previous patch. So drop all the __efi_early() related
> plumbing, except for the access to a boolean which tells us
> whether the firmware is 64-bit or not.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/x86/boot/compressed/eboot.c   | 36 ++++++++------------
>  arch/x86/boot/compressed/head_32.S |  2 +-
>  arch/x86/boot/compressed/head_64.S |  4 +--
>  arch/x86/include/asm/efi.h         | 23 +++++--------
>  4 files changed, 26 insertions(+), 39 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
> index 2bcab1ef5a56..53e67334c4c3 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -20,11 +20,17 @@
>  
>  static efi_system_table_t *sys_table;
>  
> -static struct efi_config *efi_early;
> +struct efi_config {
> +	u64 image_handle;
> +	u64 table;
> +	bool is64;
> +} __packed;
>  
> -__pure const struct efi_config *__efi_early(void)
> +static bool is64;
> +
> +__pure bool __efi_early_is64(void)
>  {
> -	return efi_early;
> +	return is64;
>  }
>  
>  __pure efi_system_table_t *efi_system_table(void)

This predates your series, but looking at the generated code I noticed
that pure isn't enough to let gcc optimize out repeated calls to is64
and system_table. Declaring them as __attribute_const__ would allow
optimization. They don't quite meet gcc's requirements for that as they
access global non-const variables, but it seems like it ought to be
safe, especially if we stop using the functions within eboot.c itself?

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2019-12-31 23:04   ` Arvind Sankar
@ 2020-01-01 18:13     ` Ard Biesheuvel
  2020-01-01 19:08       ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-01 18:13 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Wed, 1 Jan 2020 at 00:04, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Wed, Dec 18, 2019 at 07:01:31PM +0200, Ard Biesheuvel wrote:
> > The various pointers we stash in the efi_config struct which we
> > retrieve using __efi_early() are simply copies of the ones in
> > the EFI system table, which we have started accessing directly
> > in the previous patch. So drop all the __efi_early() related
> > plumbing, except for the access to a boolean which tells us
> > whether the firmware is 64-bit or not.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > ---
> >  arch/x86/boot/compressed/eboot.c   | 36 ++++++++------------
> >  arch/x86/boot/compressed/head_32.S |  2 +-
> >  arch/x86/boot/compressed/head_64.S |  4 +--
> >  arch/x86/include/asm/efi.h         | 23 +++++--------
> >  4 files changed, 26 insertions(+), 39 deletions(-)
> >
> > diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
> > index 2bcab1ef5a56..53e67334c4c3 100644
> > --- a/arch/x86/boot/compressed/eboot.c
> > +++ b/arch/x86/boot/compressed/eboot.c
> > @@ -20,11 +20,17 @@
> >
> >  static efi_system_table_t *sys_table;
> >
> > -static struct efi_config *efi_early;
> > +struct efi_config {
> > +     u64 image_handle;
> > +     u64 table;
> > +     bool is64;
> > +} __packed;
> >
> > -__pure const struct efi_config *__efi_early(void)
> > +static bool is64;
> > +
> > +__pure bool __efi_early_is64(void)
> >  {
> > -     return efi_early;
> > +     return is64;
> >  }
> >
> >  __pure efi_system_table_t *efi_system_table(void)
>
> This predates your series, but looking at the generated code I noticed
> that pure isn't enough to let gcc optimize out repeated calls to is64
> and system_table. Declaring them as __attribute_const__ would allow
> optimization. They don't quite meet gcc's requirements for that as they
> access global non-const variables, but it seems like it ought to be
> safe, especially if we stop using the functions within eboot.c itself?

The GCC documentation mentions that it does not make sense for a
function annotated as const not to take any arguments, so I'd rather
avoid it here.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-01 18:13     ` Ard Biesheuvel
@ 2020-01-01 19:08       ` Arvind Sankar
  2020-01-02  7:33         ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-01 19:08 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Wed, Jan 01, 2020 at 07:13:45PM +0100, Ard Biesheuvel wrote:
> The GCC documentation mentions that it does not make sense for a
> function annotated as const not to take any arguments, so I'd rather
> avoid it here.

Where does it say that? I only see it saying it doesn't make sense for
it to return void.

Currently if we call 5 EFI services in the same function, it has to
re-evaluate systemtable and is64 for each call, which seems wasteful,
though of course this is not exactly performance-critical code.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-01 19:08       ` Arvind Sankar
@ 2020-01-02  7:33         ` Ard Biesheuvel
  2020-01-02 14:06           ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02  7:33 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Wed, 1 Jan 2020 at 20:08, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Wed, Jan 01, 2020 at 07:13:45PM +0100, Ard Biesheuvel wrote:
> > The GCC documentation mentions that it does not make sense for a
> > function annotated as const not to take any arguments, so I'd rather
> > avoid it here.
>
> Where does it say that? I only see it saying it doesn't make sense for
> it to return void.
>

You're right. I looked into this in the past, and I misremembered, and
paraphrased it incorrectly.

The documentation does mention that const functions are not permitted
to read global memory.

> Currently if we call 5 EFI services in the same function, it has to
> re-evaluate systemtable and is64 for each call, which seems wasteful,
> though of course this is not exactly performance-critical code.

The alternative would be to use globals with external linkage in a way
that is guaranteed not to rely on GOT entries, since we'll end up with
absolute addresses that need to be fixed up first. This has caused
breakage in the past, and is the reason we use this scheme with
globals with static linkage and __pure getters.

However, hidden visibility should yield the same results so we should
be able to make it work with that instead. However, given the breakage
in the past, I don't think it's worth it since the performance gain
will be negligible.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02  7:33         ` Ard Biesheuvel
@ 2020-01-02 14:06           ` Arvind Sankar
  2020-01-02 15:20             ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 14:06 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 08:33:54AM +0100, Ard Biesheuvel wrote:
> On Wed, 1 Jan 2020 at 20:08, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Wed, Jan 01, 2020 at 07:13:45PM +0100, Ard Biesheuvel wrote:
> > > The GCC documentation mentions that it does not make sense for a
> > > function annotated as const not to take any arguments, so I'd rather
> > > avoid it here.
> >
> > Where does it say that? I only see it saying it doesn't make sense for
> > it to return void.
> >
> 
> You're right. I looked into this in the past, and I misremembered, and
> paraphrased it incorrectly.
> 
> The documentation does mention that const functions are not permitted
> to read global memory.
> 

What it says is that "[the const attribute] tells GCC that subsequent
calls to function square with the same argument value can be replaced by
the result of the first call regardless of the statements in between"
and "The const attribute prohibits a function from reading objects that
affect its return value between successive invocations. However,
functions declared with the attribute can safely read objects that do
not change their return value, such as non-volatile constants."

In this case since the globals in question never change after being set,
it should be safe -- every call to these functions does return the same
value.

> > Currently if we call 5 EFI services in the same function, it has to
> > re-evaluate systemtable and is64 for each call, which seems wasteful,
> > though of course this is not exactly performance-critical code.
> 
> The alternative would be to use globals with external linkage in a way
> that is guaranteed not to rely on GOT entries, since we'll end up with
> absolute addresses that need to be fixed up first. This has caused
> breakage in the past, and is the reason we use this scheme with
> globals with static linkage and __pure getters.
> 
> However, hidden visibility should yield the same results so we should
> be able to make it work with that instead. However, given the breakage
> in the past, I don't think it's worth it since the performance gain
> will be negligible.

This only saves the overhead of the function call, but the compiler
would still have to re-read the variables and re-test them, since so far
as it knows the firmware call could change them. With the const function
attribute, it will only load them once. To make it work with just the
variables, they'd have to be declared const and initialized in the
assembly entry code.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-20 19:41           ` Arvind Sankar
@ 2020-01-02 14:46             ` Laszlo Ersek
  2020-01-02 15:40               ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Laszlo Ersek @ 2020-01-02 14:46 UTC (permalink / raw)
  To: Arvind Sankar, Ard Biesheuvel
  Cc: Andy Lutomirski, Matthew Garrett, Ard Biesheuvel, linux-efi,
	Hans de Goede, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On 12/20/19 20:41, Arvind Sankar wrote:
> On Fri, Dec 20, 2019 at 10:11:00AM +0200, Ard Biesheuvel wrote:
>> On Fri, 20 Dec 2019 at 09:17, Andy Lutomirski <luto@amacapital.net> wrote:
>>>
>>>
>>>
>>>> On Dec 20, 2019, at 3:07 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>>>
>>>> On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
>>>>>
>>>>>> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>>>>>> +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
>>>>>> +                               TPL_CALLBACK, handle_exit_boot_services_event,
>>>>>> +                               NULL, &exit_boot_services_event);
>>>>>> +       if (status != EFI_SUCCESS) {
>>>>>> +               pr_efi_err("Failed to register for EBS() event\n");
>>>>>> +               goto free_handle;
>>>>>> +       }
>>>>>
>>>>> OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
>>>>> EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
>>>>> first?
>>>>
>>>> It doesn't, and that is kind of the point. The only guarantee you have
>>>> is that this runs before ExitBootServices() returns, but after any
>>>> other callbacks that have been registered. I know this is not 100%
>>>> what you're after, but it is the only way we can avoid poking devices
>>>> behind the backs of their drivers.
>>>>
> 
> Could we add a comment to describe why we have the two-step event
> notification, i.e. to ensure the ordering?
> 
> Regarding SEV, from what Laszlo had said [1] I had understood that the
> SEV driver left everything blacklisted -- is this necessary at all for
> SEV or did I misunderstand his comment?
> 
> [1] https://lore.kernel.org/lkml/9c58f2d2-5712-0972-6ea7-092500f37cf9@redhat.com/

Leaving all guest RAM encrypted after EBS may not be a technical
requirement for SEV. It is a security goal, however. The OS should
inherit the most secure environment possible from the firmware, and not
have to look for pages that were left unencrypted.

>>> Can you clarify (in the changelog or a comment perhaps) why you’re doing this instead of turning off busmastering before calling ExitBootServices()?  Maybe this was covered in this thread, but I missed it.
>>>
>>
>> Sure. The problem is that EBS() is the place where drivers tear down
>> rings etc and gracefully take down the device. So killing DMA for all
>> of them by clearing the BM bit of every bridge is likely to cause
>> problems, because the teardown code wasn't written with the idea in
>> mind that DMA is no longer possible. On arm64 at least, it may result
>> in the kernel being entered with a pending SError which will kill the
>> OS as soon as they are unmasked. But the UEFI drivers themselves may
>> simply hang or timeout on some DMA access.
>>
> 
> As I understand it, the order in which we want the bus-mastering
> disable to happen is
> - all PCI device drivers are stopped
> - bus mastering is disabled
> - depending on firmware, iommu might get disabled (probably out of our
>   control)
> 
> Instead of using the event notifier, could we not explicitly call
> DisconnectController() for all the PCI devices, then disable
> bus-mastering, and only then call ExitBootServices()?

This sounds worth investigating to me.

>>> Also, surely this whole mess is a a design error in EFI, at least when SEV is involved, and there should be an EFI extension to keep IOMMU enabled.  Or a specified way to *guarantee* that DMA is off when we exit boot services without hackery.
>>
>> The UEFI spec requires that all devices stop doing DMA at
>> ExitBootServices() time, which is why they register for this event and
>> disable DMA in their drivers. So from this pov, the state of the IOMMU
>> is irrelevant since no device should be doing DMA anyway. The UEFI
>> spec does not reason at all about IOMMUs.
>>
>> But indeed, the whole idea that the IOMMU is a 'feature' that you can
>> ignore if you want since it will be in passthrough mode otherwise is
>> misguided, but I'm not sure this is a firmware problem. The desire to
>> be able to run yesterday's OS on today's hardware, especially in the
>> Windows world, resulted in a situation where many security and
>> hardening features are opt-in rather than opt-out, with the adoption
>> you might expect.
> 
> Looking at the intel iommu driver [2] there is a PCD entry to control
> whether to leave the IOMMU enabled. Is it possible to check its value to
> see whether the bus-master disabling is necessary -- ie IOMMU was
> enabled during boot and its going to get turned off during
> ExitBootServices, or even check whether it's settable and if so set it
> to leave the IOMMU enabled?
> 
> [2] https://github.com/tianocore/edk2-platforms/blob/0d4d661b5a7cf3114a7d81e1c59e5cb57ceaf139/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c#L601
> 

The platform config database is a PI concept, not a UEFI concept. IOW,
EFI_PCD_PROTOCOL is specified in the Platform Init spec, and not the
UEFI spec. A UEFI OS should only rely on the UEFI spec.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 14:06           ` Arvind Sankar
@ 2020-01-02 15:20             ` Ard Biesheuvel
  2020-01-02 15:51               ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 15:20 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 15:06, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 08:33:54AM +0100, Ard Biesheuvel wrote:
> > On Wed, 1 Jan 2020 at 20:08, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > >
> > > On Wed, Jan 01, 2020 at 07:13:45PM +0100, Ard Biesheuvel wrote:
> > > > The GCC documentation mentions that it does not make sense for a
> > > > function annotated as const not to take any arguments, so I'd rather
> > > > avoid it here.
> > >
> > > Where does it say that? I only see it saying it doesn't make sense for
> > > it to return void.
> > >
> >
> > You're right. I looked into this in the past, and I misremembered, and
> > paraphrased it incorrectly.
> >
> > The documentation does mention that const functions are not permitted
> > to read global memory.
> >
>
> What it says is that "[the const attribute] tells GCC that subsequent
> calls to function square with the same argument value can be replaced by
> the result of the first call regardless of the statements in between"
> and "The const attribute prohibits a function from reading objects that
> affect its return value between successive invocations. However,
> functions declared with the attribute can safely read objects that do
> not change their return value, such as non-volatile constants."
>
> In this case since the globals in question never change after being set,
> it should be safe -- every call to these functions does return the same
> value.
>

I agree that it should be safe. However, the document I looked at literally says

"""
Many functions do not examine any values except their arguments, and
have no effects except the return value. Basically this is just
slightly more strict class than the pure attribute below, since
function is not allowed to read global memory.
"""

However, this is actually a fairly old version of the docs [0], and
the most recent version seems to permit it.

[0] https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html


> > > Currently if we call 5 EFI services in the same function, it has to
> > > re-evaluate systemtable and is64 for each call, which seems wasteful,
> > > though of course this is not exactly performance-critical code.
> >
> > The alternative would be to use globals with external linkage in a way
> > that is guaranteed not to rely on GOT entries, since we'll end up with
> > absolute addresses that need to be fixed up first. This has caused
> > breakage in the past, and is the reason we use this scheme with
> > globals with static linkage and __pure getters.
> >
> > However, hidden visibility should yield the same results so we should
> > be able to make it work with that instead. However, given the breakage
> > in the past, I don't think it's worth it since the performance gain
> > will be negligible.
>
> This only saves the overhead of the function call, but the compiler
> would still have to re-read the variables and re-test them, since so far
> as it knows the firmware call could change them. With the const function
> attribute, it will only load them once. To make it work with just the
> variables, they'd have to be declared const and initialized in the
> assembly entry code.

Yeah, good point.

I pushed as branch here;
https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const

Could you please check if that fixes the issue for efi_is_64bit() ?

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2020-01-02 14:46             ` Laszlo Ersek
@ 2020-01-02 15:40               ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 15:40 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Arvind Sankar, Andy Lutomirski, Matthew Garrett, Ard Biesheuvel,
	linux-efi, Hans de Goede, Ingo Molnar, Andy Lutomirski,
	Thomas Gleixner

On Thu, 2 Jan 2020 at 15:46, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 12/20/19 20:41, Arvind Sankar wrote:
> > On Fri, Dec 20, 2019 at 10:11:00AM +0200, Ard Biesheuvel wrote:
> >> On Fri, 20 Dec 2019 at 09:17, Andy Lutomirski <luto@amacapital.net> wrote:
> >>>
> >>>
> >>>
> >>>> On Dec 20, 2019, at 3:07 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >>>>
> >>>> On Thu, 19 Dec 2019 at 22:05, Matthew Garrett <mjg59@google.com> wrote:
> >>>>>
> >>>>>> On Wed, Dec 18, 2019 at 9:03 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> >>>>>> +       status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> >>>>>> +                               TPL_CALLBACK, handle_exit_boot_services_event,
> >>>>>> +                               NULL, &exit_boot_services_event);
> >>>>>> +       if (status != EFI_SUCCESS) {
> >>>>>> +               pr_efi_err("Failed to register for EBS() event\n");
> >>>>>> +               goto free_handle;
> >>>>>> +       }
> >>>>>
> >>>>> OVMF's SEV implementation appears to tear down AMD's IOMMU mappings at
> >>>>> EVT_SIGNAL_EXIT_BOOT_SERVICES. How are we ensuring that this happens
> >>>>> first?
> >>>>
> >>>> It doesn't, and that is kind of the point. The only guarantee you have
> >>>> is that this runs before ExitBootServices() returns, but after any
> >>>> other callbacks that have been registered. I know this is not 100%
> >>>> what you're after, but it is the only way we can avoid poking devices
> >>>> behind the backs of their drivers.
> >>>>
> >
> > Could we add a comment to describe why we have the two-step event
> > notification, i.e. to ensure the ordering?
> >
> > Regarding SEV, from what Laszlo had said [1] I had understood that the
> > SEV driver left everything blacklisted -- is this necessary at all for
> > SEV or did I misunderstand his comment?
> >
> > [1] https://lore.kernel.org/lkml/9c58f2d2-5712-0972-6ea7-092500f37cf9@redhat.com/
>
> Leaving all guest RAM encrypted after EBS may not be a technical
> requirement for SEV. It is a security goal, however. The OS should
> inherit the most secure environment possible from the firmware, and not
> have to look for pages that were left unencrypted.
>
> >>> Can you clarify (in the changelog or a comment perhaps) why you’re doing this instead of turning off busmastering before calling ExitBootServices()?  Maybe this was covered in this thread, but I missed it.
> >>>
> >>
> >> Sure. The problem is that EBS() is the place where drivers tear down
> >> rings etc and gracefully take down the device. So killing DMA for all
> >> of them by clearing the BM bit of every bridge is likely to cause
> >> problems, because the teardown code wasn't written with the idea in
> >> mind that DMA is no longer possible. On arm64 at least, it may result
> >> in the kernel being entered with a pending SError which will kill the
> >> OS as soon as they are unmasked. But the UEFI drivers themselves may
> >> simply hang or timeout on some DMA access.
> >>
> >
> > As I understand it, the order in which we want the bus-mastering
> > disable to happen is
> > - all PCI device drivers are stopped
> > - bus mastering is disabled
> > - depending on firmware, iommu might get disabled (probably out of our
> >   control)
> >
> > Instead of using the event notifier, could we not explicitly call
> > DisconnectController() for all the PCI devices, then disable
> > bus-mastering, and only then call ExitBootServices()?
>
> This sounds worth investigating to me.
>

I implemented this here:
https://lore.kernel.org/linux-efi/20191231162344.130654-1-ardb@kernel.org/

It works on all the systems I tried, including a mixed mode iMac 24"
and a mixed mode Intel Atom based tablet kindly provided by Hans.

The only thing to keep in mind is that some drivers implement
Gop->Blt() using DMA in some cases, and so we should ensure that this
is really the last thing that happens before ExitBootServices() is
called, since a simple efi_printk() may trigger a DMA access by the
graphics hardware.

> >>> Also, surely this whole mess is a a design error in EFI, at least when SEV is involved, and there should be an EFI extension to keep IOMMU enabled.  Or a specified way to *guarantee* that DMA is off when we exit boot services without hackery.
> >>
> >> The UEFI spec requires that all devices stop doing DMA at
> >> ExitBootServices() time, which is why they register for this event and
> >> disable DMA in their drivers. So from this pov, the state of the IOMMU
> >> is irrelevant since no device should be doing DMA anyway. The UEFI
> >> spec does not reason at all about IOMMUs.
> >>
> >> But indeed, the whole idea that the IOMMU is a 'feature' that you can
> >> ignore if you want since it will be in passthrough mode otherwise is
> >> misguided, but I'm not sure this is a firmware problem. The desire to
> >> be able to run yesterday's OS on today's hardware, especially in the
> >> Windows world, resulted in a situation where many security and
> >> hardening features are opt-in rather than opt-out, with the adoption
> >> you might expect.
> >
> > Looking at the intel iommu driver [2] there is a PCD entry to control
> > whether to leave the IOMMU enabled. Is it possible to check its value to
> > see whether the bus-master disabling is necessary -- ie IOMMU was
> > enabled during boot and its going to get turned off during
> > ExitBootServices, or even check whether it's settable and if so set it
> > to leave the IOMMU enabled?
> >
> > [2] https://github.com/tianocore/edk2-platforms/blob/0d4d661b5a7cf3114a7d81e1c59e5cb57ceaf139/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c#L601
> >
>
> The platform config database is a PI concept, not a UEFI concept. IOW,
> EFI_PCD_PROTOCOL is specified in the Platform Init spec, and not the
> UEFI spec. A UEFI OS should only rely on the UEFI spec.
>

Agreed. And on top of that, PCDs can be FixedAtBuild or Patchable, in
which case they cannot be controlled via the EFI_PCD_PROTOCOL.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 15:20             ` Ard Biesheuvel
@ 2020-01-02 15:51               ` Arvind Sankar
  2020-01-02 15:58                 ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 15:51 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> 
> Yeah, good point.
> 
> I pushed as branch here;
> https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> 
> Could you please check if that fixes the issue for efi_is_64bit() ?

Haven't built it yet -- but how does this handle the GOT issues you
mentioned?

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 15:51               ` Arvind Sankar
@ 2020-01-02 15:58                 ` Ard Biesheuvel
  2020-01-02 16:28                   ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 15:58 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> >
> > Yeah, good point.
> >
> > I pushed as branch here;
> > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> >
> > Could you please check if that fixes the issue for efi_is_64bit() ?
>
> Haven't built it yet -- but how does this handle the GOT issues you
> mentioned?

It doesn't. The trick is to add __attribute__((visibility("hidden")))
to the extern declaration of efi_is64, but I am having trouble to
reproduce the original issue.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 15:58                 ` Ard Biesheuvel
@ 2020-01-02 16:28                   ` Ard Biesheuvel
  2020-01-02 16:59                     ` Ard Biesheuvel
  2020-01-02 16:59                     ` Arvind Sankar
  0 siblings, 2 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 16:28 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > >
> > > Yeah, good point.
> > >
> > > I pushed as branch here;
> > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > >
> > > Could you please check if that fixes the issue for efi_is_64bit() ?
> >
> > Haven't built it yet -- but how does this handle the GOT issues you
> > mentioned?
>
> It doesn't. The trick is to add __attribute__((visibility("hidden")))
> to the extern declaration of efi_is64, but I am having trouble to
> reproduce the original issue.

Some background:

https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 16:28                   ` Ard Biesheuvel
@ 2020-01-02 16:59                     ` Ard Biesheuvel
  2020-01-02 17:26                       ` Arvind Sankar
  2020-01-02 16:59                     ` Arvind Sankar
  1 sibling, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 16:59 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 17:28, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >
> > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > >
> > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > >
> > > > Yeah, good point.
> > > >
> > > > I pushed as branch here;
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > >
> > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > >
> > > Haven't built it yet -- but how does this handle the GOT issues you
> > > mentioned?
> >
> > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > to the extern declaration of efi_is64, but I am having trouble to
> > reproduce the original issue.
>
> Some background:
>
> https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/

OK, I have done a bit more digging, and it seems like recent
toolchains can optimize away GOT indirections using R_386_GOT32X
relocations, which can be converted into R_386_GOTOFF relocations by
the linker if it is building a fully linked binary, making the actual
contents of the GOT entries irrelevant.

Note that even if the GOT entries are not fixed up, assigning a global
variable and then using it again may work by accident if the memory it
points to is writable, which is why it is not easy to reproduce
reliably.

efi_is64 only exists on 64-bit, so annotating that as 'hidden' should
work. But efi_system_table() is also used on 32-bit, so I'll leave
that one alone for now.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 16:28                   ` Ard Biesheuvel
  2020-01-02 16:59                     ` Ard Biesheuvel
@ 2020-01-02 16:59                     ` Arvind Sankar
  2020-01-02 17:03                       ` Ard Biesheuvel
  1 sibling, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 16:59 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 05:28:16PM +0100, Ard Biesheuvel wrote:
> On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >
> > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > >
> > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > >
> > > > Yeah, good point.
> > > >
> > > > I pushed as branch here;
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > >
> > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > >
> > > Haven't built it yet -- but how does this handle the GOT issues you
> > > mentioned?
> >
> > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > to the extern declaration of efi_is64, but I am having trouble to
> > reproduce the original issue.
> 
> Some background:
> 
> https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/

I wonder if commit 6d92bc9d483a ("x86/build: Build compressed x86
kernels as PIE") resolved this.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 16:59                     ` Arvind Sankar
@ 2020-01-02 17:03                       ` Ard Biesheuvel
  2020-01-02 17:21                         ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 17:03 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 17:59, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 05:28:16PM +0100, Ard Biesheuvel wrote:
> > On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > >
> > > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > >
> > > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > > >
> > > > > Yeah, good point.
> > > > >
> > > > > I pushed as branch here;
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > > >
> > > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > > >
> > > > Haven't built it yet -- but how does this handle the GOT issues you
> > > > mentioned?
> > >
> > > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > > to the extern declaration of efi_is64, but I am having trouble to
> > > reproduce the original issue.
> >
> > Some background:
> >
> > https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> > https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/
>
> I wonder if commit 6d92bc9d483a ("x86/build: Build compressed x86
> kernels as PIE") resolved this.

Good question. But note that the stub is still built with -fPIC not -fPIE.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 17:03                       ` Ard Biesheuvel
@ 2020-01-02 17:21                         ` Arvind Sankar
  0 siblings, 0 replies; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 17:21 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 06:03:48PM +0100, Ard Biesheuvel wrote:
> On Thu, 2 Jan 2020 at 17:59, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Thu, Jan 02, 2020 at 05:28:16PM +0100, Ard Biesheuvel wrote:
> > > On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > >
> > > > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > >
> > > > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > > > >
> > > > > > Yeah, good point.
> > > > > >
> > > > > > I pushed as branch here;
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > > > >
> > > > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > > > >
> > > > > Haven't built it yet -- but how does this handle the GOT issues you
> > > > > mentioned?
> > > >
> > > > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > > > to the extern declaration of efi_is64, but I am having trouble to
> > > > reproduce the original issue.
> > >
> > > Some background:
> > >
> > > https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> > > https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/
> >
> > I wonder if commit 6d92bc9d483a ("x86/build: Build compressed x86
> > kernels as PIE") resolved this.
> 
> Good question. But note that the stub is still built with -fPIC not -fPIE.

Hm libstub is -fPIC but arch/x86/boot/compressed is -fPIE. With -fPIE
gcc 5+ doesn't use GOTPCREL even with default visibility, but gcc 4.7
does. With -fPIC though you need hidden visibility to avoid GOTPCREL.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 16:59                     ` Ard Biesheuvel
@ 2020-01-02 17:26                       ` Arvind Sankar
  2020-01-02 17:30                         ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 17:26 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 05:59:27PM +0100, Ard Biesheuvel wrote:
> On Thu, 2 Jan 2020 at 17:28, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> >
> > On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > >
> > > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > >
> > > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > > >
> > > > > Yeah, good point.
> > > > >
> > > > > I pushed as branch here;
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > > >
> > > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > > >
> > > > Haven't built it yet -- but how does this handle the GOT issues you
> > > > mentioned?
> > >
> > > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > > to the extern declaration of efi_is64, but I am having trouble to
> > > reproduce the original issue.
> >
> > Some background:
> >
> > https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> > https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/
> 
> OK, I have done a bit more digging, and it seems like recent
> toolchains can optimize away GOT indirections using R_386_GOT32X
> relocations, which can be converted into R_386_GOTOFF relocations by
> the linker if it is building a fully linked binary, making the actual
> contents of the GOT entries irrelevant.
> 
> Note that even if the GOT entries are not fixed up, assigning a global
> variable and then using it again may work by accident if the memory it
> points to is writable, which is why it is not easy to reproduce
> reliably.
> 
> efi_is64 only exists on 64-bit, so annotating that as 'hidden' should
> work. But efi_system_table() is also used on 32-bit, so I'll leave
> that one alone for now.

With hidden visibility, 32-bit compiler seems to generate GOTOFF
relocations directly so it shouldn't depend on recent toolchain?

https://godbolt.org/z/79iA_3

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 17:26                       ` Arvind Sankar
@ 2020-01-02 17:30                         ` Ard Biesheuvel
  2020-01-02 17:41                           ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 17:30 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 18:26, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 05:59:27PM +0100, Ard Biesheuvel wrote:
> > On Thu, 2 Jan 2020 at 17:28, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > >
> > > On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > >
> > > > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > >
> > > > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > > > >
> > > > > > Yeah, good point.
> > > > > >
> > > > > > I pushed as branch here;
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > > > >
> > > > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > > > >
> > > > > Haven't built it yet -- but how does this handle the GOT issues you
> > > > > mentioned?
> > > >
> > > > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > > > to the extern declaration of efi_is64, but I am having trouble to
> > > > reproduce the original issue.
> > >
> > > Some background:
> > >
> > > https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> > > https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/
> >
> > OK, I have done a bit more digging, and it seems like recent
> > toolchains can optimize away GOT indirections using R_386_GOT32X
> > relocations, which can be converted into R_386_GOTOFF relocations by
> > the linker if it is building a fully linked binary, making the actual
> > contents of the GOT entries irrelevant.
> >
> > Note that even if the GOT entries are not fixed up, assigning a global
> > variable and then using it again may work by accident if the memory it
> > points to is writable, which is why it is not easy to reproduce
> > reliably.
> >
> > efi_is64 only exists on 64-bit, so annotating that as 'hidden' should
> > work. But efi_system_table() is also used on 32-bit, so I'll leave
> > that one alone for now.
>
> With hidden visibility, 32-bit compiler seems to generate GOTOFF
> relocations directly so it shouldn't depend on recent toolchain?
>
> https://godbolt.org/z/79iA_3

Yes, that was my assumption at the time as well, but we still ended up
with /some/ absolute GOT dereferences for some reason in the 32-bit
kernel.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 17:30                         ` Ard Biesheuvel
@ 2020-01-02 17:41                           ` Arvind Sankar
  2020-01-02 17:48                             ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 17:41 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 06:30:46PM +0100, Ard Biesheuvel wrote:
> On Thu, 2 Jan 2020 at 18:26, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Thu, Jan 02, 2020 at 05:59:27PM +0100, Ard Biesheuvel wrote:
> > > On Thu, 2 Jan 2020 at 17:28, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > >
> > > > On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > > >
> > > > > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > > >
> > > > > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > > > > >
> > > > > > > Yeah, good point.
> > > > > > >
> > > > > > > I pushed as branch here;
> > > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > > > > >
> > > > > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > > > > >
> > > > > > Haven't built it yet -- but how does this handle the GOT issues you
> > > > > > mentioned?
> > > > >
> > > > > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > > > > to the extern declaration of efi_is64, but I am having trouble to
> > > > > reproduce the original issue.
> > > >
> > > > Some background:
> > > >
> > > > https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> > > > https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/
> > >
> > > OK, I have done a bit more digging, and it seems like recent
> > > toolchains can optimize away GOT indirections using R_386_GOT32X
> > > relocations, which can be converted into R_386_GOTOFF relocations by
> > > the linker if it is building a fully linked binary, making the actual
> > > contents of the GOT entries irrelevant.
> > >
> > > Note that even if the GOT entries are not fixed up, assigning a global
> > > variable and then using it again may work by accident if the memory it
> > > points to is writable, which is why it is not easy to reproduce
> > > reliably.
> > >
> > > efi_is64 only exists on 64-bit, so annotating that as 'hidden' should
> > > work. But efi_system_table() is also used on 32-bit, so I'll leave
> > > that one alone for now.
> >
> > With hidden visibility, 32-bit compiler seems to generate GOTOFF
> > relocations directly so it shouldn't depend on recent toolchain?
> >
> > https://godbolt.org/z/79iA_3
> 
> Yes, that was my assumption at the time as well, but we still ended up
> with /some/ absolute GOT dereferences for some reason in the 32-bit
> kernel.

Do you remember if we ever figured out what was wrong with Matt
Fleming's patch to fixup the GOT for the EFI stub too?

For efi_system_table, if we don't want to risk creating GOT entries, one
option would be to do what you did for is64, but define the wrapper
function as an out-of-line function in the assembler code and declare it
const.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 17:41                           ` Arvind Sankar
@ 2020-01-02 17:48                             ` Ard Biesheuvel
  2020-01-02 18:10                               ` Arvind Sankar
  2020-01-02 18:38                               ` Arvind Sankar
  0 siblings, 2 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 17:48 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 18:41, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 06:30:46PM +0100, Ard Biesheuvel wrote:
> > On Thu, 2 Jan 2020 at 18:26, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > >
> > > On Thu, Jan 02, 2020 at 05:59:27PM +0100, Ard Biesheuvel wrote:
> > > > On Thu, 2 Jan 2020 at 17:28, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > > >
> > > > > On Thu, 2 Jan 2020 at 16:58, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > > > > >
> > > > > > On Thu, 2 Jan 2020 at 16:51, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > > > > > >
> > > > > > > On Thu, Jan 02, 2020 at 04:20:46PM +0100, Ard Biesheuvel wrote:
> > > > > > > >
> > > > > > > > Yeah, good point.
> > > > > > > >
> > > > > > > > I pushed as branch here;
> > > > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/log/?h=efi-libstub-attr-const
> > > > > > > >
> > > > > > > > Could you please check if that fixes the issue for efi_is_64bit() ?
> > > > > > >
> > > > > > > Haven't built it yet -- but how does this handle the GOT issues you
> > > > > > > mentioned?
> > > > > >
> > > > > > It doesn't. The trick is to add __attribute__((visibility("hidden")))
> > > > > > to the extern declaration of efi_is64, but I am having trouble to
> > > > > > reproduce the original issue.
> > > > >
> > > > > Some background:
> > > > >
> > > > > https://lore.kernel.org/lkml/5405E186.2080406@canonical.com/
> > > > > https://lore.kernel.org/lkml/20140919104021.GA11552@gmail.com/
> > > >
> > > > OK, I have done a bit more digging, and it seems like recent
> > > > toolchains can optimize away GOT indirections using R_386_GOT32X
> > > > relocations, which can be converted into R_386_GOTOFF relocations by
> > > > the linker if it is building a fully linked binary, making the actual
> > > > contents of the GOT entries irrelevant.
> > > >
> > > > Note that even if the GOT entries are not fixed up, assigning a global
> > > > variable and then using it again may work by accident if the memory it
> > > > points to is writable, which is why it is not easy to reproduce
> > > > reliably.
> > > >
> > > > efi_is64 only exists on 64-bit, so annotating that as 'hidden' should
> > > > work. But efi_system_table() is also used on 32-bit, so I'll leave
> > > > that one alone for now.
> > >
> > > With hidden visibility, 32-bit compiler seems to generate GOTOFF
> > > relocations directly so it shouldn't depend on recent toolchain?
> > >
> > > https://godbolt.org/z/79iA_3
> >
> > Yes, that was my assumption at the time as well, but we still ended up
> > with /some/ absolute GOT dereferences for some reason in the 32-bit
> > kernel.
>
> Do you remember if we ever figured out what was wrong with Matt
> Fleming's patch to fixup the GOT for the EFI stub too?
>

No, I don't think we did. It is simply infeasible to diagnose this on
someone else's laptop who is on the other side of the world.

> For efi_system_table, if we don't want to risk creating GOT entries, one
> option would be to do what you did for is64, but define the wrapper
> function as an out-of-line function in the assembler code and declare it
> const.

Yeah, that would work. It would be for 32-bit only, so we could have a
__weak implementation in C, and an asm one for i386.

Currently, I am not managing to get the 64-bit compiler to emit any
GOT based references for efi_is64, though, even without the attribute,
so I am not sure what's going on there.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 17:48                             ` Ard Biesheuvel
@ 2020-01-02 18:10                               ` Arvind Sankar
  2020-01-02 18:38                                 ` Ard Biesheuvel
  2020-01-02 18:38                               ` Arvind Sankar
  1 sibling, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 18:10 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 06:48:52PM +0100, Ard Biesheuvel wrote:
> Currently, I am not managing to get the 64-bit compiler to emit any
> GOT based references for efi_is64, though, even without the attribute,
> so I am not sure what's going on there.

With gcc 9, I do get R_X86_64_REX_GOTPCRELX relocations in libstub,
which are then eliminated by the linker -- if they weren't they would be
using addresses from the GOT. They turn into R_X86_64_PC32 with the
hidden visibility.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 18:10                               ` Arvind Sankar
@ 2020-01-02 18:38                                 ` Ard Biesheuvel
  2020-01-03 14:16                                   ` Arvind Sankar
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-02 18:38 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, 2 Jan 2020 at 19:10, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 06:48:52PM +0100, Ard Biesheuvel wrote:
> > Currently, I am not managing to get the 64-bit compiler to emit any
> > GOT based references for efi_is64, though, even without the attribute,
> > so I am not sure what's going on there.
>
> With gcc 9, I do get R_X86_64_REX_GOTPCRELX relocations in libstub,
> which are then eliminated by the linker -- if they weren't they would be
> using addresses from the GOT. They turn into R_X86_64_PC32 with the
> hidden visibility.

Indeed. I was looking at eboot.o but that gets built with -fPIE not
-fPIC [if available].

libstub objects indeed have the R_X86_64_REX_GOTPCRELX relocations, so
I'll add the hidden visibility to the extern declaration of efi_is64

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 17:48                             ` Ard Biesheuvel
  2020-01-02 18:10                               ` Arvind Sankar
@ 2020-01-02 18:38                               ` Arvind Sankar
  1 sibling, 0 replies; 87+ messages in thread
From: Arvind Sankar @ 2020-01-02 18:38 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 06:48:52PM +0100, Ard Biesheuvel wrote:
> >
> > Do you remember if we ever figured out what was wrong with Matt
> > Fleming's patch to fixup the GOT for the EFI stub too?
> >
> 
> No, I don't think we did. It is simply infeasible to diagnose this on
> someone else's laptop who is on the other side of the world.
> 

Hm looking at that code, I think it wouldn't do the GOT relocation
adjustment needed after copying the kernel for decompression. But then
it shouldn't have worked at all presumably...

Maybe we should just try again and see if it breaks anyone.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-02 18:38                                 ` Ard Biesheuvel
@ 2020-01-03 14:16                                   ` Arvind Sankar
  2020-01-03 14:23                                     ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Arvind Sankar @ 2020-01-03 14:16 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Arvind Sankar, Ard Biesheuvel, linux-efi, Hans de Goede,
	Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Thu, Jan 02, 2020 at 07:38:06PM +0100, Ard Biesheuvel wrote:
> On Thu, 2 Jan 2020 at 19:10, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> >
> > On Thu, Jan 02, 2020 at 06:48:52PM +0100, Ard Biesheuvel wrote:
> > > Currently, I am not managing to get the 64-bit compiler to emit any
> > > GOT based references for efi_is64, though, even without the attribute,
> > > so I am not sure what's going on there.
> >
> > With gcc 9, I do get R_X86_64_REX_GOTPCRELX relocations in libstub,
> > which are then eliminated by the linker -- if they weren't they would be
> > using addresses from the GOT. They turn into R_X86_64_PC32 with the
> > hidden visibility.
> 
> Indeed. I was looking at eboot.o but that gets built with -fPIE not
> -fPIC [if available].
> 
> libstub objects indeed have the R_X86_64_REX_GOTPCRELX relocations, so
> I'll add the hidden visibility to the extern declaration of efi_is64

Is there any reason not to compile the stub with -fPIE btw? Also fPIE
seems to be there even in gcc 4.1.2, the check for availability can
probably be dropped.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct
  2020-01-03 14:16                                   ` Arvind Sankar
@ 2020-01-03 14:23                                     ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2020-01-03 14:23 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Ard Biesheuvel, linux-efi, Hans de Goede, Matthew Garrett,
	Ingo Molnar, Andy Lutomirski, Thomas Gleixner

On Fri, 3 Jan 2020 at 15:17, Arvind Sankar <nivedita@alum.mit.edu> wrote:
>
> On Thu, Jan 02, 2020 at 07:38:06PM +0100, Ard Biesheuvel wrote:
> > On Thu, 2 Jan 2020 at 19:10, Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > >
> > > On Thu, Jan 02, 2020 at 06:48:52PM +0100, Ard Biesheuvel wrote:
> > > > Currently, I am not managing to get the 64-bit compiler to emit any
> > > > GOT based references for efi_is64, though, even without the attribute,
> > > > so I am not sure what's going on there.
> > >
> > > With gcc 9, I do get R_X86_64_REX_GOTPCRELX relocations in libstub,
> > > which are then eliminated by the linker -- if they weren't they would be
> > > using addresses from the GOT. They turn into R_X86_64_PC32 with the
> > > hidden visibility.
> >
> > Indeed. I was looking at eboot.o but that gets built with -fPIE not
> > -fPIC [if available].
> >
> > libstub objects indeed have the R_X86_64_REX_GOTPCRELX relocations, so
> > I'll add the hidden visibility to the extern declaration of efi_is64
>
> Is there any reason not to compile the stub with -fPIE btw? Also fPIE
> seems to be there even in gcc 4.1.2, the check for availability can
> probably be dropped.

No we should switch to -fPIE for the stub as well

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
  2019-12-19  2:50   ` Andy Lutomirski
  2019-12-19 20:04   ` Matthew Garrett
@ 2020-02-06 14:30   ` Hans de Goede
  2020-02-06 14:35     ` Ard Biesheuvel
  2 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2020-02-06 14:30 UTC (permalink / raw)
  To: Ard Biesheuvel, linux-efi
  Cc: Matthew Garrett, Ingo Molnar, Andy Lutomirski, Thomas Gleixner,
	Arvind Sankar, Matthew Garrett

Hi,

On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> From: Matthew Garrett <matthewgarrett@google.com>
> 
> Add an option to disable the busmaster bit in the control register on
> all PCI bridges during the invocation of ExitBootServices() and passing
> control to the runtime kernel. System firmware may configure the IOMMU
> to prevent malicious PCI devices from being able to attack the OS via DMA.
> However, since firmware can't guarantee that the OS is IOMMU-aware, it
> will tear down IOMMU configuration when ExitBootServices() is called.
> This leaves a window between where a hostile device could still cause
> damage before Linux configures the IOMMU again.
> 
> If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
> command line argument is passed, the EFI stub will clear the busmaster
> bit on all PCI bridges before ExitBootServices() completes. This will
> prevent any malicious PCI devices from being able to perform DMA until
> the kernel reenables busmastering after configuring the IOMMU.
> 
> This option is disabled when in EFI mixed mode environments (ie, 64-bit
> kernels with a 32-bit EFI implementation), given that the use of EFI
> events is not supported in this case.
> 
> This option may cause failures with some poorly behaved hardware and
> should not be enabled without testing. The kernel commandline options
> "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
> override the default.
> 
> Co-developed-by: Matthew Garrett <mjg59@google.com>
> Signed-off-by: Matthew Garrett <mjg59@google.com>
> [ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

I guess this might not be the latest version of this patch, but
this does seem to be the thread where most discussion on it
has happened.

My personal kernel tree atm consists of v5.5 + efi/next + my own patches
and yesterday I noticed that will not boot on a Lenovo X1 7th gen connected
to a Lenovo thunderbolt 3 gen 2 dock.

My first hunch was that I have CONFIG_EFI_DISABLE_PCI_DMA=y and that that
was causing it and indeed that is the problem.

So as (somewhat) expected CONFIG_EFI_DISABLE_PCI_DMA=y indeed stops the kernel
from booting on some systems.

When I hit this problem the efistub prints 2 messages and then the system
just hangs:

exit_boot() failed!
efi_main() failed!

When I boot the system without it being connected to the thunderbolt dock
then efi=disable_pci_dma works fine.

Let me know if I can do anything to help and getting booting while
connected to the dock to work with efi=disable_pci_dma.

Regards,

Hans



> ---
>   Documentation/admin-guide/kernel-parameters.txt |   4 +
>   arch/x86/boot/compressed/eboot.c                |   2 +
>   drivers/firmware/efi/Kconfig                    |  22 ++++
>   drivers/firmware/efi/libstub/Makefile           |   2 +-
>   drivers/firmware/efi/libstub/arm-stub.c         |   1 +
>   drivers/firmware/efi/libstub/efi-stub-helper.c  |  17 +++
>   drivers/firmware/efi/libstub/efistub.h          |   1 +
>   drivers/firmware/efi/libstub/pci.c              | 116 ++++++++++++++++++++
>   include/linux/efi.h                             |   2 +
>   9 files changed, 166 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 5a92d89a1bd4..06fd8d2c9a2c 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1180,6 +1180,10 @@
>   			claim. Specify efi=nosoftreserve to disable this
>   			reservation and treat the memory by its base type
>   			(i.e. EFI_CONVENTIONAL_MEMORY / "System RAM").
> +			disable_pci_dma: Disable the busmaster bit on all
> +			PCI bridges while in the EFI boot stub
> +			no_disable_pci_dma: Leave the busmaster bit set on all
> +			PCI bridges while in the EFI boot stub
>   
>   	efi_no_storage_paranoia [EFI; X86]
>   			Using this parameter you can use more than 50% of
> diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
> index a3000283dc7a..79c3c3308195 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -126,6 +126,8 @@ static void setup_efi_pci(struct boot_params *params)
>   	efi_handle_t h;
>   	int i;
>   
> +	efi_pci_disable_bridge_busmaster();
> +
>   	status = efi_call_early(locate_handle,
>   				EFI_LOCATE_BY_PROTOCOL,
>   				&pci_proto, NULL, &size, pci_handle);
> diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
> index bcc378c19ebe..da2f5fc862aa 100644
> --- a/drivers/firmware/efi/Kconfig
> +++ b/drivers/firmware/efi/Kconfig
> @@ -215,6 +215,28 @@ config EFI_RCI2_TABLE
>   
>   	  Say Y here for Dell EMC PowerEdge systems.
>   
> +config EFI_DISABLE_PCI_DMA
> +       bool "Clear Busmaster bit on PCI bridges during ExitBootServices()"
> +       help
> +	  Disable the busmaster bit in the control register on all PCI bridges
> +	  while calling ExitBootServices() and passing control to the runtime
> +	  kernel. System firmware may configure the IOMMU to prevent malicious
> +	  PCI devices from being able to attack the OS via DMA. However, since
> +	  firmware can't guarantee that the OS is IOMMU-aware, it will tear
> +	  down IOMMU configuration when ExitBootServices() is called. This
> +	  leaves a window between where a hostile device could still cause
> +	  damage before Linux configures the IOMMU again.
> +
> +	  If you say Y here, the EFI stub will clear the busmaster bit on all
> +	  PCI bridges before ExitBootServices() completes. This will prevent
> +	  any malicious PCI devices from being able to perform DMA until the
> +	  kernel reenables busmastering after configuring the IOMMU.
> +
> +	  This option will cause failures with some poorly behaved hardware
> +	  and should not be enabled without testing. The kernel commandline
> +	  options "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be
> +	  used to override this option.
> +
>   endmenu
>   
>   config UEFI_CPER
> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
> index c35f893897e1..98a81576213d 100644
> --- a/drivers/firmware/efi/libstub/Makefile
> +++ b/drivers/firmware/efi/libstub/Makefile
> @@ -39,7 +39,7 @@ OBJECT_FILES_NON_STANDARD	:= y
>   KCOV_INSTRUMENT			:= n
>   
>   lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
> -				   random.o
> +				   random.o pci.o
>   
>   # include the stub's generic dependencies from lib/ when building for ARM/arm64
>   arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
> diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
> index e1ec0b2cde29..aa2929098d60 100644
> --- a/drivers/firmware/efi/libstub/arm-stub.c
> +++ b/drivers/firmware/efi/libstub/arm-stub.c
> @@ -257,6 +257,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg,
>   	}
>   
>   	install_memreserve_table();
> +	efi_pci_disable_bridge_busmaster();
>   
>   	new_fdt_addr = fdt_addr;
>   	status = allocate_new_fdt_and_exit_boot(handle,
> diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
> index 8b0d59f5c8cd..4b79bfff1fd4 100644
> --- a/drivers/firmware/efi/libstub/efi-stub-helper.c
> +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
> @@ -33,6 +33,8 @@ static bool __section(.data) efi_nokaslr;
>   static bool __section(.data) efi_quiet;
>   static bool __section(.data) efi_novamap;
>   static bool __section(.data) efi_nosoftreserve;
> +static bool __section(.data) efi_disable_pci_dma =
> +					IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
>   
>   bool __pure nokaslr(void)
>   {
> @@ -51,6 +53,11 @@ bool __pure __efi_soft_reserve_enabled(void)
>   	return !efi_nosoftreserve;
>   }
>   
> +bool __pure disable_pci_dma(void)
> +{
> +	return efi_disable_pci_dma;
> +}
> +
>   #define EFI_MMAP_NR_SLACK_SLOTS	8
>   
>   struct file_info {
> @@ -499,6 +506,16 @@ efi_status_t efi_parse_options(char const *cmdline)
>   			efi_nosoftreserve = true;
>   		}
>   
> +		if (!strncmp(str, "disable_pci_dma", 15)) {
> +			str += strlen("disable_pci_dma");
> +			efi_disable_pci_dma = true;
> +		}
> +
> +		if (!strncmp(str, "no_disable_pci_dma", 18)) {
> +			str += strlen("no_disable_pci_dma");
> +			efi_disable_pci_dma = false;
> +		}
> +
>   		/* Group words together, delimited by "," */
>   		while (*str && *str != ' ' && *str != ',')
>   			str++;
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index 72e60b6afbf8..679268f67521 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -28,6 +28,7 @@
>   extern bool __pure nokaslr(void);
>   extern bool __pure is_quiet(void);
>   extern bool __pure novamap(void);
> +extern bool __pure disable_pci_dma(void);
>   
>   extern __pure efi_system_table_t  *efi_system_table(void);
>   
> diff --git a/drivers/firmware/efi/libstub/pci.c b/drivers/firmware/efi/libstub/pci.c
> new file mode 100644
> index 000000000000..e2f71f890dd1
> --- /dev/null
> +++ b/drivers/firmware/efi/libstub/pci.c
> @@ -0,0 +1,116 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCI-related functions used by the EFI stub on multiple
> + * architectures.
> + *
> + * Copyright 2019 Google, LLC
> + */
> +
> +#include <linux/efi.h>
> +#include <linux/pci.h>
> +
> +#include <asm/efi.h>
> +
> +#include "efistub.h"
> +
> +static efi_event_t __section(.data) exit_boot_services_event;
> +static efi_event_t __section(.data) disable_pci_dma_event;
> +
> +static efi_handle_t *__section(.data) pci_handle;
> +static unsigned long __section(.data) pci_handle_size;
> +
> +static efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
> +
> +static void __efiapi handle_exit_boot_services_event(efi_event_t event,
> +						     void *context)
> +{
> +	efi_call_early(signal_event, disable_pci_dma_event);
> +}
> +
> +static void __efiapi handle_disable_pci_dma_event(efi_event_t event,
> +						  void *context)
> +{
> +	efi_handle_t handle;
> +	efi_status_t status;
> +	u16 class, command;
> +	int i;
> +
> +	for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
> +		efi_pci_io_protocol_t *pci = NULL;
> +
> +		status = efi_call_early(handle_protocol, handle,
> +					&pci_proto, (void **)&pci);
> +		if (status != EFI_SUCCESS || !pci)
> +			continue;
> +
> +		status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
> +					PCI_CLASS_DEVICE, 1, &class);
> +
> +		if (status != EFI_SUCCESS || class != PCI_CLASS_BRIDGE_PCI)
> +			continue;
> +
> +		/* Disable busmastering */
> +		status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
> +					PCI_COMMAND, 1, &command);
> +		if (status != EFI_SUCCESS || !(command & PCI_COMMAND_MASTER))
> +			continue;
> +
> +		command &= ~PCI_COMMAND_MASTER;
> +		status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16,
> +					PCI_COMMAND, 1, &command);
> +		if (status != EFI_SUCCESS)
> +			pr_efi_err("Failed to disable PCI busmastering\n");
> +	}
> +}
> +
> +void efi_pci_disable_bridge_busmaster(void)
> +{
> +	efi_status_t status;
> +
> +	if (!disable_pci_dma() || !efi_is_native())
> +		return;
> +
> +	status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL,
> +				&pci_proto, NULL, &pci_handle_size, pci_handle);
> +
> +	if (status != EFI_BUFFER_TOO_SMALL) {
> +		if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
> +			pr_efi_err("Failed to locate PCI I/O handles'\n");
> +		return;
> +	}
> +
> +	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
> +				pci_handle_size, (void **)&pci_handle);
> +	if (status != EFI_SUCCESS) {
> +		pr_efi_err("Failed to allocate memory for 'pci_handle'\n");
> +		return;
> +	}
> +
> +	status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL,
> +				&pci_proto, NULL, &pci_handle_size, pci_handle);
> +	if (status != EFI_SUCCESS) {
> +		pr_efi_err("Failed to locate PCI I/O handles'\n");
> +		goto free_handle;
> +	}
> +
> +	status = efi_call_early(create_event, EVT_NOTIFY_SIGNAL,
> +				TPL_CALLBACK, handle_disable_pci_dma_event,
> +				NULL, &disable_pci_dma_event);
> +	if (status != EFI_SUCCESS) {
> +		pr_efi_err("Failed to create event to disable PCI DMA\n");
> +		goto free_handle;
> +	}
> +
> +	status = efi_call_early(create_event, EVT_SIGNAL_EXIT_BOOT_SERVICES,
> +				TPL_CALLBACK, handle_exit_boot_services_event,
> +				NULL, &exit_boot_services_event);
> +	if (status != EFI_SUCCESS) {
> +		pr_efi_err("Failed to register for EBS() event\n");
> +		goto free_handle;
> +	}
> +
> +	return;
> +
> +free_handle:
> +	efi_call_early(free_pool, pci_handle);
> +}
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 81bd1e8c201f..2864633abff0 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -1786,4 +1786,6 @@ struct linux_efi_memreserve {
>   #define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \
>   	/ sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
>   
> +void efi_pci_disable_bridge_busmaster(void);
> +
>   #endif /* _LINUX_EFI_H */
> 


^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2020-02-06 14:30   ` Hans de Goede
@ 2020-02-06 14:35     ` Ard Biesheuvel
  2020-03-04 10:38       ` Hans de Goede
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-02-06 14:35 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar, Matthew Garrett

On Thu, 6 Feb 2020 at 14:31, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> > From: Matthew Garrett <matthewgarrett@google.com>
> >
> > Add an option to disable the busmaster bit in the control register on
> > all PCI bridges during the invocation of ExitBootServices() and passing
> > control to the runtime kernel. System firmware may configure the IOMMU
> > to prevent malicious PCI devices from being able to attack the OS via DMA.
> > However, since firmware can't guarantee that the OS is IOMMU-aware, it
> > will tear down IOMMU configuration when ExitBootServices() is called.
> > This leaves a window between where a hostile device could still cause
> > damage before Linux configures the IOMMU again.
> >
> > If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
> > command line argument is passed, the EFI stub will clear the busmaster
> > bit on all PCI bridges before ExitBootServices() completes. This will
> > prevent any malicious PCI devices from being able to perform DMA until
> > the kernel reenables busmastering after configuring the IOMMU.
> >
> > This option is disabled when in EFI mixed mode environments (ie, 64-bit
> > kernels with a 32-bit EFI implementation), given that the use of EFI
> > events is not supported in this case.
> >
> > This option may cause failures with some poorly behaved hardware and
> > should not be enabled without testing. The kernel commandline options
> > "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
> > override the default.
> >
> > Co-developed-by: Matthew Garrett <mjg59@google.com>
> > Signed-off-by: Matthew Garrett <mjg59@google.com>
> > [ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> I guess this might not be the latest version of this patch, but
> this does seem to be the thread where most discussion on it
> has happened.
>
> My personal kernel tree atm consists of v5.5 + efi/next + my own patches
> and yesterday I noticed that will not boot on a Lenovo X1 7th gen connected
> to a Lenovo thunderbolt 3 gen 2 dock.
>
> My first hunch was that I have CONFIG_EFI_DISABLE_PCI_DMA=y and that that
> was causing it and indeed that is the problem.
>
> So as (somewhat) expected CONFIG_EFI_DISABLE_PCI_DMA=y indeed stops the kernel
> from booting on some systems.
>
> When I hit this problem the efistub prints 2 messages and then the system
> just hangs:
>
> exit_boot() failed!
> efi_main() failed!
>
> When I boot the system without it being connected to the thunderbolt dock
> then efi=disable_pci_dma works fine.
>
> Let me know if I can do anything to help and getting booting while
> connected to the dock to work with efi=disable_pci_dma.
>

Thanks Hans.

Can you run the UEFI shell on this system? If so, could you share the
output of devtree, both in the docked and the undocked states?

That should help us pinpoint which device is throwing an error at
ExitBootServices() time due to its driver having been disconnected.

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2020-02-06 14:35     ` Ard Biesheuvel
@ 2020-03-04 10:38       ` Hans de Goede
  2020-03-04 18:26         ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2020-03-04 10:38 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ard Biesheuvel, linux-efi, Matthew Garrett, Ingo Molnar,
	Andy Lutomirski, Thomas Gleixner, Arvind Sankar, Matthew Garrett

[-- Attachment #1: Type: text/plain, Size: 3344 bytes --]

Hi,

On 2/6/20 3:35 PM, Ard Biesheuvel wrote:
> On Thu, 6 Feb 2020 at 14:31, Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi,
>>
>> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
>>> From: Matthew Garrett <matthewgarrett@google.com>
>>>
>>> Add an option to disable the busmaster bit in the control register on
>>> all PCI bridges during the invocation of ExitBootServices() and passing
>>> control to the runtime kernel. System firmware may configure the IOMMU
>>> to prevent malicious PCI devices from being able to attack the OS via DMA.
>>> However, since firmware can't guarantee that the OS is IOMMU-aware, it
>>> will tear down IOMMU configuration when ExitBootServices() is called.
>>> This leaves a window between where a hostile device could still cause
>>> damage before Linux configures the IOMMU again.
>>>
>>> If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
>>> command line argument is passed, the EFI stub will clear the busmaster
>>> bit on all PCI bridges before ExitBootServices() completes. This will
>>> prevent any malicious PCI devices from being able to perform DMA until
>>> the kernel reenables busmastering after configuring the IOMMU.
>>>
>>> This option is disabled when in EFI mixed mode environments (ie, 64-bit
>>> kernels with a 32-bit EFI implementation), given that the use of EFI
>>> events is not supported in this case.
>>>
>>> This option may cause failures with some poorly behaved hardware and
>>> should not be enabled without testing. The kernel commandline options
>>> "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
>>> override the default.
>>>
>>> Co-developed-by: Matthew Garrett <mjg59@google.com>
>>> Signed-off-by: Matthew Garrett <mjg59@google.com>
>>> [ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>>
>> I guess this might not be the latest version of this patch, but
>> this does seem to be the thread where most discussion on it
>> has happened.
>>
>> My personal kernel tree atm consists of v5.5 + efi/next + my own patches
>> and yesterday I noticed that will not boot on a Lenovo X1 7th gen connected
>> to a Lenovo thunderbolt 3 gen 2 dock.
>>
>> My first hunch was that I have CONFIG_EFI_DISABLE_PCI_DMA=y and that that
>> was causing it and indeed that is the problem.
>>
>> So as (somewhat) expected CONFIG_EFI_DISABLE_PCI_DMA=y indeed stops the kernel
>> from booting on some systems.
>>
>> When I hit this problem the efistub prints 2 messages and then the system
>> just hangs:
>>
>> exit_boot() failed!
>> efi_main() failed!
>>
>> When I boot the system without it being connected to the thunderbolt dock
>> then efi=disable_pci_dma works fine.
>>
>> Let me know if I can do anything to help and getting booting while
>> connected to the dock to work with efi=disable_pci_dma.
>>
> 
> Thanks Hans.
> 
> Can you run the UEFI shell on this system? If so, could you share the
> output of devtree, both in the docked and the undocked states?
> 
> That should help us pinpoint which device is throwing an error at
> ExitBootServices() time due to its driver having been disconnected.

Sorry for being slow to respond. Attached are the outputs of devtree in
both states. Not sure if the list will accept this, but you should
get a direct copy.

Regards,

Hans

[-- Attachment #2: devtree-docked --]
[-- Type: application/octet-stream, Size: 23394 bytes --]

[-- Attachment #3: devtree-not-docked --]
[-- Type: application/octet-stream, Size: 8508 bytes --]

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2020-03-04 10:38       ` Hans de Goede
@ 2020-03-04 18:26         ` Ard Biesheuvel
  2020-03-04 18:49           ` Hans de Goede
  0 siblings, 1 reply; 87+ messages in thread
From: Ard Biesheuvel @ 2020-03-04 18:26 UTC (permalink / raw)
  To: Hans de Goede
  Cc: linux-efi, Matthew Garrett, Ingo Molnar, Andy Lutomirski,
	Thomas Gleixner, Arvind Sankar, Matthew Garrett

On Wed, 4 Mar 2020 at 11:39, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 2/6/20 3:35 PM, Ard Biesheuvel wrote:
> > On Thu, 6 Feb 2020 at 14:31, Hans de Goede <hdegoede@redhat.com> wrote:
> >>
> >> Hi,
> >>
> >> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> >>> From: Matthew Garrett <matthewgarrett@google.com>
> >>>
> >>> Add an option to disable the busmaster bit in the control register on
> >>> all PCI bridges during the invocation of ExitBootServices() and passing
> >>> control to the runtime kernel. System firmware may configure the IOMMU
> >>> to prevent malicious PCI devices from being able to attack the OS via DMA.
> >>> However, since firmware can't guarantee that the OS is IOMMU-aware, it
> >>> will tear down IOMMU configuration when ExitBootServices() is called.
> >>> This leaves a window between where a hostile device could still cause
> >>> damage before Linux configures the IOMMU again.
> >>>
> >>> If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
> >>> command line argument is passed, the EFI stub will clear the busmaster
> >>> bit on all PCI bridges before ExitBootServices() completes. This will
> >>> prevent any malicious PCI devices from being able to perform DMA until
> >>> the kernel reenables busmastering after configuring the IOMMU.
> >>>
> >>> This option is disabled when in EFI mixed mode environments (ie, 64-bit
> >>> kernels with a 32-bit EFI implementation), given that the use of EFI
> >>> events is not supported in this case.
> >>>
> >>> This option may cause failures with some poorly behaved hardware and
> >>> should not be enabled without testing. The kernel commandline options
> >>> "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
> >>> override the default.
> >>>
> >>> Co-developed-by: Matthew Garrett <mjg59@google.com>
> >>> Signed-off-by: Matthew Garrett <mjg59@google.com>
> >>> [ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
> >>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >>
> >> I guess this might not be the latest version of this patch, but
> >> this does seem to be the thread where most discussion on it
> >> has happened.
> >>
> >> My personal kernel tree atm consists of v5.5 + efi/next + my own patches
> >> and yesterday I noticed that will not boot on a Lenovo X1 7th gen connected
> >> to a Lenovo thunderbolt 3 gen 2 dock.
> >>
> >> My first hunch was that I have CONFIG_EFI_DISABLE_PCI_DMA=y and that that
> >> was causing it and indeed that is the problem.
> >>
> >> So as (somewhat) expected CONFIG_EFI_DISABLE_PCI_DMA=y indeed stops the kernel
> >> from booting on some systems.
> >>
> >> When I hit this problem the efistub prints 2 messages and then the system
> >> just hangs:
> >>
> >> exit_boot() failed!
> >> efi_main() failed!
> >>
> >> When I boot the system without it being connected to the thunderbolt dock
> >> then efi=disable_pci_dma works fine.
> >>
> >> Let me know if I can do anything to help and getting booting while
> >> connected to the dock to work with efi=disable_pci_dma.
> >>
> >
> > Thanks Hans.
> >
> > Can you run the UEFI shell on this system? If so, could you share the
> > output of devtree, both in the docked and the undocked states?
> >
> > That should help us pinpoint which device is throwing an error at
> > ExitBootServices() time due to its driver having been disconnected.
>
> Sorry for being slow to respond. Attached are the outputs of devtree in
> both states. Not sure if the list will accept this, but you should
> get a direct copy.
>

Interesting. The only difference that UEFI seems to know about in
terms of device hierarchy is a XHCI controller with a Realtek USB NIC
attached.

Could you try unloading the driver for that manually, or disconnecting
it? Or disconnect the whole thing from the shell?

If just unloading the realtek driver does not make a difference, but
unload/disconnecting the xhci makes it work, it is likely that it this
feature will break a lot of systems.






--- Downloads/devtree-not-docked 2020-03-04 19:18:14.596315280 +0100
+++ Downloads/devtree-docked 2020-03-04 19:18:08.856257969 +0100
@@ -11,6 +11,7 @@
    Ctrl[] PciRoot(0x0)/Pci(0x0,0x0)
    Ctrl[] Intel(R) Graphics Controller
      Ctrl[] EDP1
+     Ctrl[] DP1
        Ctrl[] Primary Console Output Device
    Ctrl[] PciRoot(0x0)/Pci(0x4,0x0)
    Ctrl[] PciRoot(0x0)/Pci(0x8,0x0)
@@ -44,6 +45,110 @@
    Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x0,0x0)
    Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)
    Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)
+   Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)
+   Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)
+   Ctrl[] eXtensible Host Controller (USB 3.0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x3,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x4,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x3,0x0)/USB(0x0,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x2,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x3,0x0)/USB(0x0,0x0)/USB(0x1,0x0)
+       Ctrl[] Realtek USB Ethernet Controller
<lots of network stuff>
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x1)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x2)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x3)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x2,0x0)/USB(0x3,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)/USB(0x0,0x0)
+     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)/USB(0x1,0x0)
+     Ctrl[] Generic Usb Keyboard
+       Ctrl[] Primary Console Input Device
+     Ctrl[] Generic Usb Mouse
+       Ctrl[] Primary Console Input Device
+     Ctrl[] Generic Usb Mouse
+       Ctrl[] Primary Console Input Device
+   Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x4,0x0)
    Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x2,0x0)
    Ctrl[] eXtensible Host Controller (USB 3.0)
    Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x4,0x0)
@@ -69,5 +174,3 @@
  Ctrl[] VenHw(2C0EEABD-4107-44A8-A787-2E38FFC52B2B)
  Ctrl[] VenHw(48B9FB42-B3B9-4A0E-BF66-36AE1C302369)
  Ctrl[] VenHw(A7F26116-CFDC-4296-8224-ED7D140170C7)
- Ctrl[] MemoryMapped(0xB,0xFF2E0000,0xFF37FFFF)
- Ctrl[] Fv(B92CF322-8AFA-4AA4-B946-005DF1D69778)

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2020-03-04 18:26         ` Ard Biesheuvel
@ 2020-03-04 18:49           ` Hans de Goede
  2020-03-04 21:59             ` Ard Biesheuvel
  0 siblings, 1 reply; 87+ messages in thread
From: Hans de Goede @ 2020-03-04 18:49 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, Matthew Garrett, Ingo Molnar, Andy Lutomirski,
	Thomas Gleixner, Arvind Sankar, Matthew Garrett

[-- Attachment #1: Type: text/plain, Size: 8499 bytes --]

Hi,

On 3/4/20 7:26 PM, Ard Biesheuvel wrote:
> On Wed, 4 Mar 2020 at 11:39, Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi,
>>
>> On 2/6/20 3:35 PM, Ard Biesheuvel wrote:
>>> On Thu, 6 Feb 2020 at 14:31, Hans de Goede <hdegoede@redhat.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
>>>>> From: Matthew Garrett <matthewgarrett@google.com>
>>>>>
>>>>> Add an option to disable the busmaster bit in the control register on
>>>>> all PCI bridges during the invocation of ExitBootServices() and passing
>>>>> control to the runtime kernel. System firmware may configure the IOMMU
>>>>> to prevent malicious PCI devices from being able to attack the OS via DMA.
>>>>> However, since firmware can't guarantee that the OS is IOMMU-aware, it
>>>>> will tear down IOMMU configuration when ExitBootServices() is called.
>>>>> This leaves a window between where a hostile device could still cause
>>>>> damage before Linux configures the IOMMU again.
>>>>>
>>>>> If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
>>>>> command line argument is passed, the EFI stub will clear the busmaster
>>>>> bit on all PCI bridges before ExitBootServices() completes. This will
>>>>> prevent any malicious PCI devices from being able to perform DMA until
>>>>> the kernel reenables busmastering after configuring the IOMMU.
>>>>>
>>>>> This option is disabled when in EFI mixed mode environments (ie, 64-bit
>>>>> kernels with a 32-bit EFI implementation), given that the use of EFI
>>>>> events is not supported in this case.
>>>>>
>>>>> This option may cause failures with some poorly behaved hardware and
>>>>> should not be enabled without testing. The kernel commandline options
>>>>> "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
>>>>> override the default.
>>>>>
>>>>> Co-developed-by: Matthew Garrett <mjg59@google.com>
>>>>> Signed-off-by: Matthew Garrett <mjg59@google.com>
>>>>> [ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
>>>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>>>>
>>>> I guess this might not be the latest version of this patch, but
>>>> this does seem to be the thread where most discussion on it
>>>> has happened.
>>>>
>>>> My personal kernel tree atm consists of v5.5 + efi/next + my own patches
>>>> and yesterday I noticed that will not boot on a Lenovo X1 7th gen connected
>>>> to a Lenovo thunderbolt 3 gen 2 dock.
>>>>
>>>> My first hunch was that I have CONFIG_EFI_DISABLE_PCI_DMA=y and that that
>>>> was causing it and indeed that is the problem.
>>>>
>>>> So as (somewhat) expected CONFIG_EFI_DISABLE_PCI_DMA=y indeed stops the kernel
>>>> from booting on some systems.
>>>>
>>>> When I hit this problem the efistub prints 2 messages and then the system
>>>> just hangs:
>>>>
>>>> exit_boot() failed!
>>>> efi_main() failed!
>>>>
>>>> When I boot the system without it being connected to the thunderbolt dock
>>>> then efi=disable_pci_dma works fine.
>>>>
>>>> Let me know if I can do anything to help and getting booting while
>>>> connected to the dock to work with efi=disable_pci_dma.
>>>>
>>>
>>> Thanks Hans.
>>>
>>> Can you run the UEFI shell on this system? If so, could you share the
>>> output of devtree, both in the docked and the undocked states?
>>>
>>> That should help us pinpoint which device is throwing an error at
>>> ExitBootServices() time due to its driver having been disconnected.
>>
>> Sorry for being slow to respond. Attached are the outputs of devtree in
>> both states. Not sure if the list will accept this, but you should
>> get a direct copy.
>>
> 
> Interesting. The only difference that UEFI seems to know about in
> terms of device hierarchy is a XHCI controller with a Realtek USB NIC
> attached.
> 
> Could you try unloading the driver for that manually, or disconnecting
> it? Or disconnect the whole thing from the shell?

How would I go about that / do that ?

> If just unloading the realtek driver does not make a difference, but
> unload/disconnecting the xhci makes it work, it is likely that it this
> feature will break a lot of systems.

Notice that it is not just the XHCI controller which gets added though,
there also is an extra PCI-e switch added to the route to the XHCI controller,
I've attached both docked and undocked lspci output under Linux. I guess
this might be transparent from a UEFI pov though.

Regards,

Hans



> --- Downloads/devtree-not-docked 2020-03-04 19:18:14.596315280 +0100
> +++ Downloads/devtree-docked 2020-03-04 19:18:08.856257969 +0100
> @@ -11,6 +11,7 @@
>      Ctrl[] PciRoot(0x0)/Pci(0x0,0x0)
>      Ctrl[] Intel(R) Graphics Controller
>        Ctrl[] EDP1
> +     Ctrl[] DP1
>          Ctrl[] Primary Console Output Device
>      Ctrl[] PciRoot(0x0)/Pci(0x4,0x0)
>      Ctrl[] PciRoot(0x0)/Pci(0x8,0x0)
> @@ -44,6 +45,110 @@
>      Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x0,0x0)
>      Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)
>      Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)
> +   Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)
> +   Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)
> +   Ctrl[] eXtensible Host Controller (USB 3.0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x3,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x4,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x3,0x0)/USB(0x0,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x2,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x3,0x0)/USB(0x0,0x0)/USB(0x1,0x0)
> +       Ctrl[] Realtek USB Ethernet Controller
> <lots of network stuff>
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x1)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x2)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x0,0x0)/USB(0x3,0x3)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x2,0x0)/USB(0x3,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)/USB(0x0,0x0)
> +     Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/USB(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)/USB(0x1,0x0)
> +     Ctrl[] Generic Usb Keyboard
> +       Ctrl[] Primary Console Input Device
> +     Ctrl[] Generic Usb Mouse
> +       Ctrl[] Primary Console Input Device
> +     Ctrl[] Generic Usb Mouse
> +       Ctrl[] Primary Console Input Device
> +   Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x4,0x0)
>      Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x2,0x0)
>      Ctrl[] eXtensible Host Controller (USB 3.0)
>      Ctrl[] PciRoot(0x0)/Pci(0x1D,0x4)/Pci(0x0,0x0)/Pci(0x4,0x0)
> @@ -69,5 +174,3 @@
>    Ctrl[] VenHw(2C0EEABD-4107-44A8-A787-2E38FFC52B2B)
>    Ctrl[] VenHw(48B9FB42-B3B9-4A0E-BF66-36AE1C302369)
>    Ctrl[] VenHw(A7F26116-CFDC-4296-8224-ED7D140170C7)
> - Ctrl[] MemoryMapped(0xB,0xFF2E0000,0xFF37FFFF)
> - Ctrl[] Fv(B92CF322-8AFA-4AA4-B946-005DF1D69778)
> 

[-- Attachment #2: lspci-docked --]
[-- Type: text/plain, Size: 3092 bytes --]

00:00.0 Host bridge: Intel Corporation Coffee Lake HOST and DRAM Controller (rev 0c)
00:02.0 VGA compatible controller: Intel Corporation UHD Graphics 620 (Whiskey Lake) (rev 02)
00:04.0 Signal processing controller: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (rev 0c)
00:08.0 System peripheral: Intel Corporation Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model
00:12.0 Signal processing controller: Intel Corporation Cannon Point-LP Thermal Controller (rev 11)
00:14.0 USB controller: Intel Corporation Cannon Point-LP USB 3.1 xHCI Controller (rev 11)
00:14.2 RAM memory: Intel Corporation Cannon Point-LP Shared SRAM (rev 11)
00:14.3 Network controller: Intel Corporation Cannon Point-LP CNVi [Wireless-AC] (rev 11)
00:15.0 Serial bus controller [0c80]: Intel Corporation Cannon Point-LP Serial IO I2C Controller #0 (rev 11)
00:15.1 Serial bus controller [0c80]: Intel Corporation Cannon Point-LP Serial IO I2C Controller #1 (rev 11)
00:16.0 Communication controller: Intel Corporation Cannon Point-LP MEI Controller #1 (rev 11)
00:16.3 Serial controller: Intel Corporation Cannon Point-LP Keyboard and Text (KT) Redirection (rev 11)
00:1d.0 PCI bridge: Intel Corporation Cannon Point-LP PCI Express Root Port #9 (rev f1)
00:1d.4 PCI bridge: Intel Corporation Cannon Point-LP PCI Express Root Port #13 (rev f1)
00:1f.0 ISA bridge: Intel Corporation Cannon Point-LP LPC Controller (rev 11)
00:1f.3 Audio device: Intel Corporation Cannon Point-LP High Definition Audio Controller (rev 11)
00:1f.4 SMBus: Intel Corporation Cannon Point-LP SMBus Controller (rev 11)
00:1f.5 Serial bus controller [0c80]: Intel Corporation Cannon Point-LP SPI Controller (rev 11)
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (6) I219-LM (rev 11)
03:00.0 Non-Volatile memory controller: Sandisk Corp WD Black 2018/PC SN720 NVMe SSD
05:00.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:00.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:01.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:02.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:04.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
07:00.0 System peripheral: Intel Corporation JHL6540 Thunderbolt 3 NHI (C step) [Alpine Ridge 4C 2016] (rev 02)
08:00.0 PCI bridge: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018] (rev 06)
09:02.0 PCI bridge: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018] (rev 06)
09:04.0 PCI bridge: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018] (rev 06)
0a:00.0 USB controller: Intel Corporation JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] (rev 06)
2d:00.0 USB controller: Intel Corporation JHL6540 Thunderbolt 3 USB Controller (C step) [Alpine Ridge 4C 2016] (rev 02)

[-- Attachment #3: lspci-not-docked --]
[-- Type: text/plain, Size: 2688 bytes --]

00:00.0 Host bridge: Intel Corporation Coffee Lake HOST and DRAM Controller (rev 0c)
00:02.0 VGA compatible controller: Intel Corporation UHD Graphics 620 (Whiskey Lake) (rev 02)
00:04.0 Signal processing controller: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (rev 0c)
00:08.0 System peripheral: Intel Corporation Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model
00:12.0 Signal processing controller: Intel Corporation Cannon Point-LP Thermal Controller (rev 11)
00:14.0 USB controller: Intel Corporation Cannon Point-LP USB 3.1 xHCI Controller (rev 11)
00:14.2 RAM memory: Intel Corporation Cannon Point-LP Shared SRAM (rev 11)
00:14.3 Network controller: Intel Corporation Cannon Point-LP CNVi [Wireless-AC] (rev 11)
00:15.0 Serial bus controller [0c80]: Intel Corporation Cannon Point-LP Serial IO I2C Controller #0 (rev 11)
00:15.1 Serial bus controller [0c80]: Intel Corporation Cannon Point-LP Serial IO I2C Controller #1 (rev 11)
00:16.0 Communication controller: Intel Corporation Cannon Point-LP MEI Controller #1 (rev 11)
00:16.3 Serial controller: Intel Corporation Cannon Point-LP Keyboard and Text (KT) Redirection (rev 11)
00:1d.0 PCI bridge: Intel Corporation Cannon Point-LP PCI Express Root Port #9 (rev f1)
00:1d.4 PCI bridge: Intel Corporation Cannon Point-LP PCI Express Root Port #13 (rev f1)
00:1f.0 ISA bridge: Intel Corporation Cannon Point-LP LPC Controller (rev 11)
00:1f.3 Audio device: Intel Corporation Cannon Point-LP High Definition Audio Controller (rev 11)
00:1f.4 SMBus: Intel Corporation Cannon Point-LP SMBus Controller (rev 11)
00:1f.5 Serial bus controller [0c80]: Intel Corporation Cannon Point-LP SPI Controller (rev 11)
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (6) I219-LM (rev 11)
03:00.0 Non-Volatile memory controller: Sandisk Corp WD Black 2018/PC SN720 NVMe SSD
05:00.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:00.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:01.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:02.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
06:04.0 PCI bridge: Intel Corporation JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] (rev 02)
07:00.0 System peripheral: Intel Corporation JHL6540 Thunderbolt 3 NHI (C step) [Alpine Ridge 4C 2016] (rev 02)
2d:00.0 USB controller: Intel Corporation JHL6540 Thunderbolt 3 USB Controller (C step) [Alpine Ridge 4C 2016] (rev 02)

[-- Attachment #4: lspci-t-docked --]
[-- Type: text/plain, Size: 710 bytes --]

-[0000:00]-+-00.0
           +-02.0
           +-04.0
           +-08.0
           +-12.0
           +-14.0
           +-14.2
           +-14.3
           +-15.0
           +-15.1
           +-16.0
           +-16.3
           +-1d.0-[03]----00.0
           +-1d.4-[05-52]----00.0-[06-52]--+-00.0-[07]----00.0
           |                               +-01.0-[08-2c]----00.0-[09-2c]--+-02.0-[0a]----00.0
           |                               |                               \-04.0-[0b-2c]--
           |                               +-02.0-[2d]----00.0
           |                               \-04.0-[2e-52]--
           +-1f.0
           +-1f.3
           +-1f.4
           +-1f.5
           \-1f.6

[-- Attachment #5: lspci-t-not-docked --]
[-- Type: text/plain, Size: 583 bytes --]

-[0000:00]-+-00.0
           +-02.0
           +-04.0
           +-08.0
           +-12.0
           +-14.0
           +-14.2
           +-14.3
           +-15.0
           +-15.1
           +-16.0
           +-16.3
           +-1d.0-[03]----00.0
           +-1d.4-[05-52]----00.0-[06-52]--+-00.0-[07]----00.0
           |                               +-01.0-[08-2c]--
           |                               +-02.0-[2d]----00.0
           |                               \-04.0-[2e-52]--
           +-1f.0
           +-1f.3
           +-1f.4
           +-1f.5
           \-1f.6

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot
  2020-03-04 18:49           ` Hans de Goede
@ 2020-03-04 21:59             ` Ard Biesheuvel
  0 siblings, 0 replies; 87+ messages in thread
From: Ard Biesheuvel @ 2020-03-04 21:59 UTC (permalink / raw)
  To: Hans de Goede
  Cc: linux-efi, Matthew Garrett, Ingo Molnar, Andy Lutomirski,
	Thomas Gleixner, Arvind Sankar, Matthew Garrett

On Wed, 4 Mar 2020 at 19:49, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 3/4/20 7:26 PM, Ard Biesheuvel wrote:
> > On Wed, 4 Mar 2020 at 11:39, Hans de Goede <hdegoede@redhat.com> wrote:
> >>
> >> Hi,
> >>
> >> On 2/6/20 3:35 PM, Ard Biesheuvel wrote:
> >>> On Thu, 6 Feb 2020 at 14:31, Hans de Goede <hdegoede@redhat.com> wrote:
> >>>>
> >>>> Hi,
> >>>>
> >>>> On 12/18/19 6:01 PM, Ard Biesheuvel wrote:
> >>>>> From: Matthew Garrett <matthewgarrett@google.com>
> >>>>>
> >>>>> Add an option to disable the busmaster bit in the control register on
> >>>>> all PCI bridges during the invocation of ExitBootServices() and passing
> >>>>> control to the runtime kernel. System firmware may configure the IOMMU
> >>>>> to prevent malicious PCI devices from being able to attack the OS via DMA.
> >>>>> However, since firmware can't guarantee that the OS is IOMMU-aware, it
> >>>>> will tear down IOMMU configuration when ExitBootServices() is called.
> >>>>> This leaves a window between where a hostile device could still cause
> >>>>> damage before Linux configures the IOMMU again.
> >>>>>
> >>>>> If CONFIG_EFI_DISABLE_PCI_DMA is enabled or the "efi=disable_pci_dma"
> >>>>> command line argument is passed, the EFI stub will clear the busmaster
> >>>>> bit on all PCI bridges before ExitBootServices() completes. This will
> >>>>> prevent any malicious PCI devices from being able to perform DMA until
> >>>>> the kernel reenables busmastering after configuring the IOMMU.
> >>>>>
> >>>>> This option is disabled when in EFI mixed mode environments (ie, 64-bit
> >>>>> kernels with a 32-bit EFI implementation), given that the use of EFI
> >>>>> events is not supported in this case.
> >>>>>
> >>>>> This option may cause failures with some poorly behaved hardware and
> >>>>> should not be enabled without testing. The kernel commandline options
> >>>>> "efi=disable_pci_dma" or "efi=no_disable_pci_dma" may be used to
> >>>>> override the default.
> >>>>>
> >>>>> Co-developed-by: Matthew Garrett <mjg59@google.com>
> >>>>> Signed-off-by: Matthew Garrett <mjg59@google.com>
> >>>>> [ardb: use EFI events to defer DMA disabling to the end of ExitBootServices()]
> >>>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >>>>
> >>>> I guess this might not be the latest version of this patch, but
> >>>> this does seem to be the thread where most discussion on it
> >>>> has happened.
> >>>>
> >>>> My personal kernel tree atm consists of v5.5 + efi/next + my own patches
> >>>> and yesterday I noticed that will not boot on a Lenovo X1 7th gen connected
> >>>> to a Lenovo thunderbolt 3 gen 2 dock.
> >>>>
> >>>> My first hunch was that I have CONFIG_EFI_DISABLE_PCI_DMA=y and that that
> >>>> was causing it and indeed that is the problem.
> >>>>
> >>>> So as (somewhat) expected CONFIG_EFI_DISABLE_PCI_DMA=y indeed stops the kernel
> >>>> from booting on some systems.
> >>>>
> >>>> When I hit this problem the efistub prints 2 messages and then the system
> >>>> just hangs:
> >>>>
> >>>> exit_boot() failed!
> >>>> efi_main() failed!
> >>>>
> >>>> When I boot the system without it being connected to the thunderbolt dock
> >>>> then efi=disable_pci_dma works fine.
> >>>>
> >>>> Let me know if I can do anything to help and getting booting while
> >>>> connected to the dock to work with efi=disable_pci_dma.
> >>>>
> >>>
> >>> Thanks Hans.
> >>>
> >>> Can you run the UEFI shell on this system? If so, could you share the
> >>> output of devtree, both in the docked and the undocked states?
> >>>
> >>> That should help us pinpoint which device is throwing an error at
> >>> ExitBootServices() time due to its driver having been disconnected.
> >>
> >> Sorry for being slow to respond. Attached are the outputs of devtree in
> >> both states. Not sure if the list will accept this, but you should
> >> get a direct copy.
> >>
> >
> > Interesting. The only difference that UEFI seems to know about in
> > terms of device hierarchy is a XHCI controller with a Realtek USB NIC
> > attached.
> >
> > Could you try unloading the driver for that manually, or disconnecting
> > it? Or disconnect the whole thing from the shell?
>
> How would I go about that / do that ?
>
> > If just unloading the realtek driver does not make a difference, but
> > unload/disconnecting the xhci makes it work, it is likely that it this
> > feature will break a lot of systems.
>
> Notice that it is not just the XHCI controller which gets added though,
> there also is an extra PCI-e switch added to the route to the XHCI controller,
> I've attached both docked and undocked lspci output under Linux. I guess
> this might be transparent from a UEFI pov though.
>

Yeah, what matters is drivers that are actually called when the EFI
stub calls ExitBootServices(), and looking at the dump, the XHCI
driver and the Realtek driver are the only ones that stand out to me
(and the Realtek one is probably the only 3rd party driver, so that
one looks the most suspect to me)

^ permalink raw reply	[flat|nested] 87+ messages in thread

end of thread, other threads:[~2020-03-04 21:59 UTC | newest]

Thread overview: 87+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 01/21] efi/libstub: remove unused __efi_call_early() macro Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 02/21] efi/x86: rename efi_is_native() to efi_is_mixed() Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 03/21] efi/libstub: use a helper to iterate over a EFI handle array Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 04/21] efi/libstub: extend native protocol definitions with mixed_mode aliases Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 05/21] efi/libstub: distinguish between native/mixed not 32/64 bit Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 06/21] efi/libstub/x86: use mixed mode helpers to populate efi_config Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 07/21] efi/libstub: drop explicit 32/64-bit protocol definitions Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 08/21] efi/libstub: use stricter typing for firmware function pointers Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 09/21] efi/libstub: annotate firmware routines as __efiapi Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls Ard Biesheuvel
2019-12-21 21:22   ` Hans de Goede
2019-12-22 12:02     ` Ard Biesheuvel
2019-12-22 12:37       ` Ard Biesheuvel
2019-12-22 12:46       ` Andy Lutomirski
2019-12-22 15:29         ` Ard Biesheuvel
2019-12-22 21:12           ` Arvind Sankar
2019-12-22 21:25             ` Ard Biesheuvel
2019-12-23 11:49       ` Hans de Goede
2019-12-23 12:00         ` Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 11/21] efi/libstub: get rid of 'sys_table_arg' macro parameter Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 12/21] efi/libstub: unify the efi_char16_printk implementations Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct Ard Biesheuvel
2019-12-24 19:34   ` Hans de Goede
2019-12-25 14:42     ` Ard Biesheuvel
2019-12-27 22:44       ` Hans de Goede
2019-12-27 22:51         ` Ard Biesheuvel
2019-12-31 23:04   ` Arvind Sankar
2020-01-01 18:13     ` Ard Biesheuvel
2020-01-01 19:08       ` Arvind Sankar
2020-01-02  7:33         ` Ard Biesheuvel
2020-01-02 14:06           ` Arvind Sankar
2020-01-02 15:20             ` Ard Biesheuvel
2020-01-02 15:51               ` Arvind Sankar
2020-01-02 15:58                 ` Ard Biesheuvel
2020-01-02 16:28                   ` Ard Biesheuvel
2020-01-02 16:59                     ` Ard Biesheuvel
2020-01-02 17:26                       ` Arvind Sankar
2020-01-02 17:30                         ` Ard Biesheuvel
2020-01-02 17:41                           ` Arvind Sankar
2020-01-02 17:48                             ` Ard Biesheuvel
2020-01-02 18:10                               ` Arvind Sankar
2020-01-02 18:38                                 ` Ard Biesheuvel
2020-01-03 14:16                                   ` Arvind Sankar
2020-01-03 14:23                                     ` Ard Biesheuvel
2020-01-02 18:38                               ` Arvind Sankar
2020-01-02 16:59                     ` Arvind Sankar
2020-01-02 17:03                       ` Ard Biesheuvel
2020-01-02 17:21                         ` Arvind Sankar
2019-12-18 17:01 ` [PATCH v2 14/21] efi/libstub: drop sys_table_arg from printk routines Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 15/21] efi/libstub: remove 'sys_table_arg' from all function prototypes Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 16/21] efi/libstub: drop protocol argument from efi_call_proto() macro Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 17/21] efi/libstub: drop 'table' argument from efi_table_attr() macro Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter Ard Biesheuvel
2019-12-31 16:51   ` Arvind Sankar
2019-12-31 17:06     ` Ard Biesheuvel
2019-12-31 17:36       ` Arvind Sankar
2019-12-18 17:01 ` [PATCH v2 19/21] efi/libstub: tidy up types and names of global cmdline variables Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 20/21] efi/libstub: import type definitions for creating and signalling events Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
2019-12-19  2:50   ` Andy Lutomirski
2019-12-19 13:17     ` Ard Biesheuvel
2019-12-19 20:04       ` Matthew Garrett
2019-12-19 20:04   ` Matthew Garrett
2019-12-20  7:06     ` Ard Biesheuvel
2019-12-20  7:17       ` Andy Lutomirski
2019-12-20  8:11         ` Ard Biesheuvel
2019-12-20 19:41           ` Arvind Sankar
2020-01-02 14:46             ` Laszlo Ersek
2020-01-02 15:40               ` Ard Biesheuvel
2019-12-20 20:43       ` Matthew Garrett
2019-12-21 16:44         ` Ard Biesheuvel
2019-12-21 21:24           ` Matthew Garrett
2019-12-21 22:54             ` Arvind Sankar
2019-12-23 14:02               ` Ard Biesheuvel
2019-12-23 15:46                 ` Arvind Sankar
2019-12-23 15:58                   ` Ard Biesheuvel
2019-12-23 16:12                     ` Arvind Sankar
2019-12-23 20:57                   ` Matthew Garrett
2020-02-06 14:30   ` Hans de Goede
2020-02-06 14:35     ` Ard Biesheuvel
2020-03-04 10:38       ` Hans de Goede
2020-03-04 18:26         ` Ard Biesheuvel
2020-03-04 18:49           ` Hans de Goede
2020-03-04 21:59             ` Ard Biesheuvel
2019-12-19 11:12 ` [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Hans de Goede
2019-12-19 13:22   ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).