diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2023-03-13 01:00:03 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-03-30 13:50:50 +0300 |
commit | fdf7c1b9ccf2f5a2c34b703fd0325a9e5aaabc4a (patch) | |
tree | 2580e912a445208205e97e0d764fa767edc2a1d9 | |
parent | 53edfda851dd1ce41ac049ce2f195dc41dd27cc1 (diff) | |
download | linux-fdf7c1b9ccf2f5a2c34b703fd0325a9e5aaabc4a.tar.xz |
efi: earlycon: Reprobe after parsing config tables
[ Upstream commit 8b3a149db461d3286d1e211112de3b44ccaeaf71 ]
Commit 732ea9db9d8a ("efi: libstub: Move screen_info handling to common
code") reorganized the earlycon handling so that all architectures pass
the screen_info data via a EFI config table instead of populating struct
screen_info directly, as the latter is only possible when the EFI stub
is baked into the kernel (and not into the decompressor).
However, this means that struct screen_info may not have been populated
yet by the time the earlycon probe takes place, and this results in a
non-functional early console.
So let's probe again right after parsing the config tables and
populating struct screen_info. Note that this means that earlycon output
starts a bit later than before, and so it may fail to capture issues
that occur while doing the early EFI initialization.
Fixes: 732ea9db9d8a ("efi: libstub: Move screen_info handling to common code")
Reported-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/firmware/efi/earlycon.c | 16 | ||||
-rw-r--r-- | drivers/firmware/efi/efi-init.c | 3 | ||||
-rw-r--r-- | include/linux/efi.h | 1 |
3 files changed, 17 insertions, 3 deletions
diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c index 4d6c5327471a..1bc632864694 100644 --- a/drivers/firmware/efi/earlycon.c +++ b/drivers/firmware/efi/earlycon.c @@ -204,6 +204,14 @@ efi_earlycon_write(struct console *con, const char *str, unsigned int num) } } +static bool __initdata fb_probed; + +void __init efi_earlycon_reprobe(void) +{ + if (fb_probed) + setup_earlycon("efifb"); +} + static int __init efi_earlycon_setup(struct earlycon_device *device, const char *opt) { @@ -211,15 +219,17 @@ static int __init efi_earlycon_setup(struct earlycon_device *device, u16 xres, yres; u32 i; - if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) + fb_wb = opt && !strcmp(opt, "ram"); + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) { + fb_probed = true; return -ENODEV; + } fb_base = screen_info.lfb_base; if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) fb_base |= (u64)screen_info.ext_lfb_base << 32; - fb_wb = opt && !strcmp(opt, "ram"); - si = &screen_info; xres = si->lfb_width; yres = si->lfb_height; diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c index 1639159493e3..5cb7fb4549f0 100644 --- a/drivers/firmware/efi/efi-init.c +++ b/drivers/firmware/efi/efi-init.c @@ -72,6 +72,9 @@ static void __init init_screen_info(void) if (memblock_is_map_memory(screen_info.lfb_base)) memblock_mark_nomap(screen_info.lfb_base, screen_info.lfb_size); + + if (IS_ENABLED(CONFIG_EFI_EARLYCON)) + efi_earlycon_reprobe(); } } diff --git a/include/linux/efi.h b/include/linux/efi.h index 98598bd1d2fa..ac22f7ca195a 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -688,6 +688,7 @@ efi_guid_to_str(efi_guid_t *guid, char *out) } extern void efi_init (void); +extern void efi_earlycon_reprobe(void); #ifdef CONFIG_EFI extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ #else |