Skip to content

Commit ae8b53a

Browse files
committed
Merge tag 'efi-next-for-v6.14' of git://git.kernel.org/pub/scm/linux/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 ...
2 parents f345fc7 + 64b45dd commit ae8b53a

File tree

23 files changed

+734
-700
lines changed

23 files changed

+734
-700
lines changed

arch/x86/include/asm/efi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ static inline u32 efi64_convert_status(efi_status_t status)
250250
#define __efi64_argmap_allocate_pool(type, size, buffer) \
251251
((type), (size), efi64_zero_upper(buffer))
252252

253+
#define __efi64_argmap_locate_handle_buffer(type, proto, key, num, buf) \
254+
((type), (proto), (key), efi64_zero_upper(num), efi64_zero_upper(buf))
255+
253256
#define __efi64_argmap_create_event(type, tpl, f, c, event) \
254257
((type), (tpl), (f), (c), efi64_zero_upper(event))
255258

arch/x86/platform/efi/efi.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,11 @@
5454
#include <asm/uv/uv.h>
5555

5656
static unsigned long efi_systab_phys __initdata;
57-
static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
5857
static unsigned long efi_runtime, efi_nr_tables;
5958

6059
unsigned long efi_fw_vendor, efi_config_table;
6160

6261
static const efi_config_table_type_t arch_tables[] __initconst = {
63-
{UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" },
6462
#ifdef CONFIG_X86_UV
6563
{UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" },
6664
#endif
@@ -72,7 +70,6 @@ static const unsigned long * const efi_tables[] = {
7270
&efi.acpi20,
7371
&efi.smbios,
7472
&efi.smbios3,
75-
&uga_phys,
7673
#ifdef CONFIG_X86_UV
7774
&uv_systab_phys,
7875
#endif
@@ -891,13 +888,6 @@ bool efi_is_table_address(unsigned long phys_addr)
891888
return false;
892889
}
893890

894-
char *efi_systab_show_arch(char *str)
895-
{
896-
if (uga_phys != EFI_INVALID_TABLE_ADDR)
897-
str += sprintf(str, "UGA=0x%lx\n", uga_phys);
898-
return str;
899-
}
900-
901891
#define EFI_FIELD(var) efi_ ## var
902892

903893
#define EFI_ATTR_SHOW(name) \

arch/x86/platform/efi/quirks.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,11 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
561561

562562
if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
563563
((efi_config_table_64_t *)p)->table = data->smbios;
564+
565+
/* Do not bother to play with mem attr table across kexec */
566+
if (!efi_guidcmp(guid, EFI_MEMORY_ATTRIBUTES_TABLE_GUID))
567+
((efi_config_table_64_t *)p)->table = EFI_INVALID_TABLE_ADDR;
568+
564569
p += sz;
565570
}
566571
early_memunmap(tablep, nr_tables * sz);

drivers/firmware/efi/efi.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,6 @@ static ssize_t systab_show(struct kobject *kobj,
148148
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
149149
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
150150

151-
if (IS_ENABLED(CONFIG_X86))
152-
str = efi_systab_show_arch(str);
153-
154151
return str - buf;
155152
}
156153

drivers/firmware/efi/libstub/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ cflags-y := $(KBUILD_CFLAGS)
1111

1212
cflags-$(CONFIG_X86_32) := -march=i386
1313
cflags-$(CONFIG_X86_64) := -mcmodel=small
14-
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
14+
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -std=gnu11 \
1515
-fPIC -fno-strict-aliasing -mno-red-zone \
1616
-mno-mmx -mno-sse -fshort-wchar \
1717
-Wno-pointer-sign \

drivers/firmware/efi/libstub/efi-stub-helper.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ bool __pure __efi_soft_reserve_enabled(void)
4747
*/
4848
efi_status_t efi_parse_options(char const *cmdline)
4949
{
50-
size_t len;
50+
char *buf __free(efi_pool) = NULL;
5151
efi_status_t status;
52-
char *str, *buf;
52+
size_t len;
53+
char *str;
5354

5455
if (!cmdline)
5556
return EFI_SUCCESS;
@@ -102,7 +103,6 @@ efi_status_t efi_parse_options(char const *cmdline)
102103
efi_parse_option_graphics(val + strlen("efifb:"));
103104
}
104105
}
105-
efi_bs_call(free_pool, buf);
106106
return EFI_SUCCESS;
107107
}
108108

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

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

