Skip to content

Commit fc3608a

Browse files
committed
efi/libstub: Use relocated version of kernel's struct screen_info
In some cases, we expose the kernel's struct screen_info to the EFI stub directly, so it gets populated before even entering the kernel. This means the early console is available as soon as the early param parsing happens, which is nice. It also means we need two different ways to pass this information, as this trick only works if the EFI stub is baked into the core kernel image, which is not always the case. Huacai reports that the preparatory refactoring that was needed to implement this alternative method for zboot resulted in a non-functional efifb earlycon for other cases as well, due to the reordering of the kernel image relocation with the population of the screen_info struct, and the latter now takes place after copying the image to its new location, which means we copy the old, uninitialized state. So let's ensure that the same-image version of alloc_screen_info() produces the correct screen_info pointer, by taking the displacement of the loaded image into account. Reported-by: Huacai Chen <[email protected]> Tested-by: Huacai Chen <[email protected]> Link: https://lore.kernel.org/linux-efi/[email protected]/ Fixes: 42c8ea3 ("efi: libstub: Factor out EFI stub entrypoint into separate file") Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 97fd768 commit fc3608a

File tree

6 files changed

+21
-14
lines changed

6 files changed

+21
-14
lines changed

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

Lines changed: 3 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",

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: 1 addition & 0 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,

drivers/firmware/efi/libstub/screen_info.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,11 @@
1515
* early, but it only works if the EFI stub is part of the core kernel image
1616
* itself. The zboot decompressor can only use the configuration table
1717
* approach.
18-
*
19-
* In order to support both methods from the same build of the EFI stub
20-
* library, provide this dummy global definition of struct screen_info. If it
21-
* is required to satisfy a link dependency, it means we need to override the
22-
* __weak alloc and free methods with the ones below, and those will be pulled
23-
* in as well.
2418
*/
25-
struct screen_info screen_info;
2619

2720
static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID;
2821

29-
struct screen_info *alloc_screen_info(void)
22+
struct screen_info *__alloc_screen_info(void)
3023
{
3124
struct screen_info *si;
3225
efi_status_t status;

drivers/firmware/efi/libstub/zboot.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ void __weak efi_cache_sync_image(unsigned long image_base,
5757
// executable code loaded into memory to be safe for execution.
5858
}
5959

60+
struct screen_info *alloc_screen_info(void)
61+
{
62+
return __alloc_screen_info();
63+
}
64+
6065
asmlinkage efi_status_t __efiapi
6166
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
6267
{

0 commit comments

Comments
 (0)