Skip to content

Commit

Permalink
Merge tag 'efi-next-for-v6.14' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/efi/efi

Pull EFI updates from Ard Biesheuvel:

 - Increase the headroom in the EFI memory map allocation created by the
   EFI stub. This is needed because event callbacks called during
   ExitBootServices() may cause fragmentation, and reallocation is not
   allowed after that.

 - Drop obsolete UGA graphics code and switch to a more ergonomic API to
   traverse handle buffers. Simplify some error paths using a __free()
   helper while at it.

 - Fix some W=1 warnings when CONFIG_EFI=n

 - Rely on the dentry cache to keep track of the contents of the
   efivarfs filesystem, rather than using a separate linked list.

 - Improve and extend efivarfs test cases.

 - Synchronize efivarfs with underlying variable store on resume from
   hibernation - this is needed because the firmware itself or another
   OS running on the same machine may have modified it.

 - Fix x86 EFI stub build with GCC 15.

 - Fix kexec/x86 false positive warning in EFI memory attributes table
   sanity check.

* tag 'efi-next-for-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: (23 commits)
  x86/efi: skip memattr table on kexec boot
  efivarfs: add variable resync after hibernation
  efivarfs: abstract initial variable creation routine
  efi: libstub: Use '-std=gnu11' to fix build with GCC 15
  selftests/efivarfs: add concurrent update tests
  selftests/efivarfs: fix tests for failed write removal
  efivarfs: fix error on write to new variable leaving remnants
  efivarfs: remove unused efivarfs_list
  efivarfs: move variable lifetime management into the inodes
  selftests/efivarfs: add check for disallowing file truncation
  efivarfs: prevent setting of zero size on the inodes in the cache
  efi: sysfb_efi: fix W=1 warnings when EFI is not set
  efi/libstub: Use __free() helper for pool deallocations
  efi/libstub: Use cleanup helpers for freeing copies of the memory map
  efi/libstub: Simplify PCI I/O handle buffer traversal
  efi/libstub: Refactor and clean up GOP resolution picker code
  efi/libstub: Simplify GOP handling code
  efi/libstub: Use C99-style for loop to traverse handle buffer
  x86/efistub: Drop long obsolete UGA support
  efivarfs: make variable_is_present use dcache lookup
  ...
  • Loading branch information
Linus Torvalds committed Jan 24, 2025
2 parents f345fc7 + 64b45dd commit ae8b53a
Show file tree
Hide file tree
Showing 23 changed files with 734 additions and 700 deletions.
3 changes: 3 additions & 0 deletions arch/x86/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ static inline u32 efi64_convert_status(efi_status_t status)
#define __efi64_argmap_allocate_pool(type, size, buffer) \
((type), (size), efi64_zero_upper(buffer))

#define __efi64_argmap_locate_handle_buffer(type, proto, key, num, buf) \
((type), (proto), (key), efi64_zero_upper(num), efi64_zero_upper(buf))

#define __efi64_argmap_create_event(type, tpl, f, c, event) \
((type), (tpl), (f), (c), efi64_zero_upper(event))

Expand Down
10 changes: 0 additions & 10 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@
#include <asm/uv/uv.h>

static unsigned long efi_systab_phys __initdata;
static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
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 = {
{UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" },
#ifdef CONFIG_X86_UV
{UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" },
#endif
Expand All @@ -72,7 +70,6 @@ static const unsigned long * const efi_tables[] = {
&efi.acpi20,
&efi.smbios,
&efi.smbios3,
&uga_phys,
#ifdef CONFIG_X86_UV
&uv_systab_phys,
#endif
Expand Down Expand Up @@ -891,13 +888,6 @@ bool efi_is_table_address(unsigned long phys_addr)
return false;
}

char *efi_systab_show_arch(char *str)
{
if (uga_phys != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "UGA=0x%lx\n", uga_phys);
return str;
}

#define EFI_FIELD(var) efi_ ## var

#define EFI_ATTR_SHOW(name) \
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/platform/efi/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,11 @@ int __init efi_reuse_config(u64 tables, int nr_tables)

if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
((efi_config_table_64_t *)p)->table = data->smbios;

/* Do not bother to play with mem attr table across kexec */
if (!efi_guidcmp(guid, EFI_MEMORY_ATTRIBUTES_TABLE_GUID))
((efi_config_table_64_t *)p)->table = EFI_INVALID_TABLE_ADDR;

p += sz;
}
early_memunmap(tablep, nr_tables * sz);
Expand Down
3 changes: 0 additions & 3 deletions drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,6 @@ static ssize_t systab_show(struct kobject *kobj,
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);

if (IS_ENABLED(CONFIG_X86))
str = efi_systab_show_arch(str);

return str - buf;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/firmware/efi/libstub/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cflags-y := $(KBUILD_CFLAGS)

cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -std=gnu11 \
-fPIC -fno-strict-aliasing -mno-red-zone \
-mno-mmx -mno-sse -fshort-wchar \
-Wno-pointer-sign \
Expand Down
9 changes: 4 additions & 5 deletions drivers/firmware/efi/libstub/efi-stub-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ bool __pure __efi_soft_reserve_enabled(void)
*/
efi_status_t efi_parse_options(char const *cmdline)
{
size_t len;
char *buf __free(efi_pool) = NULL;
efi_status_t status;
char *str, *buf;
size_t len;
char *str;

if (!cmdline)
return EFI_SUCCESS;
Expand Down Expand Up @@ -102,7 +103,6 @@ efi_status_t efi_parse_options(char const *cmdline)
efi_parse_option_graphics(val + strlen("efifb:"));
}
}
efi_bs_call(free_pool, buf);
return EFI_SUCCESS;
}

