2 Library supports diplaying graphical splash screen,
3 locking of keyboard input and printing character on
4 screen. These basic graphics operations are based on UEFI HII,
5 Graphics Output protocol or UGA Draw protocol.
7 BugBug: Currently *.BMP files are supported. This will be replaced
8 when Tiano graphics format is supported.
11 Copyright (c) 2006, Intel Corporation
12 All rights reserved. This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 #include <Protocol/SimpleTextOut.h>
26 #include <Protocol/OEMBadging.h>
27 #include <Protocol/ConsoleControl.h>
28 #include <Protocol/GraphicsOutput.h>
29 #include <Protocol/FirmwareVolume2.h>
30 #include <Protocol/UgaDraw.h>
31 #include <Protocol/FrameworkHii.h>
35 #include <Library/GraphicsLib.h>
36 #include <Library/PrintLib.h>
37 #include <Library/BaseLib.h>
38 #include <Library/MemoryAllocationLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
40 #include <Library/DebugLib.h>
41 #include <Library/PcdLib.h>
44 Return the graphics image file named FileNameGuid into Image and return it's
45 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
48 @param FileNameGuid - File Name of graphics file in the FV(s).
50 @param Image - Pointer to pointer to return graphics image. If NULL, a
51 buffer will be allocated.
53 @param ImageSize - Size of the graphics Image in bytes. Zero if no image found.
55 @retval EFI_SUCCESS - Image and ImageSize are valid.
56 @retval EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
57 @retval EFI_NOT_FOUND - FileNameGuid not found
62 GetGraphicsBitMapFromFV (
63 IN EFI_GUID
*FileNameGuid
,
69 UINTN FvProtocolCount
;
70 EFI_HANDLE
*FvHandles
;
71 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
73 UINT32 AuthenticationStatus
;
76 Status
= gBS
->LocateHandleBuffer (
78 &gEfiFirmwareVolume2ProtocolGuid
,
83 if (EFI_ERROR (Status
)) {
87 for (Index
= 0; Index
< FvProtocolCount
; Index
++) {
88 Status
= gBS
->HandleProtocol (
90 &gEfiFirmwareVolume2ProtocolGuid
,
95 // Assuming Image and ImageSize are correct on input.
97 Status
= Fv
->ReadSection (
104 &AuthenticationStatus
106 if (!EFI_ERROR (Status
)) {
108 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
110 // ImageSize updated to needed size so return
112 return EFI_BUFFER_TOO_SMALL
;
116 return EFI_NOT_FOUND
;
120 Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
121 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
122 buffer is passed in it will be used if it is big enough.
124 @param BmpImage - Pointer to BMP file
126 @param BmpImageSize - Number of bytes in BmpImage
128 @param GopBlt - Buffer containing GOP version of BmpImage.
130 @param GopBltSize - Size of GopBlt in bytes.
132 @param PixelHeight - Height of GopBlt/BmpImage in pixels
134 @param PixelWidth - Width of GopBlt/BmpImage in pixels
137 @retval EFI_SUCCESS - GopBlt and GopBltSize are returned.
138 @retval EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image
139 @retval EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.
140 GopBltSize will contain the required size.
141 @retval EFI_OUT_OF_RESOURCES - No enough buffer to allocate
148 IN UINTN BmpImageSize
,
149 IN OUT VOID
**GopBlt
,
150 IN OUT UINTN
*GopBltSize
,
151 OUT UINTN
*PixelHeight
,
152 OUT UINTN
*PixelWidth
158 BMP_IMAGE_HEADER
*BmpHeader
;
159 BMP_COLOR_MAP
*BmpColorMap
;
160 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
161 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
169 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
170 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
171 return EFI_UNSUPPORTED
;
174 if (BmpHeader
->CompressionType
!= 0) {
175 return EFI_UNSUPPORTED
;
179 // Calculate Color Map offset in the image.
182 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
185 // Calculate graphics image data address in the image
187 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
190 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
192 if (*GopBlt
== NULL
) {
193 *GopBltSize
= BltBufferSize
;
194 *GopBlt
= AllocatePool (*GopBltSize
);
196 if (*GopBlt
== NULL
) {
197 return EFI_OUT_OF_RESOURCES
;
200 if (*GopBltSize
< BltBufferSize
) {
201 *GopBltSize
= BltBufferSize
;
202 return EFI_BUFFER_TOO_SMALL
;
206 *PixelWidth
= BmpHeader
->PixelWidth
;
207 *PixelHeight
= BmpHeader
->PixelHeight
;
210 // Convert image from BMP to Blt buffer format
213 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
214 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
215 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
216 switch (BmpHeader
->BitPerPixel
) {
219 // Convert 1bit BMP to 24-bit color
221 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
222 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
223 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
224 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
235 // Convert BMP Palette to 24-bit color
237 Index
= (*Image
) >> 4;
238 Blt
->Red
= BmpColorMap
[Index
].Red
;
239 Blt
->Green
= BmpColorMap
[Index
].Green
;
240 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
241 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
244 Index
= (*Image
) & 0x0f;
245 Blt
->Red
= BmpColorMap
[Index
].Red
;
246 Blt
->Green
= BmpColorMap
[Index
].Green
;
247 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
253 // Convert BMP Palette to 24-bit color
255 Blt
->Red
= BmpColorMap
[*Image
].Red
;
256 Blt
->Green
= BmpColorMap
[*Image
].Green
;
257 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
261 Blt
->Blue
= *Image
++;
262 Blt
->Green
= *Image
++;
268 gBS
->FreePool (*GopBlt
);
271 return EFI_UNSUPPORTED
;
277 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
278 if ((ImageIndex
% 4) != 0) {
280 // Bmp Image starts each row on a 32-bit boundary!
282 Image
= Image
+ (4 - (ImageIndex
% 4));
290 Use Console Control Protocol to lock the Console In Spliter virtual handle.
291 This is the ConInHandle and ConIn handle in the EFI system table. All key
292 presses will be ignored until the Password is typed in. The only way to
293 disable the password is to type it in to a ConIn device.
295 @param Password - Password used to lock ConIn device
297 @retval EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
299 @retval EFI_UNSUPPORTED - Logo not found
308 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
310 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
311 if (EFI_ERROR (Status
)) {
312 return EFI_UNSUPPORTED
;
315 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
320 Use Console Control to turn off UGA based Simple Text Out consoles from going
321 to the UGA device. Put up LogoFile on every UGA device that is a console
323 @param LogoFile - File name of logo to display on the center of the screen.
325 @retval EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
327 @retval EFI_UNSUPPORTED - Logo not found
332 IN EFI_GUID
*LogoFile
337 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
338 EFI_OEM_BADGING_PROTOCOL
*Badging
;
347 EFI_BADGING_FORMAT Format
;
348 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
353 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
354 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
357 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
359 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
360 if (EFI_ERROR (Status
)) {
361 return EFI_UNSUPPORTED
;
366 // Try to open GOP first
368 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
369 if (EFI_ERROR(Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
370 GraphicsOutput
= NULL
;
372 // Open GOP failed, try to open UGA
374 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
376 if (EFI_ERROR (Status
)) {
377 return EFI_UNSUPPORTED
;
381 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
383 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
385 if (GraphicsOutput
!= NULL
) {
386 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
387 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
388 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
389 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
390 if (EFI_ERROR (Status
)) {
391 return EFI_UNSUPPORTED
;
394 return EFI_UNSUPPORTED
;
402 if (Badging
!= NULL
) {
403 Status
= Badging
->GetImage (
413 if (EFI_ERROR (Status
)) {
418 // Currently only support BMP format
420 if (Format
!= EfiBadgingFormatBMP
) {
421 gBS
->FreePool (ImageData
);
425 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
426 if (EFI_ERROR (Status
)) {
427 return EFI_UNSUPPORTED
;
432 Attribute
= EfiBadgingDisplayAttributeCenter
;
437 Status
= ConvertBmpToGopBlt (
445 if (EFI_ERROR (Status
)) {
446 gBS
->FreePool (ImageData
);
447 if (Badging
== NULL
) {
455 case EfiBadgingDisplayAttributeLeftTop
:
460 case EfiBadgingDisplayAttributeCenterTop
:
461 DestX
= (SizeOfX
- Width
) / 2;
465 case EfiBadgingDisplayAttributeRightTop
:
466 DestX
= (SizeOfX
- Width
- CoordinateX
);
467 DestY
= CoordinateY
;;
470 case EfiBadgingDisplayAttributeCenterRight
:
471 DestX
= (SizeOfX
- Width
- CoordinateX
);
472 DestY
= (SizeOfY
- Height
) / 2;
475 case EfiBadgingDisplayAttributeRightBottom
:
476 DestX
= (SizeOfX
- Width
- CoordinateX
);
477 DestY
= (SizeOfY
- Height
- CoordinateY
);
480 case EfiBadgingDisplayAttributeCenterBottom
:
481 DestX
= (SizeOfX
- Width
) / 2;
482 DestY
= (SizeOfY
- Height
- CoordinateY
);
485 case EfiBadgingDisplayAttributeLeftBottom
:
487 DestY
= (SizeOfY
- Height
- CoordinateY
);
490 case EfiBadgingDisplayAttributeCenterLeft
:
492 DestY
= (SizeOfY
- Height
) / 2;
495 case EfiBadgingDisplayAttributeCenter
:
496 DestX
= (SizeOfX
- Width
) / 2;
497 DestY
= (SizeOfY
- Height
) / 2;
506 if ((DestX
>= 0) && (DestY
>= 0)) {
507 if (GraphicsOutput
!= NULL
) {
508 Status
= GraphicsOutput
->Blt (
518 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
520 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
521 Status
= UgaDraw
->Blt (
523 (EFI_UGA_PIXEL
*) Blt
,
524 EfiUgaBltBufferToVideo
,
531 Width
* sizeof (EFI_UGA_PIXEL
)
534 Status
= EFI_UNSUPPORTED
;
538 gBS
->FreePool (ImageData
);
541 if (Badging
== NULL
) {
550 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
551 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
553 @retval EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
554 @retval EFI_UNSUPPORTED - Logo not found
563 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
565 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
566 if (EFI_ERROR (Status
)) {
567 return EFI_UNSUPPORTED
;
570 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
573 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
574 { 0x00, 0x00, 0x00, 0x00 },
575 { 0x98, 0x00, 0x00, 0x00 },
576 { 0x00, 0x98, 0x00, 0x00 },
577 { 0x98, 0x98, 0x00, 0x00 },
578 { 0x00, 0x00, 0x98, 0x00 },
579 { 0x98, 0x00, 0x98, 0x00 },
580 { 0x00, 0x98, 0x98, 0x00 },
581 { 0x98, 0x98, 0x98, 0x00 },
582 { 0x10, 0x10, 0x10, 0x00 },
583 { 0xff, 0x10, 0x10, 0x00 },
584 { 0x10, 0xff, 0x10, 0x00 },
585 { 0xff, 0xff, 0x10, 0x00 },
586 { 0x10, 0x10, 0xff, 0x00 },
587 { 0xf0, 0x10, 0xff, 0x00 },
588 { 0x10, 0xff, 0xff, 0x00 },
589 { 0xff, 0xff, 0xff, 0x00 }
593 Display string worker for: Print, PrintAt, IPrint, IPrintAt
595 @param GraphicsOutput - Graphics output protocol interface
597 @param UgaDraw - UGA draw protocol interface
599 @param Sto - Simple text out protocol interface
601 @param X - X coordinate to start printing
603 @param Y - Y coordinate to start printing
605 @param Foreground - Foreground color
607 @param Background - Background color
609 @param fmt - Format string
611 @param args - Print arguments
614 @retval EFI_SUCCESS - success
615 @retval EFI_OUT_OF_RESOURCES - out of resources
621 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
622 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
623 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
,
626 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
627 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
639 CHAR16
*UnicodeWeight
;
640 EFI_NARROW_GLYPH
*Glyph
;
641 EFI_HII_PROTOCOL
*Hii
;
642 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
643 UINT32 HorizontalResolution
;
644 UINT32 VerticalResolution
;
649 UINTN BufferGlyphWidth
;
652 HorizontalResolution
= 0;
653 VerticalResolution
= 0;
656 // For now, allocate an arbitrarily long buffer
658 Buffer
= AllocateZeroPool (0x10000);
659 if (Buffer
== NULL
) {
660 return EFI_OUT_OF_RESOURCES
;
663 if (GraphicsOutput
!= NULL
) {
664 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
665 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
666 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
668 // Get the current mode information from the UGA Draw Protocol
670 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
672 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
674 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
675 LineBuffer
= AllocatePool (LineBufferLen
);
676 if (LineBuffer
== NULL
) {
677 gBS
->FreePool (Buffer
);
678 return EFI_OUT_OF_RESOURCES
;
681 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
682 if (EFI_ERROR (Status
)) {
686 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
688 UnicodeWeight
= (CHAR16
*) Buffer
;
690 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
691 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
692 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
693 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
694 UnicodeWeight
[Index
] = 0;
698 BufferLen
= StrLen (Buffer
);
700 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
701 Status
= EFI_INVALID_PARAMETER
;
705 for (Index
= 0; Index
< BufferLen
; Index
++) {
706 StringIndex
= (UINT16
) Index
;
707 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
708 if (EFI_ERROR (Status
)) {
712 if (Foreground
== NULL
|| Background
== NULL
) {
713 Status
= Hii
->GlyphToBlt (
716 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
717 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
721 &LineBuffer
[Index
* GLYPH_WIDTH
]
724 Status
= Hii
->GlyphToBlt (
732 &LineBuffer
[Index
* GLYPH_WIDTH
]
738 // Blt a character to the screen
740 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
741 if (GraphicsOutput
!= NULL
) {
742 Status
= GraphicsOutput
->Blt (
752 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
754 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
755 Status
= UgaDraw
->Blt (
757 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
758 EfiUgaBltBufferToVideo
,
765 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
768 Status
= EFI_UNSUPPORTED
;
772 gBS
->FreePool (LineBuffer
);
773 gBS
->FreePool (Buffer
);
778 Prints a formatted unicode string to the default console
780 @param X - X coordinate to start printing
782 @param Y - Y coordinate to start printing
784 @param ForeGround - Foreground color
786 @param BackGround - Background color
788 @param Fmt - Format string
790 @param ... - Print arguments
793 @retval Length of string printed to the console
800 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
801 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
808 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
809 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
810 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
814 VA_START (Args
, Fmt
);
818 Handle
= gST
->ConsoleOutHandle
;
820 Status
= gBS
->HandleProtocol (
822 &gEfiGraphicsOutputProtocolGuid
,
823 (VOID
**) &GraphicsOutput
826 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
827 GraphicsOutput
= NULL
;
829 Status
= gBS
->HandleProtocol (
831 &gEfiUgaDrawProtocolGuid
,
836 if (EFI_ERROR (Status
)) {
840 Status
= gBS
->HandleProtocol (
842 &gEfiSimpleTextOutProtocolGuid
,
846 if (EFI_ERROR (Status
)) {
850 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);