]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Library/BootLogoLib/BootLogoLib.c
OvmfPkg/PlatformBds: Do not call BootLogoEnableLogo
[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 - 2015, 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 <PiDxe.h>\r
17#include <Protocol/SimpleTextOut.h>\r
18#include <Protocol/PlatformLogo.h>\r
19#include <Protocol/GraphicsOutput.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/DxeServicesLib.h>\r
27#include <Library/PcdLib.h>\r
28#include <Library/MemoryAllocationLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/ImageDecoderLib.h>\r
31\r
32/**\r
33 Show LOGO on all consoles.\r
34\r
35 @param[in] ImageFormat Format of the image file.\r
36 @param[in] LogoFile The file name of logo to display.\r
37 @param[in] Attribute The display attributes of the image returned.\r
38 @param[in] OffsetX The X offset of the image regarding the Attribute.\r
39 @param[in] OffsetY The Y offset of the image regarding the Attribute.\r
40\r
41 @retval EFI_SUCCESS Logo was displayed.\r
42 @retval EFI_UNSUPPORTED Logo was not found or cannot be displayed.\r
43**/\r
44EFI_STATUS\r
45EFIAPI\r
46BootLogoEnableLogo (\r
47 IN IMAGE_FORMAT ImageFormat,\r
48 IN EFI_GUID *Logo,\r
49 IN EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute,\r
50 IN INTN OffsetX,\r
51 IN INTN OffsetY\r
52 )\r
53{\r
54 EFI_STATUS Status;\r
55 EDKII_PLATFORM_LOGO_PROTOCOL *PlatformLogo;\r
56 UINT32 SizeOfX;\r
57 UINT32 SizeOfY;\r
58 INTN DestX;\r
59 INTN DestY;\r
60 UINT8 *ImageData;\r
61 UINTN ImageSize;\r
62 UINTN BltSize;\r
63 UINT32 Instance;\r
64 UINTN Height;\r
65 UINTN Width;\r
66 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
67 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
68 UINT32 ColorDepth;\r
69 UINT32 RefreshRate;\r
70 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
71 EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
72 UINTN NumberOfLogos;\r
73 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;\r
74 UINTN LogoDestX;\r
75 UINTN LogoDestY;\r
76 UINTN LogoHeight;\r
77 UINTN LogoWidth;\r
78 UINTN NewDestX;\r
79 UINTN NewDestY;\r
80 UINTN NewHeight;\r
81 UINTN NewWidth;\r
82 UINTN BufferSize;\r
83\r
84 UgaDraw = NULL;\r
85 //\r
86 // Try to open GOP first\r
87 //\r
88 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
89 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
90 GraphicsOutput = NULL;\r
91 //\r
92 // Open GOP failed, try to open UGA\r
93 //\r
94 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
95 if (EFI_ERROR (Status)) {\r
96 UgaDraw = NULL;\r
97 }\r
98 }\r
99 if (EFI_ERROR (Status)) {\r
100 return EFI_UNSUPPORTED;\r
101 }\r
102\r
103 Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL, (VOID **) &PlatformLogo);\r
104 if (EFI_ERROR (Status)) {\r
105 PlatformLogo = NULL;\r
106 }\r
107\r
108 if ((Logo == NULL) && (PlatformLogo == NULL)) {\r
109 return EFI_UNSUPPORTED;\r
110 }\r
111\r
112 //\r
113 // Try to open Boot Logo Protocol.\r
114 //\r
115 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
116 if (EFI_ERROR (Status)) {\r
117 BootLogo = NULL;\r
118 }\r
119\r
120 //\r
121 // Erase Cursor from screen\r
122 //\r
123 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
124\r
125 if (GraphicsOutput != NULL) {\r
126 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
127 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
128\r
129 } else {\r
130 ASSERT (UgaDraw != NULL);\r
131 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
132 if (EFI_ERROR (Status)) {\r
133 return EFI_UNSUPPORTED;\r
134 }\r
135 }\r
136\r
137 Blt = NULL;\r
138 NumberOfLogos = 0;\r
139 LogoDestX = 0;\r
140 LogoDestY = 0;\r
141 LogoHeight = 0;\r
142 LogoWidth = 0;\r
143 NewDestX = 0;\r
144 NewDestY = 0;\r
145 NewHeight = 0;\r
146 NewWidth = 0;\r
147 Instance = 0;\r
148 DestX = 0;\r
149 DestY = 0;\r
150 while (TRUE) {\r
151 ImageData = NULL;\r
152 ImageSize = 0;\r
153\r
154 if (PlatformLogo != NULL) {\r
155 //\r
156 // Get image from OEMBadging protocol.\r
157 //\r
158 Status = PlatformLogo->GetImage (\r
159 PlatformLogo,\r
160 &Instance,\r
161 &ImageFormat,\r
162 &ImageData,\r
163 &ImageSize,\r
164 &Attribute,\r
165 &OffsetX,\r
166 &OffsetY\r
167 );\r
168 if (EFI_ERROR (Status)) {\r
169 break;\r
170 }\r
171\r
172 } else {\r
173 //\r
174 // Get the specified image from FV.\r
175 //\r
176 Status = GetSectionFromAnyFv (Logo, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
177 if (EFI_ERROR (Status)) {\r
178 return EFI_UNSUPPORTED;\r
179 }\r
180 }\r
181\r
182 if (Blt != NULL) {\r
183 FreePool (Blt);\r
184 }\r
185\r
186 Status = DecodeImage (ImageFormat, ImageData, ImageSize, &Blt, &BltSize, &Width, &Height);\r
187 FreePool (ImageData);\r
188 if (EFI_ERROR (Status)) {\r
189 if (Logo != NULL) {\r
190 //\r
191 // Directly return failure for single LOGO\r
192 //\r
193 return Status;\r
194 } else {\r
195 continue;\r
196 }\r
197 }\r
198\r
199 //\r
200 // Calculate the display position according to Attribute.\r
201 //\r
202 switch (Attribute) {\r
203 case EdkiiPlatformLogoDisplayAttributeLeftTop:\r
204 DestX = 0;\r
205 DestY = 0;\r
206 break;\r
207 case EdkiiPlatformLogoDisplayAttributeCenterTop:\r
208 DestX = (SizeOfX - Width) / 2;\r
209 DestY = 0;\r
210 break;\r
211 case EdkiiPlatformLogoDisplayAttributeRightTop:\r
212 DestX = SizeOfX - Width;\r
213 DestY = 0;\r
214 break;\r
215\r
216 case EdkiiPlatformLogoDisplayAttributeCenterLeft:\r
217 DestX = 0;\r
218 DestY = (SizeOfY - Height) / 2;\r
219 break;\r
220 case EdkiiPlatformLogoDisplayAttributeCenter:\r
221 DestX = (SizeOfX - Width) / 2;\r
222 DestY = (SizeOfY - Height) / 2;\r
223 break;\r
224 case EdkiiPlatformLogoDisplayAttributeCenterRight:\r
225 DestX = SizeOfX - Width;\r
226 DestY = (SizeOfY - Height) / 2;\r
227 break;\r
228\r
229 case EdkiiPlatformLogoDisplayAttributeLeftBottom:\r
230 DestX = 0;\r
231 DestY = SizeOfY - Height;\r
232 break;\r
233 case EdkiiPlatformLogoDisplayAttributeCenterBottom:\r
234 DestX = (SizeOfX - Width) / 2;\r
235 DestY = SizeOfY - Height;\r
236 break;\r
237 case EdkiiPlatformLogoDisplayAttributeRightBottom:\r
238 DestX = SizeOfX - Width;\r
239 DestY = SizeOfY - Height;\r
240 break;\r
241\r
242 default:\r
243 ASSERT (FALSE);\r
244 break;\r
245 }\r
246\r
247 DestX += OffsetX;\r
248 DestY += OffsetY;\r
249\r
250 if ((DestX >= 0) && (DestY >= 0)) {\r
251 if (GraphicsOutput != NULL) {\r
252 Status = GraphicsOutput->Blt (\r
253 GraphicsOutput,\r
254 Blt,\r
255 EfiBltBufferToVideo,\r
256 0,\r
257 0,\r
258 (UINTN) DestX,\r
259 (UINTN) DestY,\r
260 Width,\r
261 Height,\r
262 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
263 );\r
264 } else {\r
265 ASSERT (UgaDraw != NULL);\r
266 Status = UgaDraw->Blt (\r
267 UgaDraw,\r
268 (EFI_UGA_PIXEL *) Blt,\r
269 EfiUgaBltBufferToVideo,\r
270 0,\r
271 0,\r
272 (UINTN) DestX,\r
273 (UINTN) DestY,\r
274 Width,\r
275 Height,\r
276 Width * sizeof (EFI_UGA_PIXEL)\r
277 );\r
278 }\r
279\r
280 //\r
281 // Report displayed Logo information.\r
282 //\r
283 if (!EFI_ERROR (Status)) {\r
284 NumberOfLogos++;\r
285\r
286 if (LogoWidth == 0) {\r
287 //\r
288 // The first Logo.\r
289 //\r
290 LogoDestX = (UINTN) DestX;\r
291 LogoDestY = (UINTN) DestY;\r
292 LogoWidth = Width;\r
293 LogoHeight = Height;\r
294 } else {\r
295 //\r
296 // Merge new logo with old one.\r
297 //\r
298 NewDestX = MIN ((UINTN) DestX, LogoDestX);\r
299 NewDestY = MIN ((UINTN) DestY, LogoDestY);\r
300 NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;\r
301 NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;\r
302\r
303 LogoDestX = NewDestX;\r
304 LogoDestY = NewDestY;\r
305 LogoWidth = NewWidth;\r
306 LogoHeight = NewHeight;\r
307 }\r
308 }\r
309 }\r
310\r
311 if (PlatformLogo == NULL) {\r
312 break;\r
313 }\r
314 }\r
315\r
316 if (BootLogo == NULL || NumberOfLogos == 0) {\r
317 //\r
318 // No logo displayed.\r
319 //\r
320 if (Blt != NULL) {\r
321 FreePool (Blt);\r
322 }\r
323\r
324 return Status;\r
325 }\r
326\r
327 //\r
328 // Advertise displayed Logo information.\r
329 //\r
330 if (NumberOfLogos == 1) {\r
331 //\r
332 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.\r
333 //\r
334 LogoBlt = Blt;\r
335 Status = EFI_SUCCESS;\r
336 } else {\r
337 //\r
338 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. \r
339 //\r
340 if (Blt != NULL) {\r
341 FreePool (Blt);\r
342 }\r
343\r
344 //\r
345 // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
346 //\r
347 if (LogoHeight > MAX_UINTN / LogoWidth / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {\r
348 return EFI_UNSUPPORTED;\r
349 }\r
350 BufferSize = LogoWidth * LogoHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
351\r
352 LogoBlt = AllocatePool (BufferSize);\r
353 if (LogoBlt == NULL) {\r
354 return EFI_OUT_OF_RESOURCES;\r
355 }\r
356\r
357 if (GraphicsOutput != NULL) {\r
358 Status = GraphicsOutput->Blt (\r
359 GraphicsOutput,\r
360 LogoBlt,\r
361 EfiBltVideoToBltBuffer,\r
362 LogoDestX,\r
363 LogoDestY,\r
364 0,\r
365 0,\r
366 LogoWidth,\r
367 LogoHeight,\r
368 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
369 );\r
370 } else {\r
371 Status = UgaDraw->Blt (\r
372 UgaDraw,\r
373 (EFI_UGA_PIXEL *) LogoBlt,\r
374 EfiUgaVideoToBltBuffer,\r
375 LogoDestX,\r
376 LogoDestY,\r
377 0,\r
378 0,\r
379 LogoWidth,\r
380 LogoHeight,\r
381 LogoWidth * sizeof (EFI_UGA_PIXEL)\r
382 );\r
383 }\r
384 }\r
385\r
386 if (!EFI_ERROR (Status)) {\r
387 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);\r
388 }\r
389 FreePool (LogoBlt);\r
390\r
391 return Status;\r
392}\r
393\r
394/**\r
395 Use SystemTable Conout to turn on video based Simple Text Out consoles. The \r
396 Simple Text Out screens will now be synced up with all non video output devices\r
397\r
398 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
399\r
400**/\r
401EFI_STATUS\r
402EFIAPI\r
403BootLogoDisableLogo (\r
404 VOID\r
405 )\r
406{\r
407\r
408 //\r
409 // Enable Cursor on Screen\r
410 //\r
411 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
412 return EFI_SUCCESS;\r
413}\r
414\r
415\r
416/**\r
417\r
418 Update progress bar with title above it. It only works in Graphics mode.\r
419\r
420 @param TitleForeground Foreground color for Title.\r
421 @param TitleBackground Background color for Title.\r
422 @param Title Title above progress bar.\r
423 @param ProgressColor Progress bar color.\r
424 @param Progress Progress (0-100)\r
425 @param PreviousValue The previous value of the progress.\r
426\r
427 @retval EFI_STATUS Success update the progress bar\r
428\r
429**/\r
430EFI_STATUS\r
431EFIAPI\r
432BootLogoUpdateProgress (\r
433 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
434 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
435 IN CHAR16 *Title,\r
436 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
437 IN UINTN Progress,\r
438 IN UINTN PreviousValue\r
439 )\r
440{\r
441 EFI_STATUS Status;\r
442 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
443 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
444 UINT32 SizeOfX;\r
445 UINT32 SizeOfY;\r
446 UINT32 ColorDepth;\r
447 UINT32 RefreshRate;\r
448 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
449 UINTN BlockHeight;\r
450 UINTN BlockWidth;\r
451 UINTN BlockNum;\r
452 UINTN PosX;\r
453 UINTN PosY;\r
454 UINTN Index;\r
455\r
456 if (Progress > 100) {\r
457 return EFI_INVALID_PARAMETER;\r
458 }\r
459\r
460 UgaDraw = NULL;\r
461 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
462 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
463 GraphicsOutput = NULL;\r
464\r
465 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
466 if (EFI_ERROR (Status)) {\r
467 UgaDraw = NULL;\r
468 }\r
469 }\r
470 if (EFI_ERROR (Status)) {\r
471 return EFI_UNSUPPORTED;\r
472 }\r
473\r
474 SizeOfX = 0;\r
475 SizeOfY = 0;\r
476 if (GraphicsOutput != NULL) {\r
477 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
478 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
479 } else if (UgaDraw != NULL) {\r
480 Status = UgaDraw->GetMode (\r
481 UgaDraw,\r
482 &SizeOfX,\r
483 &SizeOfY,\r
484 &ColorDepth,\r
485 &RefreshRate\r
486 );\r
487 if (EFI_ERROR (Status)) {\r
488 return EFI_UNSUPPORTED;\r
489 }\r
490 } else {\r
491 return EFI_UNSUPPORTED;\r
492 }\r
493\r
494 BlockWidth = SizeOfX / 100;\r
495 BlockHeight = SizeOfY / 50;\r
496\r
497 BlockNum = Progress;\r
498\r
499 PosX = 0;\r
500 PosY = SizeOfY * 48 / 50;\r
501\r
502 if (BlockNum == 0) {\r
503 //\r
504 // Clear progress area\r
505 //\r
506 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
507\r
508 if (GraphicsOutput != NULL) {\r
509 Status = GraphicsOutput->Blt (\r
510 GraphicsOutput,\r
511 &Color,\r
512 EfiBltVideoFill,\r
513 0,\r
514 0,\r
515 0,\r
516 PosY - EFI_GLYPH_HEIGHT - 1,\r
517 SizeOfX,\r
518 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
519 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
520 );\r
521 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
522 Status = UgaDraw->Blt (\r
523 UgaDraw,\r
524 (EFI_UGA_PIXEL *) &Color,\r
525 EfiUgaVideoFill,\r
526 0,\r
527 0,\r
528 0,\r
529 PosY - EFI_GLYPH_HEIGHT - 1,\r
530 SizeOfX,\r
531 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
532 SizeOfX * sizeof (EFI_UGA_PIXEL)\r
533 );\r
534 } else {\r
535 return EFI_UNSUPPORTED;\r
536 }\r
537 }\r
538 //\r
539 // Show progress by drawing blocks\r
540 //\r
541 for (Index = PreviousValue; Index < BlockNum; Index++) {\r
542 PosX = Index * BlockWidth;\r
543 if (GraphicsOutput != NULL) {\r
544 Status = GraphicsOutput->Blt (\r
545 GraphicsOutput,\r
546 &ProgressColor,\r
547 EfiBltVideoFill,\r
548 0,\r
549 0,\r
550 PosX,\r
551 PosY,\r
552 BlockWidth - 1,\r
553 BlockHeight,\r
554 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
555 );\r
556 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
557 Status = UgaDraw->Blt (\r
558 UgaDraw,\r
559 (EFI_UGA_PIXEL *) &ProgressColor,\r
560 EfiUgaVideoFill,\r
561 0,\r
562 0,\r
563 PosX,\r
564 PosY,\r
565 BlockWidth - 1,\r
566 BlockHeight,\r
567 (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
568 );\r
569 } else {\r
570 return EFI_UNSUPPORTED;\r
571 }\r
572 }\r
573\r
574 PrintXY (\r
575 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
576 PosY - EFI_GLYPH_HEIGHT - 1,\r
577 &TitleForeground,\r
578 &TitleBackground,\r
579 Title\r
580 );\r
581\r
582 return EFI_SUCCESS;\r
583}\r