2 Support for Basic Graphics operations.
4 BugBug: Currently *.BMP files are supported. This will be replaced
5 when Tiano graphics format is supported.
8 Copyright (c) 2006, Intel Corporation
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 #include <Protocol/SimpleTextOut.h>
23 #include <Protocol/OEMBadging.h>
24 #include <Protocol/ConsoleControl.h>
25 #include <Protocol/GraphicsOutput.h>
26 #include <Protocol/FirmwareVolume2.h>
27 #include <Protocol/UgaDraw.h>
28 #include <Protocol/FrameworkHii.h>
32 #include <Library/GraphicsLib.h>
33 #include <Library/PrintLib.h>
34 #include <Library/BaseLib.h>
35 #include <Library/MemoryAllocationLib.h>
36 #include <Library/UefiBootServicesTableLib.h>
37 #include <Library/DebugLib.h>
38 #include <Library/PcdLib.h>
41 GetGraphicsBitMapFromFV (
42 IN EFI_GUID
*FileNameGuid
,
50 Return the graphics image file named FileNameGuid into Image and return it's
51 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
56 FileNameGuid - File Name of graphics file in the FV(s).
58 Image - Pointer to pointer to return graphics image. If NULL, a
59 buffer will be allocated.
61 ImageSize - Size of the graphics Image in bytes. Zero if no image found.
66 EFI_SUCCESS - Image and ImageSize are valid.
67 EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
68 EFI_NOT_FOUND - FileNameGuid not found
73 UINTN FvProtocolCount
;
74 EFI_HANDLE
*FvHandles
;
75 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
77 UINT32 AuthenticationStatus
;
80 Status
= gBS
->LocateHandleBuffer (
82 &gEfiFirmwareVolume2ProtocolGuid
,
87 if (EFI_ERROR (Status
)) {
91 for (Index
= 0; Index
< FvProtocolCount
; Index
++) {
92 Status
= gBS
->HandleProtocol (
94 &gEfiFirmwareVolume2ProtocolGuid
,
99 // Assuming Image and ImageSize are correct on input.
101 Status
= Fv
->ReadSection (
108 &AuthenticationStatus
110 if (!EFI_ERROR (Status
)) {
112 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
114 // ImageSize updated to needed size so return
116 return EFI_BUFFER_TOO_SMALL
;
120 return EFI_NOT_FOUND
;
127 IN UINTN BmpImageSize
,
128 IN OUT VOID
**GopBlt
,
129 IN OUT UINTN
*GopBltSize
,
130 OUT UINTN
*PixelHeight
,
131 OUT UINTN
*PixelWidth
137 Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
138 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
139 buffer is passed in it will be used if it is big enough.
143 BmpImage - Pointer to BMP file
145 BmpImageSize - Number of bytes in BmpImage
147 GopBlt - Buffer containing GOP version of BmpImage.
149 GopBltSize - Size of GopBlt in bytes.
151 PixelHeight - Height of GopBlt/BmpImage in pixels
153 PixelWidth - Width of GopBlt/BmpImage in pixels
158 EFI_SUCCESS - GopBlt and GopBltSize are returned.
159 EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image
160 EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.
161 GopBltSize will contain the required size.
162 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
168 BMP_IMAGE_HEADER
*BmpHeader
;
169 BMP_COLOR_MAP
*BmpColorMap
;
170 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
171 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
179 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
180 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
181 return EFI_UNSUPPORTED
;
184 if (BmpHeader
->CompressionType
!= 0) {
185 return EFI_UNSUPPORTED
;
189 // Calculate Color Map offset in the image.
192 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
195 // Calculate graphics image data address in the image
197 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
200 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
202 if (*GopBlt
== NULL
) {
203 *GopBltSize
= BltBufferSize
;
204 *GopBlt
= AllocatePool (*GopBltSize
);
206 if (*GopBlt
== NULL
) {
207 return EFI_OUT_OF_RESOURCES
;
210 if (*GopBltSize
< BltBufferSize
) {
211 *GopBltSize
= BltBufferSize
;
212 return EFI_BUFFER_TOO_SMALL
;
216 *PixelWidth
= BmpHeader
->PixelWidth
;
217 *PixelHeight
= BmpHeader
->PixelHeight
;
220 // Convert image from BMP to Blt buffer format
223 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
224 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
225 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
226 switch (BmpHeader
->BitPerPixel
) {
229 // Convert 1bit BMP to 24-bit color
231 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
232 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
233 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
234 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
245 // Convert BMP Palette to 24-bit color
247 Index
= (*Image
) >> 4;
248 Blt
->Red
= BmpColorMap
[Index
].Red
;
249 Blt
->Green
= BmpColorMap
[Index
].Green
;
250 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
251 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
254 Index
= (*Image
) & 0x0f;
255 Blt
->Red
= BmpColorMap
[Index
].Red
;
256 Blt
->Green
= BmpColorMap
[Index
].Green
;
257 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
263 // Convert BMP Palette to 24-bit color
265 Blt
->Red
= BmpColorMap
[*Image
].Red
;
266 Blt
->Green
= BmpColorMap
[*Image
].Green
;
267 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
271 Blt
->Blue
= *Image
++;
272 Blt
->Green
= *Image
++;
278 gBS
->FreePool (*GopBlt
);
281 return EFI_UNSUPPORTED
;
287 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
288 if ((ImageIndex
% 4) != 0) {
290 // Bmp Image starts each row on a 32-bit boundary!
292 Image
= Image
+ (4 - (ImageIndex
% 4));
307 Use Console Control Protocol to lock the Console In Spliter virtual handle.
308 This is the ConInHandle and ConIn handle in the EFI system table. All key
309 presses will be ignored until the Password is typed in. The only way to
310 disable the password is to type it in to a ConIn device.
313 Password - Password used to lock ConIn device
318 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
320 EFI_UNSUPPORTED - Logo not found
325 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
327 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
328 if (EFI_ERROR (Status
)) {
329 return EFI_UNSUPPORTED
;
332 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
339 IN EFI_GUID
*LogoFile
345 Use Console Control to turn off UGA based Simple Text Out consoles from going
346 to the UGA device. Put up LogoFile on every UGA device that is a console
350 LogoFile - File name of logo to display on the center of the screen.
355 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
357 EFI_UNSUPPORTED - Logo not found
362 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
363 EFI_OEM_BADGING_PROTOCOL
*Badging
;
372 EFI_BADGING_FORMAT Format
;
373 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
378 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
379 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
382 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
384 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
385 if (EFI_ERROR (Status
)) {
386 return EFI_UNSUPPORTED
;
391 // Try to open GOP first
393 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
394 if (EFI_ERROR(Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
395 GraphicsOutput
= NULL
;
397 // Open GOP failed, try to open UGA
399 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
401 if (EFI_ERROR (Status
)) {
402 return EFI_UNSUPPORTED
;
406 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
408 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
410 if (GraphicsOutput
!= NULL
) {
411 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
412 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
413 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
414 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
415 if (EFI_ERROR (Status
)) {
416 return EFI_UNSUPPORTED
;
419 return EFI_UNSUPPORTED
;
427 if (Badging
!= NULL
) {
428 Status
= Badging
->GetImage (
438 if (EFI_ERROR (Status
)) {
443 // Currently only support BMP format
445 if (Format
!= EfiBadgingFormatBMP
) {
446 gBS
->FreePool (ImageData
);
450 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
451 if (EFI_ERROR (Status
)) {
452 return EFI_UNSUPPORTED
;
457 Attribute
= EfiBadgingDisplayAttributeCenter
;
462 Status
= ConvertBmpToGopBlt (
470 if (EFI_ERROR (Status
)) {
471 gBS
->FreePool (ImageData
);
472 if (Badging
== NULL
) {
480 case EfiBadgingDisplayAttributeLeftTop
:
485 case EfiBadgingDisplayAttributeCenterTop
:
486 DestX
= (SizeOfX
- Width
) / 2;
490 case EfiBadgingDisplayAttributeRightTop
:
491 DestX
= (SizeOfX
- Width
- CoordinateX
);
492 DestY
= CoordinateY
;;
495 case EfiBadgingDisplayAttributeCenterRight
:
496 DestX
= (SizeOfX
- Width
- CoordinateX
);
497 DestY
= (SizeOfY
- Height
) / 2;
500 case EfiBadgingDisplayAttributeRightBottom
:
501 DestX
= (SizeOfX
- Width
- CoordinateX
);
502 DestY
= (SizeOfY
- Height
- CoordinateY
);
505 case EfiBadgingDisplayAttributeCenterBottom
:
506 DestX
= (SizeOfX
- Width
) / 2;
507 DestY
= (SizeOfY
- Height
- CoordinateY
);
510 case EfiBadgingDisplayAttributeLeftBottom
:
512 DestY
= (SizeOfY
- Height
- CoordinateY
);
515 case EfiBadgingDisplayAttributeCenterLeft
:
517 DestY
= (SizeOfY
- Height
) / 2;
520 case EfiBadgingDisplayAttributeCenter
:
521 DestX
= (SizeOfX
- Width
) / 2;
522 DestY
= (SizeOfY
- Height
) / 2;
531 if ((DestX
>= 0) && (DestY
>= 0)) {
532 if (GraphicsOutput
!= NULL
) {
533 Status
= GraphicsOutput
->Blt (
543 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
545 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
546 Status
= UgaDraw
->Blt (
548 (EFI_UGA_PIXEL
*) Blt
,
549 EfiUgaBltBufferToVideo
,
556 Width
* sizeof (EFI_UGA_PIXEL
)
559 Status
= EFI_UNSUPPORTED
;
563 gBS
->FreePool (ImageData
);
566 if (Badging
== NULL
) {
583 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
584 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
592 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
593 EFI_UNSUPPORTED - Logo not found
598 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
600 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
601 if (EFI_ERROR (Status
)) {
602 return EFI_UNSUPPORTED
;
605 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
608 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
609 { 0x00, 0x00, 0x00, 0x00 },
610 { 0x98, 0x00, 0x00, 0x00 },
611 { 0x00, 0x98, 0x00, 0x00 },
612 { 0x98, 0x98, 0x00, 0x00 },
613 { 0x00, 0x00, 0x98, 0x00 },
614 { 0x98, 0x00, 0x98, 0x00 },
615 { 0x00, 0x98, 0x98, 0x00 },
616 { 0x98, 0x98, 0x98, 0x00 },
617 { 0x10, 0x10, 0x10, 0x00 },
618 { 0xff, 0x10, 0x10, 0x00 },
619 { 0x10, 0xff, 0x10, 0x00 },
620 { 0xff, 0xff, 0x10, 0x00 },
621 { 0x10, 0x10, 0xff, 0x00 },
622 { 0xf0, 0x10, 0xff, 0x00 },
623 { 0x10, 0xff, 0xff, 0x00 },
624 { 0xff, 0xff, 0xff, 0x00 }
630 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
631 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
632 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
,
635 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
636 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
644 Display string worker for: Print, PrintAt, IPrint, IPrintAt
648 GraphicsOutput - Graphics output protocol interface
650 UgaDraw - UGA draw protocol interface
652 Sto - Simple text out protocol interface
654 X - X coordinate to start printing
656 Y - Y coordinate to start printing
658 Foreground - Foreground color
660 Background - Background color
664 args - Print arguments
668 EFI_SUCCESS - success
669 EFI_OUT_OF_RESOURCES - out of resources
679 CHAR16
*UnicodeWeight
;
680 EFI_NARROW_GLYPH
*Glyph
;
681 EFI_HII_PROTOCOL
*Hii
;
682 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
683 UINT32 HorizontalResolution
;
684 UINT32 VerticalResolution
;
689 UINTN BufferGlyphWidth
;
694 // For now, allocate an arbitrarily long buffer
696 Buffer
= AllocateZeroPool (0x10000);
697 if (Buffer
== NULL
) {
698 return EFI_OUT_OF_RESOURCES
;
701 if (GraphicsOutput
!= NULL
) {
702 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
703 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
704 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
706 // Get the current mode information from the UGA Draw Protocol
708 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
710 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
712 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
713 LineBuffer
= AllocatePool (LineBufferLen
);
714 if (LineBuffer
== NULL
) {
715 gBS
->FreePool (Buffer
);
716 return EFI_OUT_OF_RESOURCES
;
719 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
720 if (EFI_ERROR (Status
)) {
724 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
726 UnicodeWeight
= (CHAR16
*) Buffer
;
728 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
729 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
730 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
731 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
732 UnicodeWeight
[Index
] = 0;
736 BufferLen
= StrLen (Buffer
);
738 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
739 Status
= EFI_INVALID_PARAMETER
;
743 for (Index
= 0; Index
< BufferLen
; Index
++) {
744 StringIndex
= (UINT16
) Index
;
745 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
746 if (EFI_ERROR (Status
)) {
750 if (Foreground
== NULL
|| Background
== NULL
) {
751 Status
= Hii
->GlyphToBlt (
754 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
755 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
759 &LineBuffer
[Index
* GLYPH_WIDTH
]
762 Status
= Hii
->GlyphToBlt (
770 &LineBuffer
[Index
* GLYPH_WIDTH
]
776 // Blt a character to the screen
778 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
779 if (GraphicsOutput
!= NULL
) {
780 Status
= GraphicsOutput
->Blt (
790 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
792 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
793 Status
= UgaDraw
->Blt (
795 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
796 EfiUgaBltBufferToVideo
,
803 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
806 Status
= EFI_UNSUPPORTED
;
810 gBS
->FreePool (LineBuffer
);
811 gBS
->FreePool (Buffer
);
820 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
821 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
829 Prints a formatted unicode string to the default console
833 X - X coordinate to start printing
835 Y - Y coordinate to start printing
837 ForeGround - Foreground color
839 BackGround - Background color
843 ... - Print arguments
847 Length of string printed to the console
853 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
854 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
855 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
859 VA_START (Args
, Fmt
);
863 Handle
= gST
->ConsoleOutHandle
;
865 Status
= gBS
->HandleProtocol (
867 &gEfiGraphicsOutputProtocolGuid
,
868 (VOID
**) &GraphicsOutput
871 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
872 GraphicsOutput
= NULL
;
874 Status
= gBS
->HandleProtocol (
876 &gEfiUgaDrawProtocolGuid
,
881 if (EFI_ERROR (Status
)) {
885 Status
= gBS
->HandleProtocol (
887 &gEfiSimpleTextOutProtocolGuid
,
891 if (EFI_ERROR (Status
)) {
895 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);