From 5f8cfbe1348dac0abce73c344af2eab0ccaae732 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 21 Mar 2018 20:36:57 +0000 Subject: [PATCH] UEFI: Ditch console mode setting, choose optimal GOP mode later in boot boot1 is too early to be deciding a good resolution. Console modes don't map cleanly/predictably to actual screen resolutions, and GOP does not reflect the actual screen resolution after a console mode change. Rip it out. Add an efi-autoresizecons command to loader to choose an optimal screen resolution based on the current environment. We'll explicitly execute this later, preferably before we draw anything of value but after we load config and pick up any tunables we may need to decide where we're going. This method also allows us to actually pass the correct framebuffer information on to the kernel. UGA autoresizing is not implemented because it doesn't have the kind of mode enumeration that GOP does. If an interested person with relevant hardware could get in contact, we can take a look at implementing UGA autoresize. This effectively "fixes" the breakage caused by r327058, but doesn't actually set the resolution correctly until the interpreter calls efi-autoresizcons. The lualoader version of this has been included for reference; the forth equivalent will follow. Reviewed by: imp (with some hestitation), manu Differential Revision: https://reviews.freebsd.org/D14788 --- stand/efi/boot1/boot1.c | 17 ++------- stand/efi/loader/framebuffer.c | 66 ++++++++++++++++++++++++++++++++++ stand/lua/core.lua | 6 ++++ stand/lua/loader.lua | 3 ++ 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/stand/efi/boot1/boot1.c b/stand/efi/boot1/boot1.c index 112ca5439522..61087dc08954 100644 --- a/stand/efi/boot1/boot1.c +++ b/stand/efi/boot1/boot1.c @@ -391,7 +391,7 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) EFI_STATUS status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; - UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; + UINTN i, hsize, nhandles; CHAR16 *text; UINT16 boot_current; size_t sz; @@ -410,22 +410,11 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) (void)ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenText); /* - * Reset the console and find the best text mode. + * Reset the console enable the cursor. Later we'll choose a better + * console size through GOP/UGA. */ conout = ST->ConOut; conout->Reset(conout, TRUE); - max_dim = best_mode = 0; - for (i = 0; i < conout->Mode->MaxMode; i++) { - status = conout->QueryMode(conout, i, &cols, &rows); - if (EFI_ERROR(status)) - continue; - if (cols * rows > max_dim) { - max_dim = cols * rows; - best_mode = i; - } - } - if (max_dim > 0) - conout->SetMode(conout, best_mode); conout->EnableCursor(conout, TRUE); conout->ClearScreen(conout); diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c index 37999ea1d372..7b3d46ca90e3 100644 --- a/stand/efi/loader/framebuffer.c +++ b/stand/efi/loader/framebuffer.c @@ -462,6 +462,72 @@ print_efifb(int mode, struct efi_fb *efifb, int verbose) } } +static int +gop_autoresize(EFI_GRAPHICS_OUTPUT *gop) +{ + struct efi_fb efifb; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + EFI_STATUS status; + UINTN infosz; + UINT32 best_mode, currdim, maxdim, mode; + + best_mode = maxdim = 0; + for (mode = 0; mode < gop->Mode->MaxMode; mode++) { + status = gop->QueryMode(gop, mode, &infosz, &info); + if (EFI_ERROR(status)) + continue; + efifb_from_gop(&efifb, gop->Mode, info); + currdim = info->HorizontalResolution * info->VerticalResolution; + /* XXX TODO: Allow tunable or something for max resolution */ + if (currdim > maxdim) { + maxdim = currdim; + best_mode = mode; + } + } + + status = gop->SetMode(gop, best_mode); + if (EFI_ERROR(status)) { + snprintf(command_errbuf, sizeof(command_errbuf), + "gop_autoresize: Unable to set mode to %u (error=%lu)", + mode, EFI_ERROR_CODE(status)); + return (CMD_ERROR); + } + return (CMD_OK); +} + +static int +uga_autoresize(EFI_UGA_DRAW_PROTOCOL *gop) +{ + + return (CMD_OK); +} + +COMMAND_SET(efi_autoresize, "efi-autoresizecons", "EFI Auto-resize Console", command_autoresize); + +static int +command_autoresize(int argc, char *argv[]) +{ + EFI_GRAPHICS_OUTPUT *gop; + EFI_UGA_DRAW_PROTOCOL *uga; + EFI_STATUS status; + u_int mode; + + gop = NULL; + uga = NULL; + status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop); + if (EFI_ERROR(status) == 0) + return (gop_autoresize(gop)); + + status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga); + if (EFI_ERROR(status) == 0) + return (uga_autoresize(uga)); + + snprintf(command_errbuf, sizeof(command_errbuf), + "%s: Neither Graphics Output Protocol nor Universal Graphics Adapter present", + argv[0]); + return (CMD_ERROR); +} + COMMAND_SET(gop, "gop", "graphics output protocol", command_gop); static int diff --git a/stand/lua/core.lua b/stand/lua/core.lua index d38822deab5f..b3d5308bf1cd 100644 --- a/stand/lua/core.lua +++ b/stand/lua/core.lua @@ -274,6 +274,12 @@ function core.isSingleUserBoot() return single_user ~= nil and single_user:lower() == "yes" end +function core.isUEFIBoot() + local efiver = loader.getenv("efi-version") + + return efiver ~= nil +end + function core.isZFSBoot() local c = loader.getenv("currdev") diff --git a/stand/lua/loader.lua b/stand/lua/loader.lua index b406ba4969e9..2486193af031 100644 --- a/stand/lua/loader.lua +++ b/stand/lua/loader.lua @@ -50,6 +50,9 @@ if result ~= nil then end config.load() +if core.isUEFIBoot() then + loader.perform("efi-autoresizecons") +end -- Our console may have been setup for a different color scheme before we get -- here, so make sure we set the default. if color.isEnabled() then