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 lock the Console In Spliter virtual handle successfully..
298 @retval EFI_UNSUPPORTED password not found
307 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
309 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
310 if (EFI_ERROR (Status
)) {
311 return EFI_UNSUPPORTED
;
314 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
319 Use Console Control to turn off UGA based Simple Text Out consoles from going
320 to the UGA device. Put up LogoFile on every UGA device that is a console
322 @param LogoFile - File name of logo to display on the center of the screen.
324 @retval EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
326 @retval EFI_UNSUPPORTED - Logo not found
331 IN EFI_GUID
*LogoFile
336 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
337 EFI_OEM_BADGING_PROTOCOL
*Badging
;
346 EFI_BADGING_FORMAT Format
;
347 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
352 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
353 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
356 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
358 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
359 if (EFI_ERROR (Status
)) {
360 return EFI_UNSUPPORTED
;
365 // Try to open GOP first
367 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
368 if (EFI_ERROR(Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
369 GraphicsOutput
= NULL
;
371 // Open GOP failed, try to open UGA
373 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
375 if (EFI_ERROR (Status
)) {
376 return EFI_UNSUPPORTED
;
380 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
382 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
384 if (GraphicsOutput
!= NULL
) {
385 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
386 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
387 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
388 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
389 if (EFI_ERROR (Status
)) {
390 return EFI_UNSUPPORTED
;
393 return EFI_UNSUPPORTED
;
401 if (Badging
!= NULL
) {
402 Status
= Badging
->GetImage (
412 if (EFI_ERROR (Status
)) {
417 // Currently only support BMP format
419 if (Format
!= EfiBadgingFormatBMP
) {
420 gBS
->FreePool (ImageData
);
424 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
425 if (EFI_ERROR (Status
)) {
426 return EFI_UNSUPPORTED
;
431 Attribute
= EfiBadgingDisplayAttributeCenter
;
436 Status
= ConvertBmpToGopBlt (
444 if (EFI_ERROR (Status
)) {
445 gBS
->FreePool (ImageData
);
446 if (Badging
== NULL
) {
454 case EfiBadgingDisplayAttributeLeftTop
:
459 case EfiBadgingDisplayAttributeCenterTop
:
460 DestX
= (SizeOfX
- Width
) / 2;
464 case EfiBadgingDisplayAttributeRightTop
:
465 DestX
= (SizeOfX
- Width
- CoordinateX
);
466 DestY
= CoordinateY
;;
469 case EfiBadgingDisplayAttributeCenterRight
:
470 DestX
= (SizeOfX
- Width
- CoordinateX
);
471 DestY
= (SizeOfY
- Height
) / 2;
474 case EfiBadgingDisplayAttributeRightBottom
:
475 DestX
= (SizeOfX
- Width
- CoordinateX
);
476 DestY
= (SizeOfY
- Height
- CoordinateY
);
479 case EfiBadgingDisplayAttributeCenterBottom
:
480 DestX
= (SizeOfX
- Width
) / 2;
481 DestY
= (SizeOfY
- Height
- CoordinateY
);
484 case EfiBadgingDisplayAttributeLeftBottom
:
486 DestY
= (SizeOfY
- Height
- CoordinateY
);
489 case EfiBadgingDisplayAttributeCenterLeft
:
491 DestY
= (SizeOfY
- Height
) / 2;
494 case EfiBadgingDisplayAttributeCenter
:
495 DestX
= (SizeOfX
- Width
) / 2;
496 DestY
= (SizeOfY
- Height
) / 2;
505 if ((DestX
>= 0) && (DestY
>= 0)) {
506 if (GraphicsOutput
!= NULL
) {
507 Status
= GraphicsOutput
->Blt (
517 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
519 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
520 Status
= UgaDraw
->Blt (
522 (EFI_UGA_PIXEL
*) Blt
,
523 EfiUgaBltBufferToVideo
,
530 Width
* sizeof (EFI_UGA_PIXEL
)
533 Status
= EFI_UNSUPPORTED
;
537 gBS
->FreePool (ImageData
);
540 if (Badging
== NULL
) {
549 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
550 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
552 @retval EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
553 @retval EFI_UNSUPPORTED - Logo not found
562 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
564 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
565 if (EFI_ERROR (Status
)) {
566 return EFI_UNSUPPORTED
;
569 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
572 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
573 { 0x00, 0x00, 0x00, 0x00 },
574 { 0x98, 0x00, 0x00, 0x00 },
575 { 0x00, 0x98, 0x00, 0x00 },
576 { 0x98, 0x98, 0x00, 0x00 },
577 { 0x00, 0x00, 0x98, 0x00 },
578 { 0x98, 0x00, 0x98, 0x00 },
579 { 0x00, 0x98, 0x98, 0x00 },
580 { 0x98, 0x98, 0x98, 0x00 },
581 { 0x10, 0x10, 0x10, 0x00 },
582 { 0xff, 0x10, 0x10, 0x00 },
583 { 0x10, 0xff, 0x10, 0x00 },
584 { 0xff, 0xff, 0x10, 0x00 },
585 { 0x10, 0x10, 0xff, 0x00 },
586 { 0xf0, 0x10, 0xff, 0x00 },
587 { 0x10, 0xff, 0xff, 0x00 },
588 { 0xff, 0xff, 0xff, 0x00 }
592 Display string worker for: Print, PrintAt, IPrint, IPrintAt
594 @param GraphicsOutput - Graphics output protocol interface
596 @param UgaDraw - UGA draw protocol interface
598 @param Sto - Simple text out protocol interface
600 @param X - X coordinate to start printing
602 @param Y - Y coordinate to start printing
604 @param Foreground - Foreground color
606 @param Background - Background color
608 @param fmt - Format string
610 @param args - Print arguments
613 @retval EFI_SUCCESS - success
614 @retval EFI_OUT_OF_RESOURCES - out of resources
620 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
621 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
622 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
,
625 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
626 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
638 CHAR16
*UnicodeWeight
;
639 EFI_NARROW_GLYPH
*Glyph
;
640 EFI_HII_PROTOCOL
*Hii
;
641 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
642 UINT32 HorizontalResolution
;
643 UINT32 VerticalResolution
;
648 UINTN BufferGlyphWidth
;
651 HorizontalResolution
= 0;
652 VerticalResolution
= 0;
655 // For now, allocate an arbitrarily long buffer
657 Buffer
= AllocateZeroPool (0x10000);
658 if (Buffer
== NULL
) {
659 return EFI_OUT_OF_RESOURCES
;
662 if (GraphicsOutput
!= NULL
) {
663 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
664 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
665 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
667 // Get the current mode information from the UGA Draw Protocol
669 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
671 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
673 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
674 LineBuffer
= AllocatePool (LineBufferLen
);
675 if (LineBuffer
== NULL
) {
676 gBS
->FreePool (Buffer
);
677 return EFI_OUT_OF_RESOURCES
;
680 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
681 if (EFI_ERROR (Status
)) {
685 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
687 UnicodeWeight
= (CHAR16
*) Buffer
;
689 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
690 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
691 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
692 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
693 UnicodeWeight
[Index
] = 0;
697 BufferLen
= StrLen (Buffer
);
699 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
700 Status
= EFI_INVALID_PARAMETER
;
704 for (Index
= 0; Index
< BufferLen
; Index
++) {
705 StringIndex
= (UINT16
) Index
;
706 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
707 if (EFI_ERROR (Status
)) {
711 if (Foreground
== NULL
|| Background
== NULL
) {
712 Status
= Hii
->GlyphToBlt (
715 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
716 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
720 &LineBuffer
[Index
* GLYPH_WIDTH
]
723 Status
= Hii
->GlyphToBlt (
731 &LineBuffer
[Index
* GLYPH_WIDTH
]
737 // Blt a character to the screen
739 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
740 if (GraphicsOutput
!= NULL
) {
741 Status
= GraphicsOutput
->Blt (
751 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
753 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
754 Status
= UgaDraw
->Blt (
756 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
757 EfiUgaBltBufferToVideo
,
764 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
767 Status
= EFI_UNSUPPORTED
;
771 gBS
->FreePool (LineBuffer
);
772 gBS
->FreePool (Buffer
);
777 Prints a formatted unicode string to the default console
779 @param X - X coordinate to start printing
781 @param Y - Y coordinate to start printing
783 @param ForeGround - Foreground color
785 @param BackGround - Background color
787 @param Fmt - Format string
789 @param ... - Print arguments
792 @retval Length of string printed to the console
799 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
800 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
807 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
808 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
809 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
813 VA_START (Args
, Fmt
);
817 Handle
= gST
->ConsoleOutHandle
;
819 Status
= gBS
->HandleProtocol (
821 &gEfiGraphicsOutputProtocolGuid
,
822 (VOID
**) &GraphicsOutput
825 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
826 GraphicsOutput
= NULL
;
828 Status
= gBS
->HandleProtocol (
830 &gEfiUgaDrawProtocolGuid
,
835 if (EFI_ERROR (Status
)) {
839 Status
= gBS
->HandleProtocol (
841 &gEfiSimpleTextOutProtocolGuid
,
845 if (EFI_ERROR (Status
)) {
849 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);