Skip to contentSkip to conversation

EFI updates for v5.8

GIT PULL In review Ard Biesheuvel 4 participants 40 messages Apr 24, 2020 – May 3, 2020

Subsystems (6)
lore
Share & tools
lore

Ard Biesheuvel

author maintainer
#0 lore raw

Hello Ingo, Thomas,

Please pull the attached changes into tip/efi/next. There is some coordination going on with the RISC-V tree this time, so please take the patches in this exact order, and apply them onto v5.7-rc2 so the first three patches can serve as a shared stable base between the efi/core branch and the riscv tree.

The following changes since commit ae83d0b416db002fe95601e7f97f64b59514d936:

Linux 5.7-rc2 (2020-04-19 14:35:30 -0700)

are available in the Git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git tags/efi-next

for you to fetch changes up to 4eb8320bd1aaa7e69d039f2c251735e3ef0b9a38:

efi: Move arch_tables check to caller (2020-04-24 14:52:16 +0200)

----------------------------------------------------------------
EFI changes for v5.8:
- preliminary changes for RISC-V
- add support for setting the resolution on the EFI framebuffer
- simplify kernel image loading for arm64
- Move .bss into .data via the linker script instead of relying on symbol annotations.
- Get rid of __pure getters to access global variables
- Clean up the config table matching arrays

----------------------------------------------------------------
Ard Biesheuvel (14):
efi/libstub: Make initrd file loader configurable efi/libstub: Unify EFI call wrappers for non-x86 efi/libstub/random: Align allocate size to EFI_ALLOC_ALIGN efi/libstub/random: Increase random alloc granularity efi/libstub/arm64: Replace 'preferred' offset with alignment check efi/libstub/arm64: Simplify randomized loading of kernel image efi/libstub: Add API function to allocate aligned memory efi/libstub/arm64: Switch to ordinary page allocator for kernel image efi/libstub: Move efi_relocate_kernel() into separate source file efi/libstub: Drop __pure getter for efi_system_table efi/libstub: Drop __pure getters for EFI stub options efi/libstub/x86: Avoid getter function for efi_is64
efi: Clean up config table description arrays
efi: Move arch_tables check to caller

Arvind Sankar (17):
efi/gop: Remove redundant current_fb_base efi/gop: Move check for framebuffer before con_out efi/gop: Get mode information outside the loop efi/gop: Factor out locating the gop into a function efi/gop: Slightly re-arrange logic of find_gop efi/gop: Move variable declarations into loop block efi/gop: Use helper macros for populating lfb_base efi/gop: Use helper macros for find_bits efi/gop: Remove unreachable code from setup_pixel_info efi/gop: Add prototypes for query_mode and set_mode efi/gop: Allow specifying mode number on command line efi/gop: Allow specifying mode by <xres>x<yres> efi/gop: Allow specifying depth as well as resolution efi/gop: Allow automatically choosing the best mode efi/arm: Remove __efistub_global annotation efi/x86: Remove __efistub_global and add relocation check
efi: Kill __efistub_global

Atish Patra (1):
efi/libstub: Move arm-stub to a common file

Zou Wei (1):
efi/libstub/arm: Make install_memreserve_table static

 Documentation/fb/efifb.rst                         |  33 +-
 arch/arm/Kconfig                                   |   2 +-
 arch/arm/boot/compressed/vmlinux.lds.S             |   2 +-
 arch/arm/include/asm/efi.h                         |   8 -
 arch/arm64/Kconfig                                 |   2 +-
 arch/arm64/include/asm/efi.h                       |   8 -
 arch/ia64/kernel/efi.c                             |  12 +-
 arch/x86/boot/compressed/vmlinux.lds.S             |   1 +
 arch/x86/include/asm/efi.h                         |  29 +-
 arch/x86/platform/efi/efi.c                        |   8 +-
 drivers/firmware/efi/Kconfig                       |  15 +-
 drivers/firmware/efi/arm-init.c                    |   4 +-
 drivers/firmware/efi/efi.c                         |  44 +-
 drivers/firmware/efi/libstub/Makefile              |  42 +-
 drivers/firmware/efi/libstub/alignedmem.c          |  57 +++
 drivers/firmware/efi/libstub/arm64-stub.c          |  94 ++--
 drivers/firmware/efi/libstub/efi-stub-helper.c     |  47 +-
 .../efi/libstub/{arm-stub.c => efi-stub.c}         |  23 +-
 drivers/firmware/efi/libstub/efistub.h             |  96 ++--
 drivers/firmware/efi/libstub/fdt.c                 |   8 +-
 drivers/firmware/efi/libstub/file.c                |  34 +-
 drivers/firmware/efi/libstub/gop.c                 | 492 ++++++++++++++++-----
 drivers/firmware/efi/libstub/mem.c                 | 191 +-------
 drivers/firmware/efi/libstub/randomalloc.c         |   6 +-
 drivers/firmware/efi/libstub/relocate.c            | 174 ++++++++
 drivers/firmware/efi/libstub/x86-stub.c            |  35 +-
 include/linux/efi.h                                |   2 +-
 27 files changed, 895 insertions(+), 574 deletions(-)
 create mode 100644 drivers/firmware/efi/libstub/alignedmem.c
 rename drivers/firmware/efi/libstub/{arm-stub.c => efi-stub.c} (96%)
 create mode 100644 drivers/firmware/efi/libstub/relocate.c
author maintainer
#1 lore raw

PATCH 1/33 efi/libstub: Move arm-stub to a common file

From: Atish Patra <[email protected]>

Most of the arm-stub code is written in an architecture independent manner. As a result, RISC-V can reuse most of the arm-stub code.

Rename the arm-stub.c to efi-stub.c so that ARM, ARM64 and RISC-V can use it. This patch doesn't introduce any functional changes.

---
 arch/arm/Kconfig                                     |  2 +-
 arch/arm64/Kconfig                                   |  2 +-
 drivers/firmware/efi/Kconfig                         |  4 ++--
 drivers/firmware/efi/libstub/Makefile                | 12 ++++++------
 .../firmware/efi/libstub/{arm-stub.c => efi-stub.c}  |  0
 5 files changed, 10 insertions(+), 10 deletions(-)
 rename drivers/firmware/efi/libstub/{arm-stub.c => efi-stub.c} (100%)
arch/arm/Kconfig +1 -1
index 66a04f6f4775..165987aa5bcd 100644
@@ -1954,7 +1954,7 @@ config EFI
 	select UCS2_STRING
 	select EFI_PARAMS_FROM_FDT
 	select EFI_STUB
-	select EFI_ARMSTUB
+	select EFI_GENERIC_STUB
 	select EFI_RUNTIME_WRAPPERS
 	---help---
 	  This option provides support for runtime services provided
arch/arm64/Kconfig +1 -1
index 40fb05d96c60..32d818c5ccda 100644
@@ -1785,7 +1785,7 @@ config EFI
 	select EFI_PARAMS_FROM_FDT
 	select EFI_RUNTIME_WRAPPERS
 	select EFI_STUB
-	select EFI_ARMSTUB
+	select EFI_GENERIC_STUB
 	default y
 	help
 	  This option provides support for runtime services provided
drivers/firmware/efi/Kconfig +2 -2
index 613828d3f106..2a2b2b96a1dc 100644
@@ -106,12 +106,12 @@ config EFI_PARAMS_FROM_FDT
 config EFI_RUNTIME_WRAPPERS
 	bool
 
-config EFI_ARMSTUB
+config EFI_GENERIC_STUB
 	bool
 
 config EFI_ARMSTUB_DTB_LOADER
 	bool "Enable the DTB loader"
-	depends on EFI_ARMSTUB
+	depends on EFI_GENERIC_STUB
 	default y
 	help
 	  Select this config option to add support for the dtb= command
drivers/firmware/efi/libstub/Makefile +6 -6
index 094eabdecfe6..75cb2c3a1519 100644
@@ -23,7 +23,7 @@ cflags-$(CONFIG_ARM)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
 				   -fno-builtin -fpic \
 				   $(call cc-option,-mno-single-pic-base)
 
-cflags-$(CONFIG_EFI_ARMSTUB)	+= -I$(srctree)/scripts/dtc/libfdt
+cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
 
 KBUILD_CFLAGS			:= $(cflags-y) -DDISABLE_BRANCH_PROFILING \
 				   -include $(srctree)/drivers/firmware/efi/libstub/hidden.h \
@@ -45,13 +45,13 @@ lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
 				   skip_spaces.o lib-cmdline.o lib-ctype.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
+efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
 
 $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
 	$(call if_changed_rule,cc_o_c)
 
-lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
-				   $(patsubst %.c,lib-%.o,$(arm-deps-y))
+lib-$(CONFIG_EFI_GENERIC_STUB)	+= efi-stub.o fdt.o string.o \
+				   $(patsubst %.c,lib-%.o,$(efi-deps-y))
 
 lib-$(CONFIG_ARM)		+= arm32-stub.o
 lib-$(CONFIG_ARM64)		+= arm64-stub.o
@@ -73,8 +73,8 @@ CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 # a verification pass to see if any absolute relocations exist in any of the
 # object files.
 #
-extra-$(CONFIG_EFI_ARMSTUB)	:= $(lib-y)
-lib-$(CONFIG_EFI_ARMSTUB)	:= $(patsubst %.o,%.stub.o,$(lib-y))
+extra-$(CONFIG_EFI_GENERIC_STUB) := $(lib-y)
+lib-$(CONFIG_EFI_GENERIC_STUB)	:= $(patsubst %.o,%.stub.o,$(lib-y))
 
 STUBCOPY_FLAGS-$(CONFIG_ARM64)	+= --prefix-alloc-sections=.init \
 				   --prefix-symbols=__efistub_
drivers/firmware/efi/libstub/efi-stub.c renamed from drivers/firmware/efi/libstub/arm-stub.c +0 -0
similarity index 100%
rename from drivers/firmware/efi/libstub/arm-stub.c
rename to drivers/firmware/efi/libstub/efi-stub.c
Signature · 1 line
2.17.1
author maintainer
#2 lore raw

PATCH 2/33 efi/libstub: Make initrd file loader configurable

In reply to Ard Biesheuvel

Loading an initrd passed via the kernel command line is deprecated: it is limited to files that reside in the same volume as the one the kernel itself was loaded from, and we have more flexible ways to achieve the same. So make it configurable so new architectures can decide not to enable it.

---
 drivers/firmware/efi/Kconfig           | 11 ++++++++
 drivers/firmware/efi/libstub/efistub.h | 38 ++++++++++++++++++++------
 drivers/firmware/efi/libstub/file.c    | 32 +++++-----------------
 3 files changed, 47 insertions(+), 34 deletions(-)
drivers/firmware/efi/Kconfig +11 -0
index 2a2b2b96a1dc..4e788dd55b03 100644
@@ -124,6 +124,17 @@ config EFI_ARMSTUB_DTB_LOADER
 	  functionality for bootloaders that do not have such support
 	  this option is necessary.
 
+config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER
+	bool "Enable the command line initrd loader"
+	depends on EFI_GENERIC_STUB
+	default y
+	help
+	  Select this config option to add support for the initrd= command
+	  line parameter, allowing an initrd that resides on the same volume
+	  as the kernel image to be loaded into memory.
+
+	  This method is deprecated.
+
 config EFI_BOOTLOADER_CONTROL
 	tristate "EFI Bootloader Control"
 	depends on EFI_VARS
drivers/firmware/efi/libstub/efistub.h +29 -9
index 67d26949fd26..7517683b31e9 100644
@@ -651,15 +651,35 @@ efi_status_t efi_parse_options(char const *cmdline);
 efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
 			   unsigned long size);
 
-efi_status_t efi_load_dtb(efi_loaded_image_t *image,
-			  unsigned long *load_addr,
-			  unsigned long *load_size);
-
-efi_status_t efi_load_initrd(efi_loaded_image_t *image,
-			     unsigned long *load_addr,
-			     unsigned long *load_size,
-			     unsigned long soft_limit,
-			     unsigned long hard_limit);
+efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+				  const efi_char16_t *optstr,
+				  int optstr_size,
+				  unsigned long soft_limit,
+				  unsigned long hard_limit,
+				  unsigned long *load_addr,
+				  unsigned long *load_size);
+
+
+static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image,
+					unsigned long *load_addr,
+					unsigned long *load_size)
+{
+	return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2,
+				    ULONG_MAX, ULONG_MAX, load_addr, load_size);
+}
+
+static inline efi_status_t efi_load_initrd(efi_loaded_image_t *image,
+					   unsigned long *load_addr,
+					   unsigned long *load_size,
+					   unsigned long soft_limit,
+					   unsigned long hard_limit)
+{
+	if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER))
+		return EFI_SUCCESS;
+
+	return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
+				    soft_limit, hard_limit, load_addr, load_size);
+}
 
 efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
 				      unsigned long *load_size,
drivers/firmware/efi/libstub/file.c +7 -25
index ea66b1f16a79..27e014ea4459 100644
@@ -121,13 +121,13 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
  * We only support loading a file from the same filesystem as
  * the kernel image.
  */
-static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
-					 const efi_char16_t *optstr,
-					 int optstr_size,
-					 unsigned long soft_limit,
-					 unsigned long hard_limit,
-					 unsigned long *load_addr,
-					 unsigned long *load_size)
+efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+				  const efi_char16_t *optstr,
+				  int optstr_size,
+				  unsigned long soft_limit,
+				  unsigned long hard_limit,
+				  unsigned long *load_addr,
+				  unsigned long *load_size)
 {
 	const efi_char16_t *cmdline = image->load_options;
 	int cmdline_len = image->load_options_size / 2;
@@ -239,21 +239,3 @@ static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 	efi_free(alloc_size, alloc_addr);
 	return status;
 }
