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
)) {
86 if (EFI_ERROR (Status
)) {
87 return EFI_UNSUPPORTED
;
91 // Try to open Boot Logo Protocol.
93 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
94 if (EFI_ERROR (Status
)) {
99 // Try to open Boot Logo 2 Protocol.
101 Status
= gBS
->LocateProtocol (&gEdkiiBootLogo2ProtocolGuid
, NULL
, (VOID
**) &BootLogo2
);
102 if (EFI_ERROR (Status
)) {
107 // Erase Cursor from screen
109 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
111 if (GraphicsOutput
!= NULL
) {
112 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
113 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
)) {
156 // Calculate the display position according to Attribute.
159 case EdkiiPlatformLogoDisplayAttributeLeftTop
:
163 case EdkiiPlatformLogoDisplayAttributeCenterTop
:
164 DestX
= (SizeOfX
- Image
.Width
) / 2;
167 case EdkiiPlatformLogoDisplayAttributeRightTop
:
168 DestX
= SizeOfX
- Image
.Width
;
172 case EdkiiPlatformLogoDisplayAttributeCenterLeft
:
174 DestY
= (SizeOfY
- Image
.Height
) / 2;
176 case EdkiiPlatformLogoDisplayAttributeCenter
:
177 DestX
= (SizeOfX
- Image
.Width
) / 2;
178 DestY
= (SizeOfY
- Image
.Height
) / 2;
180 case EdkiiPlatformLogoDisplayAttributeCenterRight
:
181 DestX
= SizeOfX
- Image
.Width
;
182 DestY
= (SizeOfY
- Image
.Height
) / 2;
185 case EdkiiPlatformLogoDisplayAttributeLeftBottom
:
187 DestY
= SizeOfY
- Image
.Height
;
189 case EdkiiPlatformLogoDisplayAttributeCenterBottom
:
190 DestX
= (SizeOfX
- Image
.Width
) / 2;
191 DestY
= SizeOfY
- Image
.Height
;
193 case EdkiiPlatformLogoDisplayAttributeRightBottom
:
194 DestX
= SizeOfX
- Image
.Width
;
195 DestY
= SizeOfY
- Image
.Height
;
207 if ((DestX
>= 0) && (DestY
>= 0)) {
208 if (GraphicsOutput
!= NULL
) {
209 Status
= GraphicsOutput
->Blt (
219 Image
.Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
222 ASSERT (UgaDraw
!= NULL
);
223 Status
= UgaDraw
->Blt (
225 (EFI_UGA_PIXEL
*) Blt
,
226 EfiUgaBltBufferToVideo
,
233 Image
.Width
* sizeof (EFI_UGA_PIXEL
)
238 // Report displayed Logo information.
240 if (!EFI_ERROR (Status
)) {
243 if (NumberOfLogos
== 1) {
247 LogoDestX
= (UINTN
) DestX
;
248 LogoDestY
= (UINTN
) DestY
;
249 LogoWidth
= Image
.Width
;
250 LogoHeight
= Image
.Height
;
253 // Merge new logo with old one.
255 NewDestX
= MIN ((UINTN
) DestX
, LogoDestX
);
256 NewDestY
= MIN ((UINTN
) DestY
, LogoDestY
);
257 LogoWidth
= MAX ((UINTN
) DestX
+ Image
.Width
, LogoDestX
+ LogoWidth
) - NewDestX
;
258 LogoHeight
= MAX ((UINTN
) DestY
+ Image
.Height
, LogoDestY
+ LogoHeight
) - NewDestY
;
260 LogoDestX
= NewDestX
;
261 LogoDestY
= NewDestY
;
267 if ((BootLogo
== NULL
&& BootLogo2
== NULL
) || NumberOfLogos
== 0) {
269 // No logo displayed.
279 // Advertise displayed Logo information.
281 if (NumberOfLogos
== 1) {
283 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
286 Status
= EFI_SUCCESS
;
289 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
296 // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
298 if (LogoHeight
> MAX_UINTN
/ LogoWidth
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
299 return EFI_UNSUPPORTED
;
301 BufferSize
= LogoWidth
* LogoHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
303 LogoBlt
= AllocatePool (BufferSize
);
304 if (LogoBlt
== NULL
) {
305 return EFI_OUT_OF_RESOURCES
;
308 if (GraphicsOutput
!= NULL
) {
309 Status
= GraphicsOutput
->Blt (
312 EfiBltVideoToBltBuffer
,
319 LogoWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
322 Status
= UgaDraw
->Blt (
324 (EFI_UGA_PIXEL
*) LogoBlt
,
325 EfiUgaVideoToBltBuffer
,
332 LogoWidth
* sizeof (EFI_UGA_PIXEL
)
337 if (!EFI_ERROR (Status
)) {
339 // Attempt to register logo with Boot Logo 2 Protocol first
341 if (BootLogo2
!= NULL
) {
342 Status
= BootLogo2
->SetBootLogo (BootLogo2
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
345 // If Boot Logo 2 Protocol is not available or registration with Boot Logo 2
346 // Protocol failed, then attempt to register logo with Boot Logo Protocol
348 if (EFI_ERROR (Status
) && BootLogo
!= NULL
) {
349 Status
= BootLogo
->SetBootLogo (BootLogo
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
352 // Status of this function is EFI_SUCCESS even if registration with Boot
353 // Logo 2 Protocol or Boot Logo Protocol fails.
355 Status
= EFI_SUCCESS
;
363 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
364 Simple Text Out screens will now be synced up with all non video output devices
366 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
371 BootLogoDisableLogo (
377 // Enable Cursor on Screen
379 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
386 Update progress bar with title above it. It only works in Graphics mode.
388 @param TitleForeground Foreground color for Title.
389 @param TitleBackground Background color for Title.
390 @param Title Title above progress bar.
391 @param ProgressColor Progress bar color.
392 @param Progress Progress (0-100)
393 @param PreviousValue The previous value of the progress.
395 @retval EFI_STATUS Success update the progress bar
400 BootLogoUpdateProgress (
401 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground
,
402 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground
,
404 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor
,
406 IN UINTN PreviousValue
410 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
411 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
416 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color
;
424 if (Progress
> 100) {
425 return EFI_INVALID_PARAMETER
;
429 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
430 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
431 GraphicsOutput
= NULL
;
433 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
434 if (EFI_ERROR (Status
)) {
438 if (EFI_ERROR (Status
)) {
439 return EFI_UNSUPPORTED
;
444 if (GraphicsOutput
!= NULL
) {
445 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
446 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
447 } else if (UgaDraw
!= NULL
) {
448 Status
= UgaDraw
->GetMode (
455 if (EFI_ERROR (Status
)) {
456 return EFI_UNSUPPORTED
;
459 return EFI_UNSUPPORTED
;
462 BlockWidth
= SizeOfX
/ 100;
463 BlockHeight
= SizeOfY
/ 50;
468 PosY
= SizeOfY
* 48 / 50;
472 // Clear progress area
474 SetMem (&Color
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0x0);
476 if (GraphicsOutput
!= NULL
) {
477 Status
= GraphicsOutput
->Blt (
484 PosY
- EFI_GLYPH_HEIGHT
- 1,
486 SizeOfY
- (PosY
- EFI_GLYPH_HEIGHT
- 1),
487 SizeOfX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
489 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
490 Status
= UgaDraw
->Blt (
492 (EFI_UGA_PIXEL
*) &Color
,
497 PosY
- EFI_GLYPH_HEIGHT
- 1,
499 SizeOfY
- (PosY
- EFI_GLYPH_HEIGHT
- 1),
500 SizeOfX
* sizeof (EFI_UGA_PIXEL
)
503 return EFI_UNSUPPORTED
;
507 // Show progress by drawing blocks
509 for (Index
= PreviousValue
; Index
< BlockNum
; Index
++) {
510 PosX
= Index
* BlockWidth
;
511 if (GraphicsOutput
!= NULL
) {
512 Status
= GraphicsOutput
->Blt (
522 (BlockWidth
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
524 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
525 Status
= UgaDraw
->Blt (
527 (EFI_UGA_PIXEL
*) &ProgressColor
,
535 (BlockWidth
) * sizeof (EFI_UGA_PIXEL
)
538 return EFI_UNSUPPORTED
;
543 (SizeOfX
- StrLen (Title
) * EFI_GLYPH_WIDTH
) / 2,
544 PosY
- EFI_GLYPH_HEIGHT
- 1,