Expand Down Expand Up @@ -250,7 +250,7 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
u64, const union efistub_event *);
struct { u32 hash_log_extend_event; } mixed_mode;
} method;
struct efistub_measured_event *evt;
struct efistub_measured_event *evt __free(efi_pool) = NULL;
int size = struct_size(evt, tagged_event.tagged_event_data,
events[event].event_data_len);
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
Expand Down Expand Up @@ -312,7 +312,6 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,

status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
load_addr, load_size, &evt->event_data);
efi_bs_call(free_pool, evt);

if (status == EFI_SUCCESS)
return EFI_SUCCESS;
Expand Down
49 changes: 20 additions & 29 deletions drivers/firmware/efi/libstub/efi-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*/

#include <linux/efi.h>
#include <linux/screen_info.h>
#include <asm/efi.h>

#include "efistub.h"
Expand Down Expand Up @@ -53,25 +54,16 @@ void __weak free_screen_info(struct screen_info *si)

static struct screen_info *setup_graphics(void)
{
efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
efi_status_t status;
unsigned long size;
void **gop_handle = NULL;
struct screen_info *si = NULL;
struct screen_info *si, tmp = {};

size = 0;
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
&gop_proto, NULL, &size, gop_handle);
if (status == EFI_BUFFER_TOO_SMALL) {
si = alloc_screen_info();
if (!si)
return NULL;
status = efi_setup_gop(si, &gop_proto, size);
if (status != EFI_SUCCESS) {
free_screen_info(si);
return NULL;
}
}
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
return NULL;

si = alloc_screen_info();
if (!si)
return NULL;

*si = tmp;
return si;
}

Expand Down Expand Up @@ -112,8 +104,8 @@ static u32 get_supported_rt_services(void)

efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
{
char *cmdline __free(efi_pool) = NULL;
efi_status_t status;
char *cmdline;

/*
* Get the command line from EFI, using the LOADED_IMAGE
Expand All @@ -128,25 +120,24 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)

if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
status = efi_parse_options(cmdline);
if (status != EFI_SUCCESS)
goto fail_free_cmdline;
if (status != EFI_SUCCESS) {
efi_err("Failed to parse EFI load options\n");
return status;
}
}

if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
cmdline[0] == 0) {
status = efi_parse_options(CONFIG_CMDLINE);
if (status != EFI_SUCCESS)
goto fail_free_cmdline;
if (status != EFI_SUCCESS) {
efi_err("Failed to parse built-in command line\n");
return status;
}
}

*cmdline_ptr = cmdline;
*cmdline_ptr = no_free_ptr(cmdline);
return EFI_SUCCESS;

fail_free_cmdline:
efi_err("Failed to parse options\n");
efi_bs_call(free_pool, cmdline);
return status;
}

efi_status_t efi_stub_common(efi_handle_t handle,
Expand Down
20 changes: 11 additions & 9 deletions drivers/firmware/efi/libstub/efistub.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H

#include <linux/compiler.h>
#include <linux/cleanup.h>
#include <linux/efi.h>
#include <linux/kernel.h>
#include <linux/kern_levels.h>
Expand Down Expand Up @@ -122,11 +123,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
#define efi_get_handle_num(size) \
((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32)))

#define for_each_efi_handle(handle, array, size, i) \
for (i = 0; \
i < efi_get_handle_num(size) && \
((handle = efi_get_handle_at((array), i)) || true); \
i++)
#define for_each_efi_handle(handle, array, num) \
for (int __i = 0; __i < (num) && \
((handle = efi_get_handle_at((array), __i)) || true); \
__i++)

static inline
void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
Expand Down Expand Up @@ -171,7 +171,7 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
* the EFI memory map. Other related structures, e.g. x86 e820ext, need
* to factor in this headroom requirement as well.
*/
#define EFI_MMAP_NR_SLACK_SLOTS 8
#define EFI_MMAP_NR_SLACK_SLOTS 32

typedef struct efi_generic_dev_path efi_device_path_protocol_t;

Expand Down Expand Up @@ -314,7 +314,9 @@ union efi_boot_services {
void *close_protocol;
void *open_protocol_information;
void *protocols_per_handle;
void *locate_handle_buffer;
efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *,
void *, unsigned long *,
efi_handle_t **);
efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *,
void **);
efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...);
Expand Down Expand Up @@ -1053,6 +1055,7 @@ void efi_puts(const char *str);
__printf(1, 2) int efi_printk(char const *fmt, ...);

void efi_free(unsigned long size, unsigned long addr);
DEFINE_FREE(efi_pool, void *, if (_T) efi_bs_call(free_pool, _T));

void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size);

Expand Down Expand Up @@ -1082,8 +1085,7 @@ 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);
efi_status_t efi_setup_gop(struct screen_info *si);

efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
const efi_char16_t *optstr,
Expand Down
Loading

0 comments on commit ae8b53a

Please sign in to comment.