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
147 IN UINTN BmpImageSize
,
148 IN OUT VOID
**GopBlt
,
149 IN OUT UINTN
*GopBltSize
,
150 OUT UINTN
*PixelHeight
,
151 OUT UINTN
*PixelWidth
157 BMP_IMAGE_HEADER
*BmpHeader
;
158 BMP_COLOR_MAP
*BmpColorMap
;
159 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
160 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
168 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
169 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
170 return EFI_UNSUPPORTED
;
173 if (BmpHeader
->CompressionType
!= 0) {
174 return EFI_UNSUPPORTED
;
178 // Calculate Color Map offset in the image.
181 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
184 // Calculate graphics image data address in the image
186 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
189 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
191 if (*GopBlt
== NULL
) {
192 *GopBltSize
= BltBufferSize
;
193 *GopBlt
= AllocatePool (*GopBltSize
);
195 if (*GopBlt
== NULL
) {
196 return EFI_OUT_OF_RESOURCES
;
199 if (*GopBltSize
< BltBufferSize
) {
200 *GopBltSize
= BltBufferSize
;
201 return EFI_BUFFER_TOO_SMALL
;
205 *PixelWidth
= BmpHeader
->PixelWidth
;
206 *PixelHeight
= BmpHeader
->PixelHeight
;
209 // Convert image from BMP to Blt buffer format
212 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
213 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
214 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
215 switch (BmpHeader
->BitPerPixel
) {
218 // Convert 1bit BMP to 24-bit color
220 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
221 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
222 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
223 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
234 // Convert BMP Palette to 24-bit color
236 Index
= (*Image
) >> 4;
237 Blt
->Red
= BmpColorMap
[Index
].Red
;
238 Blt
->Green
= BmpColorMap
[Index
].Green
;
239 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
240 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
243 Index
= (*Image
) & 0x0f;
244 Blt
->Red
= BmpColorMap
[Index
].Red
;
245 Blt
->Green
= BmpColorMap
[Index
].Green
;
246 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
252 // Convert BMP Palette to 24-bit color
254 Blt
->Red
= BmpColorMap
[*Image
].Red
;
255 Blt
->Green
= BmpColorMap
[*Image
].Green
;
256 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
260 Blt
->Blue
= *Image
++;
261 Blt
->Green
= *Image
++;
267 gBS
->FreePool (*GopBlt
);
270 return EFI_UNSUPPORTED
;
276 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
277 if ((ImageIndex
% 4) != 0) {
279 // Bmp Image starts each row on a 32-bit boundary!
281 Image
= Image
+ (4 - (ImageIndex
% 4));
289 Use Console Control Protocol to lock the Console In Spliter virtual handle.
290 This is the ConInHandle and ConIn handle in the EFI system table. All key
291 presses will be ignored until the Password is typed in. The only way to
292 disable the password is to type it in to a ConIn device.
294 @param Password - Password used to lock ConIn device
296 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully..
297 @retval EFI_UNSUPPORTED password not found
306 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
308 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
309 if (EFI_ERROR (Status
)) {
310 return EFI_UNSUPPORTED
;
313 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
318 Use Console Control to turn off UGA based Simple Text Out consoles from going
319 to the UGA device. Put up LogoFile on every UGA device that is a console
321 @param LogoFile - File name of logo to display on the center of the screen.
323 @retval EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
325 @retval EFI_UNSUPPORTED - Logo not found
330 IN EFI_GUID
*LogoFile
335 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
336 EFI_OEM_BADGING_PROTOCOL
*Badging
;
345 EFI_BADGING_FORMAT Format
;
346 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
351 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
352 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
355 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
357 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
358 if (EFI_ERROR (Status
)) {
359 return EFI_UNSUPPORTED
;
364 // Try to open GOP first
366 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
367 if (EFI_ERROR(Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
368 GraphicsOutput
= NULL
;
370 // Open GOP failed, try to open UGA
372 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
374 if (EFI_ERROR (Status
)) {
375 return EFI_UNSUPPORTED
;
379 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
381 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
383 if (GraphicsOutput
!= NULL
) {
384 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
385 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
386 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
387 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
388 if (EFI_ERROR (Status
)) {
389 return EFI_UNSUPPORTED
;
392 return EFI_UNSUPPORTED
;
400 if (Badging
!= NULL
) {
401 Status
= Badging
->GetImage (
411 if (EFI_ERROR (Status
)) {
416 // Currently only support BMP format
418 if (Format
!= EfiBadgingFormatBMP
) {
419 gBS
->FreePool (ImageData
);
423 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
424 if (EFI_ERROR (Status
)) {
425 return EFI_UNSUPPORTED
;
430 Attribute
= EfiBadgingDisplayAttributeCenter
;
435 Status
= ConvertBmpToGopBlt (
443 if (EFI_ERROR (Status
)) {
444 gBS
->FreePool (ImageData
);
445 if (Badging
== NULL
) {
453 case EfiBadgingDisplayAttributeLeftTop
:
458 case EfiBadgingDisplayAttributeCenterTop
:
459 DestX
= (SizeOfX
- Width
) / 2;
463 case EfiBadgingDisplayAttributeRightTop
:
464 DestX
= (SizeOfX
- Width
- CoordinateX
);
465 DestY
= CoordinateY
;;
468 case EfiBadgingDisplayAttributeCenterRight
:
469 DestX
= (SizeOfX
- Width
- CoordinateX
);
470 DestY
= (SizeOfY
- Height
) / 2;
473 case EfiBadgingDisplayAttributeRightBottom
:
474 DestX
= (SizeOfX
- Width
- CoordinateX
);
475 DestY
= (SizeOfY
- Height
- CoordinateY
);
478 case EfiBadgingDisplayAttributeCenterBottom
:
479 DestX
= (SizeOfX
- Width
) / 2;
480 DestY
= (SizeOfY
- Height
- CoordinateY
);
483 case EfiBadgingDisplayAttributeLeftBottom
:
485 DestY
= (SizeOfY
- Height
- CoordinateY
);
488 case EfiBadgingDisplayAttributeCenterLeft
:
490 DestY
= (SizeOfY
- Height
) / 2;
493 case EfiBadgingDisplayAttributeCenter
:
494 DestX
= (SizeOfX
- Width
) / 2;
495 DestY
= (SizeOfY
- Height
) / 2;
504 if ((DestX
>= 0) && (DestY
>= 0)) {
505 if (GraphicsOutput
!= NULL
) {
506 Status
= GraphicsOutput
->Blt (
516 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
518 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
519 Status
= UgaDraw
->Blt (
521 (EFI_UGA_PIXEL
*) Blt
,
522 EfiUgaBltBufferToVideo
,
529 Width
* sizeof (EFI_UGA_PIXEL
)
532 Status
= EFI_UNSUPPORTED
;
536 gBS
->FreePool (ImageData
);
539 if (Badging
== NULL
) {
548 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
549 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
551 @retval EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
552 @retval EFI_UNSUPPORTED - Logo not found
561 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
563 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
564 if (EFI_ERROR (Status
)) {
565 return EFI_UNSUPPORTED
;
568 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
571 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
572 { 0x00, 0x00, 0x00, 0x00 },
573 { 0x98, 0x00, 0x00, 0x00 },
574 { 0x00, 0x98, 0x00, 0x00 },
575 { 0x98, 0x98, 0x00, 0x00 },
576 { 0x00, 0x00, 0x98, 0x00 },
577 { 0x98, 0x00, 0x98, 0x00 },
578 { 0x00, 0x98, 0x98, 0x00 },
579 { 0x98, 0x98, 0x98, 0x00 },
580 { 0x10, 0x10, 0x10, 0x00 },
581 { 0xff, 0x10, 0x10, 0x00 },
582 { 0x10, 0xff, 0x10, 0x00 },
583 { 0xff, 0xff, 0x10, 0x00 },
584 { 0x10, 0x10, 0xff, 0x00 },
585 { 0xf0, 0x10, 0xff, 0x00 },
586 { 0x10, 0xff, 0xff, 0x00 },
587 { 0xff, 0xff, 0xff, 0x00 }
591 Display string worker for: Print, PrintAt, IPrint, IPrintAt
593 @param GraphicsOutput - Graphics output protocol interface
595 @param UgaDraw - UGA draw protocol interface
597 @param Sto - Simple text out protocol interface
599 @param X - X coordinate to start printing
601 @param Y - Y coordinate to start printing
603 @param Foreground - Foreground color
605 @param Background - Background color
607 @param fmt - Format string
609 @param args - Print arguments
612 @retval EFI_SUCCESS - success
613 @retval EFI_OUT_OF_RESOURCES - out of resources
618 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
619 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
620 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
,
623 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
624 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
636 CHAR16
*UnicodeWeight
;
637 EFI_NARROW_GLYPH
*Glyph
;
638 EFI_HII_PROTOCOL
*Hii
;
639 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
640 UINT32 HorizontalResolution
;
641 UINT32 VerticalResolution
;
646 UINTN BufferGlyphWidth
;
649 HorizontalResolution
= 0;
650 VerticalResolution
= 0;
653 // For now, allocate an arbitrarily long buffer
655 Buffer
= AllocateZeroPool (0x10000);
656 if (Buffer
== NULL
) {
657 return EFI_OUT_OF_RESOURCES
;
660 if (GraphicsOutput
!= NULL
) {
661 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
662 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
663 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
665 // Get the current mode information from the UGA Draw Protocol
667 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
669 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
671 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
672 LineBuffer
= AllocatePool (LineBufferLen
);
673 if (LineBuffer
== NULL
) {
674 gBS
->FreePool (Buffer
);
675 return EFI_OUT_OF_RESOURCES
;
678 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
679 if (EFI_ERROR (Status
)) {
683 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
685 UnicodeWeight
= (CHAR16
*) Buffer
;
687 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
688 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
689 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
690 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
691 UnicodeWeight
[Index
] = 0;
695 BufferLen
= StrLen (Buffer
);
697 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
698 Status
= EFI_INVALID_PARAMETER
;
702 for (Index
= 0; Index
< BufferLen
; Index
++) {
703 StringIndex
= (UINT16
) Index
;
704 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
705 if (EFI_ERROR (Status
)) {
709 if (Foreground
== NULL
|| Background
== NULL
) {
710 Status
= Hii
->GlyphToBlt (
713 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
714 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
718 &LineBuffer
[Index
* GLYPH_WIDTH
]
721 Status
= Hii
->GlyphToBlt (
729 &LineBuffer
[Index
* GLYPH_WIDTH
]
735 // Blt a character to the screen
737 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
738 if (GraphicsOutput
!= NULL
) {
739 Status
= GraphicsOutput
->Blt (
749 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
751 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
752 Status
= UgaDraw
->Blt (
754 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
755 EfiUgaBltBufferToVideo
,
762 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
765 Status
= EFI_UNSUPPORTED
;
769 gBS
->FreePool (LineBuffer
);
770 gBS
->FreePool (Buffer
);
775 Prints a formatted unicode string to the default console
777 @param X - X coordinate to start printing
779 @param Y - Y coordinate to start printing
781 @param ForeGround - Foreground color
783 @param BackGround - Background color
785 @param Fmt - Format string
787 @param ... Variable argument list whose contents are accessed based on
788 the format string specified by Format.
791 @retval Length of string printed to the console
798 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
799 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
806 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
807 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
808 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
812 VA_START (Args
, Fmt
);
816 Handle
= gST
->ConsoleOutHandle
;
818 Status
= gBS
->HandleProtocol (
820 &gEfiGraphicsOutputProtocolGuid
,
821 (VOID
**) &GraphicsOutput
824 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
825 GraphicsOutput
= NULL
;
827 Status
= gBS
->HandleProtocol (
829 &gEfiUgaDrawProtocolGuid
,
834 if (EFI_ERROR (Status
)) {
838 Status
= gBS
->HandleProtocol (
840 &gEfiSimpleTextOutProtocolGuid
,
844 if (EFI_ERROR (Status
)) {
848 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);