Skip to content

Commit 877c20b

Browse files
committed
Merge tag 'efi-fixes-for-v6.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI fixes from Ard Biesheuvel: - Set the NX compat flag for arm64 and zboot, to ensure compatibility with EFI firmware that complies with tightening requirements imposed across the ecosystem. - Improve identification of Ampere Altra systems based on SMBIOS data. - Fix some issues related to the EFI framebuffer that were introduced as a result from some refactoring related to zboot and the merge with sysfb. - Makefile tweak to avoid rebuilding vmlinuz unnecessarily. - Fix efi_random_alloc() return value on out of memory condition. * tag 'efi-fixes-for-v6.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: efi/libstub: randomalloc: Return EFI_OUT_OF_RESOURCES on failure efi/libstub: Use relocated version of kernel's struct screen_info efi/libstub: zboot: Add compressed image to make targets efi: sysfb_efi: Add quirk for Lenovo Yoga Book X91F/L efi: sysfb_efi: Fix DMI quirks not working for simpledrm efi/libstub: smbios: Drop unused 'recsize' parameter arm64: efi: Use SMBIOS processor version to key off Ampere quirk efi/libstub: smbios: Use length member instead of record struct size efi: earlycon: Reprobe after parsing config tables arm64: efi: Set NX compat flag in PE/COFF header efi/libstub: arm64: Remap relocated image with strict permissions efi/libstub: zboot: Mark zboot EFI application as NX compatible
2 parents 19a6b66 + 0b1d9de commit 877c20b

File tree

19 files changed

+147
-40
lines changed

19 files changed

+147
-40
lines changed

arch/arm64/kernel/efi-header.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
.long .Lefi_header_end - .L_head // SizeOfHeaders
6767
.long 0 // CheckSum
6868
.short IMAGE_SUBSYSTEM_EFI_APPLICATION // Subsystem
69-
.short 0 // DllCharacteristics
69+
.short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT // DllCharacteristics
7070
.quad 0 // SizeOfStackReserve
7171
.quad 0 // SizeOfStackCommit
7272
.quad 0 // SizeOfHeapReserve

drivers/firmware/efi/earlycon.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,22 +215,32 @@ efi_earlycon_write(struct console *con, const char *str, unsigned int num)
215215
}
216216
}
217217

218+
static bool __initdata fb_probed;
219+
220+
void __init efi_earlycon_reprobe(void)
221+
{
222+
if (fb_probed)
223+
setup_earlycon("efifb");
224+
}
225+
218226
static int __init efi_earlycon_setup(struct earlycon_device *device,
219227
const char *opt)
220228
{
221229
struct screen_info *si;
222230
u16 xres, yres;
223231
u32 i;
224232

225-
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
233+
fb_wb = opt && !strcmp(opt, "ram");
234+
235+
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) {
236+
fb_probed = true;
226237
return -ENODEV;
238+
}
227239

228240
fb_base = screen_info.lfb_base;
229241
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
230242
fb_base |= (u64)screen_info.ext_lfb_base << 32;
231243

232-
fb_wb = opt && !strcmp(opt, "ram");
233-
234244
si = &screen_info;
235245
xres = si->lfb_width;
236246
yres = si->lfb_height;

drivers/firmware/efi/efi-init.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ static void __init init_screen_info(void)
7272
if (memblock_is_map_memory(screen_info.lfb_base))
7373
memblock_mark_nomap(screen_info.lfb_base,
7474
screen_info.lfb_size);
75+
76+
if (IS_ENABLED(CONFIG_EFI_EARLYCON))
77+
efi_earlycon_reprobe();
7578
}
7679
}
7780

drivers/firmware/efi/libstub/Makefile.zboot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
4444
$(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
4545
$(call if_changed,objcopy)
4646

47-
targets += zboot-header.o vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
47+
targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
8585
}
8686
}
8787

88-
if (image->image_base != _text)
88+
if (image->image_base != _text) {
8989
efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
90+
image->image_base = _text;
91+
}
9092

9193
if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN))
9294
efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n",
@@ -139,6 +141,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
139141
*image_addr = *reserve_addr;
140142
memcpy((void *)*image_addr, _text, kernel_size);
141143
caches_clean_inval_pou(*image_addr, *image_addr + kernel_codesize);
144+
efi_remap_image(*image_addr, *reserve_size, kernel_codesize);
142145

143146
return EFI_SUCCESS;
144147
}

drivers/firmware/efi/libstub/arm64.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,43 @@
1616

