MdeModulePkg/BootLogoLib: Remove invalid if judgments
[mirror_edk2.git] / MdeModulePkg / Library / BootLogoLib / BootLogoLib.c
CommitLineData
8dfe7fd2
RN
1/** @file\r
2 This library is only intended to be used by PlatformBootManagerLib\r
3 to show progress bar and LOGO.\r
4\r
e0ac9c8a 5Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
8dfe7fd2
RN
6This program and the accompanying materials are licensed and made available under\r
7the terms and conditions of the BSD License that accompanies this distribution.\r
8The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php.\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
e0ac9c8a
RN
16#include <Uefi.h>\r
17#include <Protocol/GraphicsOutput.h>\r
8dfe7fd2
RN
18#include <Protocol/SimpleTextOut.h>\r
19#include <Protocol/PlatformLogo.h>\r
8dfe7fd2
RN
20#include <Protocol/UgaDraw.h>\r
21#include <Protocol/BootLogo.h>\r
22#include <Library/BaseLib.h>\r
23#include <Library/UefiLib.h>\r
24#include <Library/BaseMemoryLib.h>\r
25#include <Library/UefiBootServicesTableLib.h>\r
8dfe7fd2
RN
26#include <Library/PcdLib.h>\r
27#include <Library/MemoryAllocationLib.h>\r
28#include <Library/DebugLib.h>\r
8dfe7fd2
RN
29\r
30/**\r
e0ac9c8a 31 Show LOGO returned from Edkii Platform Logo protocol on all consoles.\r
8dfe7fd2
RN
32\r
33 @retval EFI_SUCCESS Logo was displayed.\r
34 @retval EFI_UNSUPPORTED Logo was not found or cannot be displayed.\r
35**/\r
36EFI_STATUS\r
37EFIAPI\r
38BootLogoEnableLogo (\r
e0ac9c8a 39 VOID\r
8dfe7fd2
RN
40 )\r
41{\r
e0ac9c8a
RN
42 EFI_STATUS Status;\r
43 EDKII_PLATFORM_LOGO_PROTOCOL *PlatformLogo;\r
44 EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute;\r
45 INTN OffsetX;\r
46 INTN OffsetY;\r
47 UINT32 SizeOfX;\r
48 UINT32 SizeOfY;\r
49 INTN DestX;\r
50 INTN DestY;\r
51 UINT32 Instance;\r
52 EFI_IMAGE_INPUT Image;\r
53 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
54 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
55 UINT32 ColorDepth;\r
56 UINT32 RefreshRate;\r
57 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
58 EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
59 UINTN NumberOfLogos;\r
60 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;\r
61 UINTN LogoDestX;\r
62 UINTN LogoDestY;\r
63 UINTN LogoHeight;\r
64 UINTN LogoWidth;\r
65 UINTN NewDestX;\r
66 UINTN NewDestY;\r
67 UINTN BufferSize;\r
68\r
69 Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL, (VOID **) &PlatformLogo);\r
70 if (EFI_ERROR (Status)) {\r
71 return EFI_UNSUPPORTED;\r
72 }\r
8dfe7fd2
RN
73\r
74 UgaDraw = NULL;\r
75 //\r
76 // Try to open GOP first\r
77 //\r
78 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
79 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
80 GraphicsOutput = NULL;\r
81 //\r
82 // Open GOP failed, try to open UGA\r
83 //\r
84 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
85 if (EFI_ERROR (Status)) {\r
86 UgaDraw = NULL;\r
87 }\r
88 }\r
89 if (EFI_ERROR (Status)) {\r
90 return EFI_UNSUPPORTED;\r
91 }\r
92\r
8dfe7fd2
RN
93 //\r
94 // Try to open Boot Logo Protocol.\r
95 //\r
96 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
97 if (EFI_ERROR (Status)) {\r
98 BootLogo = NULL;\r
99 }\r
100\r
101 //\r
102 // Erase Cursor from screen\r
103 //\r
104 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
105\r
106 if (GraphicsOutput != NULL) {\r
107 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
108 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
109\r
110 } else {\r
111 ASSERT (UgaDraw != NULL);\r
112 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
113 if (EFI_ERROR (Status)) {\r
114 return EFI_UNSUPPORTED;\r
115 }\r
116 }\r
117\r
118 Blt = NULL;\r
119 NumberOfLogos = 0;\r
120 LogoDestX = 0;\r
121 LogoDestY = 0;\r
122 LogoHeight = 0;\r
123 LogoWidth = 0;\r
124 NewDestX = 0;\r
125 NewDestY = 0;\r
8dfe7fd2 126 Instance = 0;\r
8084b26e
RN
127 DestX = 0;\r
128 DestY = 0;\r
8dfe7fd2 129 while (TRUE) {\r
e0ac9c8a
RN
130 //\r
131 // Get image from PlatformLogo protocol.\r
132 //\r
133 Status = PlatformLogo->GetImage (\r
134 PlatformLogo,\r
135 &Instance,\r
136 &Image,\r
137 &Attribute,\r
138 &OffsetX,\r
139 &OffsetY\r
140 );\r
141 if (EFI_ERROR (Status)) {\r
142 break;\r
143 }\r
8dfe7fd2 144\r
8dfe7fd2
RN
145 if (Blt != NULL) {\r
146 FreePool (Blt);\r
147 }\r
e0ac9c8a 148 Blt = Image.Bitmap;\r
8dfe7fd2
RN
149\r
150 //\r
151 // Calculate the display position according to Attribute.\r
152 //\r
153 switch (Attribute) {\r
154 case EdkiiPlatformLogoDisplayAttributeLeftTop:\r
b9335cf5
RN
155 DestX = 0;\r
156 DestY = 0;\r
8dfe7fd2 157 break;\r
8dfe7fd2 158 case EdkiiPlatformLogoDisplayAttributeCenterTop:\r
e0ac9c8a 159 DestX = (SizeOfX - Image.Width) / 2;\r
b9335cf5 160 DestY = 0;\r
8dfe7fd2 161 break;\r
8dfe7fd2 162 case EdkiiPlatformLogoDisplayAttributeRightTop:\r
e0ac9c8a 163 DestX = SizeOfX - Image.Width;\r
b9335cf5 164 DestY = 0;\r
8dfe7fd2
RN
165 break;\r
166\r
b9335cf5
RN
167 case EdkiiPlatformLogoDisplayAttributeCenterLeft:\r
168 DestX = 0;\r
e0ac9c8a 169 DestY = (SizeOfY - Image.Height) / 2;\r
8dfe7fd2 170 break;\r
b9335cf5 171 case EdkiiPlatformLogoDisplayAttributeCenter:\r
e0ac9c8a
RN
172 DestX = (SizeOfX - Image.Width) / 2;\r
173 DestY = (SizeOfY - Image.Height) / 2;\r
8dfe7fd2 174 break;\r
b9335cf5 175 case EdkiiPlatformLogoDisplayAttributeCenterRight:\r
e0ac9c8a
RN
176 DestX = SizeOfX - Image.Width;\r
177 DestY = (SizeOfY - Image.Height) / 2;\r
8dfe7fd2
RN
178 break;\r
179\r
b9335cf5
RN
180 case EdkiiPlatformLogoDisplayAttributeLeftBottom:\r
181 DestX = 0;\r
e0ac9c8a 182 DestY = SizeOfY - Image.Height;\r
b9335cf5
RN
183 break;\r
184 case EdkiiPlatformLogoDisplayAttributeCenterBottom:\r
e0ac9c8a
RN
185 DestX = (SizeOfX - Image.Width) / 2;\r
186 DestY = SizeOfY - Image.Height;\r
b9335cf5
RN
187 break;\r
188 case EdkiiPlatformLogoDisplayAttributeRightBottom:\r
e0ac9c8a
RN
189 DestX = SizeOfX - Image.Width;\r
190 DestY = SizeOfY - Image.Height;\r
8dfe7fd2
RN
191 break;\r
192\r
193 default:\r
194 ASSERT (FALSE);\r
e0ac9c8a 195 continue;\r
8dfe7fd2
RN
196 break;\r
197 }\r
198\r
b9335cf5
RN
199 DestX += OffsetX;\r
200 DestY += OffsetY;\r
201\r
8dfe7fd2
RN
202 if ((DestX >= 0) && (DestY >= 0)) {\r
203 if (GraphicsOutput != NULL) {\r
204 Status = GraphicsOutput->Blt (\r
205 GraphicsOutput,\r
206 Blt,\r
207 EfiBltBufferToVideo,\r
208 0,\r
209 0,\r
210 (UINTN) DestX,\r
211 (UINTN) DestY,\r
e0ac9c8a
RN
212 Image.Width,\r
213 Image.Height,\r
214 Image.Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
8dfe7fd2
RN
215 );\r
216 } else {\r
217 ASSERT (UgaDraw != NULL);\r
218 Status = UgaDraw->Blt (\r
219 UgaDraw,\r
220 (EFI_UGA_PIXEL *) Blt,\r
221 EfiUgaBltBufferToVideo,\r
222 0,\r
223 0,\r
224 (UINTN) DestX,\r
225 (UINTN) DestY,\r
e0ac9c8a
RN
226 Image.Width,\r
227 Image.Height,\r
228 Image.Width * sizeof (EFI_UGA_PIXEL)\r
8dfe7fd2
RN
229 );\r
230 }\r
231\r
232 //\r
233 // Report displayed Logo information.\r
234 //\r
235 if (!EFI_ERROR (Status)) {\r
236 NumberOfLogos++;\r
237\r
e0ac9c8a 238 if (NumberOfLogos == 1) {\r
8dfe7fd2
RN
239 //\r
240 // The first Logo.\r
241 //\r
242 LogoDestX = (UINTN) DestX;\r
243 LogoDestY = (UINTN) DestY;\r
e0ac9c8a
RN
244 LogoWidth = Image.Width;\r
245 LogoHeight = Image.Height;\r
8dfe7fd2
RN
246 } else {\r
247 //\r
248 // Merge new logo with old one.\r
249 //\r
250 NewDestX = MIN ((UINTN) DestX, LogoDestX);\r
251 NewDestY = MIN ((UINTN) DestY, LogoDestY);\r
e0ac9c8a
RN
252 LogoWidth = MAX ((UINTN) DestX + Image.Width, LogoDestX + LogoWidth) - NewDestX;\r
253 LogoHeight = MAX ((UINTN) DestY + Image.Height, LogoDestY + LogoHeight) - NewDestY;\r
8dfe7fd2
RN
254\r
255 LogoDestX = NewDestX;\r
256 LogoDestY = NewDestY;\r
8dfe7fd2
RN
257 }\r
258 }\r
259 }\r
8dfe7fd2
RN
260 }\r
261\r
262 if (BootLogo == NULL || NumberOfLogos == 0) {\r
263 //\r
264 // No logo displayed.\r
265 //\r
266 if (Blt != NULL) {\r
267 FreePool (Blt);\r
268 }\r
269\r
270 return Status;\r
271 }\r
272\r
273 //\r
274 // Advertise displayed Logo information.\r
275 //\r
276 if (NumberOfLogos == 1) {\r
277 //\r
278 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.\r
279 //\r
280 LogoBlt = Blt;\r
281 Status = EFI_SUCCESS;\r
282 } else {\r
283 //\r
284 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. \r
285 //\r
286 if (Blt != NULL) {\r
287 FreePool (Blt);\r
288 }\r
289\r
290 //\r
291 // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
292 //\r
293 if (LogoHeight > MAX_UINTN / LogoWidth / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {\r
294 return EFI_UNSUPPORTED;\r
295 }\r
296 BufferSize = LogoWidth * LogoHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
297\r
298 LogoBlt = AllocatePool (BufferSize);\r
299 if (LogoBlt == NULL) {\r
300 return EFI_OUT_OF_RESOURCES;\r
301 }\r
302\r
303 if (GraphicsOutput != NULL) {\r
304 Status = GraphicsOutput->Blt (\r
305 GraphicsOutput,\r
306 LogoBlt,\r
307 EfiBltVideoToBltBuffer,\r
308 LogoDestX,\r
309 LogoDestY,\r
310 0,\r
311 0,\r
312 LogoWidth,\r
313 LogoHeight,\r
314 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
315 );\r
316 } else {\r
317 Status = UgaDraw->Blt (\r
318 UgaDraw,\r
319 (EFI_UGA_PIXEL *) LogoBlt,\r
320 EfiUgaVideoToBltBuffer,\r
321 LogoDestX,\r
322 LogoDestY,\r
323 0,\r
324 0,\r
325 LogoWidth,\r
326 LogoHeight,\r
327 LogoWidth * sizeof (EFI_UGA_PIXEL)\r
328 );\r
329 }\r
330 }\r
331\r
332 if (!EFI_ERROR (Status)) {\r
333 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);\r
334 }\r
335 FreePool (LogoBlt);\r
336\r
337 return Status;\r
338}\r
339\r
340/**\r
341 Use SystemTable Conout to turn on video based Simple Text Out consoles. The \r
342 Simple Text Out screens will now be synced up with all non video output devices\r
343\r
344 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
345\r
346**/\r
347EFI_STATUS\r
348EFIAPI\r
349BootLogoDisableLogo (\r
350 VOID\r
351 )\r
352{\r
353\r
354 //\r
355 // Enable Cursor on Screen\r
356 //\r
357 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
358 return EFI_SUCCESS;\r
359}\r
360\r
361\r
362/**\r
363\r
364 Update progress bar with title above it. It only works in Graphics mode.\r
365\r
366 @param TitleForeground Foreground color for Title.\r
367 @param TitleBackground Background color for Title.\r
368 @param Title Title above progress bar.\r
369 @param ProgressColor Progress bar color.\r
370 @param Progress Progress (0-100)\r
371 @param PreviousValue The previous value of the progress.\r
372\r
373 @retval EFI_STATUS Success update the progress bar\r
374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
378BootLogoUpdateProgress (\r
379 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
380 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
381 IN CHAR16 *Title,\r
382 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
383 IN UINTN Progress,\r
384 IN UINTN PreviousValue\r
385 )\r
386{\r
387 EFI_STATUS Status;\r
388 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
389 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
390 UINT32 SizeOfX;\r
391 UINT32 SizeOfY;\r
392 UINT32 ColorDepth;\r
393 UINT32 RefreshRate;\r
394 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
395 UINTN BlockHeight;\r
396 UINTN BlockWidth;\r
397 UINTN BlockNum;\r
398 UINTN PosX;\r
399 UINTN PosY;\r
400 UINTN Index;\r
401\r
402 if (Progress > 100) {\r
403 return EFI_INVALID_PARAMETER;\r
404 }\r
405\r
406 UgaDraw = NULL;\r
407 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
408 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
409 GraphicsOutput = NULL;\r
410\r
411 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
412 if (EFI_ERROR (Status)) {\r
413 UgaDraw = NULL;\r
414 }\r
415 }\r
416 if (EFI_ERROR (Status)) {\r
417 return EFI_UNSUPPORTED;\r
418 }\r
419\r
420 SizeOfX = 0;\r
421 SizeOfY = 0;\r
422 if (GraphicsOutput != NULL) {\r
423 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
424 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
425 } else if (UgaDraw != NULL) {\r
426 Status = UgaDraw->GetMode (\r
427 UgaDraw,\r
428 &SizeOfX,\r
429 &SizeOfY,\r
430 &ColorDepth,\r
431 &RefreshRate\r
432 );\r
433 if (EFI_ERROR (Status)) {\r
434 return EFI_UNSUPPORTED;\r
435 }\r
436 } else {\r
437 return EFI_UNSUPPORTED;\r
438 }\r
439\r
440 BlockWidth = SizeOfX / 100;\r
441 BlockHeight = SizeOfY / 50;\r
442\r
443 BlockNum = Progress;\r
444\r
445 PosX = 0;\r
446 PosY = SizeOfY * 48 / 50;\r
447\r
448 if (BlockNum == 0) {\r
449 //\r
450 // Clear progress area\r
451 //\r
452 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
453\r
454 if (GraphicsOutput != NULL) {\r
455 Status = GraphicsOutput->Blt (\r
456 GraphicsOutput,\r
457 &Color,\r
458 EfiBltVideoFill,\r
459 0,\r
460 0,\r
461 0,\r
462 PosY - EFI_GLYPH_HEIGHT - 1,\r
463 SizeOfX,\r
464 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
465 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
466 );\r
467 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
468 Status = UgaDraw->Blt (\r
469 UgaDraw,\r
470 (EFI_UGA_PIXEL *) &Color,\r
471 EfiUgaVideoFill,\r
472 0,\r
473 0,\r
474 0,\r
475 PosY - EFI_GLYPH_HEIGHT - 1,\r
476 SizeOfX,\r
477 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
478 SizeOfX * sizeof (EFI_UGA_PIXEL)\r
479 );\r
480 } else {\r
481 return EFI_UNSUPPORTED;\r
482 }\r
483 }\r
484 //\r
485 // Show progress by drawing blocks\r
486 //\r
487 for (Index = PreviousValue; Index < BlockNum; Index++) {\r
488 PosX = Index * BlockWidth;\r
489 if (GraphicsOutput != NULL) {\r
490 Status = GraphicsOutput->Blt (\r
491 GraphicsOutput,\r
492 &ProgressColor,\r
493 EfiBltVideoFill,\r
494 0,\r
495 0,\r
496 PosX,\r
497 PosY,\r
498 BlockWidth - 1,\r
499 BlockHeight,\r
500 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
501 );\r
502 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
503 Status = UgaDraw->Blt (\r
504 UgaDraw,\r
505 (EFI_UGA_PIXEL *) &ProgressColor,\r
506 EfiUgaVideoFill,\r
507 0,\r
508 0,\r
509 PosX,\r
510 PosY,\r
511 BlockWidth - 1,\r
512 BlockHeight,\r
513 (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
514 );\r
515 } else {\r
516 return EFI_UNSUPPORTED;\r
517 }\r
518 }\r
519\r
520 PrintXY (\r
521 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
522 PosY - EFI_GLYPH_HEIGHT - 1,\r
523 &TitleForeground,\r
524 &TitleBackground,\r
525 Title\r
526 );\r
527\r
528 return EFI_SUCCESS;\r
529}\r