From 4620951195e9578d01410af5944c04e0de230ecb Mon Sep 17 00:00:00 2001 From: srs5694 Date: Fri, 14 Dec 2012 14:29:26 -0500 Subject: [PATCH] "resolution" option now takes either x & y resolution or a UEFI mode number. --- NEWS.txt | 12 ++++++ docs/refind/configfile.html | 4 +- libeg/libegint.h | 2 +- libeg/screen.c | 74 ++++++++++++++++++++++--------------- refind.conf-sample | 19 ++++++---- refind/config.c | 7 +++- refind/screen.c | 7 +++- 7 files changed, 81 insertions(+), 44 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index b7a7d88..2598bc9 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -3,6 +3,18 @@ - Added identifying screen header to line editor. +- Fixed bug that caused rEFInd's display to be mis-sized upon return + from a program that set the resolution itself. + +- Adjusted "resolution" refind.conf parameter so that it can accept EITHER + a resolution as width and height OR a single digit as a UEFI mode number + (which is system-specific). This is done because some systems present the + same mode twice in their mode lists, perhaps varying in refresh rate, + monitor output, or some other salient characteristics; specifying the + mode number enables selecting the higher-numbered mode, whereas using + horizontal and vertical resolution values selects the lowest-numbered + mode. + - Added "textmode" refind.conf parameter to set the text mode used in text-only displays, and for the line editor and boot-time handoff display even in graphics mode. diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html index ab72f1b..682b962 100644 --- a/docs/refind/configfile.html +++ b/docs/refind/configfile.html @@ -185,8 +185,8 @@ timeout 20 resolution - Two integer values - Sets the video resolution used by rEFInd; takes a width and a height as options. For instance, resolution 1024 768 sets the resolution to 1024x768. If you set a resolution that doesn't work on a UEFI-based system, rEFInd displays a message along with a list of valid modes. On an system built around EFI 1.x (such as a Mac), setting an incorrect resolution fails silently; you'll get the system's default resolution. You'll also get the system's default resolution if you set either resolution value to 0 or if you pass anything but two numbers. (Note that passing a resolution with an x, as in 1024x768, will be interpreted as one option and so will cause the default resolution to be used.) Also, be aware that it is possible to set a valid resolution for your video card that's invalid for your monitor. If you do this, your monitor will go blank until you've booted an OS that resets the video mode. + one or two integer values + Sets the video resolution used by rEFInd; takes either a width and a height or a single UEFI video mode number as options. For instance, resolution 1024 768 sets the resolution to 1024x768. On UEFI systems, resolution 1 sets video mode 1, the resolution of which varies from system to system. If you set a resolution that doesn't work on a UEFI-based system, rEFInd displays a message along with a list of valid modes. On an system built around EFI 1.x (such as a Mac), setting an incorrect resolution fails silently; you'll get the system's default resolution. You'll also get the system's default resolution if you set both resolution values to 0 or if you pass anything but two numbers. (Note that passing a resolution with an x, as in 1024x768, will be interpreted as one option and so will cause the default resolution to be used.) Also, be aware that it is possible to set a valid resolution for your video card that's invalid for your monitor. If you do this, your monitor will go blank until you've booted an OS that resets the video mode. use_graphics_for diff --git a/libeg/libegint.h b/libeg/libegint.h index 8c7f1e1..400a65c 100644 --- a/libeg/libegint.h +++ b/libeg/libegint.h @@ -52,7 +52,7 @@ typedef EG_IMAGE * (*EG_DECODE_FUNC)(IN UINT8 *FileData, IN UINTN FileDataLength /* functions */ -BOOLEAN egSetScreenSize(IN UINTN ScreenWidth, IN UINTN ScreenHeight); +BOOLEAN egSetScreenSize(IN OUT UINTN *ScreenWidth, IN OUT UINTN *ScreenHeight); VOID egRestrictImageArea(IN EG_IMAGE *Image, IN UINTN AreaPosX, IN UINTN AreaPosY, diff --git a/libeg/screen.c b/libeg/screen.c index 3200ef9..d2d12db 100644 --- a/libeg/screen.c +++ b/libeg/screen.c @@ -101,43 +101,59 @@ VOID egInitScreen(VOID) } } -// Sets the screen resolution to the specified value, if possible. -// If the specified value is not valid, displays a warning with the valid -// modes on UEFI systems, or silently fails on EFI 1.x systems. Note that -// this function attempts to set ANY screen resolution, even 0x0 or -// ridiculously large values. +// Sets the screen resolution to the specified value, if possible. If *ScreenHeight +// is 0 and GOP mode is detected, assume that *ScreenWidth contains a GOP mode +// number rather than a horizontal resolution. If the specified resolution is not +// valid, displays a warning with the valid modes on GOP (UEFI) systems, or silently +// fails on UGA (EFI 1.x) systems. Note that this function attempts to set ANY screen +// resolution, even 0x0 or ridiculously large values. +// Upon success, returns actual screen resolution in *ScreenWidth and *ScreenHeight. +// These values are unchanged upon failure. // Returns TRUE if successful, FALSE if not. -BOOLEAN egSetScreenSize(IN UINTN ScreenWidth, IN UINTN ScreenHeight) { - EFI_STATUS Status = EFI_SUCCESS; - EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; - UINT32 ModeNum = 0; - UINTN Size; - BOOLEAN ModeSet = FALSE; - UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate; +BOOLEAN egSetScreenSize(IN OUT UINTN *ScreenWidth, IN OUT UINTN *ScreenHeight) { + EFI_STATUS Status = EFI_SUCCESS; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINT32 ModeNum = 0; + UINTN Size; + BOOLEAN ModeSet = FALSE; + UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate; if (GraphicsOutput != NULL) { // GOP mode (UEFI) - // Do a loop through the modes to see if the specified one is available; - // and if so, switch to it.... - while ((Status == EFI_SUCCESS) && (!ModeSet)) { + if (*ScreenHeight == 0) { // User specified a mode number (stored in *ScreenWidth); use it directly + ModeNum = (UINT32) *ScreenWidth; Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); - if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info)) && - (Info->HorizontalResolution == ScreenWidth) && (Info->VerticalResolution == ScreenHeight)) { + if (Status == EFI_SUCCESS) { Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum); - ModeSet = (Status == EFI_SUCCESS); - } // if - ModeNum++; - } // while() + if (Status == EFI_SUCCESS) { + ModeSet = TRUE; + *ScreenWidth = Info->HorizontalResolution; + *ScreenHeight = Info->VerticalResolution; + } + } + } else { // User specified width & height; must find mode + // Do a loop through the modes to see if the specified one is available; + // and if so, switch to it.... + while ((Status == EFI_SUCCESS) && (!ModeSet)) { + Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); + if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info)) && + (Info->HorizontalResolution == *ScreenWidth) && (Info->VerticalResolution == *ScreenHeight)) { + Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum); + ModeSet = (Status == EFI_SUCCESS); + } // if + ModeNum++; + } // while() + } // if/else if (ModeSet) { - egScreenWidth = ScreenWidth; - egScreenHeight = ScreenHeight; + egScreenWidth = *ScreenWidth; + egScreenHeight = *ScreenHeight; } else {// If unsuccessful, display an error message for the user.... SwitchToText(FALSE); - Print(L"Error setting graphics mode %d x %d; using default mode!\nAvailable modes are:\n", ScreenWidth, ScreenHeight); + Print(L"Error setting graphics mode %d x %d; using default mode!\nAvailable modes are:\n", *ScreenWidth, *ScreenHeight); ModeNum = 0; do { Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); - if (Status == EFI_SUCCESS) { + if ((Status == EFI_SUCCESS) && (Info != NULL)) { Print(L"Mode %d: %d x %d\n", ModeNum, Info->HorizontalResolution, Info->VerticalResolution); } // else } while ((ModeNum++ < 10) || (Status == EFI_SUCCESS)); @@ -156,10 +172,10 @@ BOOLEAN egSetScreenSize(IN UINTN ScreenWidth, IN UINTN ScreenHeight) { // Try to use current color depth & refresh rate for new mode. Maybe not the best choice // in all cases, but I don't know how to probe for alternatives.... Status = refit_call5_wrapper(UgaDraw->GetMode, UgaDraw, &UGAWidth, &UGAHeight, &UGADepth, &UGARefreshRate); - Status = refit_call5_wrapper(UgaDraw->SetMode, UgaDraw, ScreenWidth, ScreenHeight, UGADepth, UGARefreshRate); + Status = refit_call5_wrapper(UgaDraw->SetMode, UgaDraw, *ScreenWidth, *ScreenHeight, UGADepth, UGARefreshRate); if (Status == EFI_SUCCESS) { - egScreenWidth = ScreenWidth; - egScreenHeight = ScreenHeight; + egScreenWidth = *ScreenWidth; + egScreenHeight = *ScreenHeight; ModeSet = TRUE; } else { // TODO: Find a list of supported modes and display it. @@ -192,7 +208,7 @@ UINT32 egSetTextMode(UINT32 RequestedMode) { UsedMode = RequestedMode; } else { SwitchToText(FALSE); - Print(L"Error setting text mode %d; available modes are:\n", ST->ConOut->Mode->Mode); + Print(L"Error setting text mode %d; available modes are:\n", RequestedMode); do { Status = refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, i, &Width, &Height); if (Status == EFI_SUCCESS) diff --git a/refind.conf-sample b/refind.conf-sample index 4ae887f..c15d905 100644 --- a/refind.conf-sample +++ b/refind.conf-sample @@ -71,17 +71,20 @@ timeout 20 # #textmode 2 -# Set the screen's video resolution. Pass this option two values, -# corresponding to the X and Y resolutions. Note that not all resolutions -# are supported. On UEFI systems, passing an incorrect value results in a -# message being shown on the screen to that effect, along with a list of -# supported modes. On EFI 1.x systems (e.g., Macintoshes), setting an -# incorrect mode silently fails. On both types of systems, setting an -# incorrect resolution results in the default resolution being used. -# A resolution of 1024x768 usually works, but higher values often don't. +# Set the screen's video resolution. Pass this option either: +# * two values, corresponding to the X and Y resolutions +# * one value, corresponding to a GOP (UEFI) video mode +# Note that not all resolutions are supported. On UEFI systems, passing +# an incorrect value results in a message being shown on the screen to +# that effect, along with a list of supported modes. On EFI 1.x systems +# (e.g., Macintoshes), setting an incorrect mode silently fails. On both +# types of systems, setting an incorrect resolution results in the default +# resolution being used. A resolution of 1024x768 usually works, but higher +# values often don't. # Default is "0 0" (use the system default resolution, usually 800x600). # #resolution 1024 768 +#resolution 3 # Launch specified OSes in graphics mode. By default, rEFInd switches # to text mode and displays basic pre-launch information when launching diff --git a/refind/config.c b/refind/config.c index 9149b9b..416461d 100644 --- a/refind/config.c +++ b/refind/config.c @@ -463,9 +463,12 @@ VOID ReadConfig(CHAR16 *FileName) } else if (StriCmp(TokenList[0], L"textmode") == 0) { HandleInt(TokenList, TokenCount, &(GlobalConfig.RequestedTextMode)); - } else if ((StriCmp(TokenList[0], L"resolution") == 0) && (TokenCount == 3)) { + } else if ((StriCmp(TokenList[0], L"resolution") == 0) && ((TokenCount == 2) || (TokenCount == 3))) { GlobalConfig.RequestedScreenWidth = Atoi(TokenList[1]); - GlobalConfig.RequestedScreenHeight = Atoi(TokenList[2]); + if (TokenCount == 3) + GlobalConfig.RequestedScreenHeight = Atoi(TokenList[2]); + else + GlobalConfig.RequestedScreenHeight = 0; } else if (StriCmp(TokenList[0], L"use_graphics_for") == 0) { GlobalConfig.GraphicsFor = 0; diff --git a/refind/screen.c b/refind/screen.c index 6aa04be..dc1f21d 100644 --- a/refind/screen.c +++ b/refind/screen.c @@ -115,8 +115,8 @@ VOID SetupScreen(VOID) { GlobalConfig.RequestedTextMode = egSetTextMode(GlobalConfig.RequestedTextMode); - if ((GlobalConfig.RequestedScreenWidth > 0) && (GlobalConfig.RequestedScreenHeight > 0) && - egSetScreenSize(GlobalConfig.RequestedScreenWidth, GlobalConfig.RequestedScreenHeight)) { + if ((GlobalConfig.RequestedScreenWidth > 0) && + (egSetScreenSize(&GlobalConfig.RequestedScreenWidth, &GlobalConfig.RequestedScreenHeight))) { UGAWidth = GlobalConfig.RequestedScreenWidth; UGAHeight = GlobalConfig.RequestedScreenHeight; } // if user requested a particular screen resolution @@ -206,6 +206,9 @@ VOID BeginExternalScreen(IN BOOLEAN UseGraphicsMode, IN CHAR16 *Title) VOID FinishExternalScreen(VOID) { + // Reset the screen resolution, in case external program changed it.... + SetupScreen(); + // make sure we clean up later GraphicsScreenDirty = TRUE; -- 2.39.2