-
-efi_status_t efi_load_dtb(efi_loaded_image_t *image,
-			  unsigned long *load_addr,
-			  unsigned long *load_size)
-{
-	return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2,
-				    ULONG_MAX, ULONG_MAX, load_addr, load_size);
-}
-
-efi_status_t efi_load_initrd(efi_loaded_image_t *image,
-			     unsigned long *load_addr,
-			     unsigned long *load_size,
-			     unsigned long soft_limit,
-			     unsigned long hard_limit)
-{
-	return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
-				    soft_limit, hard_limit, load_addr, load_size);
-}
Signature · 1 line
2.17.1
author maintainer
#4 lore raw

PATCH 3/33 efi/libstub: Unify EFI call wrappers for non-x86

In reply to Ard Biesheuvel

We have wrappers around EFI calls so that x86 can define special versions for mixed mode, while all other architectures can use the same simple definition that just issues the call directly. In preparation for the arrival of yet another architecture that doesn't need anything special here (RISC-V), let's move the default definition into a shared header.

---
 arch/arm/include/asm/efi.h             |  8 --------
 arch/arm64/include/asm/efi.h           |  8 --------
 drivers/firmware/efi/libstub/efistub.h | 16 ++++++++++++++++
 3 files changed, 16 insertions(+), 16 deletions(-)
arch/arm/include/asm/efi.h +0 -8
index 5ac46e2860bc..9383f236e795 100644
@@ -50,14 +50,6 @@ void efi_virtmap_unload(void);
 
 /* arch specific definitions used by the stub code */
 
-#define efi_bs_call(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
-#define efi_rt_call(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
-#define efi_is_native()		(true)
-
-#define efi_table_attr(inst, attr)	(inst->attr)
-
-#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);
 
arch/arm64/include/asm/efi.h +0 -8
index 45e821222774..d4ab3f73e7a3 100644
@@ -86,14 +86,6 @@ 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_bs_call(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
-#define efi_rt_call(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
-#define efi_is_native()		(true)
-
-#define efi_table_attr(inst, attr)	(inst->attr)
-
-#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
-
 #define alloc_screen_info(x...)		&screen_info
 
 static inline void free_screen_info(struct screen_info *si)
drivers/firmware/efi/libstub/efistub.h +16 -0
index 7517683b31e9..d9ad8582dbea 100644
@@ -39,6 +39,22 @@ extern bool __pure novamap(void);
 
 extern __pure efi_system_table_t  *efi_system_table(void);
 
+#ifndef efi_bs_call
+#define efi_bs_call(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
+#endif
+#ifndef efi_rt_call
+#define efi_rt_call(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
+#endif
+#ifndef efi_is_native
+#define efi_is_native()		(true)
+#endif
+#ifndef efi_table_attr
+#define efi_table_attr(inst, attr)	(inst->attr)
+#endif
+#ifndef efi_call_proto
+#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
+#endif
+
 #define pr_efi(msg)		do {			\
 	if (!is_quiet()) efi_printk("EFI stub: "msg);	\
 } while (0)
Signature · 1 line
2.17.1
author maintainer
#8 lore raw

PATCH 4/33 efi/libstub/arm: Make install_memreserve_table static

In reply to Ard Biesheuvel

From: Zou Wei <[email protected]>

Fix the following sparse warning:

drivers/firmware/efi/libstub/arm-stub.c:68:6: warning:
symbol 'install_memreserve_table' was not declared. Should it be static?

---
 drivers/firmware/efi/libstub/efi-stub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/efi/libstub/efi-stub.c +1 -1
index 99a5cde7c2d8..8a26cc11ca4a 100644
@@ -65,7 +65,7 @@ static struct screen_info *setup_graphics(void)
 	return si;
 }
 
