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 This program and the accompanying materials are licensed and made available under
8 the terms and conditions of the BSD License that accompanies this distribution.
9 The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Protocol/GraphicsOutput.h>
19 #include <Protocol/SimpleTextOut.h>
20 #include <Protocol/PlatformLogo.h>
21 #include <Protocol/UgaDraw.h>
22 #include <Protocol/BootLogo.h>
23 #include <Protocol/BootLogo2.h>
24 #include <Library/BaseLib.h>
25 #include <Library/UefiLib.h>
26 #include <Library/BaseMemoryLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/PcdLib.h>
29 #include <Library/MemoryAllocationLib.h>
30 #include <Library/DebugLib.h>
33 Show LOGO returned from Edkii Platform Logo protocol on all consoles.
35 @retval EFI_SUCCESS Logo was displayed.
36 @retval EFI_UNSUPPORTED Logo was not found or cannot be displayed.
45 EDKII_PLATFORM_LOGO_PROTOCOL
*PlatformLogo
;
46 EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute
;
54 EFI_IMAGE_INPUT Image
;
55 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
56 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
59 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
60 EFI_BOOT_LOGO_PROTOCOL
*BootLogo
;
61 EDKII_BOOT_LOGO2_PROTOCOL
*BootLogo2
;
63 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LogoBlt
;
72 Status
= gBS
->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid
, NULL
, (VOID
**) &PlatformLogo
);
73 if (EFI_ERROR (Status
)) {
74 return EFI_UNSUPPORTED
;
79 // Try to open GOP first
81 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
82 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
83 GraphicsOutput
= NULL
;
85 // Open GOP failed, try to open UGA
87 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
88 if (EFI_ERROR (Status
)) {
92 if (EFI_ERROR (Status
)) {
93 return EFI_UNSUPPORTED
;
97 // Try to open Boot Logo Protocol.
99 Status
= gBS
->LocateProtocol (&gEfiBootLogoProtocolGuid
, NULL
, (VOID
**) &BootLogo
);
100 if (EFI_ERROR (Status
)) {
105 // Try to open Boot Logo 2 Protocol.
107 Status
= gBS
->LocateProtocol (&gEdkiiBootLogo2ProtocolGuid
, NULL
, (VOID
**) &BootLogo2
);
108 if (EFI_ERROR (Status
)) {
113 // Erase Cursor from screen
115 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
117 if (GraphicsOutput
!= NULL
) {
118 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
119 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
122 ASSERT (UgaDraw
!= NULL
);
123 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
124 if (EFI_ERROR (Status
)) {
125 return EFI_UNSUPPORTED
;
142 // Get image from PlatformLogo protocol.
144 Status
= PlatformLogo
->GetImage (
152 if (EFI_ERROR (Status
)) {
162 // Calculate the display position according to Attribute.
165 case EdkiiPlatformLogoDisplayAttributeLeftTop
:
169 case EdkiiPlatformLogoDisplayAttributeCenterTop
:
170 DestX
= (SizeOfX
- Image
.Width
) / 2;
173 case EdkiiPlatformLogoDisplayAttributeRightTop
:
174 DestX
= SizeOfX
- Image
.Width
;
178 case EdkiiPlatformLogoDisplayAttributeCenterLeft
:
180 DestY
= (SizeOfY
- Image
.Height
) / 2;
182 case EdkiiPlatformLogoDisplayAttributeCenter
:
183 DestX
= (SizeOfX
- Image
.Width
) / 2;
184 DestY
= (SizeOfY
- Image
.Height
) / 2;
186 case EdkiiPlatformLogoDisplayAttributeCenterRight
:
187 DestX
= SizeOfX
- Image
.Width
;
188 DestY
= (SizeOfY
- Image
.Height
) / 2;
191 case EdkiiPlatformLogoDisplayAttributeLeftBottom
:
193 DestY
= SizeOfY
- Image
.Height
;
195 case EdkiiPlatformLogoDisplayAttributeCenterBottom
:
196 DestX
= (SizeOfX
- Image
.Width
) / 2;
197 DestY
= SizeOfY
- Image
.Height
;
199 case EdkiiPlatformLogoDisplayAttributeRightBottom
:
200 DestX
= SizeOfX
- Image
.Width
;
201 DestY
= SizeOfY
- Image
.Height
;
213 if ((DestX
>= 0) && (DestY
>= 0)) {
214 if (GraphicsOutput
!= NULL
) {
215 Status
= GraphicsOutput
->Blt (
225 Image
.Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
228 ASSERT (UgaDraw
!= NULL
);
229 Status
= UgaDraw
->Blt (
231 (EFI_UGA_PIXEL
*) Blt
,
232 EfiUgaBltBufferToVideo
,
239 Image
.Width
* sizeof (EFI_UGA_PIXEL
)
244 // Report displayed Logo information.
246 if (!EFI_ERROR (Status
)) {
249 if (NumberOfLogos
== 1) {
253 LogoDestX
= (UINTN
) DestX
;
254 LogoDestY
= (UINTN
) DestY
;
255 LogoWidth
= Image
.Width
;
256 LogoHeight
= Image
.Height
;
259 // Merge new logo with old one.
261 NewDestX
= MIN ((UINTN
) DestX
, LogoDestX
);
262 NewDestY
= MIN ((UINTN
) DestY
, LogoDestY
);
263 LogoWidth
= MAX ((UINTN
) DestX
+ Image
.Width
, LogoDestX
+ LogoWidth
) - NewDestX
;
264 LogoHeight
= MAX ((UINTN
) DestY
+ Image
.Height
, LogoDestY
+ LogoHeight
) - NewDestY
;
266 LogoDestX
= NewDestX
;
267 LogoDestY
= NewDestY
;
273 if ((BootLogo
== NULL
&& BootLogo2
== NULL
) || NumberOfLogos
== 0) {
275 // No logo displayed.
285 // Advertise displayed Logo information.
287 if (NumberOfLogos
== 1) {
289 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
292 Status
= EFI_SUCCESS
;
295 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
302 // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
304 if (LogoHeight
> MAX_UINTN
/ LogoWidth
/ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)) {
305 return EFI_UNSUPPORTED
;
307 BufferSize
= LogoWidth
* LogoHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
309 LogoBlt
= AllocatePool (BufferSize
);
310 if (LogoBlt
== NULL
) {
311 return EFI_OUT_OF_RESOURCES
;
314 if (GraphicsOutput
!= NULL
) {
315 Status
= GraphicsOutput
->Blt (
318 EfiBltVideoToBltBuffer
,
325 LogoWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
328 Status
= UgaDraw
->Blt (
330 (EFI_UGA_PIXEL
*) LogoBlt
,
331 EfiUgaVideoToBltBuffer
,
338 LogoWidth
* sizeof (EFI_UGA_PIXEL
)
343 if (!EFI_ERROR (Status
)) {
345 // Attempt to register logo with Boot Logo 2 Protocol first
347 if (BootLogo2
!= NULL
) {
348 Status
= BootLogo2
->SetBootLogo (BootLogo2
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
351 // If Boot Logo 2 Protocol is not available or registration with Boot Logo 2
352 // Protocol failed, then attempt to register logo with Boot Logo Protocol
354 if (EFI_ERROR (Status
) && BootLogo
!= NULL
) {
355 Status
= BootLogo
->SetBootLogo (BootLogo
, LogoBlt
, LogoDestX
, LogoDestY
, LogoWidth
, LogoHeight
);
358 // Status of this function is EFI_SUCCESS even if registration with Boot
359 // Logo 2 Protocol or Boot Logo Protocol fails.
361 Status
= EFI_SUCCESS
;
369 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
370 Simple Text Out screens will now be synced up with all non video output devices
372 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
377 BootLogoDisableLogo (
383 // Enable Cursor on Screen
385 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
392 Update progress bar with title above it. It only works in Graphics mode.
394 @param TitleForeground Foreground color for Title.
395 @param TitleBackground Background color for Title.
396 @param Title Title above progress bar.
397 @param ProgressColor Progress bar color.
398 @param Progress Progress (0-100)
399 @param PreviousValue The previous value of the progress.
401 @retval EFI_STATUS Success update the progress bar
406 BootLogoUpdateProgress (
407 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground
,
408 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground
,
410 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor
,
412 IN UINTN PreviousValue
416 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
417 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
422 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color
;
430 if (Progress
> 100) {
431 return EFI_INVALID_PARAMETER
;
435 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
436 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
437 GraphicsOutput
= NULL
;
439 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
440 if (EFI_ERROR (Status
)) {
444 if (EFI_ERROR (Status
)) {
445 return EFI_UNSUPPORTED
;
450 if (GraphicsOutput
!= NULL
) {
451 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
452 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
453 } else if (UgaDraw
!= NULL
) {
454 Status
= UgaDraw
->GetMode (
461 if (EFI_ERROR (Status
)) {
462 return EFI_UNSUPPORTED
;
465 return EFI_UNSUPPORTED
;
468 BlockWidth
= SizeOfX
/ 100;
469 BlockHeight
= SizeOfY
/ 50;
474 PosY
= SizeOfY
* 48 / 50;
478 // Clear progress area
480 SetMem (&Color
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0x0);
482 if (GraphicsOutput
!= NULL
) {
483 Status
= GraphicsOutput
->Blt (
490 PosY
- EFI_GLYPH_HEIGHT
- 1,
492 SizeOfY
- (PosY
- EFI_GLYPH_HEIGHT
- 1),
493 SizeOfX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
495 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
496 Status
= UgaDraw
->Blt (
498 (EFI_UGA_PIXEL
*) &Color
,
503 PosY
- EFI_GLYPH_HEIGHT
- 1,
505 SizeOfY
- (PosY
- EFI_GLYPH_HEIGHT
- 1),
506 SizeOfX
* sizeof (EFI_UGA_PIXEL
)
509 return EFI_UNSUPPORTED
;
513 // Show progress by drawing blocks
515 for (Index
= PreviousValue
; Index
< BlockNum
; Index
++) {
516 PosX
= Index
* BlockWidth
;
517 if (GraphicsOutput
!= NULL
) {
518 Status
= GraphicsOutput
->Blt (
528 (BlockWidth
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
530 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
531 Status
= UgaDraw
->Blt (
533 (EFI_UGA_PIXEL
*) &ProgressColor
,
541 (BlockWidth
) * sizeof (EFI_UGA_PIXEL
)
544 return EFI_UNSUPPORTED
;
549 (SizeOfX
- StrLen (Title
) * EFI_GLYPH_WIDTH
) / 2,
550 PosY
- EFI_GLYPH_HEIGHT
- 1,