From f622584e7b061f66b83ce2036cdb0f507b2353d5 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Tue, 8 Jan 2013 22:22:20 -0500 Subject: [PATCH] Improvements to icon- and banner-positioning code. Fixes crash if banner image is too big. --- NEWS.txt | 7 +++++++ libeg/screen.c | 8 ++++++-- refind/main.c | 2 +- refind/menu.c | 13 ++++++++----- refind/menu.h | 1 + refind/screen.c | 21 ++++++++++++++++----- refind/screen.h | 4 +--- 7 files changed, 40 insertions(+), 16 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 9d5c047..4357400 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,10 @@ +0.6.5 (1/??/2013): +------------------ + +- Fixed bug that could cause rEFInd to crash if fed a banner image that's + too big. Note that "too big" can be substantially smaller than the screen + resolution! + 0.6.4 (1/8/2013): ----------------- diff --git a/libeg/screen.c b/libeg/screen.c index 1856cbd..4aea0af 100644 --- a/libeg/screen.c +++ b/libeg/screen.c @@ -355,7 +355,11 @@ VOID egClearScreen(IN EG_PIXEL *Color) VOID egDrawImage(IN EG_IMAGE *Image, IN UINTN ScreenPosX, IN UINTN ScreenPosY) { - if (!egHasGraphics) + // NOTE: Weird seemingly redundant tests because some placement code can "wrap around" and + // send "negative" values, which of course become very large unsigned ints that can then + // wrap around AGAIN if values are added to them..... + if (!egHasGraphics || ((ScreenPosX + Image->Width) > egScreenWidth) || ((ScreenPosY + Image->Height) > egScreenHeight) || + (ScreenPosX > egScreenWidth) || (ScreenPosY > egScreenHeight)) return; if (Image->HasAlpha) { @@ -370,7 +374,7 @@ VOID egDrawImage(IN EG_IMAGE *Image, IN UINTN ScreenPosX, IN UINTN ScreenPosY) refit_call10_wrapper(UgaDraw->Blt, UgaDraw, (EFI_UGA_PIXEL *)Image->PixelData, EfiUgaBltBufferToVideo, 0, 0, ScreenPosX, ScreenPosY, Image->Width, Image->Height, 0); } -} +} /* VOID egDrawImage() */ VOID egDrawImageArea(IN EG_IMAGE *Image, IN UINTN AreaPosX, IN UINTN AreaPosY, diff --git a/refind/main.c b/refind/main.c index 9f4578f..5f5a64d 100644 --- a/refind/main.c +++ b/refind/main.c @@ -128,7 +128,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.4"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.4.1"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); diff --git a/refind/menu.c b/refind/menu.c index 7de9d8b..5154892 100644 --- a/refind/menu.c +++ b/refind/menu.c @@ -68,6 +68,7 @@ typedef VOID (*MENU_STYLE_FUNC)(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *S static CHAR16 ArrowUp[2] = { ARROW_UP, 0 }; static CHAR16 ArrowDown[2] = { ARROW_DOWN, 0 }; +// Text and icon spacing constants.... #define TEXT_YMARGIN (2) #define TEXT_XMARGIN (8) #define TEXT_LINE_HEIGHT (FONT_CELL_HEIGHT + TEXT_YMARGIN * 2) @@ -544,9 +545,6 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, MergeStrings(&DisplayStrings[i], Screen->Entries[i]->Title, 0); if (StrLen(DisplayStrings[i]) > MenuWidth) DisplayStrings[i][MenuWidth - 1] = 0; -// DisplayStrings[i] = AllocateZeroPool(256 * sizeof(CHAR16)); -// SPrint(DisplayStrings[i], ((MenuWidth < 255) ? MenuWidth : 255) * sizeof(CHAR16), -// L" %s ", Screen->Entries[i]->Title); // TODO: use more elaborate techniques for shortening too long strings (ellipses in the middle) // TODO: account for double-width characters } // for @@ -691,7 +689,7 @@ static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *Sta EntriesPosX = (UGAWidth + (Screen->TitleImage->Width + TITLEICON_SPACING) - MenuWidth) >> 1; else EntriesPosX = (UGAWidth - MenuWidth) >> 1; - EntriesPosY = ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_YOFFSET + TEXT_LINE_HEIGHT * 2; + EntriesPosY = ComputeRow0PosX() + TEXT_LINE_HEIGHT * 2; TimeoutPosY = EntriesPosY + (Screen->EntryCount + 1) * TEXT_LINE_HEIGHT; // initial painting @@ -859,6 +857,10 @@ static VOID PaintIcon(IN EG_EMBEDDED_IMAGE *BuiltInIcon, IN CHAR16 *ExternalFile } } // static VOID PaintIcon() +inline UINTN ComputeRow0PosX(VOID) { + return ((UGAHeight / 2) - (5 * ROW0_TILESIZE / 6)); +} // UINTN ComputeRow0PosX() + // Display main menu in graphics mode VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText) { @@ -889,7 +891,8 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT } } row0PosX = (UGAWidth + TILE_XSPACING - (ROW0_TILESIZE + TILE_XSPACING) * row0Count) >> 1; - row0PosY = ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_YOFFSET; + row0PosY = ComputeRow0PosX(); +// row0PosY = ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_YOFFSET; row1PosX = (UGAWidth + TILE_XSPACING - (ROW1_TILESIZE + TILE_XSPACING) * row1Count) >> 1; row1PosY = row0PosY + ROW0_TILESIZE + TILE_YSPACING; if (row1Count > 0) diff --git a/refind/menu.h b/refind/menu.h index 2d3e658..6023502 100644 --- a/refind/menu.h +++ b/refind/menu.h @@ -94,6 +94,7 @@ struct _refit_menu_screen; VOID AddMenuInfoLine(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *InfoLine); VOID AddMenuEntry(IN REFIT_MENU_SCREEN *Screen, IN REFIT_MENU_ENTRY *Entry); +inline UINTN ComputeRow0PosX(VOID); VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText); UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry); UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT REFIT_MENU_ENTRY **ChosenEntry); diff --git a/refind/screen.c b/refind/screen.c index 14a43ed..d632755 100644 --- a/refind/screen.c +++ b/refind/screen.c @@ -47,6 +47,7 @@ #include "config.h" #include "libegint.h" #include "lib.h" +#include "menu.h" #include "../include/refit_call_wrapper.h" #include "../include/egemb_refind_banner.h" @@ -435,23 +436,33 @@ VOID SwitchToGraphicsAndClear(VOID) VOID BltClearScreen(IN BOOLEAN ShowBanner) { static EG_IMAGE *Banner = NULL; + INTN BannerPosX, BannerPosY; if (ShowBanner && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_BANNER)) { // load banner on first call if (Banner == NULL) { - if (GlobalConfig.BannerFileName == NULL) + if (GlobalConfig.BannerFileName == NULL) { Banner = egPrepareEmbeddedImage(&egemb_refind_banner, FALSE); - else + } else { Banner = egLoadImage(SelfDir, GlobalConfig.BannerFileName, FALSE); + if ((Banner == NULL) || (Banner->Width > UGAWidth) || (Banner->Height > UGAHeight)) { + MyFreePool(Banner); + Banner = egPrepareEmbeddedImage(&egemb_refind_banner, FALSE); + } // if unusable image + } if (Banner != NULL) MenuBackgroundPixel = Banner->PixelData[0]; } // clear and draw banner egClearScreen(&MenuBackgroundPixel); - if (Banner != NULL) - BltImage(Banner, (UGAWidth - Banner->Width) >> 1, - ((UGAHeight - LAYOUT_TOTAL_HEIGHT) >> 1) + LAYOUT_BANNER_HEIGHT - Banner->Height); + if (Banner != NULL) { + BannerPosX = (Banner->Width < UGAWidth) ? ((UGAWidth - Banner->Width) / 2) : 0; + BannerPosY = ComputeRow0PosX() - Banner->Height - LAYOUT_BANNER_YGAP; + if (BannerPosY < 0) + BannerPosY = 0; + BltImage(Banner, (UINTN) BannerPosX, (UINTN) BannerPosY); + } } else { // clear to standard background color diff --git a/refind/screen.h b/refind/screen.h index 3fc089f..2647fc7 100644 --- a/refind/screen.h +++ b/refind/screen.h @@ -61,9 +61,7 @@ //#define LAYOUT_TEXT_WIDTH (512) #define LAYOUT_TEXT_WIDTH (425) -#define LAYOUT_TOTAL_HEIGHT (368) -#define LAYOUT_BANNER_HEIGHT (32) -#define LAYOUT_BANNER_YOFFSET (LAYOUT_BANNER_HEIGHT + 32) +#define LAYOUT_BANNER_YGAP 32 #define FONT_CELL_WIDTH (7) #define FONT_CELL_HEIGHT (12) -- 2.39.2