1717
static bool system_needs_vamap(void)
1818
{
19-
const u8 *type1_family = efi_get_smbios_string(1, family);
19+
const struct efi_smbios_type4_record *record;
20+
const u32 __aligned(1) *socid;
21+
const u8 *version;
2022

2123
/*
2224
* Ampere eMAG, Altra, and Altra Max machines crash in SetTime() if
23-
* SetVirtualAddressMap() has not been called prior.
25+
* SetVirtualAddressMap() has not been called prior. Most Altra systems
26+
* can be identified by the SMCCC soc ID, which is conveniently exposed
27+
* via the type 4 SMBIOS records. Otherwise, test the processor version
28+
* field. eMAG systems all appear to have the processor version field
29+
* set to "eMAG".
2430
*/
25-
if (!type1_family || (
26-
strcmp(type1_family, "eMAG") &&
27-
strcmp(type1_family, "Altra") &&
28-
strcmp(type1_family, "Altra Max")))
31+
record = (struct efi_smbios_type4_record *)efi_get_smbios_record(4);
32+
if (!record)
2933
return false;
3034

31-
efi_warn("Working around broken SetVirtualAddressMap()\n");
32-
return true;
35+
socid = (u32 *)record->processor_id;
36+
switch (*socid & 0xffff000f) {
37+
static char const altra[] = "Ampere(TM) Altra(TM) Processor";
38+
static char const emag[] = "eMAG";
39+
40+
default:
41+
version = efi_get_smbios_string(&record->header, 4,
42+
processor_version);
43+
if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
44+
strncmp(version, emag, sizeof(emag) - 1)))
45+
break;
46+
47+
fallthrough;
48+
49+
case 0x0a160001: // Altra
50+
case 0x0a160002: // Altra Max
51+
efi_warn("Working around broken SetVirtualAddressMap()\n");
52+
return true;
53+
}
54+
55+
return false;
3356
}
3457

3558
efi_status_t check_platform_features(void)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@
55

66
#include "efistub.h"
77

8+
static unsigned long screen_info_offset;
9+
10+
struct screen_info *alloc_screen_info(void)
11+
{
12+
if (IS_ENABLED(CONFIG_ARM))
13+
return __alloc_screen_info();
14+
return (void *)&screen_info + screen_info_offset;
15+
}
16+
817
/*
918
* EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
1019
* LoongArch. This is the entrypoint that is described in the PE/COFF header
@@ -56,6 +65,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
5665
return status;
5766
}
5867

68+
screen_info_offset = image_addr - (unsigned long)image->image_base;
69+
5970
status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
6071

6172
efi_free(image_size, image_addr);

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@
4747
static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
4848
static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
4949

50-
struct screen_info * __weak alloc_screen_info(void)
51-
{
52-
return &screen_info;
53-
}
54-
5550
void __weak free_screen_info(struct screen_info *si)
5651
{
5752
}

drivers/firmware/efi/libstub/efistub.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ efi_enable_reset_attack_mitigation(void) { }
10621062
void efi_retrieve_tpm2_eventlog(void);
10631063

10641064
struct screen_info *alloc_screen_info(void);
1065+
struct screen_info *__alloc_screen_info(void);
10651066
void free_screen_info(struct screen_info *si);
10661067

10671068
void efi_cache_sync_image(unsigned long image_base,
@@ -1074,6 +1075,8 @@ struct efi_smbios_record {
10741075
u16 handle;
10751076
};
10761077

1078+
const struct efi_smbios_record *efi_get_smbios_record(u8 type);
1079+
10771080
struct efi_smbios_type1_record {
10781081
struct efi_smbios_record header;
10791082

@@ -1087,14 +1090,46 @@ struct efi_smbios_type1_record {
10871090
u8 family;
10881091
};
10891092

1090-
#define efi_get_smbios_string(__type, __name) ({ \
1091-
int size = sizeof(struct efi_smbios_type ## __type ## _record); \
1093+
struct efi_smbios_type4_record {
1094+
struct efi_smbios_record header;
1095+
1096+
u8 socket;
1097+
u8 processor_type;
1098+
u8 processor_family;
1099+
u8 processor_manufacturer;
1100+
u8 processor_id[8];
1101+
u8 processor_version;
1102+
u8 voltage;
1103+
u16 external_clock;
1104+
u16 max_speed;
1105+
u16 current_speed;
1106+
u8 status;
1107+
u8 processor_upgrade;
1108+
u16 l1_cache_handle;
1109+
u16 l2_cache_handle;
1110+
u16 l3_cache_handle;
1111+
u8 serial_number;
1112+
u8 asset_tag;
1113+
u8 part_number;
1114+
u8 core_count;
1115+
u8 enabled_core_count;
1116+
u8 thread_count;
1117+
u16 processor_characteristics;
1118+
u16 processor_family2;
1119+
u16 core_count2;
1120+
u16 enabled_core_count2;
1121+
u16 thread_count2;
1122+
u16 thread_enabled;
1123+
};
1124+
1125+
#define efi_get_smbios_string(__record, __type, __name) ({ \
10921126
int off = offsetof(struct efi_smbios_type ## __type ## _record, \
10931127
__name); \
1094-
__efi_get_smbios_string(__type, off, size); \
1128+
__efi_get_smbios_string((__record), __type, off); \
10951129
})
10961130

1097-
const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
1131+
const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
1132+
u8 type, int offset);
10981133

10991134
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
11001135
unsigned long code_size);

drivers/firmware/efi/libstub/randomalloc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ efi_status_t efi_random_alloc(unsigned long size,
101101
* to calculate the randomly chosen address, and allocate it directly
102102
* using EFI_ALLOCATE_ADDRESS.
103103
*/
104+
status = EFI_OUT_OF_RESOURCES;
104105
for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
105106
efi_memory_desc_t *md = (void *)map->map + map_offset;
106107
efi_physical_addr_t target;

0 commit comments

Comments
 (0)