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
;
425 if (Badging
!= NULL
) {
426 Status
= Badging
->GetImage (
436 if (EFI_ERROR (Status
)) {
441 // Currently only support BMP format
443 if (Format
!= EfiBadgingFormatBMP
) {
444 gBS
->FreePool (ImageData
);
448 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
449 if (EFI_ERROR (Status
)) {
450 return EFI_UNSUPPORTED
;
455 Attribute
= EfiBadgingDisplayAttributeCenter
;
460 Status
= ConvertBmpToGopBlt (
468 if (EFI_ERROR (Status
)) {
469 gBS
->FreePool (ImageData
);
470 if (Badging
== NULL
) {
478 case EfiBadgingDisplayAttributeLeftTop
:
483 case EfiBadgingDisplayAttributeCenterTop
:
484 DestX
= (SizeOfX
- Width
) / 2;
488 case EfiBadgingDisplayAttributeRightTop
:
489 DestX
= (SizeOfX
- Width
- CoordinateX
);
490 DestY
= CoordinateY
;;
493 case EfiBadgingDisplayAttributeCenterRight
:
494 DestX
= (SizeOfX
- Width
- CoordinateX
);
495 DestY
= (SizeOfY
- Height
) / 2;
498 case EfiBadgingDisplayAttributeRightBottom
:
499 DestX
= (SizeOfX
- Width
- CoordinateX
);
500 DestY
= (SizeOfY
- Height
- CoordinateY
);
503 case EfiBadgingDisplayAttributeCenterBottom
:
504 DestX
= (SizeOfX
- Width
) / 2;
505 DestY
= (SizeOfY
- Height
- CoordinateY
);
508 case EfiBadgingDisplayAttributeLeftBottom
:
510 DestY
= (SizeOfY
- Height
- CoordinateY
);
513 case EfiBadgingDisplayAttributeCenterLeft
:
515 DestY
= (SizeOfY
- Height
) / 2;
518 case EfiBadgingDisplayAttributeCenter
:
519 DestX
= (SizeOfX
- Width
) / 2;
520 DestY
= (SizeOfY
- Height
) / 2;
529 if ((DestX
>= 0) && (DestY
>= 0)) {
530 if (GraphicsOutput
!= NULL
) {
531 Status
= GraphicsOutput
->Blt (
541 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
543 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
544 Status
= UgaDraw
->Blt (
546 (EFI_UGA_PIXEL
*) Blt
,
547 EfiUgaBltBufferToVideo
,
554 Width
* sizeof (EFI_UGA_PIXEL
)
557 Status
= EFI_UNSUPPORTED
;
561 gBS
->FreePool (ImageData
);
564 if (Badging
== NULL
) {
581 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
582 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
590 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
591 EFI_UNSUPPORTED - Logo not found
596 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
598 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
599 if (EFI_ERROR (Status
)) {
600 return EFI_UNSUPPORTED
;
603 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
606 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
607 { 0x00, 0x00, 0x00, 0x00 },
608 { 0x98, 0x00, 0x00, 0x00 },
609 { 0x00, 0x98, 0x00, 0x00 },
610 { 0x98, 0x98, 0x00, 0x00 },
611 { 0x00, 0x00, 0x98, 0x00 },
612 { 0x98, 0x00, 0x98, 0x00 },
613 { 0x00, 0x98, 0x98, 0x00 },
614 { 0x98, 0x98, 0x98, 0x00 },
615 { 0x10, 0x10, 0x10, 0x00 },
616 { 0xff, 0x10, 0x10, 0x00 },
617 { 0x10, 0xff, 0x10, 0x00 },
618 { 0xff, 0xff, 0x10, 0x00 },
619 { 0x10, 0x10, 0xff, 0x00 },
620 { 0xf0, 0x10, 0xff, 0x00 },
621 { 0x10, 0xff, 0xff, 0x00 },
622 { 0xff, 0xff, 0xff, 0x00 }
628 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
629 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
630 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
,
633 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
634 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
642 Display string worker for: Print, PrintAt, IPrint, IPrintAt
646 GraphicsOutput - Graphics output protocol interface
648 UgaDraw - UGA draw protocol interface
650 Sto - Simple text out protocol interface
652 X - X coordinate to start printing
654 Y - Y coordinate to start printing
656 Foreground - Foreground color
658 Background - Background color
662 args - Print arguments
666 EFI_SUCCESS - success
667 EFI_OUT_OF_RESOURCES - out of resources
677 CHAR16
*UnicodeWeight
;
678 EFI_NARROW_GLYPH
*Glyph
;
679 EFI_HII_PROTOCOL
*Hii
;
680 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
681 UINT32 HorizontalResolution
;
682 UINT32 VerticalResolution
;
687 UINTN BufferGlyphWidth
;
692 // For now, allocate an arbitrarily long buffer
694 Buffer
= AllocateZeroPool (0x10000);
695 if (Buffer
== NULL
) {
696 return EFI_OUT_OF_RESOURCES
;
699 if (GraphicsOutput
!= NULL
) {
700 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
701 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
702 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
704 // Get the current mode information from the UGA Draw Protocol
706 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
708 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
710 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
711 LineBuffer
= AllocatePool (LineBufferLen
);
712 if (LineBuffer
== NULL
) {
713 gBS
->FreePool (Buffer
);
714 return EFI_OUT_OF_RESOURCES
;
717 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
718 if (EFI_ERROR (Status
)) {
722 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
724 UnicodeWeight
= (CHAR16
*) Buffer
;
726 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
727 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
728 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
729 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
730 UnicodeWeight
[Index
] = 0;
734 BufferLen
= StrLen (Buffer
);
736 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
737 Status
= EFI_INVALID_PARAMETER
;
741 for (Index
= 0; Index
< BufferLen
; Index
++) {
742 StringIndex
= (UINT16
) Index
;
743 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
744 if (EFI_ERROR (Status
)) {
748 if (Foreground
== NULL
|| Background
== NULL
) {
749 Status
= Hii
->GlyphToBlt (
752 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
753 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
757 &LineBuffer
[Index
* GLYPH_WIDTH
]
760 Status
= Hii
->GlyphToBlt (
768 &LineBuffer
[Index
* GLYPH_WIDTH
]
774 // Blt a character to the screen
776 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
777 if (GraphicsOutput
!= NULL
) {
778 Status
= GraphicsOutput
->Blt (
788 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
790 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
791 Status
= UgaDraw
->Blt (
793 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
794 EfiUgaBltBufferToVideo
,
801 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
804 Status
= EFI_UNSUPPORTED
;
808 gBS
->FreePool (LineBuffer
);
809 gBS
->FreePool (Buffer
);
818 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
819 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
827 Prints a formatted unicode string to the default console
831 X - X coordinate to start printing
833 Y - Y coordinate to start printing
835 ForeGround - Foreground color
837 BackGround - Background color
841 ... - Print arguments
845 Length of string printed to the console
851 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
852 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
853 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
857 VA_START (Args
, Fmt
);
861 Handle
= gST
->ConsoleOutHandle
;
863 Status
= gBS
->HandleProtocol (
865 &gEfiGraphicsOutputProtocolGuid
,
866 (VOID
**) &GraphicsOutput
869 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
870 GraphicsOutput
= NULL
;
872 Status
= gBS
->HandleProtocol (
874 &gEfiUgaDrawProtocolGuid
,
879 if (EFI_ERROR (Status
)) {
883 Status
= gBS
->HandleProtocol (
885 &gEfiSimpleTextOutProtocolGuid
,
889 if (EFI_ERROR (Status
)) {
893 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);