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/HiiFramework.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>
40 GetGraphicsBitMapFromFV (
41 IN EFI_GUID
*FileNameGuid
,
49 Return the graphics image file named FileNameGuid into Image and return it's
50 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
55 FileNameGuid - File Name of graphics file in the FV(s).
57 Image - Pointer to pointer to return graphics image. If NULL, a
58 buffer will be allocated.
60 ImageSize - Size of the graphics Image in bytes. Zero if no image found.
65 EFI_SUCCESS - Image and ImageSize are valid.
66 EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
67 EFI_NOT_FOUND - FileNameGuid not found
72 UINTN FvProtocolCount
;
73 EFI_HANDLE
*FvHandles
;
74 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
76 UINT32 AuthenticationStatus
;
79 Status
= gBS
->LocateHandleBuffer (
81 &gEfiFirmwareVolume2ProtocolGuid
,
86 if (EFI_ERROR (Status
)) {
90 for (Index
= 0; Index
< FvProtocolCount
; Index
++) {
91 Status
= gBS
->HandleProtocol (
93 &gEfiFirmwareVolume2ProtocolGuid
,
98 // Assuming Image and ImageSize are correct on input.
100 Status
= Fv
->ReadSection (
107 &AuthenticationStatus
109 if (!EFI_ERROR (Status
)) {
111 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
113 // ImageSize updated to needed size so return
115 return EFI_BUFFER_TOO_SMALL
;
119 return EFI_NOT_FOUND
;
126 IN UINTN BmpImageSize
,
127 IN OUT VOID
**GopBlt
,
128 IN OUT UINTN
*GopBltSize
,
129 OUT UINTN
*PixelHeight
,
130 OUT UINTN
*PixelWidth
136 Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
137 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
138 buffer is passed in it will be used if it is big enough.
142 BmpImage - Pointer to BMP file
144 BmpImageSize - Number of bytes in BmpImage
146 GopBlt - Buffer containing GOP version of BmpImage.
148 GopBltSize - Size of GopBlt in bytes.
150 PixelHeight - Height of GopBlt/BmpImage in pixels
152 PixelWidth - Width of GopBlt/BmpImage in pixels
157 EFI_SUCCESS - GopBlt and GopBltSize are returned.
158 EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image
159 EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.
160 GopBltSize will contain the required size.
161 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
167 BMP_IMAGE_HEADER
*BmpHeader
;
168 BMP_COLOR_MAP
*BmpColorMap
;
169 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
170 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
178 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
179 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
180 return EFI_UNSUPPORTED
;
183 if (BmpHeader
->CompressionType
!= 0) {
184 return EFI_UNSUPPORTED
;
188 // Calculate Color Map offset in the image.
191 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
194 // Calculate graphics image data address in the image
196 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
199 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
201 if (*GopBlt
== NULL
) {
202 *GopBltSize
= BltBufferSize
;
203 *GopBlt
= AllocatePool (*GopBltSize
);
205 if (*GopBlt
== NULL
) {
206 return EFI_OUT_OF_RESOURCES
;
209 if (*GopBltSize
< BltBufferSize
) {
210 *GopBltSize
= BltBufferSize
;
211 return EFI_BUFFER_TOO_SMALL
;
215 *PixelWidth
= BmpHeader
->PixelWidth
;
216 *PixelHeight
= BmpHeader
->PixelHeight
;
219 // Convert image from BMP to Blt buffer format
222 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
223 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
224 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
225 switch (BmpHeader
->BitPerPixel
) {
228 // Convert 1bit BMP to 24-bit color
230 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
231 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
232 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
233 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
244 // Convert BMP Palette to 24-bit color
246 Index
= (*Image
) >> 4;
247 Blt
->Red
= BmpColorMap
[Index
].Red
;
248 Blt
->Green
= BmpColorMap
[Index
].Green
;
249 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
250 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
253 Index
= (*Image
) & 0x0f;
254 Blt
->Red
= BmpColorMap
[Index
].Red
;
255 Blt
->Green
= BmpColorMap
[Index
].Green
;
256 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
262 // Convert BMP Palette to 24-bit color
264 Blt
->Red
= BmpColorMap
[*Image
].Red
;
265 Blt
->Green
= BmpColorMap
[*Image
].Green
;
266 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
270 Blt
->Blue
= *Image
++;
271 Blt
->Green
= *Image
++;
277 gBS
->FreePool (*GopBlt
);
280 return EFI_UNSUPPORTED
;
286 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
287 if ((ImageIndex
% 4) != 0) {
289 // Bmp Image starts each row on a 32-bit boundary!
291 Image
= Image
+ (4 - (ImageIndex
% 4));
306 Use Console Control Protocol to lock the Console In Spliter virtual handle.
307 This is the ConInHandle and ConIn handle in the EFI system table. All key
308 presses will be ignored until the Password is typed in. The only way to
309 disable the password is to type it in to a ConIn device.
312 Password - Password used to lock ConIn device
317 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
319 EFI_UNSUPPORTED - Logo not found
324 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
326 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
327 if (EFI_ERROR (Status
)) {
328 return EFI_UNSUPPORTED
;
331 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
338 IN EFI_GUID
*LogoFile
344 Use Console Control to turn off UGA based Simple Text Out consoles from going
345 to the UGA device. Put up LogoFile on every UGA device that is a console
349 LogoFile - File name of logo to display on the center of the screen.
354 EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
356 EFI_UNSUPPORTED - Logo not found
361 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
362 EFI_OEM_BADGING_PROTOCOL
*Badging
;
371 EFI_BADGING_FORMAT Format
;
372 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
377 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
378 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
381 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
383 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
384 if (EFI_ERROR (Status
)) {
385 return EFI_UNSUPPORTED
;
390 // Try to open GOP first
392 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
393 if (EFI_ERROR(Status
)) {
394 GraphicsOutput
= NULL
;
396 // Open GOP failed, try to open UGA
398 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
399 if (EFI_ERROR (Status
)) {
400 return EFI_UNSUPPORTED
;
405 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
407 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
409 if (GraphicsOutput
!= NULL
) {
410 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
411 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
413 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
414 if (EFI_ERROR (Status
)) {
415 return EFI_UNSUPPORTED
;
424 if (Badging
!= NULL
) {
425 Status
= Badging
->GetImage (
435 if (EFI_ERROR (Status
)) {
440 // Currently only support BMP format
442 if (Format
!= EfiBadgingFormatBMP
) {
443 gBS
->FreePool (ImageData
);
447 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
448 if (EFI_ERROR (Status
)) {
449 return EFI_UNSUPPORTED
;
454 Attribute
= EfiBadgingDisplayAttributeCenter
;
459 Status
= ConvertBmpToGopBlt (
467 if (EFI_ERROR (Status
)) {
468 gBS
->FreePool (ImageData
);
469 if (Badging
== NULL
) {
477 case EfiBadgingDisplayAttributeLeftTop
:
482 case EfiBadgingDisplayAttributeCenterTop
:
483 DestX
= (SizeOfX
- Width
) / 2;
487 case EfiBadgingDisplayAttributeRightTop
:
488 DestX
= (SizeOfX
- Width
- CoordinateX
);
489 DestY
= CoordinateY
;;
492 case EfiBadgingDisplayAttributeCenterRight
:
493 DestX
= (SizeOfX
- Width
- CoordinateX
);
494 DestY
= (SizeOfY
- Height
) / 2;
497 case EfiBadgingDisplayAttributeRightBottom
:
498 DestX
= (SizeOfX
- Width
- CoordinateX
);
499 DestY
= (SizeOfY
- Height
- CoordinateY
);
502 case EfiBadgingDisplayAttributeCenterBottom
:
503 DestX
= (SizeOfX
- Width
) / 2;
504 DestY
= (SizeOfY
- Height
- CoordinateY
);
507 case EfiBadgingDisplayAttributeLeftBottom
:
509 DestY
= (SizeOfY
- Height
- CoordinateY
);
512 case EfiBadgingDisplayAttributeCenterLeft
:
514 DestY
= (SizeOfY
- Height
) / 2;
517 case EfiBadgingDisplayAttributeCenter
:
518 DestX
= (SizeOfX
- Width
) / 2;
519 DestY
= (SizeOfY
- Height
) / 2;
528 if ((DestX
>= 0) && (DestY
>= 0)) {
529 if (GraphicsOutput
!= NULL
) {
530 Status
= GraphicsOutput
->Blt (
540 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
543 Status
= UgaDraw
->Blt (
545 (EFI_UGA_PIXEL
*) Blt
,
546 EfiUgaBltBufferToVideo
,
553 Width
* sizeof (EFI_UGA_PIXEL
)
558 gBS
->FreePool (ImageData
);
561 if (Badging
== NULL
) {
578 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
579 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
587 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
588 EFI_UNSUPPORTED - Logo not found
593 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
595 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
596 if (EFI_ERROR (Status
)) {
597 return EFI_UNSUPPORTED
;
600 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
603 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
604 { 0x00, 0x00, 0x00, 0x00 },
605 { 0x98, 0x00, 0x00, 0x00 },
606 { 0x00, 0x98, 0x00, 0x00 },
607 { 0x98, 0x98, 0x00, 0x00 },
608 { 0x00, 0x00, 0x98, 0x00 },
609 { 0x98, 0x00, 0x98, 0x00 },
610 { 0x00, 0x98, 0x98, 0x00 },
611 { 0x98, 0x98, 0x98, 0x00 },
612 { 0x10, 0x10, 0x10, 0x00 },
613 { 0xff, 0x10, 0x10, 0x00 },
614 { 0x10, 0xff, 0x10, 0x00 },
615 { 0xff, 0xff, 0x10, 0x00 },
616 { 0x10, 0x10, 0xff, 0x00 },
617 { 0xf0, 0x10, 0xff, 0x00 },
618 { 0x10, 0xff, 0xff, 0x00 },
619 { 0xff, 0xff, 0xff, 0x00 }
625 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
626 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
627 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
,
630 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
631 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
639 Display string worker for: Print, PrintAt, IPrint, IPrintAt
643 GraphicsOutput - Graphics output protocol interface
645 UgaDraw - UGA draw protocol interface
647 Sto - Simple text out protocol interface
649 X - X coordinate to start printing
651 Y - Y coordinate to start printing
653 Foreground - Foreground color
655 Background - Background color
659 args - Print arguments
663 EFI_SUCCESS - success
664 EFI_OUT_OF_RESOURCES - out of resources
674 CHAR16
*UnicodeWeight
;
675 EFI_NARROW_GLYPH
*Glyph
;
676 EFI_HII_PROTOCOL
*Hii
;
677 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
678 UINT32 HorizontalResolution
;
679 UINT32 VerticalResolution
;
684 UINTN BufferGlyphWidth
;
689 // For now, allocate an arbitrarily long buffer
691 Buffer
= AllocateZeroPool (0x10000);
692 if (Buffer
== NULL
) {
693 return EFI_OUT_OF_RESOURCES
;
696 if (GraphicsOutput
!= NULL
) {
697 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
698 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
701 // Get the current mode information from the UGA Draw Protocol
703 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
705 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
707 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
708 LineBuffer
= AllocatePool (LineBufferLen
);
709 if (LineBuffer
== NULL
) {
710 gBS
->FreePool (Buffer
);
711 return EFI_OUT_OF_RESOURCES
;
714 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
715 if (EFI_ERROR (Status
)) {
719 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
721 UnicodeWeight
= (CHAR16
*) Buffer
;
723 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
724 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
725 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
726 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
727 UnicodeWeight
[Index
] = 0;
731 BufferLen
= StrLen (Buffer
);
733 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
734 Status
= EFI_INVALID_PARAMETER
;
738 for (Index
= 0; Index
< BufferLen
; Index
++) {
739 StringIndex
= (UINT16
) Index
;
740 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
741 if (EFI_ERROR (Status
)) {
745 if (Foreground
== NULL
|| Background
== NULL
) {
746 Status
= Hii
->GlyphToBlt (
749 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
750 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
754 &LineBuffer
[Index
* GLYPH_WIDTH
]
757 Status
= Hii
->GlyphToBlt (
765 &LineBuffer
[Index
* GLYPH_WIDTH
]
771 // Blt a character to the screen
773 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
774 if (GraphicsOutput
!= NULL
) {
775 Status
= GraphicsOutput
->Blt (
785 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
788 Status
= UgaDraw
->Blt (
790 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
791 EfiUgaBltBufferToVideo
,
798 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
803 gBS
->FreePool (LineBuffer
);
804 gBS
->FreePool (Buffer
);
813 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
814 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
822 Prints a formatted unicode string to the default console
826 X - X coordinate to start printing
828 Y - Y coordinate to start printing
830 ForeGround - Foreground color
832 BackGround - Background color
836 ... - Print arguments
840 Length of string printed to the console
846 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
847 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
848 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
852 VA_START (Args
, Fmt
);
856 Handle
= gST
->ConsoleOutHandle
;
858 Status
= gBS
->HandleProtocol (
860 &gEfiGraphicsOutputProtocolGuid
,
861 (VOID
**) &GraphicsOutput
864 if (EFI_ERROR (Status
)) {
865 GraphicsOutput
= NULL
;
867 Status
= gBS
->HandleProtocol (
869 &gEfiUgaDrawProtocolGuid
,
873 if (EFI_ERROR (Status
)) {
878 Status
= gBS
->HandleProtocol (
880 &gEfiSimpleTextOutProtocolGuid
,
884 if (EFI_ERROR (Status
)) {
888 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);