-void install_memreserve_table(void)
+static void install_memreserve_table(void)
 {
 	struct linux_efi_memreserve *rsv;
 	efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
Signature · 1 line
2.17.1
author maintainer
#10 lore raw

PATCH 6/33 efi/gop: Move check for framebuffer before con_out

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

If the gop doesn't have a framebuffer, there's no point in checking for con_out support.

---
 drivers/firmware/efi/libstub/gop.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/firmware/efi/libstub/gop.c +6 -5
index f40d535dccb8..201b66970b2b 100644
@@ -113,15 +113,16 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		if (status != EFI_SUCCESS)
 			continue;
 
+		mode = efi_table_attr(gop, mode);
+		info = efi_table_attr(mode, info);
+		if (info->pixel_format == PIXEL_BLT_ONLY)
+			continue;
+
 		status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 
-		mode = efi_table_attr(gop, mode);
-		info = efi_table_attr(mode, info);
-
-		if ((!first_gop || conout_found) &&
-		    info->pixel_format != PIXEL_BLT_ONLY) {
+		if (!first_gop || conout_found) {
 			/*
 			 * Systems that use the UEFI Console Splitter may
 			 * provide multiple GOP devices, not all of which are
Signature · 1 line
2.17.1
author maintainer
#11 lore raw

PATCH 7/33 efi/gop: Get mode information outside the loop

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Move extraction of the mode information parameters outside the loop to find the gop, and eliminate some redundant variables.

---
 drivers/firmware/efi/libstub/gop.c | 38 +++++++++++-------------------
 1 file changed, 14 insertions(+), 24 deletions(-)
drivers/firmware/efi/libstub/gop.c +14 -24
index 201b66970b2b..d692b8c65813 100644
@@ -89,12 +89,9 @@ 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;
-	u32 pixels_per_scan_line;
-	u32 ext_lfb_base;
+	efi_graphics_output_protocol_mode_t *mode;
+	efi_graphics_output_mode_info_t *info = NULL;
 	efi_physical_addr_t fb_base;
-	efi_pixel_bitmask_t pixel_info;
-	int pixel_format;
 	efi_status_t status;
 	efi_handle_t h;
 	int i;
@@ -103,8 +100,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 	gop = NULL;
 
 	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;
@@ -129,15 +124,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 			 * backed by real hardware. The workaround is to search
 			 * for a GOP implementing the ConOut protocol, and if
 			 * one isn't found, to just fall back to the first GOP.
-			 */
-			width = info->horizontal_resolution;
-			height = info->vertical_resolution;
-			pixel_format = info->pixel_format;
-			pixel_info = info->pixel_information;
-			pixels_per_scan_line = info->pixels_per_scan_line;
-			fb_base = efi_table_attr(mode, frame_buffer_base);
-
-			/*
+			 *
 			 * Once we've found a GOP supporting ConOut,
 			 * don't bother looking any further.
 			 */
@@ -152,21 +139,24 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		return EFI_NOT_FOUND;
 
 	/* EFI framebuffer */
+	mode = efi_table_attr(first_gop, mode);
+	info = efi_table_attr(mode, info);
+
 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
 
-	si->lfb_width = width;
-	si->lfb_height = height;
-	si->lfb_base = fb_base;
+	si->lfb_width  = info->horizontal_resolution;
+	si->lfb_height = info->vertical_resolution;
 
-	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
-	if (ext_lfb_base) {
+	fb_base		 = efi_table_attr(mode, frame_buffer_base);
+	si->lfb_base	 = fb_base;
+	si->ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
+	if (si->ext_lfb_base)
 		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
-		si->ext_lfb_base = ext_lfb_base;
-	}
 
 	si->pages = 1;
 
-	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+	setup_pixel_info(si, info->pixels_per_scan_line,
+			     info->pixel_information, info->pixel_format);
 
 	si->lfb_size = si->lfb_linelength * si->lfb_height;
 
Signature · 1 line
2.17.1
author maintainer
#13 lore raw

PATCH 9/33 efi/gop: Slightly re-arrange logic of find_gop

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Small cleanup to get rid of conout_found.

---
 drivers/firmware/efi/libstub/gop.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)
drivers/firmware/efi/libstub/gop.c +13 -17
index 92abcf558845..a7d3efe36c78 100644
@@ -99,7 +99,6 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
 
 	for_each_efi_handle(h, handles, size, i) {
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
-		bool conout_found = false;
 		void *dummy = NULL;
 
 		status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
@@ -111,25 +110,22 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
 		if (info->pixel_format == PIXEL_BLT_ONLY)
 			continue;
 
+		/*
+		 * Systems that use the UEFI Console Splitter may
+		 * provide multiple GOP devices, not all of which are
+		 * backed by real hardware. The workaround is to search
+		 * for a GOP implementing the ConOut protocol, and if
+		 * one isn't found, to just fall back to the first GOP.
+		 *
+		 * Once we've found a GOP supporting ConOut,
+		 * don't bother looking any further.
+		 */
 		status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
 		if (status == EFI_SUCCESS)
-			conout_found = true;
-
-		if (!first_gop || conout_found) {
-			/*
-			 * Systems that use the UEFI Console Splitter may
-			 * provide multiple GOP devices, not all of which are
-			 * backed by real hardware. The workaround is to search
-			 * for a GOP implementing the ConOut protocol, and if
-			 * one isn't found, to just fall back to the first GOP.
-			 *
-			 * Once we've found a GOP supporting ConOut,
-			 * don't bother looking any further.
-			 */
+			return gop;
+
+		if (!first_gop)
 			first_gop = gop;
-			if (conout_found)
-				break;
-		}
 	}
 
 	return first_gop;
Signature · 1 line
2.17.1
author maintainer
#14 lore raw

PATCH 10/33 efi/gop: Move variable declarations into loop block

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Declare the variables inside the block where they're used.

Get rid of a couple of redundant initializers.

---
 drivers/firmware/efi/libstub/gop.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/firmware/efi/libstub/gop.c +8 -5
index a7d3efe36c78..0d195060a370 100644
@@ -88,16 +88,19 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 static efi_graphics_output_protocol_t *
 find_gop(efi_guid_t *proto, unsigned long size, void **handles)
 {
-	efi_graphics_output_protocol_t *gop, *first_gop;
-	efi_graphics_output_protocol_mode_t *mode;
-	efi_graphics_output_mode_info_t *info = NULL;
-	efi_status_t status;
+	efi_graphics_output_protocol_t *first_gop;
 	efi_handle_t h;
 	int i;
 
 	first_gop = NULL;
 
 	for_each_efi_handle(h, handles, size, i) {
+		efi_status_t status;
+
+		efi_graphics_output_protocol_t *gop;
+		efi_graphics_output_protocol_mode_t *mode;
+		efi_graphics_output_mode_info_t *info;
+
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
 		void *dummy = NULL;
 
@@ -136,7 +139,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 {
 	efi_graphics_output_protocol_t *gop;
 	efi_graphics_output_protocol_mode_t *mode;
-	efi_graphics_output_mode_info_t *info = NULL;
+	efi_graphics_output_mode_info_t *info;
 	efi_physical_addr_t fb_base;
 
 	gop = find_gop(proto, size, handles);
Signature · 1 line
2.17.1
author maintainer
#16 lore raw

PATCH 12/33 efi/gop: Use helper macros for find_bits

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Use the __ffs/__fls macros to calculate the position and size of the mask.

Correct type of mask to u32 instead of unsigned long.

---
 drivers/firmware/efi/libstub/gop.c | 26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)
drivers/firmware/efi/libstub/gop.c +8 -18
index 7b0baf9a912f..8bf424f35759 100644
@@ -5,6 +5,7 @@
  *
  * ----------------------------------------------------------------------- */
 
+#include <linux/bitops.h>
 #include <linux/efi.h>
 #include <linux/screen_info.h>
 #include <asm/efi.h>
@@ -12,27 +13,16 @@
 
 #include "efistub.h"
 
-static void find_bits(unsigned long mask, u8 *pos, u8 *size)
+static void find_bits(u32 mask, u8 *pos, u8 *size)
 {
-	u8 first, len;
-
-	first = 0;
-	len = 0;
-
-	if (mask) {
-		while (!(mask & 0x1)) {
-			mask = mask >> 1;
-			first++;
-		}
-
-		while (mask & 0x1) {
-			mask = mask >> 1;
-			len++;
-		}
+	if (!mask) {
+		*pos = *size = 0;
+		return;
 	}
 
-	*pos = first;
-	*size = len;
+	/* UEFI spec guarantees that the set bits are contiguous */
+	*pos  = __ffs(mask);
+	*size = __fls(mask) - *pos + 1;
 }
 
 static void
Signature · 1 line
2.17.1
author maintainer
#17 lore raw

PATCH 13/33 efi/gop: Remove unreachable code from setup_pixel_info

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

pixel_format must be one of
PIXEL_RGB_RESERVED_8BIT_PER_COLOR
PIXEL_BGR_RESERVED_8BIT_PER_COLOR
PIXEL_BIT_MASK
since we skip PIXEL_BLT_ONLY when finding a gop.

Remove the redundant code and add another check in find_gop to skip any pixel formats that we don't know about, in case a later version of the UEFI spec adds one.

Reformat the code a little.

---
 drivers/firmware/efi/libstub/gop.c | 66 ++++++++++++------------------
 1 file changed, 26 insertions(+), 40 deletions(-)
drivers/firmware/efi/libstub/gop.c +26 -40
index 8bf424f35759..2d91699e3061 100644
@@ -29,49 +29,34 @@ static void
 setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 		 efi_pixel_bitmask_t pixel_info, int pixel_format)
 {
-	if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
-		si->lfb_depth = 32;
-		si->lfb_linelength = pixels_per_scan_line * 4;
-		si->red_size = 8;
-		si->red_pos = 0;
-		si->green_size = 8;
-		si->green_pos = 8;
-		si->blue_size = 8;
-		si->blue_pos = 16;
-		si->rsvd_size = 8;
-		si->rsvd_pos = 24;
-	} else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
-		si->lfb_depth = 32;
-		si->lfb_linelength = pixels_per_scan_line * 4;
-		si->red_size = 8;
-		si->red_pos = 16;
-		si->green_size = 8;
-		si->green_pos = 8;
-		si->blue_size = 8;
-		si->blue_pos = 0;
-		si->rsvd_size = 8;
-		si->rsvd_pos = 24;
-	} else if (pixel_format == PIXEL_BIT_MASK) {
-		find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
-		find_bits(pixel_info.green_mask, &si->green_pos,
-			  &si->green_size);
-		find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
-		find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
-			  &si->rsvd_size);
+	if (pixel_format == PIXEL_BIT_MASK) {
+		find_bits(pixel_info.red_mask,
+			  &si->red_pos, &si->red_size);
+		find_bits(pixel_info.green_mask,
+			  &si->green_pos, &si->green_size);
+		find_bits(pixel_info.blue_mask,
+			  &si->blue_pos, &si->blue_size);
+		find_bits(pixel_info.reserved_mask,
+			  &si->rsvd_pos, &si->rsvd_size);
 		si->lfb_depth = si->red_size + si->green_size +
 			si->blue_size + si->rsvd_size;
 		si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
 	} else {
-		si->lfb_depth = 4;
-		si->lfb_linelength = si->lfb_width / 2;
-		si->red_size = 0;
-		si->red_pos = 0;
-		si->green_size = 0;
-		si->green_pos = 0;
-		si->blue_size = 0;
-		si->blue_pos = 0;
-		si->rsvd_size = 0;
-		si->rsvd_pos = 0;
+		if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
+			si->red_pos   = 0;
+			si->blue_pos  = 16;
+		} else /* PIXEL_BGR_RESERVED_8BIT_PER_COLOR */ {
+			si->blue_pos  = 0;
+			si->red_pos   = 16;
+		}
+
+		si->green_pos = 8;
+		si->rsvd_pos  = 24;
+		si->red_size = si->green_size =
+			si->blue_size = si->rsvd_size = 8;
+
+		si->lfb_depth = 32;
+		si->lfb_linelength = pixels_per_scan_line * 4;
 	}
 }
 
@@ -100,7 +85,8 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
 
 		mode = efi_table_attr(gop, mode);
 		info = efi_table_attr(mode, info);
-		if (info->pixel_format == PIXEL_BLT_ONLY)
+		if (info->pixel_format == PIXEL_BLT_ONLY ||
+		    info->pixel_format >= PIXEL_FORMAT_MAX)
 			continue;
 
 		/*
Signature · 1 line
2.17.1
author maintainer
#18 lore raw

PATCH 14/33 efi/gop: Add prototypes for query_mode and set_mode

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Add prototypes and argmap for the Graphics Output Protocol's QueryMode and SetMode functions.

---
 arch/x86/include/asm/efi.h             | 4 ++++
 drivers/firmware/efi/libstub/efistub.h | 6 ++++--
 2 files changed, 8 insertions(+), 2 deletions(-)
arch/x86/include/asm/efi.h +4 -0
index 8391c115c0ec..f59cba117dcb 100644
@@ -307,6 +307,10 @@ static inline u32 efi64_convert_status(efi_status_t status)
 #define __efi64_argmap_load_file(protocol, path, policy, bufsize, buf)	\
 	((protocol), (path), (policy), efi64_zero_upper(bufsize), (buf))
 
+/* Graphics Output Protocol */
+#define __efi64_argmap_query_mode(gop, mode, size, info)		\
+	((gop), (mode), efi64_zero_upper(size), efi64_zero_upper(info))
+
 /*
  * The macros below handle the plumbing for the argument mapping. To add a
  * mapping for a specific EFI method, simply define a macro
drivers/firmware/efi/libstub/efistub.h +4 -2
index d9ad8582dbea..321244ed20a4 100644
@@ -314,8 +314,10 @@ typedef union efi_graphics_output_protocol efi_graphics_output_protocol_t;
 
 union efi_graphics_output_protocol {
 	struct {
-		void *query_mode;
-		void *set_mode;
+		efi_status_t (__efiapi *query_mode)(efi_graphics_output_protocol_t *,
+						    u32, unsigned long *,
+						    efi_graphics_output_mode_info_t **);
+		efi_status_t (__efiapi *set_mode)  (efi_graphics_output_protocol_t *, u32);
 		void *blt;
 		efi_graphics_output_protocol_mode_t *mode;
 	};
Signature · 1 line
2.17.1
author maintainer
#19 lore raw

PATCH 15/33 efi/gop: Allow specifying mode number on command line

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Add the ability to choose a video mode for the selected gop by using a command-line argument of the form
video=efifb:mode=<n>

---
 Documentation/fb/efifb.rst                    |  20 +++-
 .../firmware/efi/libstub/efi-stub-helper.c    |   3 +
 drivers/firmware/efi/libstub/efistub.h        |   2 +
 drivers/firmware/efi/libstub/gop.c            | 107 ++++++++++++++++++
 4 files changed, 129 insertions(+), 3 deletions(-)
Documentation/fb/efifb.rst +17 -3
index 04840331a00e..367fbda2f4da 100644
@@ -2,8 +2,10 @@
 What is efifb?
 ==============
 
-This is a generic EFI platform driver for Intel based Apple computers.
-efifb is only for EFI booted Intel Macs.
+This is a generic EFI platform driver for systems with UEFI firmware. The
+system must be booted via the EFI stub for this to be usable. efifb supports
+both firmware with Graphics Output Protocol (GOP) displays as well as older
+systems with only Universal Graphics Adapter (UGA) displays.
 
 Supported Hardware
 ==================
@@ -12,11 +14,14 @@ Supported Hardware
 - Macbook
 - Macbook Pro 15"/17"
 - MacMini
+- ARM/ARM64/X86 systems with UEFI firmware
 
 How to use it?
 ==============
 
-efifb does not have any kind of autodetection of your machine.
+For UGA displays, efifb does not have any kind of autodetection of your
+machine.
+
 You have to add the following kernel parameters in your elilo.conf::
 
 	Macbook :
@@ -28,6 +33,9 @@ You have to add the following kernel parameters in your elilo.conf::
 	Macbook Pro 17", iMac 20" :
 		video=efifb:i20
 
+For GOP displays, efifb can autodetect the display's resolution and framebuffer
+address, so these should work out of the box without any special parameters.
+
 Accepted options:
 
 ======= ===========================================================
@@ -36,4 +44,10 @@ nowc	Don't map the framebuffer write combined. This can be used
 	when large amounts of console data are written.
 ======= ===========================================================
 
+Options for GOP displays:
+
+mode=n
+        The EFI stub will set the mode of the display to mode number n if
+        possible.
+
 Edgar Hucek <[email protected]>
drivers/firmware/efi/libstub/efi-stub-helper.c +3 -0
index 9f34c7242939..c6092b6038cf 100644
@@ -105,6 +105,9 @@ efi_status_t efi_parse_options(char const *cmdline)
 				efi_disable_pci_dma = true;
 			if (parse_option_str(val, "no_disable_early_pci_dma"))
 				efi_disable_pci_dma = false;
+		} else if (!strcmp(param, "video") &&
+			   val && strstarts(val, "efifb:")) {
+			efi_parse_option_graphics(val + strlen("efifb:"));
 		}
 	}
 	efi_bs_call(free_pool, buf);
drivers/firmware/efi/libstub/efistub.h +2 -0
index 321244ed20a4..9af65be3b278 100644
@@ -666,6 +666,8 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
 
 efi_status_t efi_parse_options(char const *cmdline);
 
+void efi_parse_option_graphics(char *option);
+
 efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
 			   unsigned long size);
 
drivers/firmware/efi/libstub/gop.c +107 -0

124 lines not on this page · raw message

Signature · 1 line
2.17.1
author maintainer
#20 lore raw

PATCH 16/33 efi/gop: Allow specifying mode by <xres>x<yres>

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Add the ability to choose a video mode using a command-line argument of the form
video=efifb:<xres>x<yres>

---
 Documentation/fb/efifb.rst         |  5 ++
 drivers/firmware/efi/libstub/gop.c | 84 +++++++++++++++++++++++++++++-
 2 files changed, 88 insertions(+), 1 deletion(-)
Documentation/fb/efifb.rst +5 -0
index 367fbda2f4da..635275071307 100644
@@ -50,4 +50,9 @@ mode=n
         The EFI stub will set the mode of the display to mode number n if
         possible.
 
+<xres>x<yres>
+        The EFI stub will search for a display mode that matches the specified
+        horizontal and vertical resolution, and set the mode of the display to
+        it if one is found.
+
 Edgar Hucek <[email protected]>
drivers/firmware/efi/libstub/gop.c +83 -1

123 lines not on this page · raw message

Signature · 1 line
2.17.1
author maintainer
#22 lore raw

PATCH 18/33 efi/gop: Allow automatically choosing the best mode

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Add the ability to automatically pick the highest resolution video mode (defined as the product of vertical and horizontal resolution) by using a command-line argument of the form
video=efifb:auto

If there are multiple modes with the highest resolution, pick one with the highest color depth.

---
 Documentation/fb/efifb.rst         |  6 +++
 drivers/firmware/efi/libstub/gop.c | 84 +++++++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 1 deletion(-)
Documentation/fb/efifb.rst +6 -0
index eca38466487a..519550517fd4 100644
@@ -57,4 +57,10 @@ mode=n
         "rgb" or "bgr" to match specifically those pixel formats, or a number
         for a mode with matching bits per pixel.
 
+auto
+        The EFI stub will choose the mode with the highest resolution (product
+        of horizontal and vertical resolution). If there are multiple modes
+        with the highest resolution, it will choose one with the highest color
+        depth.
+
 Edgar Hucek <[email protected]>
drivers/firmware/efi/libstub/gop.c +83 -1

114 lines not on this page · raw message

Signature · 1 line
2.17.1
author maintainer
#23 lore raw

PATCH 19/33 efi/libstub/random: Align allocate size to EFI_ALLOC_ALIGN

In reply to Ard Biesheuvel

The EFI stub uses a per-architecture #define for the minimum base and size alignment of page allocations, which is set to 4 KB for all architecures except arm64, which uses 64 KB, to ensure that allocations can always be (un)mapped efficiently, regardless of the page size used by the kernel proper, which could be a kexec'ee

The API wrappers around page based allocations assume that this alignment is always taken into account, and so efi_free() will also round up its size argument to EFI_ALLOC_ALIGN.

Currently, efi_random_alloc() does not honour this alignment for the allocated size, and so freeing such an allocation may result in unrelated memory to be freed, potentially leading to issues after boot. So let's round up size in efi_random_alloc() as well.

Fixes 2ddbfc81eac84a29 ("efi: stub: add implementation of efi_random_alloc()")
---
 drivers/firmware/efi/libstub/randomalloc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/firmware/efi/libstub/randomalloc.c +3 -1
index 4578f59e160c..6200dfa650f5 100644
@@ -74,6 +74,8 @@ efi_status_t efi_random_alloc(unsigned long size,
 	if (align < EFI_ALLOC_ALIGN)
 		align = EFI_ALLOC_ALIGN;
 
+	size = round_up(size, EFI_ALLOC_ALIGN);
+
 	/* count the suitable slots in each memory map entry */
 	for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
 		efi_memory_desc_t *md = (void *)memory_map + map_offset;
@@ -109,7 +111,7 @@ efi_status_t efi_random_alloc(unsigned long size,
 		}
 
 		target = round_up(md->phys_addr, align) + target_slot * align;
-		pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+		pages = size / EFI_PAGE_SIZE;
 
 		status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
 				     EFI_LOADER_DATA, pages, &target);
Signature · 1 line
2.17.1
author maintainer
#24 lore raw

PATCH 20/33 efi/libstub/random: Increase random alloc granularity

In reply to Ard Biesheuvel

The implementation of efi_random_alloc() arbitrarily truncates the provided random seed to 16 bits, which limits the granularity of the randomly chosen allocation offset in memory. This is currently only an issue if the size of physical memory exceeds 128 GB, but going forward, we will reduce the allocation alignment to 64 KB, and this means we need to increase the granularity to ensure that the random memory allocations are distributed evenly.

We will need to switch to 64-bit arithmetic for the multiplication, but this does not result in 64-bit integer intrinsic calls on ARM or on i386.

---
 drivers/firmware/efi/libstub/randomalloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/efi/libstub/randomalloc.c +1 -1
index 6200dfa650f5..a408df474d83 100644
@@ -87,7 +87,7 @@ efi_status_t efi_random_alloc(unsigned long size,
 	}
 
 	/* find a random number between 0 and total_slots */