317316
if (status == EFI_SUCCESS)
318317
return EFI_SUCCESS;

drivers/firmware/efi/libstub/efi-stub.c

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
#include <linux/efi.h>
13+
#include <linux/screen_info.h>
1314
#include <asm/efi.h>
1415

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

5455
static struct screen_info *setup_graphics(void)
5556
{
56-
efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
57-
efi_status_t status;
58-
unsigned long size;
59-
void **gop_handle = NULL;
60-
struct screen_info *si = NULL;
57+
struct screen_info *si, tmp = {};
6158

62-
size = 0;
63-
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
64-
&gop_proto, NULL, &size, gop_handle);
65-
if (status == EFI_BUFFER_TOO_SMALL) {
66-
si = alloc_screen_info();
67-
if (!si)
68-
return NULL;
69-
status = efi_setup_gop(si, &gop_proto, size);
70-
if (status != EFI_SUCCESS) {
71-
free_screen_info(si);
72-
return NULL;
73-
}
74-
}
59+
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
60+
return NULL;
61+
62+
si = alloc_screen_info();
63+
if (!si)
64+
return NULL;
65+
66+
*si = tmp;
7567
return si;
7668
}
7769

@@ -112,8 +104,8 @@ static u32 get_supported_rt_services(void)
112104

113105
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
114106
{
107+
char *cmdline __free(efi_pool) = NULL;
115108
efi_status_t status;
116-
char *cmdline;
117109

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

129121
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
130122
status = efi_parse_options(cmdline);
131-
if (status != EFI_SUCCESS)
132-
goto fail_free_cmdline;
123+
if (status != EFI_SUCCESS) {
124+
efi_err("Failed to parse EFI load options\n");
125+
return status;
126+
}
133127
}
134128

135129
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
136130
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
137131
cmdline[0] == 0) {
138132
status = efi_parse_options(CONFIG_CMDLINE);
139-
if (status != EFI_SUCCESS)
140-
goto fail_free_cmdline;
133+
if (status != EFI_SUCCESS) {
134+
efi_err("Failed to parse built-in command line\n");
135+
return status;
136+
}
141137
}
142138

143-
*cmdline_ptr = cmdline;
139+
*cmdline_ptr = no_free_ptr(cmdline);
144140
return EFI_SUCCESS;
145-
146-
fail_free_cmdline:
147-
efi_err("Failed to parse options\n");
148-
efi_bs_call(free_pool, cmdline);
149-
return status;
150141
}
151142

152143
efi_status_t efi_stub_common(efi_handle_t handle,

drivers/firmware/efi/libstub/efistub.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
55

66
#include <linux/compiler.h>
7+
#include <linux/cleanup.h>
78
#include <linux/efi.h>
89
#include <linux/kernel.h>
910
#include <linux/kern_levels.h>
@@ -122,11 +123,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
122123
#define efi_get_handle_num(size) \
123124
((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32)))
124125

125-
#define for_each_efi_handle(handle, array, size, i) \
126-
for (i = 0; \
127-
i < efi_get_handle_num(size) && \
128-
((handle = efi_get_handle_at((array), i)) || true); \
129-
i++)
126+
#define for_each_efi_handle(handle, array, num) \
127+
for (int __i = 0; __i < (num) && \
128+
((handle = efi_get_handle_at((array), __i)) || true); \
129+
__i++)
130130

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

176176
typedef struct efi_generic_dev_path efi_device_path_protocol_t;
177177

@@ -314,7 +314,9 @@ union efi_boot_services {
314314
void *close_protocol;
315315
void *open_protocol_information;
316316
void *protocols_per_handle;
317-
void *locate_handle_buffer;
317+
efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *,
318+
void *, unsigned long *,
319+
efi_handle_t **);
318320
efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *,
319321
void **);
320322
efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...);
@@ -1053,6 +1055,7 @@ void efi_puts(const char *str);
10531055
__printf(1, 2) int efi_printk(char const *fmt, ...);
10541056

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

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

@@ -1082,8 +1085,7 @@ efi_status_t efi_parse_options(char const *cmdline);
10821085

10831086
void efi_parse_option_graphics(char *option);
10841087

1085-
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
1086-
unsigned long size);
1088+
efi_status_t efi_setup_gop(struct screen_info *si);
10871089

10881090
efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
10891091
const efi_char16_t *optstr,

0 commit comments

Comments
 (0)