lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 1 | /* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 2 | * |
| 3 | * Redistribution and use in source and binary forms, with or without |
| 4 | * modification, are permitted provided that the following conditions are |
| 5 | * met: |
| 6 | * * Redistributions of source code must retain the above copyright |
| 7 | * notice, this list of conditions and the following disclaimer. |
| 8 | * * Redistributions in binary form must reproduce the above |
| 9 | * copyright notice, this list of conditions and the following |
| 10 | * disclaimer in the documentation and/or other materials provided |
| 11 | * with the distribution. |
| 12 | * * Neither the name of The Linux Foundation, Inc. nor the names of its |
| 13 | * contributors may be used to endorse or promote products derived |
| 14 | * from this software without specific prior written permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| 26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | */ |
| 28 | |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 29 | #include <Library/BaseLib.h> |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 30 | #include <Library/BaseMemoryLib.h> |
| 31 | #include <Library/DebugLib.h> |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 32 | #include <Library/DrawUI.h> |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 33 | #include <Library/Fonts.h> |
| 34 | #include <Library/MemoryAllocationLib.h> |
| 35 | #include <Library/UefiBootServicesTableLib.h> |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 36 | #include <Library/UpdateDeviceTree.h> |
| 37 | #include <Protocol/GraphicsOutput.h> |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 38 | #include <Uefi.h> |
Prakruthi Deepak Heragu | e4ce21b | 2019-09-18 11:52:11 -0700 | [diff] [blame] | 39 | #include <Protocol/HiiFont.h> |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 40 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 41 | STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutputProtocol; |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 42 | STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt; |
Prakruthi Deepak Heragu | e4ce21b | 2019-09-18 11:52:11 -0700 | [diff] [blame] | 43 | STATIC EFI_HII_FONT_PROTOCOL *gHiiFont = NULL; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 44 | |
| 45 | STATIC CHAR16 *mFactorName[] = { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 46 | [1] = (CHAR16 *)L"", [2] = (CHAR16 *)SYSFONT_2x, |
| 47 | [3] = (CHAR16 *)SYSFONT_3x, [4] = (CHAR16 *)SYSFONT_4x, |
| 48 | [5] = (CHAR16 *)SYSFONT_5x, [6] = (CHAR16 *)SYSFONT_6x, |
| 49 | [7] = (CHAR16 *)SYSFONT_7x, [8] = (CHAR16 *)SYSFONT_8x, |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 50 | }; |
| 51 | |
| 52 | STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mColors[] = { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 53 | [BGR_WHITE] = {0xff, 0xff, 0xff, 0x00}, |
| 54 | [BGR_BLACK] = {0x00, 0x00, 0x00, 0x00}, |
| 55 | [BGR_ORANGE] = {0x00, 0xa5, 0xff, 0x00}, |
| 56 | [BGR_YELLOW] = {0x00, 0xff, 0xff, 0x00}, |
| 57 | [BGR_RED] = {0x00, 0x00, 0x98, 0x00}, |
| 58 | [BGR_GREEN] = {0x00, 0xff, 0x00, 0x00}, |
| 59 | [BGR_BLUE] = {0xff, 0x00, 0x00, 0x00}, |
| 60 | [BGR_CYAN] = {0xff, 0xff, 0x00, 0x00}, |
| 61 | [BGR_SILVER] = {0xc0, 0xc0, 0xc0, 0x00}, |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 62 | }; |
| 63 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 64 | STATIC UINT32 GetResolutionWidth (VOID) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 65 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 66 | STATIC UINT32 Width; |
| 67 | EFI_HANDLE ConsoleHandle = (EFI_HANDLE)NULL; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 68 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 69 | /* Get the width from the protocal at the first time */ |
| 70 | if (Width) |
| 71 | return Width; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 72 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 73 | if (GraphicsOutputProtocol == NULL) { |
| 74 | ConsoleHandle = gST->ConsoleOutHandle; |
| 75 | if (ConsoleHandle == NULL) { |
| 76 | DEBUG ( |
| 77 | (EFI_D_ERROR, |
| 78 | "Failed to get the handle for the active console input device.\n")); |
| 79 | return 0; |
lijuang | 46df844 | 2017-09-28 19:06:36 +0800 | [diff] [blame] | 80 | } |
| 81 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 82 | gBS->HandleProtocol (ConsoleHandle, &gEfiGraphicsOutputProtocolGuid, |
| 83 | (VOID **)&GraphicsOutputProtocol); |
| 84 | if (GraphicsOutputProtocol == NULL) { |
| 85 | DEBUG ((EFI_D_ERROR, "Failed to get the graphics output protocol.\n")); |
| 86 | return 0; |
| 87 | } |
| 88 | } |
| 89 | Width = GraphicsOutputProtocol->Mode->Info->HorizontalResolution; |
| 90 | if (!Width) |
| 91 | DEBUG ((EFI_D_ERROR, "Failed to get the width of the screen.\n")); |
| 92 | |
| 93 | return Width; |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 94 | } |
| 95 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 96 | STATIC UINT32 GetResolutionHeight (VOID) |
| 97 | { |
| 98 | STATIC UINT32 Height; |
| 99 | EFI_HANDLE ConsoleHandle = (EFI_HANDLE)NULL; |
| 100 | |
| 101 | /* Get the height from the protocal at the first time */ |
| 102 | if (Height) |
| 103 | return Height; |
| 104 | |
| 105 | if (GraphicsOutputProtocol == NULL) { |
| 106 | ConsoleHandle = gST->ConsoleOutHandle; |
| 107 | if (ConsoleHandle == NULL) { |
| 108 | DEBUG ( |
| 109 | (EFI_D_ERROR, |
| 110 | "Failed to get the handle for the active console input device.\n")); |
| 111 | return 0; |
| 112 | } |
| 113 | |
| 114 | gBS->HandleProtocol (ConsoleHandle, &gEfiGraphicsOutputProtocolGuid, |
| 115 | (VOID **)&GraphicsOutputProtocol); |
| 116 | if (GraphicsOutputProtocol == NULL) { |
| 117 | DEBUG ((EFI_D_ERROR, "Failed to get the graphics output protocol.\n")); |
| 118 | return 0; |
| 119 | } |
| 120 | } |
| 121 | Height = GraphicsOutputProtocol->Mode->Info->VerticalResolution; |
| 122 | if (!Height) |
| 123 | DEBUG ((EFI_D_ERROR, "Failed to get the height of the screen.\n")); |
| 124 | |
| 125 | return Height; |
| 126 | } |
| 127 | |
| 128 | EFI_STATUS BackUpBootLogoBltBuffer (VOID) |
| 129 | { |
| 130 | EFI_STATUS Status; |
| 131 | UINT32 Width; |
| 132 | UINT32 Height; |
| 133 | UINT64 BufferSize; |
| 134 | |
| 135 | /* Return directly if it's already backed up the boot logo blt buffer */ |
| 136 | if (LogoBlt) |
| 137 | return EFI_SUCCESS; |
| 138 | |
| 139 | Width = GetResolutionWidth (); |
| 140 | Height = GetResolutionHeight (); |
| 141 | if (!Width || !Height) { |
| 142 | DEBUG ((EFI_D_ERROR, "Failed to get width or height\n")); |
| 143 | return EFI_UNSUPPORTED; |
| 144 | } |
| 145 | |
| 146 | /* Ensure the Height * Width doesn't overflow */ |
| 147 | if (Height > DivU64x64Remainder ((UINTN)~0, Width, NULL)) { |
| 148 | DEBUG ((EFI_D_ERROR, "Height * Width overflow\n")); |
| 149 | return EFI_UNSUPPORTED; |
| 150 | } |
| 151 | BufferSize = MultU64x64 (Width, Height); |
| 152 | |
| 153 | /* Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't |
| 154 | * overflow */ |
| 155 | if (BufferSize > |
| 156 | DivU64x32 ((UINTN)~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { |
| 157 | DEBUG ((EFI_D_ERROR, |
| 158 | "BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) overflow\n")); |
| 159 | return EFI_UNSUPPORTED; |
| 160 | } |
| 161 | |
| 162 | LogoBlt = AllocateZeroPool ((UINTN)BufferSize * |
| 163 | sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); |
| 164 | if (LogoBlt == NULL) { |
| 165 | return EFI_OUT_OF_RESOURCES; |
| 166 | } |
| 167 | |
| 168 | Status = GraphicsOutputProtocol->Blt ( |
| 169 | GraphicsOutputProtocol, LogoBlt, EfiBltVideoToBltBuffer, 0, 0, 0, 0, |
| 170 | Width, Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); |
| 171 | |
| 172 | if (Status != EFI_SUCCESS) { |
| 173 | FreePool (LogoBlt); |
| 174 | LogoBlt = NULL; |
| 175 | } |
| 176 | |
| 177 | return Status; |
| 178 | } |
| 179 | |
| 180 | // This function would restore the boot logo if the display on the screen is |
| 181 | // changed. |
lijuang | a4a9a65 | 2017-09-29 09:34:16 +0800 | [diff] [blame] | 182 | VOID RestoreBootLogoBitBuffer (VOID) |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 183 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 184 | EFI_STATUS Status; |
| 185 | UINT32 Width; |
| 186 | UINT32 Height; |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 187 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 188 | /* Return directly if the boot logo bit buffer is null */ |
| 189 | if (!LogoBlt) { |
| 190 | return; |
| 191 | } |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 192 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 193 | Width = GetResolutionWidth (); |
| 194 | Height = GetResolutionHeight (); |
| 195 | if (!Width || !Height) { |
| 196 | DEBUG ((EFI_D_ERROR, "Failed to get width or height\n")); |
| 197 | return; |
| 198 | } |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 199 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 200 | /* Ensure the Height * Width doesn't overflow */ |
| 201 | if (Height > DivU64x64Remainder ((UINTN)~0, Width, NULL)) { |
| 202 | DEBUG ((EFI_D_ERROR, "Height * Width overflow\n")); |
| 203 | return; |
| 204 | } |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 205 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 206 | Status = GraphicsOutputProtocol->Blt ( |
| 207 | GraphicsOutputProtocol, LogoBlt, EfiBltBufferToVideo, 0, 0, 0, 0, Width, |
| 208 | Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 209 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 210 | if (Status != EFI_SUCCESS) { |
| 211 | FreePool (LogoBlt); |
| 212 | LogoBlt = NULL; |
| 213 | } |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 214 | } |
| 215 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 216 | VOID FreeBootLogoBltBuffer (VOID) |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 217 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 218 | if (LogoBlt) { |
| 219 | FreePool (LogoBlt); |
| 220 | LogoBlt = NULL; |
| 221 | } |
lijuang | ace9d67 | 2016-08-30 15:43:37 +0800 | [diff] [blame] | 222 | } |
| 223 | |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 224 | STATIC UINT32 GetDisplayMode (VOID) |
| 225 | { |
| 226 | if (GetResolutionWidth () < GetResolutionHeight ()) { |
| 227 | return PORTRAIT_MODE; |
| 228 | } |
| 229 | |
| 230 | return HORIZONTAL_MODE; |
| 231 | } |
| 232 | |
| 233 | /* Get max row */ |
| 234 | STATIC UINT32 GetMaxRow (VOID) |
| 235 | { |
| 236 | EFI_STATUS Status; |
| 237 | UINT32 FontBaseHeight = EFI_GLYPH_HEIGHT; |
| 238 | UINT32 MaxRow = 0; |
| 239 | EFI_IMAGE_OUTPUT *Blt = NULL; |
| 240 | |
Prakruthi Deepak Heragu | e4ce21b | 2019-09-18 11:52:11 -0700 | [diff] [blame] | 241 | Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, |
| 242 | (VOID **) &gHiiFont); |
| 243 | if (EFI_ERROR (Status)) { |
| 244 | return MaxRow; |
| 245 | } |
| 246 | |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 247 | Status = gHiiFont->GetGlyph (gHiiFont, 'a', NULL, &Blt, NULL); |
| 248 | if (!EFI_ERROR (Status)) { |
| 249 | if (Blt) { |
| 250 | FontBaseHeight = Blt->Height; |
| 251 | } |
| 252 | } |
| 253 | MaxRow = GetResolutionHeight() / FontBaseHeight; |
| 254 | return MaxRow; |
| 255 | } |
| 256 | |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 257 | /* Get Max font count per row */ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 258 | STATIC UINT32 GetMaxFontCount (VOID) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 259 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 260 | EFI_STATUS Status; |
| 261 | UINT32 FontBaseWidth = EFI_GLYPH_WIDTH; |
| 262 | UINT32 max_count = 0; |
| 263 | EFI_IMAGE_OUTPUT *Blt = NULL; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 264 | |
Prakruthi Deepak Heragu | e4ce21b | 2019-09-18 11:52:11 -0700 | [diff] [blame] | 265 | Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, |
| 266 | (VOID **) &gHiiFont); |
| 267 | if (EFI_ERROR (Status)) { |
| 268 | return max_count; |
| 269 | } |
| 270 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 271 | Status = gHiiFont->GetGlyph (gHiiFont, 'a', NULL, &Blt, NULL); |
| 272 | if (!EFI_ERROR (Status)) { |
| 273 | if (Blt) |
| 274 | FontBaseWidth = Blt->Width; |
| 275 | } |
| 276 | max_count = GetResolutionWidth () / FontBaseWidth; |
| 277 | return max_count; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | /** |
| 281 | Get Font's scale factor |
| 282 | @param[in] ScaleFactorType The type of the scale factor. |
| 283 | @retval ScaleFactor Get the suitable scale factor base on the |
| 284 | scale factor's type. |
| 285 | **/ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 286 | STATIC UINT32 |
| 287 | GetFontScaleFactor (UINT32 ScaleFactorType) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 288 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 289 | UINT32 NumPerRow = 0; |
| 290 | UINT32 ScaleFactor = 0; |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 291 | UINT32 ScaleFactor1 = 0; |
| 292 | UINT32 ScaleFactor2 = 0; |
| 293 | UINT32 MaxRow = 0; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 294 | |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 295 | NumPerRow = CHAR_NUM_PERROW_POR; |
| 296 | MaxRow = MAX_ROW_FOR_POR; |
| 297 | if (GetDisplayMode () == HORIZONTAL_MODE) { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 298 | NumPerRow = CHAR_NUM_PERROW_HOR; |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 299 | MaxRow = MAX_ROW_FOR_HOR; |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 300 | } |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 301 | ScaleFactor1 = GetMaxFontCount () / NumPerRow; |
| 302 | ScaleFactor2 = GetMaxRow () / MaxRow; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 303 | |
lijuang | 45882c3 | 2019-06-18 13:46:55 +0800 | [diff] [blame] | 304 | ScaleFactor = ScaleFactor1 > ScaleFactor2 ? ScaleFactor2 : ScaleFactor1; |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 305 | if (ScaleFactor < 2) { |
| 306 | ScaleFactor = 1; |
| 307 | } else if (ScaleFactor > ((ARRAY_SIZE (mFactorName) - 1) / MAX_FACTORTYPE)) { |
| 308 | ScaleFactor = (ARRAY_SIZE (mFactorName) - 1) / MAX_FACTORTYPE; |
| 309 | } |
lijuang | 64679b7 | 2017-09-26 15:52:10 +0800 | [diff] [blame] | 310 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 311 | return ScaleFactor * ScaleFactorType; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 312 | } |
| 313 | |
| 314 | /* Get factor name base on the scale factor type */ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 315 | STATIC CHAR16 * |
| 316 | GetFontFactorName (UINT32 ScaleFactorType) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 317 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 318 | UINT32 ScaleFactor = GetFontScaleFactor (ScaleFactorType); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 319 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 320 | if (ScaleFactor <= (ARRAY_SIZE (mFactorName) - 1)) { |
| 321 | return mFactorName[ScaleFactor]; |
| 322 | } else { |
| 323 | return (CHAR16 *)SYSFONT_3x; |
| 324 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 325 | } |
| 326 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 327 | STATIC VOID |
| 328 | SetBltBuffer (EFI_IMAGE_OUTPUT *BltBuffer) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 329 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 330 | BltBuffer->Width = (UINT16)GetResolutionWidth (); |
| 331 | BltBuffer->Height = (UINT16)GetResolutionHeight (); |
| 332 | BltBuffer->Image.Screen = GraphicsOutputProtocol; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 333 | } |
| 334 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 335 | STATIC VOID |
| 336 | SetDisplayInfo (MENU_MSG_INFO *TargetMenu, |
| 337 | EFI_FONT_DISPLAY_INFO *FontDisplayInfo) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 338 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 339 | /* Foreground */ |
| 340 | FontDisplayInfo->ForegroundColor.Blue = mColors[TargetMenu->FgColor].Blue; |
| 341 | FontDisplayInfo->ForegroundColor.Green = mColors[TargetMenu->FgColor].Green; |
| 342 | FontDisplayInfo->ForegroundColor.Red = mColors[TargetMenu->FgColor].Red; |
| 343 | /* Background */ |
| 344 | FontDisplayInfo->BackgroundColor.Blue = mColors[TargetMenu->BgColor].Blue; |
| 345 | FontDisplayInfo->BackgroundColor.Green = mColors[TargetMenu->BgColor].Green; |
| 346 | FontDisplayInfo->BackgroundColor.Red = mColors[TargetMenu->BgColor].Red; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 347 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 348 | /* Set font name */ |
| 349 | FontDisplayInfo->FontInfoMask = |
| 350 | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE; |
| 351 | gBS->CopyMem (&FontDisplayInfo->FontInfo.FontName, |
| 352 | GetFontFactorName (TargetMenu->ScaleFactorType), |
| 353 | StrSize (GetFontFactorName (TargetMenu->ScaleFactorType))); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 354 | } |
| 355 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 356 | STATIC VOID |
| 357 | StrAlignRight (CHAR8 *Msg, CHAR8 *FilledChar, UINT32 ScaleFactorType) |
| 358 | { |
| 359 | UINT32 i = 0; |
| 360 | UINT32 diff = 0; |
lijuang | 8704a70 | 2018-10-25 14:36:36 +0800 | [diff] [blame] | 361 | CHAR8 *StrSourceTemp = NULL; |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 362 | UINT32 Max_x = GetMaxFontCount (); |
| 363 | UINT32 factor = GetFontScaleFactor (ScaleFactorType); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 364 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 365 | if (Max_x / factor > AsciiStrLen (Msg)) { |
| 366 | diff = Max_x / factor - AsciiStrLen (Msg); |
lijuang | 8704a70 | 2018-10-25 14:36:36 +0800 | [diff] [blame] | 367 | StrSourceTemp = AllocateZeroPool (MAX_MSG_SIZE); |
| 368 | if (StrSourceTemp == NULL) { |
| 369 | DEBUG ((EFI_D_ERROR, |
| 370 | "Failed to allocate zero pool for StrSourceTemp.\n")); |
| 371 | return; |
| 372 | } |
| 373 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 374 | for (i = 0; i < diff; i++) { |
| 375 | AsciiStrnCatS (StrSourceTemp, MAX_MSG_SIZE, FilledChar, 1); |
| 376 | } |
| 377 | AsciiStrnCatS (StrSourceTemp, MAX_MSG_SIZE, Msg, Max_x / factor); |
| 378 | gBS->CopyMem (Msg, StrSourceTemp, AsciiStrSize (StrSourceTemp)); |
lijuang | 8704a70 | 2018-10-25 14:36:36 +0800 | [diff] [blame] | 379 | FreePool (StrSourceTemp); |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 380 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 381 | } |
| 382 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 383 | STATIC VOID |
| 384 | StrAlignLeft (CHAR8 *Msg, |
| 385 | UINT32 MaxMsgSize, |
| 386 | CHAR8 *FilledChar, |
| 387 | UINT32 ScaleFactorType) |
| 388 | { |
| 389 | UINT32 i = 0; |
| 390 | UINT32 diff = 0; |
lijuang | 8704a70 | 2018-10-25 14:36:36 +0800 | [diff] [blame] | 391 | CHAR8 *StrSourceTemp = NULL; |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 392 | UINT32 Max_x = GetMaxFontCount (); |
| 393 | UINT32 factor = GetFontScaleFactor (ScaleFactorType); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 394 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 395 | if (Max_x / factor > AsciiStrLen (Msg)) { |
| 396 | diff = Max_x / factor - AsciiStrLen (Msg); |
Raghavendra Rao Ananta | dca6a8e | 2018-11-15 13:56:20 -0800 | [diff] [blame] | 397 | StrSourceTemp = AllocateZeroPool (MAX_MSG_SIZE); |
lijuang | 8704a70 | 2018-10-25 14:36:36 +0800 | [diff] [blame] | 398 | if (StrSourceTemp == NULL) { |
| 399 | DEBUG ((EFI_D_ERROR, |
| 400 | "Failed to allocate zero pool for StrSourceTemp.\n")); |
| 401 | return; |
| 402 | } |
| 403 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 404 | for (i = 0; i < diff; i++) { |
| 405 | AsciiStrnCatS (StrSourceTemp, MAX_MSG_SIZE, FilledChar, 1); |
| 406 | } |
Raghavendra Rao Ananta | dca6a8e | 2018-11-15 13:56:20 -0800 | [diff] [blame] | 407 | AsciiStrnCatS (Msg, MaxMsgSize, |
| 408 | StrSourceTemp, AsciiStrLen (StrSourceTemp)); |
lijuang | 8704a70 | 2018-10-25 14:36:36 +0800 | [diff] [blame] | 409 | FreePool (StrSourceTemp); |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 410 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 411 | } |
| 412 | |
| 413 | /* Message string manipulation base on the attribute of the message |
| 414 | * LINEATION: Fill a string with "_", for drawing a line |
| 415 | * ALIGN_RIGHT: String align right and fill this string with " " |
| 416 | * ALIGN_LEFT: String align left and fill this string with " " |
| 417 | * OPTION_ITEM: String align left and fill this string with " ", |
| 418 | * for updating the whole line's background |
| 419 | */ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 420 | STATIC VOID |
| 421 | ManipulateMenuMsg (MENU_MSG_INFO *TargetMenu) |
| 422 | { |
| 423 | switch (TargetMenu->Attribute) { |
| 424 | case LINEATION: |
| 425 | StrAlignLeft (TargetMenu->Msg, sizeof (TargetMenu->Msg), "_", |
| 426 | TargetMenu->ScaleFactorType); |
| 427 | break; |
| 428 | case ALIGN_RIGHT: |
| 429 | StrAlignRight (TargetMenu->Msg, " ", TargetMenu->ScaleFactorType); |
| 430 | break; |
| 431 | case ALIGN_LEFT: |
| 432 | case OPTION_ITEM: |
| 433 | StrAlignLeft (TargetMenu->Msg, sizeof (TargetMenu->Msg), " ", |
| 434 | TargetMenu->ScaleFactorType); |
| 435 | break; |
| 436 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 437 | } |
| 438 | |
| 439 | /** |
| 440 | Draw menu on the screen |
| 441 | @param[in] TargetMenu The message info. |
| 442 | @param[in, out] pHeight The Pointer for increased height. |
| 443 | @retval EFI_SUCCESS The entry point is executed successfully. |
| 444 | @retval other Some error occurs when executing this entry point. |
| 445 | **/ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 446 | EFI_STATUS |
| 447 | DrawMenu (MENU_MSG_INFO *TargetMenu, UINT32 *pHeight) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 448 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 449 | EFI_STATUS Status = EFI_SUCCESS; |
| 450 | EFI_FONT_DISPLAY_INFO *FontDisplayInfo = NULL; |
| 451 | EFI_IMAGE_OUTPUT *BltBuffer = NULL; |
| 452 | EFI_HII_ROW_INFO *RowInfoArray = NULL; |
| 453 | UINTN RowInfoArraySize; |
| 454 | CHAR16 FontMessage[MAX_MSG_SIZE]; |
| 455 | UINT32 Height = GetResolutionHeight (); |
| 456 | UINT32 Width = GetResolutionWidth (); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 457 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 458 | if (!Height || !Width) { |
| 459 | Status = EFI_OUT_OF_RESOURCES; |
| 460 | goto Exit; |
| 461 | } |
lijuang | 4734bc8 | 2016-08-16 16:13:19 +0800 | [diff] [blame] | 462 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 463 | if (TargetMenu->Location >= Height) { |
| 464 | DEBUG ((EFI_D_ERROR, "Error: Check the CHAR_NUM_PERROW: Y-axis(%d)" |
| 465 | " is larger than Y-max(%d)\n", |
| 466 | TargetMenu->Location, Height)); |
| 467 | Status = EFI_ABORTED; |
| 468 | goto Exit; |
| 469 | } |
lijuang | 31edca6 | 2016-09-01 16:36:41 +0800 | [diff] [blame] | 470 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 471 | BltBuffer = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT)); |
| 472 | if (BltBuffer == NULL) { |
| 473 | DEBUG ((EFI_D_ERROR, "Failed to allocate zero pool for BltBuffer.\n")); |
| 474 | Status = EFI_OUT_OF_RESOURCES; |
| 475 | goto Exit; |
| 476 | } |
| 477 | SetBltBuffer (BltBuffer); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 478 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 479 | FontDisplayInfo = AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO) + 100); |
| 480 | if (FontDisplayInfo == NULL) { |
| 481 | DEBUG ( |
| 482 | (EFI_D_ERROR, "Failed to allocate zero pool for FontDisplayInfo.\n")); |
| 483 | Status = EFI_OUT_OF_RESOURCES; |
| 484 | goto Exit; |
| 485 | } |
| 486 | SetDisplayInfo (TargetMenu, FontDisplayInfo); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 487 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 488 | ManipulateMenuMsg (TargetMenu); |
| 489 | AsciiStrToUnicodeStr (TargetMenu->Msg, FontMessage); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 490 | |
Prakruthi Deepak Heragu | e4ce21b | 2019-09-18 11:52:11 -0700 | [diff] [blame] | 491 | Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, |
| 492 | (VOID **) &gHiiFont); |
| 493 | if (EFI_ERROR (Status)) { |
| 494 | goto Exit; |
| 495 | } |
| 496 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 497 | Status = gHiiFont->StringToImage ( |
| 498 | gHiiFont, |
| 499 | /* Set to 0 for Bitmap mode */ |
| 500 | EFI_HII_DIRECT_TO_SCREEN | EFI_HII_OUT_FLAG_WRAP, FontMessage, |
| 501 | FontDisplayInfo, &BltBuffer, 0, /* BltX */ |
| 502 | TargetMenu->Location, /* BltY */ |
| 503 | &RowInfoArray, &RowInfoArraySize, NULL); |
| 504 | if (Status != EFI_SUCCESS) { |
| 505 | DEBUG ((EFI_D_ERROR, "Failed to render a string to the display: %r\n", |
| 506 | Status)); |
| 507 | goto Exit; |
| 508 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 509 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 510 | if (pHeight && RowInfoArraySize && RowInfoArray) { |
| 511 | *pHeight = RowInfoArraySize * RowInfoArray[0].LineHeight; |
| 512 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 513 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 514 | /* For Bitmap mode, use EfiBltBufferToVideo, and set DestX,DestY as needed */ |
| 515 | GraphicsOutputProtocol->Blt (GraphicsOutputProtocol, BltBuffer->Image.Bitmap, |
| 516 | EfiBltVideoToVideo, 0, /* SrcX */ |
| 517 | 0, /* SrcY */ |
| 518 | 0, /* DestX */ |
| 519 | 0, /* DestY */ |
| 520 | BltBuffer->Width, BltBuffer->Height, |
| 521 | BltBuffer->Width * |
| 522 | sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 523 | |
lijuang | 31edca6 | 2016-09-01 16:36:41 +0800 | [diff] [blame] | 524 | Exit: |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 525 | if (RowInfoArray) { |
| 526 | FreePool (RowInfoArray); |
| 527 | RowInfoArray = NULL; |
| 528 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 529 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 530 | if (BltBuffer) { |
| 531 | FreePool (BltBuffer); |
| 532 | BltBuffer = NULL; |
| 533 | } |
lijuang | 31edca6 | 2016-09-01 16:36:41 +0800 | [diff] [blame] | 534 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 535 | if (FontDisplayInfo) { |
| 536 | FreePool (FontDisplayInfo); |
| 537 | FontDisplayInfo = NULL; |
| 538 | } |
| 539 | return Status; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 540 | } |
| 541 | |
| 542 | /** |
| 543 | Set the message info |
| 544 | @param[in] Msg Message. |
| 545 | @param[in] ScaleFactorType The scale factor type of the message. |
| 546 | @param[in] FgColor The foreground color of the message. |
| 547 | @param[in] BgColor The background color of the message. |
| 548 | @param[in] Attribute The attribute of the message. |
| 549 | @param[in] Location The location of the message. |
| 550 | @param[in] Action The action of the message. |
| 551 | @param[out] MenuMsgInfo The message info. |
| 552 | **/ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 553 | VOID |
| 554 | SetMenuMsgInfo (MENU_MSG_INFO *MenuMsgInfo, |
| 555 | CHAR8 *Msg, |
| 556 | UINT32 ScaleFactorType, |
| 557 | UINT32 FgColor, |
| 558 | UINT32 BgColor, |
| 559 | UINT32 Attribute, |
| 560 | UINT32 Location, |
| 561 | UINT32 Action) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 562 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 563 | gBS->CopyMem (&MenuMsgInfo->Msg, Msg, AsciiStrSize (Msg)); |
| 564 | MenuMsgInfo->ScaleFactorType = ScaleFactorType; |
| 565 | MenuMsgInfo->FgColor = FgColor; |
| 566 | MenuMsgInfo->BgColor = BgColor; |
| 567 | MenuMsgInfo->Attribute = Attribute; |
| 568 | MenuMsgInfo->Location = Location; |
| 569 | MenuMsgInfo->Action = Action; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 570 | } |
| 571 | |
| 572 | /** |
| 573 | Update the background color of the message |
| 574 | @param[in] MenuMsgInfo The message info. |
| 575 | @param[in] NewBgColor The new background color of the message. |
| 576 | @retval EFI_SUCCESS The entry point is executed successfully. |
| 577 | @retval other Some error occurs when executing this entry point. |
| 578 | **/ |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 579 | EFI_STATUS |
| 580 | UpdateMsgBackground (MENU_MSG_INFO *MenuMsgInfo, UINT32 NewBgColor) |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 581 | { |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 582 | MENU_MSG_INFO *target_msg_info = NULL; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 583 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 584 | target_msg_info = AllocateZeroPool (sizeof (MENU_MSG_INFO)); |
| 585 | if (target_msg_info == NULL) { |
| 586 | DEBUG ((EFI_D_ERROR, "Failed to allocate zero pool for message info.\n")); |
| 587 | return EFI_OUT_OF_RESOURCES; |
| 588 | } |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 589 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 590 | SetMenuMsgInfo (target_msg_info, MenuMsgInfo->Msg, |
| 591 | MenuMsgInfo->ScaleFactorType, MenuMsgInfo->FgColor, |
| 592 | NewBgColor, MenuMsgInfo->Attribute, MenuMsgInfo->Location, |
| 593 | MenuMsgInfo->Action); |
| 594 | DrawMenu (target_msg_info, NULL); |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 595 | |
lijuang | c336a29 | 2017-08-22 19:48:49 +0800 | [diff] [blame] | 596 | FreePool (target_msg_info); |
| 597 | target_msg_info = NULL; |
| 598 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 599 | return EFI_SUCCESS; |
lijuang | c9d156e | 2016-07-27 18:31:00 +0800 | [diff] [blame] | 600 | } |
lijuang | 6e995df | 2017-05-12 18:46:04 +0800 | [diff] [blame] | 601 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 602 | VOID DrawMenuInit (VOID) |
| 603 | { |
| 604 | EFI_STATUS Status = EFI_SUCCESS; |
lijuang | 6e995df | 2017-05-12 18:46:04 +0800 | [diff] [blame] | 605 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 606 | /* Backup the boot logo blt buffer before the screen gets changed */ |
| 607 | Status = BackUpBootLogoBltBuffer (); |
| 608 | if (Status != EFI_SUCCESS) |
| 609 | DEBUG ((EFI_D_VERBOSE, "Backup the boot logo blt buffer failed: %r\n", |
| 610 | Status)); |
lijuang | 6e995df | 2017-05-12 18:46:04 +0800 | [diff] [blame] | 611 | |
Jeevan Shriram | 17f173d | 2017-10-24 22:11:07 -0700 | [diff] [blame] | 612 | /* Clear the screen before start drawing menu */ |
| 613 | gST->ConOut->ClearScreen (gST->ConOut); |
lijuang | 6e995df | 2017-05-12 18:46:04 +0800 | [diff] [blame] | 614 | } |