blob: 2f1c0aa6468ea9bd1808d7bdc725bc94f2bc33f9 [file] [log] [blame]
lijuang45882c32019-06-18 13:46:55 +08001/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
lijuangc9d156e2016-07-27 18:31:00 +08002 *
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
lijuangc9d156e2016-07-27 18:31:00 +080029#include <Library/BaseLib.h>
lijuangc9d156e2016-07-27 18:31:00 +080030#include <Library/BaseMemoryLib.h>
31#include <Library/DebugLib.h>
lijuangc9d156e2016-07-27 18:31:00 +080032#include <Library/DrawUI.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070033#include <Library/Fonts.h>
34#include <Library/MemoryAllocationLib.h>
35#include <Library/UefiBootServicesTableLib.h>
lijuangc9d156e2016-07-27 18:31:00 +080036#include <Library/UpdateDeviceTree.h>
37#include <Protocol/GraphicsOutput.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070038#include <Uefi.h>
Prakruthi Deepak Herague4ce21b2019-09-18 11:52:11 -070039#include <Protocol/HiiFont.h>
lijuangc9d156e2016-07-27 18:31:00 +080040
Jeevan Shriram17f173d2017-10-24 22:11:07 -070041STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutputProtocol;
lijuangace9d672016-08-30 15:43:37 +080042STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
Prakruthi Deepak Herague4ce21b2019-09-18 11:52:11 -070043STATIC EFI_HII_FONT_PROTOCOL *gHiiFont = NULL;
lijuangc9d156e2016-07-27 18:31:00 +080044
45STATIC CHAR16 *mFactorName[] = {
Jeevan Shriram17f173d2017-10-24 22:11:07 -070046 [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,
lijuangc9d156e2016-07-27 18:31:00 +080050};
51
52STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mColors[] = {
Jeevan Shriram17f173d2017-10-24 22:11:07 -070053 [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},
lijuangc9d156e2016-07-27 18:31:00 +080062};
63
Jeevan Shriram17f173d2017-10-24 22:11:07 -070064STATIC UINT32 GetResolutionWidth (VOID)
lijuangc9d156e2016-07-27 18:31:00 +080065{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070066 STATIC UINT32 Width;
67 EFI_HANDLE ConsoleHandle = (EFI_HANDLE)NULL;
lijuangc9d156e2016-07-27 18:31:00 +080068
Jeevan Shriram17f173d2017-10-24 22:11:07 -070069 /* Get the width from the protocal at the first time */
70 if (Width)
71 return Width;
lijuangc9d156e2016-07-27 18:31:00 +080072
Jeevan Shriram17f173d2017-10-24 22:11:07 -070073 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;
lijuang46df8442017-09-28 19:06:36 +080080 }
81
Jeevan Shriram17f173d2017-10-24 22:11:07 -070082 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;
lijuangace9d672016-08-30 15:43:37 +080094}
95
Jeevan Shriram17f173d2017-10-24 22:11:07 -070096STATIC 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
128EFI_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.
lijuanga4a9a652017-09-29 09:34:16 +0800182VOID RestoreBootLogoBitBuffer (VOID)
lijuangace9d672016-08-30 15:43:37 +0800183{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700184 EFI_STATUS Status;
185 UINT32 Width;
186 UINT32 Height;
lijuangace9d672016-08-30 15:43:37 +0800187
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700188 /* Return directly if the boot logo bit buffer is null */
189 if (!LogoBlt) {
190 return;
191 }
lijuangace9d672016-08-30 15:43:37 +0800192
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700193 Width = GetResolutionWidth ();
194 Height = GetResolutionHeight ();
195 if (!Width || !Height) {
196 DEBUG ((EFI_D_ERROR, "Failed to get width or height\n"));
197 return;
198 }
lijuangace9d672016-08-30 15:43:37 +0800199
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700200 /* 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 }
lijuangace9d672016-08-30 15:43:37 +0800205
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700206 Status = GraphicsOutputProtocol->Blt (
207 GraphicsOutputProtocol, LogoBlt, EfiBltBufferToVideo, 0, 0, 0, 0, Width,
208 Height, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
lijuangace9d672016-08-30 15:43:37 +0800209
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700210 if (Status != EFI_SUCCESS) {
211 FreePool (LogoBlt);
212 LogoBlt = NULL;
213 }
lijuangace9d672016-08-30 15:43:37 +0800214}
215
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700216VOID FreeBootLogoBltBuffer (VOID)
lijuangace9d672016-08-30 15:43:37 +0800217{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700218 if (LogoBlt) {
219 FreePool (LogoBlt);
220 LogoBlt = NULL;
221 }
lijuangace9d672016-08-30 15:43:37 +0800222}
223
lijuang45882c32019-06-18 13:46:55 +0800224STATIC UINT32 GetDisplayMode (VOID)
225{
226 if (GetResolutionWidth () < GetResolutionHeight ()) {
227 return PORTRAIT_MODE;
228 }
229
230 return HORIZONTAL_MODE;
231}
232
233/* Get max row */
234STATIC 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 Herague4ce21b2019-09-18 11:52:11 -0700241 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL,
242 (VOID **) &gHiiFont);
243 if (EFI_ERROR (Status)) {
244 return MaxRow;
245 }
246
lijuang45882c32019-06-18 13:46:55 +0800247 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
lijuangc9d156e2016-07-27 18:31:00 +0800257/* Get Max font count per row */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700258STATIC UINT32 GetMaxFontCount (VOID)
lijuangc9d156e2016-07-27 18:31:00 +0800259{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700260 EFI_STATUS Status;
261 UINT32 FontBaseWidth = EFI_GLYPH_WIDTH;
262 UINT32 max_count = 0;
263 EFI_IMAGE_OUTPUT *Blt = NULL;
lijuangc9d156e2016-07-27 18:31:00 +0800264
Prakruthi Deepak Herague4ce21b2019-09-18 11:52:11 -0700265 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL,
266 (VOID **) &gHiiFont);
267 if (EFI_ERROR (Status)) {
268 return max_count;
269 }
270
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700271 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;
lijuangc9d156e2016-07-27 18:31:00 +0800278}
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 Shriram17f173d2017-10-24 22:11:07 -0700286STATIC UINT32
287GetFontScaleFactor (UINT32 ScaleFactorType)
lijuangc9d156e2016-07-27 18:31:00 +0800288{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700289 UINT32 NumPerRow = 0;
290 UINT32 ScaleFactor = 0;
lijuang45882c32019-06-18 13:46:55 +0800291 UINT32 ScaleFactor1 = 0;
292 UINT32 ScaleFactor2 = 0;
293 UINT32 MaxRow = 0;
lijuangc9d156e2016-07-27 18:31:00 +0800294
lijuang45882c32019-06-18 13:46:55 +0800295 NumPerRow = CHAR_NUM_PERROW_POR;
296 MaxRow = MAX_ROW_FOR_POR;
297 if (GetDisplayMode () == HORIZONTAL_MODE) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700298 NumPerRow = CHAR_NUM_PERROW_HOR;
lijuang45882c32019-06-18 13:46:55 +0800299 MaxRow = MAX_ROW_FOR_HOR;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700300 }
lijuang45882c32019-06-18 13:46:55 +0800301 ScaleFactor1 = GetMaxFontCount () / NumPerRow;
302 ScaleFactor2 = GetMaxRow () / MaxRow;
lijuangc9d156e2016-07-27 18:31:00 +0800303
lijuang45882c32019-06-18 13:46:55 +0800304 ScaleFactor = ScaleFactor1 > ScaleFactor2 ? ScaleFactor2 : ScaleFactor1;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700305 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 }
lijuang64679b72017-09-26 15:52:10 +0800310
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700311 return ScaleFactor * ScaleFactorType;
lijuangc9d156e2016-07-27 18:31:00 +0800312}
313
314/* Get factor name base on the scale factor type */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700315STATIC CHAR16 *
316GetFontFactorName (UINT32 ScaleFactorType)
lijuangc9d156e2016-07-27 18:31:00 +0800317{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700318 UINT32 ScaleFactor = GetFontScaleFactor (ScaleFactorType);
lijuangc9d156e2016-07-27 18:31:00 +0800319
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700320 if (ScaleFactor <= (ARRAY_SIZE (mFactorName) - 1)) {
321 return mFactorName[ScaleFactor];
322 } else {
323 return (CHAR16 *)SYSFONT_3x;
324 }
lijuangc9d156e2016-07-27 18:31:00 +0800325}
326
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700327STATIC VOID
328SetBltBuffer (EFI_IMAGE_OUTPUT *BltBuffer)
lijuangc9d156e2016-07-27 18:31:00 +0800329{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700330 BltBuffer->Width = (UINT16)GetResolutionWidth ();
331 BltBuffer->Height = (UINT16)GetResolutionHeight ();
332 BltBuffer->Image.Screen = GraphicsOutputProtocol;
lijuangc9d156e2016-07-27 18:31:00 +0800333}
334
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700335STATIC VOID
336SetDisplayInfo (MENU_MSG_INFO *TargetMenu,
337 EFI_FONT_DISPLAY_INFO *FontDisplayInfo)
lijuangc9d156e2016-07-27 18:31:00 +0800338{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700339 /* 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;
lijuangc9d156e2016-07-27 18:31:00 +0800347
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700348 /* 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)));
lijuangc9d156e2016-07-27 18:31:00 +0800354}
355
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700356STATIC VOID
357StrAlignRight (CHAR8 *Msg, CHAR8 *FilledChar, UINT32 ScaleFactorType)
358{
359 UINT32 i = 0;
360 UINT32 diff = 0;
lijuang8704a702018-10-25 14:36:36 +0800361 CHAR8 *StrSourceTemp = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700362 UINT32 Max_x = GetMaxFontCount ();
363 UINT32 factor = GetFontScaleFactor (ScaleFactorType);
lijuangc9d156e2016-07-27 18:31:00 +0800364
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700365 if (Max_x / factor > AsciiStrLen (Msg)) {
366 diff = Max_x / factor - AsciiStrLen (Msg);
lijuang8704a702018-10-25 14:36:36 +0800367 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 Shriram17f173d2017-10-24 22:11:07 -0700374 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));
lijuang8704a702018-10-25 14:36:36 +0800379 FreePool (StrSourceTemp);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700380 }
lijuangc9d156e2016-07-27 18:31:00 +0800381}
382
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700383STATIC VOID
384StrAlignLeft (CHAR8 *Msg,
385 UINT32 MaxMsgSize,
386 CHAR8 *FilledChar,
387 UINT32 ScaleFactorType)
388{
389 UINT32 i = 0;
390 UINT32 diff = 0;
lijuang8704a702018-10-25 14:36:36 +0800391 CHAR8 *StrSourceTemp = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700392 UINT32 Max_x = GetMaxFontCount ();
393 UINT32 factor = GetFontScaleFactor (ScaleFactorType);
lijuangc9d156e2016-07-27 18:31:00 +0800394
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700395 if (Max_x / factor > AsciiStrLen (Msg)) {
396 diff = Max_x / factor - AsciiStrLen (Msg);
Raghavendra Rao Anantadca6a8e2018-11-15 13:56:20 -0800397 StrSourceTemp = AllocateZeroPool (MAX_MSG_SIZE);
lijuang8704a702018-10-25 14:36:36 +0800398 if (StrSourceTemp == NULL) {
399 DEBUG ((EFI_D_ERROR,
400 "Failed to allocate zero pool for StrSourceTemp.\n"));
401 return;
402 }
403
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700404 for (i = 0; i < diff; i++) {
405 AsciiStrnCatS (StrSourceTemp, MAX_MSG_SIZE, FilledChar, 1);
406 }
Raghavendra Rao Anantadca6a8e2018-11-15 13:56:20 -0800407 AsciiStrnCatS (Msg, MaxMsgSize,
408 StrSourceTemp, AsciiStrLen (StrSourceTemp));
lijuang8704a702018-10-25 14:36:36 +0800409 FreePool (StrSourceTemp);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700410 }
lijuangc9d156e2016-07-27 18:31:00 +0800411}
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 Shriram17f173d2017-10-24 22:11:07 -0700420STATIC VOID
421ManipulateMenuMsg (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 }
lijuangc9d156e2016-07-27 18:31:00 +0800437}
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 Shriram17f173d2017-10-24 22:11:07 -0700446EFI_STATUS
447DrawMenu (MENU_MSG_INFO *TargetMenu, UINT32 *pHeight)
lijuangc9d156e2016-07-27 18:31:00 +0800448{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700449 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 ();
lijuangc9d156e2016-07-27 18:31:00 +0800457
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700458 if (!Height || !Width) {
459 Status = EFI_OUT_OF_RESOURCES;
460 goto Exit;
461 }
lijuang4734bc82016-08-16 16:13:19 +0800462
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700463 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 }
lijuang31edca62016-09-01 16:36:41 +0800470
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700471 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);
lijuangc9d156e2016-07-27 18:31:00 +0800478
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700479 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);
lijuangc9d156e2016-07-27 18:31:00 +0800487
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700488 ManipulateMenuMsg (TargetMenu);
489 AsciiStrToUnicodeStr (TargetMenu->Msg, FontMessage);
lijuangc9d156e2016-07-27 18:31:00 +0800490
Prakruthi Deepak Herague4ce21b2019-09-18 11:52:11 -0700491 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL,
492 (VOID **) &gHiiFont);
493 if (EFI_ERROR (Status)) {
494 goto Exit;
495 }
496
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700497 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 }
lijuangc9d156e2016-07-27 18:31:00 +0800509
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700510 if (pHeight && RowInfoArraySize && RowInfoArray) {
511 *pHeight = RowInfoArraySize * RowInfoArray[0].LineHeight;
512 }
lijuangc9d156e2016-07-27 18:31:00 +0800513
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700514 /* 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));
lijuangc9d156e2016-07-27 18:31:00 +0800523
lijuang31edca62016-09-01 16:36:41 +0800524Exit:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700525 if (RowInfoArray) {
526 FreePool (RowInfoArray);
527 RowInfoArray = NULL;
528 }
lijuangc9d156e2016-07-27 18:31:00 +0800529
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700530 if (BltBuffer) {
531 FreePool (BltBuffer);
532 BltBuffer = NULL;
533 }
lijuang31edca62016-09-01 16:36:41 +0800534
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700535 if (FontDisplayInfo) {
536 FreePool (FontDisplayInfo);
537 FontDisplayInfo = NULL;
538 }
539 return Status;
lijuangc9d156e2016-07-27 18:31:00 +0800540}
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 Shriram17f173d2017-10-24 22:11:07 -0700553VOID
554SetMenuMsgInfo (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)
lijuangc9d156e2016-07-27 18:31:00 +0800562{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700563 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;
lijuangc9d156e2016-07-27 18:31:00 +0800570}
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 Shriram17f173d2017-10-24 22:11:07 -0700579EFI_STATUS
580UpdateMsgBackground (MENU_MSG_INFO *MenuMsgInfo, UINT32 NewBgColor)
lijuangc9d156e2016-07-27 18:31:00 +0800581{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700582 MENU_MSG_INFO *target_msg_info = NULL;
lijuangc9d156e2016-07-27 18:31:00 +0800583
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700584 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 }
lijuangc9d156e2016-07-27 18:31:00 +0800589
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700590 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);
lijuangc9d156e2016-07-27 18:31:00 +0800595
lijuangc336a292017-08-22 19:48:49 +0800596 FreePool (target_msg_info);
597 target_msg_info = NULL;
598
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700599 return EFI_SUCCESS;
lijuangc9d156e2016-07-27 18:31:00 +0800600}
lijuang6e995df2017-05-12 18:46:04 +0800601
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700602VOID DrawMenuInit (VOID)
603{
604 EFI_STATUS Status = EFI_SUCCESS;
lijuang6e995df2017-05-12 18:46:04 +0800605
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700606 /* 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));
lijuang6e995df2017-05-12 18:46:04 +0800611
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700612 /* Clear the screen before start drawing menu */
613 gST->ConOut->ClearScreen (gST->ConOut);
lijuang6e995df2017-05-12 18:46:04 +0800614}