2 This library is only intended to be used by PlatformBootManagerLib
3 to show progress bar and LOGO.
5 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 Copyright (c) 2016, Microsoft Corporation<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Protocol/GraphicsOutput.h>
13 #include <Protocol/SimpleTextOut.h>
14 #include <Protocol/PlatformLogo.h>
15 #include <Protocol/UgaDraw.h>
16 #include <Protocol/BootLogo.h>
17 #include <Protocol/BootLogo2.h>
18 #include <Library/BaseLib.h>
19 #include <Library/UefiLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/DebugLib.h>
27 Show LOGO returned from Edkii Platform Logo protocol on all consoles.
29 @retval EFI_SUCCESS Logo was displayed.
30 @retval EFI_UNSUPPORTED Logo was not found or cannot be displayed.
39 EDKII_PLATFORM_LOGO_PROTOCOL
*PlatformLogo
;
40 EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute
;
48 EFI_IMAGE_INPUT Image
;
49 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
50 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
53 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
54 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
55 EDKII_BOOT_LOGO2_PROTOCOL
*BootLogo2
;
57 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LogoBlt
;
66 Status
= gBS
->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid
, NULL
, (VOID
**)&PlatformLogo
);
67 if (EFI_ERROR (Status
)) {
68 return EFI_UNSUPPORTED
;
73 // Try to open GOP first
75 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
76 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
77 GraphicsOutput
= NULL
;
79 // Open GOP failed, try to open UGA
81 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**)&UgaDraw
);
82 if (EFI_ERROR (Status
)) {
87 if (EFI_ERROR (Status
)) {
88 return EFI_UNSUPPORTED
;
92 // Try to open Boot Logo Protocol.
94 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**)&BootLogo
);
95 if (EFI_ERROR (Status
)) {
100 // Try to open Boot Logo 2 Protocol.
102 Status
= gBS
->LocateProtocol (&gEdkiiBootLogo2ProtocolGuid
, NULL
, (VOID
**)&BootLogo2
);
103 if (EFI_ERROR (Status
)) {
108 // Erase Cursor from screen
110 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
112 if (GraphicsOutput
!= NULL
) {
113 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
114 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
116 ASSERT (UgaDraw
!= NULL
);
117 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
118 if (EFI_ERROR (Status
)) {
119 return EFI_UNSUPPORTED
;
136 // Get image from PlatformLogo protocol.
138 Status
= PlatformLogo
->GetImage (
146 if (EFI_ERROR (Status
)) {
157 // Calculate the display position according to Attribute.
160 case EdkiiPlatformLogoDisplayAttributeLeftTop
:
164 case EdkiiPlatformLogoDisplayAttributeCenterTop
:
165 DestX
= (SizeOfX
- Image
.Width
) / 2;
168 case EdkiiPlatformLogoDisplayAttributeRightTop
:
169 DestX
= SizeOfX
- Image
.Width
;
173 case EdkiiPlatformLogoDisplayAttributeCenterLeft
:
175 DestY
= (SizeOfY
- Image
.Height
) / 2;
177 case EdkiiPlatformLogoDisplayAttributeCenter
:
178 DestX
= (SizeOfX
- Image
.Width
) / 2;
179 DestY
= (SizeOfY
- Image
.Height
) / 2;
181 case EdkiiPlatformLogoDisplayAttributeCenterRight
:
182 DestX
= SizeOfX
- Image
.Width
;
183 DestY
= (SizeOfY
- Image
.Height
) / 2;
186 case EdkiiPlatformLogoDisplayAttributeLeftBottom
:
188 DestY
= SizeOfY
- Image
.Height
;
190 case EdkiiPlatformLogoDisplayAttributeCenterBottom
:
191 DestX
= (SizeOfX
- Image
.Width
) / 2;
192 DestY
= SizeOfY
- Image
.Height
;
194 case EdkiiPlatformLogoDisplayAttributeRightBottom
:
195 DestX
= SizeOfX
- Image
.Width
;
196 DestY
= SizeOfY
- Image
.Height
;
208 if ((DestX
>= 0) && (DestY
>= 0)) {
209 if (GraphicsOutput
!= NULL
) {
210 Status
= GraphicsOutput
->Blt (
220 Image
.Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
223 ASSERT (UgaDraw
!= NULL
);
224 Status
= UgaDraw
->Blt (
226 (EFI_UGA_PIXEL
*)Blt
,
227 EfiUgaBltBufferToVideo
,
234 Image
.Width
* sizeof (EFI_UGA_PIXEL
)
239 // Report displayed Logo information.
241 if (!EFI_ERROR (Status
)) {
244 if (NumberOfLogos
== 1) {
248 LogoDestX
= (UINTN
)DestX
;
249 LogoDestY
= (UINTN
)DestY
;
250 LogoWidth
= Image
.Width
;
251 LogoHeight
= Image
.Height
;
254 // Merge new logo with old one.
256 NewDestX
= MIN ((UINTN
)DestX
, LogoDestX
);
257 NewDestY
= MIN ((UINTN
)DestY
, LogoDestY
);
258 LogoWidth
= MAX ((UINTN
)DestX
+ Image
.Width
, LogoDestX
+ LogoWidth
) - NewDestX
;
259 LogoHeight
= MAX ((UINTN
)DestY
+ Image
.Height
, LogoDestY
+ LogoHeight
) - NewDestY
;
261 LogoDestX
= NewDestX
;
262 LogoDestY
= NewDestY
;
268 if (((BootLogo
== NULL
) && (BootLogo2
== NULL
)) || (NumberOfLogos
== 0)) {
270 // No logo displayed.
280 // Advertise displayed Logo information.
282 if (NumberOfLogos
== 1) {
284 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
287 Status
= EFI_SUCCESS
;
290 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
297 // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
299 if (LogoHeight
> MAX_UINTN
/ LogoWidth
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
300 return EFI_UNSUPPORTED
;
303 BufferSize
= LogoWidth
* LogoHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
305 LogoBlt
= AllocatePool (BufferSize
);
306 if (LogoBlt
== NULL
) {
307 return EFI_OUT_OF_RESOURCES
;
310 if (GraphicsOutput
!= NULL
) {
311 Status
= GraphicsOutput
->Blt (
314 EfiBltVideoToBltBuffer
,
321 LogoWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
324 Status
= UgaDraw
->Blt (
326 (EFI_UGA_PIXEL
*)LogoBlt
,
327 EfiUgaVideoToBltBuffer
,
334 LogoWidth
* sizeof (EFI_UGA_PIXEL
)
339 if (!EFI_ERROR (Status
)) {
341 // Attempt to register logo with Boot Logo 2 Protocol first
343 if (BootLogo2
!= NULL
) {
344 Status
= BootLogo2
->SetBootLogo (BootLogo2
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
348 // If Boot Logo 2 Protocol is not available or registration with Boot Logo 2
349 // Protocol failed, then attempt to register logo with Boot Logo Protocol
351 if (EFI_ERROR (Status
) && (BootLogo
!= NULL
)) {
352 Status
= BootLogo
->SetBootLogo (BootLogo
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
356 // Status of this function is EFI_SUCCESS even if registration with Boot
357 // Logo 2 Protocol or Boot Logo Protocol fails.
359 Status
= EFI_SUCCESS
;
368 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
369 Simple Text Out screens will now be synced up with all non video output devices
371 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
376 BootLogoDisableLogo (
381 // Enable Cursor on Screen
383 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
389 Update progress bar with title above it. It only works in Graphics mode.
391 @param TitleForeground Foreground color for Title.
392 @param TitleBackground Background color for Title.
393 @param Title Title above progress bar.
394 @param ProgressColor Progress bar color.
395 @param Progress Progress (0-100)
396 @param PreviousValue The previous value of the progress.
398 @retval EFI_STATUS Success update the progress bar
403 BootLogoUpdateProgress (
404 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground
,
405 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground
,
407 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor
,
409 IN UINTN PreviousValue
413 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
414 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
419 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color
;
427 if (Progress
> 100) {
428 return EFI_INVALID_PARAMETER
;
432 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
433 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
434 GraphicsOutput
= NULL
;
436 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**)&UgaDraw
);
437 if (EFI_ERROR (Status
)) {
442 if (EFI_ERROR (Status
)) {
443 return EFI_UNSUPPORTED
;
448 if (GraphicsOutput
!= NULL
) {
449 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
450 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
451 } else if (UgaDraw
!= NULL
) {
452 Status
= UgaDraw
->GetMode (
459 if (EFI_ERROR (Status
)) {
460 return EFI_UNSUPPORTED
;
463 return EFI_UNSUPPORTED
;
466 BlockWidth
= SizeOfX
/ 100;
467 BlockHeight
= SizeOfY
/ 50;
472 PosY
= SizeOfY
* 48 / 50;
476 // Clear progress area
478 SetMem (&Color
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0x0);
480 if (GraphicsOutput
!= NULL
) {
481 Status
= GraphicsOutput
->Blt (
488 PosY
- EFI_GLYPH_HEIGHT
- 1,
490 SizeOfY
- (PosY
- EFI_GLYPH_HEIGHT
- 1),
491 SizeOfX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
493 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
494 Status
= UgaDraw
->Blt (
496 (EFI_UGA_PIXEL
*)&Color
,
501 PosY
- EFI_GLYPH_HEIGHT
- 1,
503 SizeOfY
- (PosY
- EFI_GLYPH_HEIGHT
- 1),
504 SizeOfX
* sizeof (EFI_UGA_PIXEL
)
507 return EFI_UNSUPPORTED
;
512 // Show progress by drawing blocks
514 for (Index
= PreviousValue
; Index
< BlockNum
; Index
++) {
515 PosX
= Index
* BlockWidth
;
516 if (GraphicsOutput
!= NULL
) {
517 Status
= GraphicsOutput
->Blt (
527 (BlockWidth
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
529 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
530 Status
= UgaDraw
->Blt (
532 (EFI_UGA_PIXEL
*)&ProgressColor
,
540 (BlockWidth
) * sizeof (EFI_UGA_PIXEL
)
543 return EFI_UNSUPPORTED
;
548 (SizeOfX
- StrLen (Title
) * EFI_GLYPH_WIDTH
) / 2,
549 PosY
- EFI_GLYPH_HEIGHT
- 1,