-	target_slot = (total_slots * (u16)random_seed) >> 16;
+	target_slot = (total_slots * (u64)(random_seed & U32_MAX)) >> 32;
 
 	/*
 	 * target_slot is now a value in the range [0, total_slots), and so
Signature · 1 line
2.17.1
author maintainer
#26 lore raw

PATCH 22/33 efi/libstub/arm64: Simplify randomized loading of kernel image

In reply to Ard Biesheuvel

The KASLR code path in the arm64 version of the EFI stub incorporates some overly complicated logic to randomly allocate a region of the right
alignment: there is no need to randomize the placement of the kernel modulo 2 MiB separately from the placement of the 2 MiB aligned allocation itself - we can simply follow the same logic used by the non-randomized placement, which is to allocate at the correct alignment, and only take TEXT_OFFSET into account if it is not a round multiple of the alignment.

---
 drivers/firmware/efi/libstub/arm64-stub.c | 32 ++++-------------------
 1 file changed, 5 insertions(+), 27 deletions(-)
drivers/firmware/efi/libstub/arm64-stub.c +5 -27
index cfd535c13242..6fc3bd9a56db 100644
@@ -52,7 +52,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 {
 	efi_status_t status;
 	unsigned long kernel_size, kernel_memsize = 0;
-	u64 phys_seed = 0;
+	u32 phys_seed = 0;
 
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
 		if (!nokaslr()) {
@@ -74,36 +74,15 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 
 	kernel_size = _edata - _text;
 	kernel_memsize = kernel_size + (_end - _edata);
+	*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align;
 
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
-		/*
-		 * Produce a displacement in the interval [0, MIN_KIMG_ALIGN)
-		 * that doesn't violate this kernel's de-facto alignment
-		 * constraints.
-		 */
-		u32 mask = (MIN_KIMG_ALIGN - 1) & ~(EFI_KIMG_ALIGN - 1);
-		u32 offset = (phys_seed >> 32) & mask;
-
-		/*
-		 * With CONFIG_RANDOMIZE_TEXT_OFFSET=y, TEXT_OFFSET may not
-		 * be a multiple of EFI_KIMG_ALIGN, and we must ensure that
-		 * we preserve the misalignment of 'offset' relative to
-		 * EFI_KIMG_ALIGN so that statically allocated objects whose
-		 * alignment exceeds PAGE_SIZE appear correctly aligned in
-		 * memory.
-		 */
-		offset |= TEXT_OFFSET % EFI_KIMG_ALIGN;
-
 		/*
 		 * If KASLR is enabled, and we have some randomness available,
 		 * locate the kernel at a randomized offset in physical memory.
 		 */
-		*reserve_size = kernel_memsize + offset;
-		status = efi_random_alloc(*reserve_size,
-					  MIN_KIMG_ALIGN, reserve_addr,
-					  (u32)phys_seed);
-
-		*image_addr = *reserve_addr + offset;
+		status = efi_random_alloc(*reserve_size, min_kimg_align,
+					  reserve_addr, phys_seed);
 	} else {
 		status = EFI_OUT_OF_RESOURCES;
 	}
@@ -119,7 +98,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 			return EFI_SUCCESS;
 		}
 
-		*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align;
 		status = efi_low_alloc(*reserve_size,
 				       min_kimg_align, reserve_addr);
 
@@ -128,9 +106,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 			*reserve_size = 0;
 			return status;
 		}
-		*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align;
 	}
 
+	*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align;
 	memcpy((void *)*image_addr, _text, kernel_size);
 
 	return EFI_SUCCESS;
Signature · 1 line
2.17.1
author maintainer
#25 lore raw

PATCH 21/33 efi/libstub/arm64: Replace 'preferred' offset with alignment check

In reply to Ard Biesheuvel

The notion of a 'preferred' load offset for the kernel dates back to the times when the kernel's primary mapping overlapped with the linear region, and memory below it could not be used at all.

Today, the arm64 kernel does not really care where it is loaded in physical memory, as long as the alignment requirements are met, and so there is no point in unconditionally moving the kernel to a new location in memory at boot. Instead, we can
- check for a KASLR seed, and randomly reallocate the kernel if one is provided
- otherwise, check whether the alignment requirements are met for the current placement of the kernel, and just run it in place if they are
- finally, do an ordinary page allocation and reallocate the kernel to a suitably aligned buffer anywhere in memory.

By the same reasoning, there is no need to take TEXT_OFFSET into account if it is a round multiple of the minimum alignment, which is the usual case for relocatable kernels with TEXT_OFFSET randomization disabled. Otherwise, it suffices to use the relative misaligment of TEXT_OFFSET when reallocating the kernel.

---
 drivers/firmware/efi/libstub/arm64-stub.c | 62 +++++++++--------------
 1 file changed, 25 insertions(+), 37 deletions(-)
drivers/firmware/efi/libstub/arm64-stub.c +25 -37
index fc9f8ab533a7..cfd535c13242 100644
@@ -34,6 +34,15 @@ efi_status_t check_platform_features(void)
 	return EFI_SUCCESS;
 }
 
+/*
+ * Relocatable kernels can fix up the misalignment with respect to
+ * MIN_KIMG_ALIGN, so they only require a minimum alignment of EFI_KIMG_ALIGN
+ * (which accounts for the alignment of statically allocated objects such as
+ * the swapper stack.)
+ */
+static const u64 min_kimg_align = IS_ENABLED(CONFIG_RELOCATABLE) ? EFI_KIMG_ALIGN
+								 : MIN_KIMG_ALIGN;
+
 efi_status_t handle_kernel_image(unsigned long *image_addr,
 				 unsigned long *image_size,
 				 unsigned long *reserve_addr,
@@ -43,7 +52,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 {
 	efi_status_t status;
 	unsigned long kernel_size, kernel_memsize = 0;
-	unsigned long preferred_offset;
 	u64 phys_seed = 0;
 
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
@@ -61,14 +69,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 		}
 	}
 
-	/*
-	 * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
-	 * a 2 MB aligned base, which itself may be lower than dram_base, as
-	 * long as the resulting offset equals or exceeds it.
-	 */
-	preferred_offset = round_down(dram_base, MIN_KIMG_ALIGN) + TEXT_OFFSET;
-	if (preferred_offset < dram_base)
-		preferred_offset += MIN_KIMG_ALIGN;
+	if (image->image_base != _text)
+		pr_efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
 
 	kernel_size = _edata - _text;
 	kernel_memsize = kernel_size + (_end - _edata);
@@ -103,46 +105,32 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 
 		*image_addr = *reserve_addr + offset;
 	} else {
-		/*
-		 * Else, try a straight allocation at the preferred offset.
-		 * This will work around the issue where, if dram_base == 0x0,
-		 * efi_low_alloc() refuses to allocate at 0x0 (to prevent the
-		 * address of the allocation to be mistaken for a FAIL return
-		 * value or a NULL pointer). It will also ensure that, on
-		 * platforms where the [dram_base, dram_base + TEXT_OFFSET)
-		 * interval is partially occupied by the firmware (like on APM
-		 * Mustang), we can still place the kernel at the address
-		 * 'dram_base + TEXT_OFFSET'.
-		 */
-		*image_addr = (unsigned long)_text;
-		if (*image_addr == preferred_offset)
-			return EFI_SUCCESS;
-
-		*image_addr = *reserve_addr = preferred_offset;
-		*reserve_size = round_up(kernel_memsize, EFI_ALLOC_ALIGN);
-
-		status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
-				     EFI_LOADER_DATA,
-				     *reserve_size / EFI_PAGE_SIZE,
-				     (efi_physical_addr_t *)reserve_addr);
+		status = EFI_OUT_OF_RESOURCES;
 	}
 
 	if (status != EFI_SUCCESS) {
-		*reserve_size = kernel_memsize + TEXT_OFFSET;
+		if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align)) {
+			/*
+			 * Just execute from wherever we were loaded by the
+			 * UEFI PE/COFF loader if the alignment is suitable.
+			 */
+			*image_addr = (u64)_text;
+			*reserve_size = 0;
+			return EFI_SUCCESS;
+		}
+
+		*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align;
 		status = efi_low_alloc(*reserve_size,
-				       MIN_KIMG_ALIGN, reserve_addr);
+				       min_kimg_align, reserve_addr);
 
 		if (status != EFI_SUCCESS) {
 			pr_efi_err("Failed to relocate kernel\n");
 			*reserve_size = 0;
 			return status;
 		}
-		*image_addr = *reserve_addr + TEXT_OFFSET;
+		*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align;
 	}
 
-	if (image->image_base != _text)
-		pr_efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
-
 	memcpy((void *)*image_addr, _text, kernel_size);
 
 	return EFI_SUCCESS;
Signature · 1 line
2.17.1
author maintainer
#28 lore raw

PATCH 24/33 efi/libstub/arm64: Switch to ordinary page allocator for kernel image

In reply to Ard Biesheuvel

It is no longer necessary to locate the kernel as low as possible in physical memory, and so we can switch from efi_low_alloc() [which is a rather nasty concoction on top of GetMemoryMap()] to a new helper called efi_allocate_pages_aligned(), which simply rounds up the size to account for the alignment, and frees the misaligned pages again.

So considering that the kernel can live anywhere in the physical address space, as long as its alignment requirements are met, let's switch to efi_allocate_pages_aligned() to allocate the pages.

---
 drivers/firmware/efi/libstub/arm64-stub.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/efi/libstub/arm64-stub.c +2 -2
index 6fc3bd9a56db..99b67e88a33b 100644
@@ -98,8 +98,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 			return EFI_SUCCESS;
 		}
 
-		status = efi_low_alloc(*reserve_size,
-				       min_kimg_align, reserve_addr);
+		status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
+						    ULONG_MAX, min_kimg_align);
 
 		if (status != EFI_SUCCESS) {
 			pr_efi_err("Failed to relocate kernel\n");
Signature · 1 line
2.17.1
author maintainer
#31 lore raw

PATCH 27/33 efi/x86: Remove __efistub_global and add relocation check

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Instead of using __efistub_global to force variables into the .data section, leave them in the .bss but pull the EFI stub's .bss section into .data in the linker script for the compressed kernel.

Add relocation checking for x86 as well to catch non-PC-relative relocations that require runtime processing, since the EFI stub does not do any runtime relocation processing.

This will catch, for example, data relocations created by static initializers of pointers.

---
 arch/x86/boot/compressed/vmlinux.lds.S |  1 +
 drivers/firmware/efi/libstub/Makefile  | 32 +++++++++++++++++---------
 drivers/firmware/efi/libstub/efistub.h |  4 ----
 3 files changed, 22 insertions(+), 15 deletions(-)
arch/x86/boot/compressed/vmlinux.lds.S +1 -0
index 508cfa6828c5..0dc5c2b9614b 100644
@@ -52,6 +52,7 @@ SECTIONS
 		_data = . ;
 		*(.data)
 		*(.data.*)
+		*(.bss.efistub)
 		_edata = . ;
 	}
 	. = ALIGN(L1_CACHE_BYTES);
drivers/firmware/efi/libstub/Makefile +21 -11
index aa3ab9a4105e..8d246b51bd49 100644
@@ -60,6 +60,25 @@ lib-$(CONFIG_X86)		+= x86-stub.o
 CFLAGS_arm32-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+#
+# For x86, bootloaders like systemd-boot or grub-efi do not zero-initialize the
+# .bss section, so the .bss section of the EFI stub needs to be included in the
+# .data section of the compressed kernel to ensure initialization. Rename the
+# .bss section here so it's easy to pick out in the linker script.
+#
+STUBCOPY_FLAGS-$(CONFIG_X86)	+= --rename-section .bss=.bss.efistub,load,alloc
+STUBCOPY_RELOC-$(CONFIG_X86_32)	:= R_386_32
+STUBCOPY_RELOC-$(CONFIG_X86_64)	:= R_X86_64_64
+
+#
+# ARM discards the .data section because it disallows r/w data in the
+# decompressor. So move our .data to .data.efistub and .bss to .bss.efistub,
+# which are preserved explicitly by the decompressor linker script.
+#
+STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub	\
+				   --rename-section .bss=.bss.efistub,load,alloc
+STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
+
 #
 # arm64 puts the stub in the kernel proper, which will unnecessarily retain all
 # code indefinitely unless it is annotated as __init/__initdata/__initconst etc.
@@ -74,8 +93,8 @@ CFLAGS_arm64-stub.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 # a verification pass to see if any absolute relocations exist in any of the
 # object files.
 #
-extra-$(CONFIG_EFI_GENERIC_STUB) := $(lib-y)
-lib-$(CONFIG_EFI_GENERIC_STUB)	:= $(patsubst %.o,%.stub.o,$(lib-y))
+extra-y				:= $(lib-y)
+lib-y				:= $(patsubst %.o,%.stub.o,$(lib-y))
 
 STUBCOPY_FLAGS-$(CONFIG_ARM64)	+= --prefix-alloc-sections=.init \
 				   --prefix-symbols=__efistub_
