]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Library/BootLogoLib/BootLogoLib.c
MdeModulePkg/BootLogoLib: Remove invalid if judgments
[mirror_edk2.git] / MdeModulePkg / Library / BootLogoLib / BootLogoLib.c
... / ...
CommitLineData
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
5Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
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
16#include <Uefi.h>\r
17#include <Protocol/GraphicsOutput.h>\r
18#include <Protocol/SimpleTextOut.h>\r
19#include <Protocol/PlatformLogo.h>\r
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
26#include <Library/PcdLib.h>\r
27#include <Library/MemoryAllocationLib.h>\r
28#include <Library/DebugLib.h>\r
29\r
30/**\r
31 Show LOGO returned from Edkii Platform Logo protocol on all consoles.\r
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
39 VOID\r
40 )\r
41{\r
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
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
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
126 Instance = 0;\r
127 DestX = 0;\r
128 DestY = 0;\r
129 while (TRUE) {\r
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
144\r
145 if (Blt != NULL) {\r
146 FreePool (Blt);\r
147 }\r
148 Blt = Image.Bitmap;\r
149\r
150 //\r
151 // Calculate the display position according to Attribute.\r
152 //\r
153 switch (Attribute) {\r
154 case EdkiiPlatformLogoDisplayAttributeLeftTop:\r
155 DestX = 0;\r
156 DestY = 0;\r
157 break;\r
158 case EdkiiPlatformLogoDisplayAttributeCenterTop:\r
159 DestX = (SizeOfX - Image.Width) / 2;\r
160 DestY = 0;\r
161 break;\r
162 case EdkiiPlatformLogoDisplayAttributeRightTop:\r
163 DestX = SizeOfX - Image.Width;\r
164 DestY = 0;\r
165 break;\r
166\r
167 case EdkiiPlatformLogoDisplayAttributeCenterLeft:\r
168 DestX = 0;\r
169 DestY = (SizeOfY - Image.Height) / 2;\r
170 break;\r
171 case EdkiiPlatformLogoDisplayAttributeCenter:\r
172 DestX = (SizeOfX - Image.Width) / 2;\r
173 DestY = (SizeOfY - Image.Height) / 2;\r
174 break;\r
175 case EdkiiPlatformLogoDisplayAttributeCenterRight:\r
176 DestX = SizeOfX - Image.Width;\r
177 DestY = (SizeOfY - Image.Height) / 2;\r
178 break;\r
179\r
180 case EdkiiPlatformLogoDisplayAttributeLeftBottom:\r
181 DestX = 0;\r
182 DestY = SizeOfY - Image.Height;\r
183 break;\r
184 case EdkiiPlatformLogoDisplayAttributeCenterBottom:\r
185 DestX = (SizeOfX - Image.Width) / 2;\r
186 DestY = SizeOfY - Image.Height;\r
187 break;\r
188 case EdkiiPlatformLogoDisplayAttributeRightBottom:\r
189 DestX = SizeOfX - Image.Width;\r
190 DestY = SizeOfY - Image.Height;\r
191 break;\r
192\r
193 default:\r
194 ASSERT (FALSE);\r
195 continue;\r
196 break;\r
197 }\r
198\r
199 DestX += OffsetX;\r
200 DestY += OffsetY;\r
201\r
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
212 Image.Width,\r
213 Image.Height,\r
214 Image.Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
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
226 Image.Width,\r
227 Image.Height,\r
228 Image.Width * sizeof (EFI_UGA_PIXEL)\r
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
238 if (NumberOfLogos == 1) {\r
239 //\r
240 // The first Logo.\r
241 //\r
242 LogoDestX = (UINTN) DestX;\r
243 LogoDestY = (UINTN) DestY;\r
244 LogoWidth = Image.Width;\r
245 LogoHeight = Image.Height;\r
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
252 LogoWidth = MAX ((UINTN) DestX + Image.Width, LogoDestX + LogoWidth) - NewDestX;\r
253 LogoHeight = MAX ((UINTN) DestY + Image.Height, LogoDestY + LogoHeight) - NewDestY;\r
254\r
255 LogoDestX = NewDestX;\r
256 LogoDestY = NewDestY;\r
257 }\r
258 }\r
259 }\r
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