efi: earlycon: Reprobe after parsing config tables
authorArd Biesheuvel <ardb@kernel.org>
Sun, 12 Mar 2023 22:00:03 +0000 (23:00 +0100)
committerArd Biesheuvel <ardb@kernel.org>
Mon, 13 Mar 2023 22:28:43 +0000 (23:28 +0100)
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>
drivers/firmware/efi/earlycon.c
drivers/firmware/efi/efi-init.c
include/linux/efi.h

index f54e6fd..f80a9af 100644 (file)
@@ -215,6 +215,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)
 {
@@ -222,15 +230,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;
index 2c16080..ef0820f 100644 (file)
@@ -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();
        }
 }
 
index 04a733f..7aa62c9 100644 (file)
@@ -693,6 +693,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