@@ -98,12 +117,3 @@ quiet_cmd_stubcopy = STUBCPY $@
 		/bin/false;						\
 	fi;								\
 	$(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@
-
-#
-# ARM discards the .data section because it disallows r/w data in the
-# decompressor. So move our .data to .data.efistub and .bss to .bss.efistub,
-# which are preserved explicitly by the decompressor linker script.
-#
-STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub	\
-				   --rename-section .bss=.bss.efistub,load,alloc
-STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
drivers/firmware/efi/libstub/efistub.h +0 -4
index 96e25b17c88e..5244eacc5d4b 100644
@@ -25,11 +25,7 @@
 #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
 #endif
 
-#if defined(CONFIG_X86)
-#define __efistub_global	__section(.data)
-#else
 #define __efistub_global
-#endif
 
 extern bool __pure nochunk(void);
 extern bool __pure nokaslr(void);
Signature · 1 line
2.17.1
author maintainer
#32 lore raw

PATCH 28/33 efi: Kill __efistub_global

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Now that both arm and x86 are using the linker script to place the EFI stub's global variables in the correct section, remove __efistub_global.

---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 15 +++++++--------
 drivers/firmware/efi/libstub/efi-stub.c        |  4 ++--
 drivers/firmware/efi/libstub/efistub.h         |  2 --
 drivers/firmware/efi/libstub/gop.c             |  2 +-
 drivers/firmware/efi/libstub/x86-stub.c        |  2 +-
 5 files changed, 11 insertions(+), 14 deletions(-)
drivers/firmware/efi/libstub/efi-stub-helper.c +7 -8
index c6092b6038cf..14e56a64f208 100644
@@ -12,14 +12,13 @@
 
 #include "efistub.h"
 
-static bool __efistub_global efi_nochunk;
-static bool __efistub_global efi_nokaslr;
-static bool __efistub_global efi_noinitrd;
-static bool __efistub_global efi_quiet;
-static bool __efistub_global efi_novamap;
-static bool __efistub_global efi_nosoftreserve;
-static bool __efistub_global efi_disable_pci_dma =
-					IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
+static bool efi_nochunk;
+static bool efi_nokaslr;
+static bool efi_noinitrd;
+static bool efi_quiet;
+static bool efi_novamap;
+static bool efi_nosoftreserve;
+static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
 
 bool __pure nochunk(void)
 {
drivers/firmware/efi/libstub/efi-stub.c +2 -2
index 8a26cc11ca4a..8455c590c7b9 100644
@@ -36,9 +36,9 @@
 #endif
 
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
-static bool __efistub_global flat_va_mapping;
+static bool flat_va_mapping;
 
-static efi_system_table_t *__efistub_global sys_table;
+static efi_system_table_t *sys_table;
 
 __pure efi_system_table_t *efi_system_table(void)
 {
drivers/firmware/efi/libstub/efistub.h +0 -2
index 5244eacc5d4b..9a87fff1d4ba 100644
@@ -25,8 +25,6 @@
 #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
 #endif
 
-#define __efistub_global
-
 extern bool __pure nochunk(void);
 extern bool __pure nokaslr(void);
 extern bool __pure noinitrd(void);
drivers/firmware/efi/libstub/gop.c +1 -1
index fa05a0b0adfd..216327d0b034 100644
@@ -32,7 +32,7 @@ static struct {
 			u8 depth;
 		} res;
 	};
-} cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
+} cmdline = { .option = EFI_CMDLINE_NONE };
 
 static bool parse_modenum(char *option, char **next)
 {
drivers/firmware/efi/libstub/x86-stub.c +1 -1
index 05ccb229fb45..1c3807d0c321 100644
@@ -20,7 +20,7 @@
 /* Maximum physical address for 64-bit kernel with 4-level paging */
 #define MAXMEM_X86_64_4LEVEL (1ull << 46)
 
-static efi_system_table_t *sys_table __efistub_global;
+static efi_system_table_t *sys_table;
 extern const bool efi_is64;
 extern u32 image_offset;
 
Signature · 1 line
2.17.1
author maintainer
#34 lore raw

PATCH 30/33 efi/libstub: Drop __pure getters for EFI stub options

In reply to Ard Biesheuvel

The practice of using __pure getter functions to access global variables in the EFI stub dates back to the time when we had to carefully prevent GOT entries from being emitted, because we could not rely on the toolchain to do this for us.

Today, we use the hidden visibility pragma for all EFI stub source files, which now all live in the same subdirectory, and we apply a sanity check on the objects, so we can get rid of these getter functions and simply refer to global data objects directly.

So switch over the remaining boolean variables carrying options set on the kernel command line.

---
 drivers/firmware/efi/libstub/arm64-stub.c     |  2 +-
 .../firmware/efi/libstub/efi-stub-helper.c    | 31 ++++---------------
 drivers/firmware/efi/libstub/efi-stub.c       |  6 ++--
 drivers/firmware/efi/libstub/efistub.h        | 12 +++----
 drivers/firmware/efi/libstub/fdt.c            |  2 +-
 drivers/firmware/efi/libstub/file.c           |  2 +-
 drivers/firmware/efi/libstub/x86-stub.c       |  4 +--
 7 files changed, 20 insertions(+), 39 deletions(-)
drivers/firmware/efi/libstub/arm64-stub.c +1 -1
index 99b67e88a33b..ba4db35015a3 100644
@@ -55,7 +55,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 	u32 phys_seed = 0;
 
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
-		if (!nokaslr()) {
+		if (!efi_nokaslr) {
 			status = efi_get_random_bytes(sizeof(phys_seed),
 						      (u8 *)&phys_seed);
 			if (status == EFI_NOT_FOUND) {
drivers/firmware/efi/libstub/efi-stub-helper.c +6 -25
index 0b1688b10ddc..1c92ac231f94 100644
@@ -12,34 +12,15 @@
 
 #include "efistub.h"
 
-static bool efi_nochunk;
-static bool efi_nokaslr;
-static bool efi_noinitrd;
-static bool efi_quiet;
-static bool efi_novamap;
+bool efi_nochunk;
+bool efi_nokaslr;
+bool efi_noinitrd;
+bool efi_quiet;
+bool efi_novamap;
+
 static bool efi_nosoftreserve;
 static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
 
-bool __pure nochunk(void)
-{
-	return efi_nochunk;
-}
-bool __pure nokaslr(void)
-{
-	return efi_nokaslr;
-}
-bool __pure noinitrd(void)
-{
-	return efi_noinitrd;
-}
-bool __pure is_quiet(void)
-{
-	return efi_quiet;
-}
-bool __pure novamap(void)
-{
-	return efi_novamap;
-}
 bool __pure __efi_soft_reserve_enabled(void)
 {
 	return !efi_nosoftreserve;
drivers/firmware/efi/libstub/efi-stub.c +3 -3
index 8edfd4022803..ee225b323687 100644
@@ -263,7 +263,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
 	if (!fdt_addr)
 		pr_efi("Generating empty DTB\n");
 
-	if (!noinitrd()) {
+	if (!efi_noinitrd) {
 		max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
 		status = efi_load_initrd_dev_path(&initrd_addr, &initrd_size,
 						  max_addr);
@@ -294,7 +294,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
 			   EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
 
 	/* hibernation expects the runtime regions to stay in the same place */
-	if (!IS_ENABLED(CONFIG_HIBERNATION) && !nokaslr() && !flat_va_mapping) {
+	if (!IS_ENABLED(CONFIG_HIBERNATION) && !efi_nokaslr && !flat_va_mapping) {
 		/*
 		 * Randomize the base of the UEFI runtime services region.
 		 * Preserve the 2 MB alignment of the region by taking a
@@ -367,7 +367,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
 		size = in->num_pages * EFI_PAGE_SIZE;
 
 		in->virt_addr = in->phys_addr;
-		if (novamap()) {
+		if (efi_novamap) {
 			continue;
 		}
 
drivers/firmware/efi/libstub/efistub.h +6 -6
index c1481c5abea4..5ff63230a1f1 100644
@@ -25,11 +25,11 @@
 #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
 #endif
 
-extern bool __pure nochunk(void);
-extern bool __pure nokaslr(void);
-extern bool __pure noinitrd(void);
-extern bool __pure is_quiet(void);
-extern bool __pure novamap(void);
+extern bool efi_nochunk;
+extern bool efi_nokaslr;
+extern bool efi_noinitrd;
+extern bool efi_quiet;
+extern bool efi_novamap;
 
 extern const efi_system_table_t *efi_system_table;
 
@@ -50,7 +50,7 @@ extern const efi_system_table_t *efi_system_table;
 #endif
 
 #define pr_efi(msg)		do {			\
-	if (!is_quiet()) efi_printk("EFI stub: "msg);	\
+	if (!efi_quiet) efi_printk("EFI stub: "msg);	\
 } while (0)
 
 #define pr_efi_err(msg) efi_printk("EFI stub: ERROR: "msg)
drivers/firmware/efi/libstub/fdt.c +1 -1
index 06d5e7fc8e34..3074a5e27c65 100644
@@ -310,7 +310,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
 	if (status == EFI_SUCCESS) {
 		efi_set_virtual_address_map_t *svam;
 
-		if (novamap())
+		if (efi_novamap)
 			return EFI_SUCCESS;
 
 		/* Install the new virtual address map */
drivers/firmware/efi/libstub/file.c +1 -1
index 27e014ea4459..50aaf15f9ad5 100644
@@ -142,7 +142,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
 	if (!load_addr || !load_size)
 		return EFI_INVALID_PARAMETER;
 
-	if (IS_ENABLED(CONFIG_X86) && !nochunk())
+	if (IS_ENABLED(CONFIG_X86) && !efi_nochunk)
 		efi_chunk_size = EFI_READ_CHUNK_SIZE;
 
 	alloc_addr = alloc_size = 0;
drivers/firmware/efi/libstub/x86-stub.c +2 -2
index 3f132f51ab0f..bddbc103a34b 100644
@@ -427,7 +427,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 		if (status != EFI_SUCCESS)
 			goto fail2;
 
-		if (!noinitrd()) {
+		if (!efi_noinitrd) {
 			status = efi_load_initrd(image, &ramdisk_addr,
 						 &ramdisk_size,
 						 hdr->initrd_addr_max,
@@ -787,7 +787,7 @@ unsigned long efi_main(efi_handle_t handle,
 	 * permit an initrd loaded from the LINUX_EFI_INITRD_MEDIA_GUID device
 	 * path to supersede it.
 	 */
-	if (!noinitrd()) {
+	if (!efi_noinitrd) {
 		unsigned long addr, size;
 
 		status = efi_load_initrd_dev_path(&addr, &size, ULONG_MAX);
Signature · 1 line
2.17.1
author maintainer
#35 lore raw

PATCH 31/33 efi/libstub/x86: Avoid getter function for efi_is64

In reply to Ard Biesheuvel

We no longer need to take special care when using global variables in the EFI stub, so switch to a simple symbol reference for efi_is64.

---
 arch/x86/include/asm/efi.h              | 11 ++++++++---
 drivers/firmware/efi/libstub/x86-stub.c |  8 --------
 2 files changed, 8 insertions(+), 11 deletions(-)
arch/x86/include/asm/efi.h +8 -3
index 78e839925a81..cd0c3fbf6156 100644
@@ -225,14 +225,19 @@ efi_status_t efi_set_virtual_address_map(unsigned long memory_map_size,
 
 /* arch specific definitions used by the stub code */
 
-__attribute_const__ bool efi_is_64bit(void);
+extern const bool efi_is64;
+
+static inline bool efi_is_64bit(void)
+{
+	if (IS_ENABLED(CONFIG_EFI_MIXED))
+		return efi_is64;
+	return IS_ENABLED(CONFIG_X86_64);
+}
 
 static inline bool efi_is_native(void)
 {
 	if (!IS_ENABLED(CONFIG_X86_64))
 		return true;
-	if (!IS_ENABLED(CONFIG_EFI_MIXED))
-		return true;
 	return efi_is_64bit();
 }
 
drivers/firmware/efi/libstub/x86-stub.c +0 -8
index bddbc103a34b..597793fe8d22 100644
@@ -21,16 +21,8 @@
 #define MAXMEM_X86_64_4LEVEL (1ull << 46)
 
 const efi_system_table_t *efi_system_table;
-extern const bool efi_is64;
 extern u32 image_offset;
 
-__attribute_const__ bool efi_is_64bit(void)
-{
-	if (IS_ENABLED(CONFIG_EFI_MIXED))
-		return efi_is64;
-	return IS_ENABLED(CONFIG_X86_64);
-}
-
 static efi_status_t
 preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
 {
Signature · 1 line
2.17.1
author maintainer
#36 lore raw

PATCH 32/33 efi: Clean up config table description arrays

In reply to Ard Biesheuvel

Increase legibility by adding whitespace to the efi_config_table_type_t arrays that describe which EFI config tables we look for when going over the firmware provided list. While at it, replace the 'name' char pointer with a char array, which is more space efficient on relocatable 64-bit kernels, as it avoids a 8 byte pointer and the associated relocation data (24 bytes when using RELA format)

---
 arch/ia64/kernel/efi.c          | 12 ++++++------
 arch/x86/platform/efi/efi.c     |  8 ++++----
 drivers/firmware/efi/arm-init.c |  4 ++--
 drivers/firmware/efi/efi.c      | 28 ++++++++++++++--------------
 include/linux/efi.h             |  2 +-
 5 files changed, 27 insertions(+), 27 deletions(-)
arch/ia64/kernel/efi.c +6 -6
index f69f3fe0532e..a54eacbc61a9 100644
@@ -57,12 +57,12 @@ unsigned long hcdp_phys = EFI_INVALID_TABLE_ADDR;
 unsigned long sal_systab_phys = EFI_INVALID_TABLE_ADDR;
 
 static const efi_config_table_type_t arch_tables[] __initconst = {
-	{ESI_TABLE_GUID, "ESI", &esi_phys},
-	{HCDP_TABLE_GUID, "HCDP", &hcdp_phys},
-	{MPS_TABLE_GUID, "MPS", &mps_phys},
-	{PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys},
-	{SAL_SYSTEM_TABLE_GUID, "SALsystab", &sal_systab_phys},
-	{NULL_GUID, NULL, 0},
+	{ESI_TABLE_GUID,				&esi_phys,		"ESI"		},
+	{HCDP_TABLE_GUID,				&hcdp_phys,		"HCDP"		},
+	{MPS_TABLE_GUID,				&mps_phys,		"MPS"		},
+	{PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID,	&palo_phys,		"PALO"		},
+	{SAL_SYSTEM_TABLE_GUID,				&sal_systab_phys,	"SALsystab"	},
+	{},
 };
 
 extern efi_status_t efi_call_phys (void *, ...);
arch/x86/platform/efi/efi.c +4 -4
index 1aae5302501d..e966115d105c 100644
@@ -62,12 +62,12 @@ static unsigned long efi_runtime, efi_nr_tables;
 unsigned long efi_fw_vendor, efi_config_table;
 
 static const efi_config_table_type_t arch_tables[] __initconst = {
-	{EFI_PROPERTIES_TABLE_GUID, "PROP", &prop_phys},
-	{UGA_IO_PROTOCOL_GUID, "UGA", &uga_phys},
+	{EFI_PROPERTIES_TABLE_GUID,	&prop_phys,		"PROP"		},
+	{UGA_IO_PROTOCOL_GUID,		&uga_phys,		"UGA"		},
 #ifdef CONFIG_X86_UV
-	{UV_SYSTEM_TABLE_GUID, "UVsystab", &uv_systab_phys},
+	{UV_SYSTEM_TABLE_GUID,		&uv_systab_phys,	"UVsystab"	},
 #endif
-	{NULL_GUID, NULL, NULL},
+	{},
 };
 
 static const unsigned long * const efi_tables[] = {
drivers/firmware/efi/arm-init.c +2 -2
index 9e5e62f5f94d..c697e70ca7e7 100644
@@ -54,8 +54,8 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
 static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
 
 static const efi_config_table_type_t arch_tables[] __initconst = {
-	{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table},
-	{NULL_GUID, NULL, NULL}
+	{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
+	{}
 };
 
 static void __init init_screen_info(void)
drivers/firmware/efi/efi.c +14 -14
index 911a2bd0f6b7..e49c0b6db988 100644
@@ -502,21 +502,21 @@ void __init efi_mem_reserve(phys_addr_t addr, u64 size)
 }
 
 static const efi_config_table_type_t common_tables[] __initconst = {
-	{ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
-	{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
-	{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
-	{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
-	{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
-	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi_mem_attr_table},
-	{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi_rng_seed},
-	{LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
-	{LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
-	{LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &mem_reserve},
-	{EFI_RT_PROPERTIES_TABLE_GUID, "RTPROP", &rt_prop},
+	{ACPI_20_TABLE_GUID,			&efi.acpi20,		"ACPI 2.0"	},
+	{ACPI_TABLE_GUID,			&efi.acpi,		"ACPI"		},
+	{SMBIOS_TABLE_GUID,			&efi.smbios,		"SMBIOS"	},
+	{SMBIOS3_TABLE_GUID,			&efi.smbios3,		"SMBIOS 3.0"	},
+	{EFI_SYSTEM_RESOURCE_TABLE_GUID,	&efi.esrt,		"ESRT"		},
+	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID,	&efi_mem_attr_table,	"MEMATTR"	},
+	{LINUX_EFI_RANDOM_SEED_TABLE_GUID,	&efi_rng_seed,		"RNG"		},
+	{LINUX_EFI_TPM_EVENT_LOG_GUID,		&efi.tpm_log,		"TPMEventLog"	},
+	{LINUX_EFI_TPM_FINAL_LOG_GUID,		&efi.tpm_final_log,	"TPMFinalLog"	},
+	{LINUX_EFI_MEMRESERVE_TABLE_GUID,	&mem_reserve,		"MEMRESERVE"	},
+	{EFI_RT_PROPERTIES_TABLE_GUID,		&rt_prop,		"RTPROP"	},
 #ifdef CONFIG_EFI_RCI2_TABLE
-	{DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys},
+	{DELLEMC_EFI_RCI2_TABLE_GUID,		&rci2_table_phys			},
 #endif
-	{NULL_GUID, NULL, NULL},
+	{},
 };
 
 static __init int match_config_table(const efi_guid_t *guid,
@@ -529,7 +529,7 @@ static __init int match_config_table(const efi_guid_t *guid,
 		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
 			if (!efi_guidcmp(*guid, table_types[i].guid)) {
 				*(table_types[i].ptr) = table;
-				if (table_types[i].name)
+				if (table_types[i].name[0])
 					pr_cont(" %s=0x%lx ",
 						table_types[i].name, table);
 				return 1;
include/linux/efi.h +1 -1
index 251f1f783cdf..9b7c7ec319ac 100644
@@ -379,8 +379,8 @@ typedef union {
 
 typedef struct {
 	efi_guid_t guid;
-	const char *name;
 	unsigned long *ptr;
+	const char name[16];
 } efi_config_table_type_t;
 
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
Signature · 1 line
2.17.1
author maintainer
#37 lore raw

PATCH 33/33 efi: Move arch_tables check to caller

In reply to Ard Biesheuvel

Instead of making match_config_table() test its table_types pointer for NULL-ness, omit the call entirely if no arch_tables pointer was provided to efi_config_parse_tables().

---
 drivers/firmware/efi/efi.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)
drivers/firmware/efi/efi.c +8 -10
index e49c0b6db988..48d0188936c3 100644
@@ -525,15 +525,13 @@ static __init int match_config_table(const efi_guid_t *guid,
 {
 	int i;
 
-	if (table_types) {
-		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
-			if (!efi_guidcmp(*guid, table_types[i].guid)) {
-				*(table_types[i].ptr) = table;
-				if (table_types[i].name[0])
-					pr_cont(" %s=0x%lx ",
-						table_types[i].name, table);
-				return 1;
-			}
+	for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
+		if (!efi_guidcmp(*guid, table_types[i].guid)) {
+			*(table_types[i].ptr) = table;
+			if (table_types[i].name[0])
+				pr_cont("%s=0x%lx ",
+					table_types[i].name, table);
+			return 1;
 		}
 	}
 
@@ -570,7 +568,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
 			table = tbl32[i].table;
 		}
 
-		if (!match_config_table(guid, table, common_tables))
+		if (!match_config_table(guid, table, common_tables) && arch_tables)
 			match_config_table(guid, table, arch_tables);
 	}
 	pr_cont("\n");
Signature · 1 line
2.17.1
author maintainer
#33 lore raw

PATCH 29/33 efi/libstub: Drop __pure getter for efi_system_table

In reply to Ard Biesheuvel

The practice of using __pure getter functions to access global variables in the EFI stub dates back to the time when we had to carefully prevent GOT entries from being emitted, because we could not rely on the toolchain to do this for us.

Today, we use the hidden visibility pragma for all EFI stub source files, which now all live in the same subdirectory, and we apply a sanity check on the objects, so we can get rid of these getter functions and simply refer to global data objects directly.

Start with efi_system_table(), and convert it into a global variable. While at it, make it a pointer-to-const, because we can.

---
 arch/x86/include/asm/efi.h                    | 14 ++++++-----
 .../firmware/efi/libstub/efi-stub-helper.c    |  6 ++---
 drivers/firmware/efi/libstub/efi-stub.c       | 13 ++++-------
 drivers/firmware/efi/libstub/efistub.h        |  6 ++---
 drivers/firmware/efi/libstub/fdt.c            |  6 ++---
 drivers/firmware/efi/libstub/x86-stub.c       | 23 ++++++++-----------
 6 files changed, 30 insertions(+), 38 deletions(-)
arch/x86/include/asm/efi.h +8 -6
index f59cba117dcb..78e839925a81 100644
@@ -339,15 +339,17 @@ static inline u32 efi64_convert_status(efi_status_t status)
 
 #define efi_bs_call(func, ...)						\
 	(efi_is_native()						\
-		? efi_system_table()->boottime->func(__VA_ARGS__)	\
-		: __efi64_thunk_map(efi_table_attr(efi_system_table(),	\
-				boottime), func, __VA_ARGS__))
+		? efi_system_table->boottime->func(__VA_ARGS__)		\
+		: __efi64_thunk_map(efi_table_attr(efi_system_table,	\
+						   boottime),		\
+				    func, __VA_ARGS__))
 
 #define efi_rt_call(func, ...)						\
 	(efi_is_native()						\
-		? efi_system_table()->runtime->func(__VA_ARGS__)	\
-		: __efi64_thunk_map(efi_table_attr(efi_system_table(),	\
-				runtime), func, __VA_ARGS__))
+		? efi_system_table->runtime->func(__VA_ARGS__)		\
+		: __efi64_thunk_map(efi_table_attr(efi_system_table,	\
+						   runtime),		\
+				    func, __VA_ARGS__))
 
 extern bool efi_reboot_required(void);
 extern bool efi_is_table_address(unsigned long phys_addr);
drivers/firmware/efi/libstub/efi-stub-helper.c +3 -3
index 14e56a64f208..0b1688b10ddc 100644
@@ -287,8 +287,8 @@ 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);
-	int nr_tables = efi_table_attr(efi_system_table(), nr_tables);
+	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++) {
@@ -305,7 +305,7 @@ 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_call_proto(efi_table_attr(efi_system_table, con_out),
 		       output_string, str);
 }
 
drivers/firmware/efi/libstub/efi-stub.c +4 -9
index 8455c590c7b9..8edfd4022803 100644
@@ -38,12 +38,7 @@
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 static bool flat_va_mapping;
 
-static efi_system_table_t *sys_table;
-
-__pure efi_system_table_t *efi_system_table(void)
-{
-	return sys_table;
-}
+const efi_system_table_t *efi_system_table;
 
 static struct screen_info *setup_graphics(void)
 {
@@ -167,10 +162,10 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
 	efi_properties_table_t *prop_tbl;
 	unsigned long max_addr;
 
-	sys_table = sys_table_arg;
+	efi_system_table = sys_table_arg;
 
 	/* Check if we were booted by the EFI firmware */
-	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
+	if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
 		status = EFI_INVALID_PARAMETER;
 		goto fail;
 	}
@@ -184,7 +179,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
 	 * information about the running image, such as size and the command
 	 * line.
 	 */
-	status = sys_table->boottime->handle_protocol(handle,
+	status = efi_system_table->boottime->handle_protocol(handle,
 					&loaded_image_proto, (void *)&image);
 	if (status != EFI_SUCCESS) {
 		pr_efi_err("Failed to get loaded image protocol\n");
drivers/firmware/efi/libstub/efistub.h +3 -3
index 9a87fff1d4ba..c1481c5abea4 100644
@@ -31,13 +31,13 @@ extern bool __pure noinitrd(void);
 extern bool __pure is_quiet(void);
 extern bool __pure novamap(void);
 
-extern __pure efi_system_table_t  *efi_system_table(void);
+extern const efi_system_table_t *efi_system_table;
 
 #ifndef efi_bs_call
-#define efi_bs_call(func, ...)	efi_system_table()->boottime->func(__VA_ARGS__)
+#define efi_bs_call(func, ...)	efi_system_table->boottime->func(__VA_ARGS__)
 #endif
 #ifndef efi_rt_call
-#define efi_rt_call(func, ...)	efi_system_table()->runtime->func(__VA_ARGS__)
+#define efi_rt_call(func, ...)	efi_system_table->runtime->func(__VA_ARGS__)
 #endif
 #ifndef efi_is_native
 #define efi_is_native()		(true)
drivers/firmware/efi/libstub/fdt.c +3 -3
index 46cffac7a5f1..06d5e7fc8e34 100644
@@ -110,7 +110,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
 
 	/* 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)efi_system_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)
@@ -314,7 +314,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
 			return EFI_SUCCESS;
 
 		/* Install the new virtual address map */
-		svam = efi_system_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);
 
@@ -348,7 +348,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
 	efi_free(MAX_FDT_SIZE, *new_fdt_addr);
 
 fail:
-	efi_system_table()->boottime->free_pool(runtime_map);
+	efi_system_table->boottime->free_pool(runtime_map);
 
 	return EFI_LOAD_ERROR;
 }
drivers/firmware/efi/libstub/x86-stub.c +9 -14
index 1c3807d0c321..3f132f51ab0f 100644
@@ -20,15 +20,10 @@
 /* Maximum physical address for 64-bit kernel with 4-level paging */
 #define MAXMEM_X86_64_4LEVEL (1ull << 46)
 
-static efi_system_table_t *sys_table;
+const efi_system_table_t *efi_system_table;
 extern const bool efi_is64;
 extern u32 image_offset;
 
-__pure efi_system_table_t *efi_system_table(void)
-{
-	return sys_table;
-}
-
 __attribute_const__ bool efi_is_64bit(void)
 {
 	if (IS_ENABLED(CONFIG_EFI_MIXED))
@@ -227,7 +222,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);
+		efi_table_attr(efi_system_table, fw_vendor);
 
 	if (!memcmp(fw_vendor, apple, sizeof(apple))) {
 		if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
@@ -377,10 +372,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 	unsigned long ramdisk_addr;
 	unsigned long ramdisk_size;
 
-	sys_table = sys_table_arg;
+	efi_system_table = sys_table_arg;
 
 	/* Check if we were booted by the EFI firmware */
-	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+	if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		efi_exit(handle, EFI_INVALID_PARAMETER);
 
 	status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
@@ -446,7 +441,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 		}
 	}
 
-	efi_stub_entry(handle, sys_table, boot_params);
+	efi_stub_entry(handle, sys_table_arg, boot_params);
 	/* not reached */
 
 fail2:
@@ -651,14 +646,14 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
 				   : EFI32_LOADER_SIGNATURE;
 	memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
 
-	p->efi->efi_systab		= (unsigned long)efi_system_table();
+	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)efi_system_table() >> 32;
+	p->efi->efi_systab_hi		= (unsigned long)efi_system_table >> 32;
 	p->efi->efi_memmap_hi		= (unsigned long)*map->map >> 32;
 #endif
 
@@ -719,10 +714,10 @@ unsigned long efi_main(efi_handle_t handle,
 	efi_status_t status;
 	unsigned long cmdline_paddr;
 
-	sys_table = sys_table_arg;
+	efi_system_table = sys_table_arg;
 
 	/* Check if we were booted by the EFI firmware */
-	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+	if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		efi_exit(handle, EFI_INVALID_PARAMETER);
 
 	/*
Signature · 1 line
2.17.1
author maintainer
#29 lore raw

PATCH 25/33 efi/libstub: Move efi_relocate_kernel() into separate source file

In reply to Ard Biesheuvel

Move efi_relocate_kernel() into a separate source file, so that it only gets pulled into builds for architectures that use it. Since efi_relocate_kernel() is the only user of efi_low_alloc(), let's move that over as well.

---
 drivers/firmware/efi/libstub/Makefile   |   2 +-
 drivers/firmware/efi/libstub/efistub.h  |  15 --
 drivers/firmware/efi/libstub/mem.c      | 168 -----------------------
 drivers/firmware/efi/libstub/relocate.c | 174 ++++++++++++++++++++++++
 4 files changed, 175 insertions(+), 184 deletions(-)
 create mode 100644 drivers/firmware/efi/libstub/relocate.c
drivers/firmware/efi/libstub/Makefile +1 -1
index bb8af2b16c49..9a712a6e2f87 100644
@@ -43,7 +43,7 @@ KCOV_INSTRUMENT			:= n
 lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
 				   file.o mem.o random.o randomalloc.o pci.o \
 				   skip_spaces.o lib-cmdline.o lib-ctype.o \
-				   alignedmem.o
+				   alignedmem.o relocate.o
 
 # include the stub's generic dependencies from lib/ when building for ARM/arm64
 efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
drivers/firmware/efi/libstub/efistub.h +0 -15
index baa0bc166074..2a0698d9dc78 100644
@@ -639,21 +639,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len,
 
 efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
 
-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(unsigned long size, unsigned long align,
-			   unsigned long *addr)
-{
-	/*
-	 * Don't allocate at 0x0. It will confuse code that
-	 * checks pointers against NULL. Skip the first 8
-	 * bytes so we start at a nice even number.
-	 */
-	return efi_low_alloc_above(size, align, addr, 0x8);
-}
-
 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
 				unsigned long max);
 
drivers/firmware/efi/libstub/mem.c +0 -168

177 lines not on this page · raw message

drivers/firmware/efi/libstub/relocate.c new file +174 -0

174 lines not on this page · raw message

Signature · 1 line
2.17.1
author maintainer
#30 lore raw

PATCH 26/33 efi/arm: Remove __efistub_global annotation

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Instead of using __efistub_global to force variables into the .data section, leave them in the .bss but pull the EFI stub's .bss section into .data in the linker script for the compressed kernel.

---
 arch/arm/boot/compressed/vmlinux.lds.S | 2 +-
 drivers/firmware/efi/libstub/Makefile  | 7 ++++---
 drivers/firmware/efi/libstub/efistub.h | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)
arch/arm/boot/compressed/vmlinux.lds.S +1 -1
index b247f399de71..b6793c7932a9 100644
@@ -78,7 +78,7 @@ SECTIONS
      * The EFI stub always executes from RAM, and runs strictly before the
      * decompressor, so we can make an exception for its r/w data, and keep it
      */
-    *(.data.efistub)
+    *(.data.efistub .bss.efistub)
     __pecoff_data_end = .;
 
     /*
drivers/firmware/efi/libstub/Makefile +4 -3
index 9a712a6e2f87..aa3ab9a4105e 100644
@@ -101,8 +101,9 @@ quiet_cmd_stubcopy = STUBCPY $@
 
 #
 # ARM discards the .data section because it disallows r/w data in the
-# decompressor. So move our .data to .data.efistub, which is preserved
-# explicitly by the decompressor linker script.
+# decompressor. So move our .data to .data.efistub and .bss to .bss.efistub,
+# which are preserved explicitly by the decompressor linker script.
 #
-STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub
+STUBCOPY_FLAGS-$(CONFIG_ARM)	+= --rename-section .data=.data.efistub	\
+				   --rename-section .bss=.bss.efistub,load,alloc
 STUBCOPY_RELOC-$(CONFIG_ARM)	:= R_ARM_ABS
drivers/firmware/efi/libstub/efistub.h +1 -1
index 2a0698d9dc78..96e25b17c88e 100644
@@ -25,7 +25,7 @@
 #define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
 #endif
 
-#if defined(CONFIG_ARM) || defined(CONFIG_X86)
+#if defined(CONFIG_X86)
 #define __efistub_global	__section(.data)
 #else
 #define __efistub_global
Signature · 1 line
2.17.1
author maintainer
#27 lore raw

PATCH 23/33 efi/libstub: Add API function to allocate aligned memory

In reply to Ard Biesheuvel

Break out the code to create an aligned page allocation from mem.c and move it into a function efi_allocate_pages_aligned() in alignedmem.c. Update efi_allocate_pages() to invoke it unless the minimum alignment equals the EFI page size (4 KB), in which case the ordinary page allocator is sufficient. This way, efi_allocate_pages_aligned() will only be pulled into the build if it is actually being used (which will be on arm64 only in the immediate future)

---
 drivers/firmware/efi/libstub/Makefile     |  3 +-
 drivers/firmware/efi/libstub/alignedmem.c | 57 +++++++++++++++++++++++
 drivers/firmware/efi/libstub/efistub.h    |  3 ++
 drivers/firmware/efi/libstub/mem.c        | 25 ++++------
 4 files changed, 71 insertions(+), 17 deletions(-)
 create mode 100644 drivers/firmware/efi/libstub/alignedmem.c
drivers/firmware/efi/libstub/Makefile +2 -1
index 75cb2c3a1519..bb8af2b16c49 100644
@@ -42,7 +42,8 @@ KCOV_INSTRUMENT			:= n
 
 lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
 				   file.o mem.o random.o randomalloc.o pci.o \
-				   skip_spaces.o lib-cmdline.o lib-ctype.o
+				   skip_spaces.o lib-cmdline.o lib-ctype.o \
+				   alignedmem.o
 
 # include the stub's generic dependencies from lib/ when building for ARM/arm64
 efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
drivers/firmware/efi/libstub/alignedmem.c new file +57 -0

57 lines not on this page · raw message

drivers/firmware/efi/libstub/efistub.h +3 -0
index 9af65be3b278..baa0bc166074 100644
@@ -657,6 +657,9 @@ efi_status_t efi_low_alloc(unsigned long size, unsigned long align,
 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
 				unsigned long max);
 
+efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
+					unsigned long max, unsigned long align);
+
 efi_status_t efi_relocate_kernel(unsigned long *image_addr,
 				 unsigned long image_size,
 				 unsigned long alloc_size,
drivers/firmware/efi/libstub/mem.c +9 -16
index 869a79c8946f..0020b0fa9587 100644
@@ -93,31 +93,24 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
 				unsigned long max)
 {
-	efi_physical_addr_t alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
-	int slack = EFI_ALLOC_ALIGN / EFI_PAGE_SIZE - 1;
+	efi_physical_addr_t alloc_addr;
 	efi_status_t status;
 
-	size = round_up(size, EFI_ALLOC_ALIGN);
+	if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
+		return efi_allocate_pages_aligned(size, addr, max,
+						  EFI_ALLOC_ALIGN);
+
+	alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
 	status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
-			     EFI_LOADER_DATA, size / EFI_PAGE_SIZE + slack,
+			     EFI_LOADER_DATA, DIV_ROUND_UP(size, EFI_PAGE_SIZE),
 			     &alloc_addr);
 	if (status != EFI_SUCCESS)
 		return status;
 
-	*addr = ALIGN((unsigned long)alloc_addr, EFI_ALLOC_ALIGN);
-
-	if (slack > 0) {
-		int l = (alloc_addr % EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
-
-		if (l) {
-			efi_bs_call(free_pages, alloc_addr, slack - l + 1);
-			slack = l - 1;
-		}
-		if (slack)
-			efi_bs_call(free_pages, *addr + size, slack);
-	}
+	*addr = alloc_addr;
 	return EFI_SUCCESS;
 }
+
 /**
  * efi_low_alloc_above() - allocate pages at or above given address
  * @size:	size of the memory area to allocate
Signature · 1 line
2.17.1
author maintainer
#21 lore raw

PATCH 17/33 efi/gop: Allow specifying depth as well as resolution

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Extend the video mode argument to handle an optional color depth specification of the form

	video=efifb:<xres>x<yres>[-(rgb|bgr|<bpp>)]
---
 Documentation/fb/efifb.rst         |  8 +++--
 drivers/firmware/efi/libstub/gop.c | 48 ++++++++++++++++++++++++++----
 2 files changed, 48 insertions(+), 8 deletions(-)
Documentation/fb/efifb.rst +5 -3
index 635275071307..eca38466487a 100644
@@ -50,9 +50,11 @@ mode=n
         The EFI stub will set the mode of the display to mode number n if
         possible.
 
-<xres>x<yres>
+<xres>x<yres>[-(rgb|bgr|<bpp>)]
         The EFI stub will search for a display mode that matches the specified
-        horizontal and vertical resolution, and set the mode of the display to
-        it if one is found.
+        horizontal and vertical resolution, and optionally bit depth, and set
+        the mode of the display to it if one is found. The bit depth can either
+        "rgb" or "bgr" to match specifically those pixel formats, or a number
+        for a mode with matching bits per pixel.
 
 Edgar Hucek <[email protected]>
drivers/firmware/efi/libstub/gop.c +43 -5

102 lines not on this page · raw message

Signature · 1 line
2.17.1
author maintainer
#15 lore raw

PATCH 11/33 efi/gop: Use helper macros for populating lfb_base

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Use the lower/upper_32_bits macros from kernel.h to initialize si->lfb_base and si->ext_lfb_base.

---
 drivers/firmware/efi/libstub/gop.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/efi/libstub/gop.c +2 -2
index 0d195060a370..7b0baf9a912f 100644
@@ -158,8 +158,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 	si->lfb_height = info->vertical_resolution;
 
 	fb_base		 = efi_table_attr(mode, frame_buffer_base);
-	si->lfb_base	 = fb_base;
-	si->ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
+	si->lfb_base	 = lower_32_bits(fb_base);
+	si->ext_lfb_base = upper_32_bits(fb_base);
 	if (si->ext_lfb_base)
 		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
 
Signature · 1 line
2.17.1
author maintainer
#12 lore raw

PATCH 8/33 efi/gop: Factor out locating the gop into a function

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

Move the loop to find a gop into its own function.

---
 drivers/firmware/efi/libstub/gop.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)
drivers/firmware/efi/libstub/gop.c +17 -6
index d692b8c65813..92abcf558845 100644
@@ -85,19 +85,17 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 	}
 }
 
-static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
-			      unsigned long size, void **handles)
+static efi_graphics_output_protocol_t *
+find_gop(efi_guid_t *proto, unsigned long size, void **handles)
 {
 	efi_graphics_output_protocol_t *gop, *first_gop;
 	efi_graphics_output_protocol_mode_t *mode;
 	efi_graphics_output_mode_info_t *info = NULL;
-	efi_physical_addr_t fb_base;
 	efi_status_t status;
 	efi_handle_t h;
 	int i;
 
 	first_gop = NULL;
-	gop = NULL;
 
 	for_each_efi_handle(h, handles, size, i) {
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
@@ -134,12 +132,25 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		}
 	}
 
+	return first_gop;
+}
+
+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;
+	efi_graphics_output_protocol_mode_t *mode;
+	efi_graphics_output_mode_info_t *info = NULL;
+	efi_physical_addr_t fb_base;
+
+	gop = find_gop(proto, size, handles);
+
 	/* Did we find any GOPs? */
-	if (!first_gop)
+	if (!gop)
 		return EFI_NOT_FOUND;
 
 	/* EFI framebuffer */
-	mode = efi_table_attr(first_gop, mode);
+	mode = efi_table_attr(gop, mode);
 	info = efi_table_attr(mode, info);
 
 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
Signature · 1 line
2.17.1
author maintainer
#9 lore raw

PATCH 5/33 efi/gop: Remove redundant current_fb_base

In reply to Ard Biesheuvel

From: Arvind Sankar <[email protected]>

current_fb_base isn't used for anything except assigning to fb_base if we locate a suitable gop.

---
 drivers/firmware/efi/libstub/gop.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/firmware/efi/libstub/gop.c +1 -3
index 55e6b3f286fe..f40d535dccb8 100644
@@ -108,7 +108,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
 		bool conout_found = false;
 		void *dummy = NULL;
-		efi_physical_addr_t current_fb_base;
 
 		status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
 		if (status != EFI_SUCCESS)
@@ -120,7 +119,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 
 		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) {
@@ -136,7 +134,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 			pixel_format = info->pixel_format;
 			pixel_info = info->pixel_information;
 			pixels_per_scan_line = info->pixels_per_scan_line;
-			fb_base = current_fb_base;
+			fb_base = efi_table_attr(mode, frame_buffer_base);
 
 			/*
 			 * Once we've found a GOP supporting ConOut,
Signature · 1 line
2.17.1
author maintainer
#3 lore raw

Re: [PATCH 02/33] efi/libstub: Make initrd file loader configurable

In reply to Ard Biesheuvel
Quoted 19 lines · Ard Biesheuvel

Loading an initrd passed via the kernel command line is deprecated: it is limited to files that reside in the same volume as the one the kernel itself was loaded from, and we have more flexible ways to achieve the same. So make it configurable so new architectures can decide not to enable it.

---
 drivers/firmware/efi/Kconfig           | 11 ++++++++
 drivers/firmware/efi/libstub/efistub.h | 38 ++++++++++++++++++++------
 drivers/firmware/efi/libstub/file.c    | 32 +++++-----------------
 3 files changed, 47 insertions(+), 34 deletions(-)
drivers/firmware/efi/Kconfig +0 -0
index 2a2b2b96a1dc..4e788dd55b03 100644

drivers/firmware/efi/Kconfig config EFI_ARMSTUB_DTB_LOADER · line 129

Quoted 6 lines
drivers/firmware/efi/Kconfig +3 -0
@@ -124,6 +124,17 @@ config EFI_ARMSTUB_DTB_LOADER
          functionality for bootloaders that do not have such support
          this option is necessary.
 
+config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER
+       bool "Enable the command line initrd loader"
+       depends on EFI_GENERIC_STUB

Right after hitting send, I realised this should be

depends on EFI_GENERIC_STUB || X86

Care to fix that up before applying, please?

Quoted 110 lines
drivers/firmware/efi/Kconfig +8 -0
+       default y
+       help
+         Select this config option to add support for the initrd= command
+         line parameter, allowing an initrd that resides on the same volume
+         as the kernel image to be loaded into memory.
+
+         This method is deprecated.
+
 config EFI_BOOTLOADER_CONTROL
        tristate "EFI Bootloader Control"
        depends on EFI_VARS
drivers/firmware/efi/libstub/efistub.h +29 -9
index 67d26949fd26..7517683b31e9 100644
@@ -651,15 +651,35 @@ efi_status_t efi_parse_options(char const *cmdline);
 efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
                           unsigned long size);
 
-efi_status_t efi_load_dtb(efi_loaded_image_t *image,
-                         unsigned long *load_addr,
-                         unsigned long *load_size);
-
-efi_status_t efi_load_initrd(efi_loaded_image_t *image,
-                            unsigned long *load_addr,
-                            unsigned long *load_size,
-                            unsigned long soft_limit,
-                            unsigned long hard_limit);
+efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+                                 const efi_char16_t *optstr,
+                                 int optstr_size,
+                                 unsigned long soft_limit,
+                                 unsigned long hard_limit,
+                                 unsigned long *load_addr,
+                                 unsigned long *load_size);
+
+
+static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image,
+                                       unsigned long *load_addr,
+                                       unsigned long *load_size)
+{
+       return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2,
+                                   ULONG_MAX, ULONG_MAX, load_addr, load_size);
+}
+
+static inline efi_status_t efi_load_initrd(efi_loaded_image_t *image,
+                                          unsigned long *load_addr,
+                                          unsigned long *load_size,
+                                          unsigned long soft_limit,
+                                          unsigned long hard_limit)
+{
+       if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER))
+               return EFI_SUCCESS;
+
+       return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
+                                   soft_limit, hard_limit, load_addr, load_size);
+}
 
 efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
                                      unsigned long *load_size,
drivers/firmware/efi/libstub/file.c +7 -26
index ea66b1f16a79..27e014ea4459 100644
@@ -121,13 +121,13 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
  * We only support loading a file from the same filesystem as
  * the kernel image.
  */
-static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
-                                        const efi_char16_t *optstr,
-                                        int optstr_size,
-                                        unsigned long soft_limit,
-                                        unsigned long hard_limit,
-                                        unsigned long *load_addr,
-                                        unsigned long *load_size)
+efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
+                                 const efi_char16_t *optstr,
+                                 int optstr_size,
+                                 unsigned long soft_limit,
+                                 unsigned long hard_limit,
+                                 unsigned long *load_addr,
+                                 unsigned long *load_size)
 {
        const efi_char16_t *cmdline = image->load_options;
        int cmdline_len = image->load_options_size / 2;
@@ -239,21 +239,3 @@ static efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
        efi_free(alloc_size, alloc_addr);
        return status;
 }
-
-efi_status_t efi_load_dtb(efi_loaded_image_t *image,
-                         unsigned long *load_addr,
-                         unsigned long *load_size)
-{
-       return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2,
-                                   ULONG_MAX, ULONG_MAX, load_addr, load_size);
-}
-
-efi_status_t efi_load_initrd(efi_loaded_image_t *image,
-                            unsigned long *load_addr,
-                            unsigned long *load_size,
-                            unsigned long soft_limit,
-                            unsigned long hard_limit)
-{
-       return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
-                                   soft_limit, hard_limit, load_addr, load_size);
-}
--

2.17.1

#38 lore raw
In reply to Ard Biesheuvel
Quoted 30 lines · Ard Biesheuvel

Hello Ingo, Thomas,

Please pull the attached changes into tip/efi/next. There is some coordination going on with the RISC-V tree this time, so please take the patches in this exact order, and apply them onto v5.7-rc2 so the first three patches can serve as a shared stable base between the efi/core branch and the riscv tree.

The following changes since commit ae83d0b416db002fe95601e7f97f64b59514d936:

Linux 5.7-rc2 (2020-04-19 14:35:30 -0700)

are available in the Git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git tags/efi-next

for you to fetch changes up to 4eb8320bd1aaa7e69d039f2c251735e3ef0b9a38:

efi: Move arch_tables check to caller (2020-04-24 14:52:16 +0200)

----------------------------------------------------------------
EFI changes for v5.8:
- preliminary changes for RISC-V
- add support for setting the resolution on the EFI framebuffer
- simplify kernel image loading for arm64
- Move .bss into .data via the linker script instead of relying on symbol annotations.
- Get rid of __pure getters to access global variables
- Clean up the config table matching arrays

Quoted 4 lines
 27 files changed, 895 insertions(+), 574 deletions(-)
 create mode 100644 drivers/firmware/efi/libstub/alignedmem.c
 rename drivers/firmware/efi/libstub/{arm-stub.c => efi-stub.c} (96%)
 create mode 100644 drivers/firmware/efi/libstub/relocate.c

Pulled into tip:efi/core, thanks a lot Ard!

Ingo

author maintainer
#39 lore raw
Quoted 34 lines · Ingo Molnar
Quoted 29 lines · Ard Biesheuvel

Hello Ingo, Thomas,

Please pull the attached changes into tip/efi/next. There is some coordination going on with the RISC-V tree this time, so please take the patches in this exact order, and apply them onto v5.7-rc2 so the first three patches can serve as a shared stable base between the efi/core branch and the riscv tree.

The following changes since commit ae83d0b416db002fe95601e7f97f64b59514d936:

Linux 5.7-rc2 (2020-04-19 14:35:30 -0700)

are available in the Git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git tags/efi-next

for you to fetch changes up to 4eb8320bd1aaa7e69d039f2c251735e3ef0b9a38:

efi: Move arch_tables check to caller (2020-04-24 14:52:16 +0200)

----------------------------------------------------------------
EFI changes for v5.8:
- preliminary changes for RISC-V
- add support for setting the resolution on the EFI framebuffer
- simplify kernel image loading for arm64
- Move .bss into .data via the linker script instead of relying on symbol annotations.
- Get rid of __pure getters to access global variables
- Clean up the config table matching arrays

Quoted 7 lines
Quoted 4 lines
 27 files changed, 895 insertions(+), 574 deletions(-)
 create mode 100644 drivers/firmware/efi/libstub/alignedmem.c
 rename drivers/firmware/efi/libstub/{arm-stub.c => efi-stub.c} (96%)
 create mode 100644 drivers/firmware/efi/libstub/relocate.c

Pulled into tip:efi/core, thanks a lot Ard!

Thanks Ingo

I guess this means you didn't spot my remark regarding patch #3, which needs a Kconfig depends tweak for x86. I'll send that out as a followup patch.

#5 lore raw

Re: [PATCH 03/33] efi/libstub: Unify EFI call wrappers for non-x86

In reply to Ard Biesheuvel

Hi,

Quoted 8 lines · Ard Biesheuvel

We have wrappers around EFI calls so that x86 can define special versions for mixed mode, while all other architectures can use the same simple definition that just issues the call directly. In preparation for the arrival of yet another architecture that doesn't need anything special here (RISC-V), let's move the default definition into a shared header.

This patch causes an immediate reboot in linux-next when booting in qemu with an efi32 bios. Bisect log attached.

Qemu command line:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -m 1G \
	-no-reboot -snapshot \
	-bios OVMF-pure-efi-32.fd \
	-drive file=rootfs.ext2,format=raw \
	--append 'earlycon=uart8250,io,0x3f8,9600n8 panic=-1 root=/dev/sda console=ttyS0' \
	-nographic

The same command succeeds with OVMF-pure-efi-64.fd.

Bisect log attached.

File locations:

	https://github.com/groeck/linux-build-test/blob/master/rootfs/firmware/OVMF-pure-efi-32.fd
	https://github.com/groeck/linux-build-test/blob/master/rootfs/x86_64/rootfs.ext2.gz

Guenter

---
# bad: [fb9d670f57e3f6478602328bbbf71138be06ca4f] Add linux-next specific files for 20200501
# good: [6a8b55ed4056ea5559ebe4f6a4b247f627870d4c] Linux 5.7-rc3
git bisect start 'HEAD' 'v5.7-rc3'
# good: [068b80b68a670f0b17288c8a3d1ee751f35162ab] Merge remote-tracking branch 'drm/drm-next'
git bisect good 068b80b68a670f0b17288c8a3d1ee751f35162ab
# bad: [46c70fc6a3ac35cd72ddad248dcbe4eee716d2a5] Merge remote-tracking branch 'drivers-x86/for-next' git bisect bad 46c70fc6a3ac35cd72ddad248dcbe4eee716d2a5
# good: [3fc893798e1ca8276eaf2b0e3210f2ff927f0c80] Merge remote-tracking branch 'integrity/next-integrity' git bisect good 3fc893798e1ca8276eaf2b0e3210f2ff927f0c80
# bad: [88188475d4d3fd10edabb172a7dc71e4bf997c19] Merge remote-tracking branch 'tip/auto-latest'
git bisect bad 88188475d4d3fd10edabb172a7dc71e4bf997c19
# good: [a51a8decbc07a511d9a05b2aff93bd8b10bfe812] Merge branch 'objtool/core'
git bisect good a51a8decbc07a511d9a05b2aff93bd8b10bfe812
# good: [12414a49ebe9d6584f4942a4bfd98ce5c34e034b] Merge remote-tracking branch 'spi/for-next'
git bisect good 12414a49ebe9d6584f4942a4bfd98ce5c34e034b
# good: [703b321501c95c658275fd76775282fe45989641] kcsan: Introduce ASSERT_EXCLUSIVE_BITS(var, mask) git bisect good 703b321501c95c658275fd76775282fe45989641
# bad: [e71356fe29e7bd5cd5e07800d4940a7481fb0854] efi/libstub/arm64: Switch to ordinary page allocator for kernel image git bisect bad e71356fe29e7bd5cd5e07800d4940a7481fb0854
# bad: [9867fc9de6a6a7a54edb2c43540c6db226e84a14] efi/gop: Use helper macros for find_bits
git bisect bad 9867fc9de6a6a7a54edb2c43540c6db226e84a14
# bad: [8cd207973c37175bf44727e28aa9c74fcf18de5e] efi/gop: Move check for framebuffer before con_out git bisect bad 8cd207973c37175bf44727e28aa9c74fcf18de5e
# bad: [22090f84bc3f8081e0ec180ccaedc85820085376] efi/libstub: unify EFI call wrappers for non-x86 git bisect bad 22090f84bc3f8081e0ec180ccaedc85820085376
# good: [cf6b83664895a5c7e97710df282e220bd047f0f5] efi/libstub: Make initrd file loader configurable git bisect good cf6b83664895a5c7e97710df282e220bd047f0f5

# first bad commit: [22090f84bc3f8081e0ec180ccaedc85820085376] efi/libstub: unify EFI call wrappers for non-x86
#6 lore raw

Re: [PATCH 03/33] efi/libstub: Unify EFI call wrappers for non-x86

Quoted 26 lines · Guenter Roeck

Hi,

Quoted 8 lines · Ard Biesheuvel

We have wrappers around EFI calls so that x86 can define special versions for mixed mode, while all other architectures can use the same simple definition that just issues the call directly. In preparation for the arrival of yet another architecture that doesn't need anything special here (RISC-V), let's move the default definition into a shared header.

This patch causes an immediate reboot in linux-next when booting in qemu with an efi32 bios. Bisect log attached.

Qemu command line:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -m 1G \
	-no-reboot -snapshot \
	-bios OVMF-pure-efi-32.fd \
	-drive file=rootfs.ext2,format=raw \
	--append 'earlycon=uart8250,io,0x3f8,9600n8 panic=-1 root=/dev/sda console=ttyS0' \
	-nographic

The same command succeeds with OVMF-pure-efi-64.fd.

Quoted 8 lines

Bisect log attached.

File locations:

	https://github.com/groeck/linux-build-test/blob/master/rootfs/firmware/OVMF-pure-efi-32.fd
	https://github.com/groeck/linux-build-test/blob/master/rootfs/x86_64/rootfs.ext2.gz

Guenter

The issue is that efi_is_native is an inline function on x86, not a macro, so the #ifndef efi_is_native is broken.

We can either turn it into a macro, or add

	#define efi_is_native efi_is_native

in arch/x86/include/asm/efi.h.

author maintainer
#7 lore raw

Re: [PATCH 03/33] efi/libstub: Unify EFI call wrappers for non-x86

Quoted 37 lines · Arvind Sankar
Quoted 26 lines · Guenter Roeck

Hi,

Quoted 8 lines · Ard Biesheuvel

We have wrappers around EFI calls so that x86 can define special versions for mixed mode, while all other architectures can use the same simple definition that just issues the call directly. In preparation for the arrival of yet another architecture that doesn't need anything special here (RISC-V), let's move the default definition into a shared header.

This patch causes an immediate reboot in linux-next when booting in qemu with an efi32 bios. Bisect log attached.

Qemu command line:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -m 1G \
      -no-reboot -snapshot \
      -bios OVMF-pure-efi-32.fd \
      -drive file=rootfs.ext2,format=raw \
      --append 'earlycon=uart8250,io,0x3f8,9600n8 panic=-1 root=/dev/sda console=ttyS0' \
      -nographic

The same command succeeds with OVMF-pure-efi-64.fd.

Quoted 8 lines

Bisect log attached.

File locations:

      https://github.com/groeck/linux-build-test/blob/master/rootfs/firmware/OVMF-pure-efi-32.fd
      https://github.com/groeck/linux-build-test/blob/master/rootfs/x86_64/rootfs.ext2.gz

Guenter

Quoted 6 lines

The issue is that efi_is_native is an inline function on x86, not a macro, so the #ifndef efi_is_native is broken.

We can either turn it into a macro, or add

        #define efi_is_native efi_is_native

in arch/x86/include/asm/efi.h.

Indeed. Fix here:

https://lore.kernel.org/linux-efi/[email protected]/T/#u