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 Return the graphics image file named FileNameGuid into Image and return it's
42 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
45 @param FileNameGuid - File Name of graphics file in the FV(s).
47 @param Image - Pointer to pointer to return graphics image. If NULL, a
48 buffer will be allocated.
50 @param ImageSize - Size of the graphics Image in bytes. Zero if no image found.
52 @retval EFI_SUCCESS - Image and ImageSize are valid.
53 @retval EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
54 @retval EFI_NOT_FOUND - FileNameGuid not found
59 GetGraphicsBitMapFromFV (
60 IN EFI_GUID
*FileNameGuid
,
66 UINTN FvProtocolCount
;
67 EFI_HANDLE
*FvHandles
;
68 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
70 UINT32 AuthenticationStatus
;
73 Status
= gBS
->LocateHandleBuffer (
75 &gEfiFirmwareVolume2ProtocolGuid
,
80 if (EFI_ERROR (Status
)) {
84 for (Index
= 0; Index
< FvProtocolCount
; Index
++) {
85 Status
= gBS
->HandleProtocol (
87 &gEfiFirmwareVolume2ProtocolGuid
,
92 // Assuming Image and ImageSize are correct on input.
94 Status
= Fv
->ReadSection (
101 &AuthenticationStatus
103 if (!EFI_ERROR (Status
)) {
105 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
107 // ImageSize updated to needed size so return
109 return EFI_BUFFER_TOO_SMALL
;
113 return EFI_NOT_FOUND
;
117 Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
118 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
119 buffer is passed in it will be used if it is big enough.
121 @param BmpImage - Pointer to BMP file
123 @param BmpImageSize - Number of bytes in BmpImage
125 @param GopBlt - Buffer containing GOP version of BmpImage.
127 @param GopBltSize - Size of GopBlt in bytes.
129 @param PixelHeight - Height of GopBlt/BmpImage in pixels
131 @param PixelWidth - Width of GopBlt/BmpImage in pixels
134 @retval EFI_SUCCESS - GopBlt and GopBltSize are returned.
135 @retval EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image
136 @retval EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.
137 GopBltSize will contain the required size.
138 @retval EFI_OUT_OF_RESOURCES - No enough buffer to allocate
145 IN UINTN BmpImageSize
,
146 IN OUT VOID
**GopBlt
,
147 IN OUT UINTN
*GopBltSize
,
148 OUT UINTN
*PixelHeight
,
149 OUT UINTN
*PixelWidth
155 BMP_IMAGE_HEADER
*BmpHeader
;
156 BMP_COLOR_MAP
*BmpColorMap
;
157 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
;
158 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
166 BmpHeader
= (BMP_IMAGE_HEADER
*) BmpImage
;
167 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M') {
168 return EFI_UNSUPPORTED
;
171 if (BmpHeader
->CompressionType
!= 0) {
172 return EFI_UNSUPPORTED
;
176 // Calculate Color Map offset in the image.
179 BmpColorMap
= (BMP_COLOR_MAP
*) (Image
+ sizeof (BMP_IMAGE_HEADER
));
182 // Calculate graphics image data address in the image
184 Image
= ((UINT8
*) BmpImage
) + BmpHeader
->ImageOffset
;
187 BltBufferSize
= BmpHeader
->PixelWidth
* BmpHeader
->PixelHeight
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
189 if (*GopBlt
== NULL
) {
190 *GopBltSize
= BltBufferSize
;
191 *GopBlt
= AllocatePool (*GopBltSize
);
193 if (*GopBlt
== NULL
) {
194 return EFI_OUT_OF_RESOURCES
;
197 if (*GopBltSize
< BltBufferSize
) {
198 *GopBltSize
= BltBufferSize
;
199 return EFI_BUFFER_TOO_SMALL
;
203 *PixelWidth
= BmpHeader
->PixelWidth
;
204 *PixelHeight
= BmpHeader
->PixelHeight
;
207 // Convert image from BMP to Blt buffer format
210 for (Height
= 0; Height
< BmpHeader
->PixelHeight
; Height
++) {
211 Blt
= &BltBuffer
[(BmpHeader
->PixelHeight
- Height
- 1) * BmpHeader
->PixelWidth
];
212 for (Width
= 0; Width
< BmpHeader
->PixelWidth
; Width
++, Image
++, Blt
++) {
213 switch (BmpHeader
->BitPerPixel
) {
216 // Convert 1bit BMP to 24-bit color
218 for (Index
= 0; Index
< 8 && Width
< BmpHeader
->PixelWidth
; Index
++) {
219 Blt
->Red
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Red
;
220 Blt
->Green
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Green
;
221 Blt
->Blue
= BmpColorMap
[((*Image
) >> (7 - Index
)) & 0x1].Blue
;
232 // Convert BMP Palette to 24-bit color
234 Index
= (*Image
) >> 4;
235 Blt
->Red
= BmpColorMap
[Index
].Red
;
236 Blt
->Green
= BmpColorMap
[Index
].Green
;
237 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
238 if (Width
< (BmpHeader
->PixelWidth
- 1)) {
241 Index
= (*Image
) & 0x0f;
242 Blt
->Red
= BmpColorMap
[Index
].Red
;
243 Blt
->Green
= BmpColorMap
[Index
].Green
;
244 Blt
->Blue
= BmpColorMap
[Index
].Blue
;
250 // Convert BMP Palette to 24-bit color
252 Blt
->Red
= BmpColorMap
[*Image
].Red
;
253 Blt
->Green
= BmpColorMap
[*Image
].Green
;
254 Blt
->Blue
= BmpColorMap
[*Image
].Blue
;
258 Blt
->Blue
= *Image
++;
259 Blt
->Green
= *Image
++;
265 gBS
->FreePool (*GopBlt
);
268 return EFI_UNSUPPORTED
;
274 ImageIndex
= (UINTN
) (Image
- ImageHeader
);
275 if ((ImageIndex
% 4) != 0) {
277 // Bmp Image starts each row on a 32-bit boundary!
279 Image
= Image
+ (4 - (ImageIndex
% 4));
287 Use Console Control Protocol to lock the Console In Spliter virtual handle.
288 This is the ConInHandle and ConIn handle in the EFI system table. All key
289 presses will be ignored until the Password is typed in. The only way to
290 disable the password is to type it in to a ConIn device.
292 @param Password - Password used to lock ConIn device
294 @retval EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
296 @retval EFI_UNSUPPORTED - Logo not found
305 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
307 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
308 if (EFI_ERROR (Status
)) {
309 return EFI_UNSUPPORTED
;
312 Status
= ConsoleControl
->LockStdIn (ConsoleControl
, Password
);
317 Use Console Control to turn off UGA based Simple Text Out consoles from going
318 to the UGA device. Put up LogoFile on every UGA device that is a console
320 @param LogoFile - File name of logo to display on the center of the screen.
322 @retval EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
324 @retval EFI_UNSUPPORTED - Logo not found
329 IN EFI_GUID
*LogoFile
334 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
335 EFI_OEM_BADGING_PROTOCOL
*Badging
;
344 EFI_BADGING_FORMAT Format
;
345 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute
;
350 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
351 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
354 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
356 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
357 if (EFI_ERROR (Status
)) {
358 return EFI_UNSUPPORTED
;
363 // Try to open GOP first
365 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiGraphicsOutputProtocolGuid
, (VOID
**) &GraphicsOutput
);
366 if (EFI_ERROR(Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
367 GraphicsOutput
= NULL
;
369 // Open GOP failed, try to open UGA
371 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
, &gEfiUgaDrawProtocolGuid
, (VOID
**) &UgaDraw
);
373 if (EFI_ERROR (Status
)) {
374 return EFI_UNSUPPORTED
;
378 Status
= gBS
->LocateProtocol (&gEfiOEMBadgingProtocolGuid
, NULL
, (VOID
**) &Badging
);
380 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenGraphics
);
382 if (GraphicsOutput
!= NULL
) {
383 SizeOfX
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
384 SizeOfY
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
385 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
386 Status
= UgaDraw
->GetMode (UgaDraw
, &SizeOfX
, &SizeOfY
, &ColorDepth
, &RefreshRate
);
387 if (EFI_ERROR (Status
)) {
388 return EFI_UNSUPPORTED
;
391 return EFI_UNSUPPORTED
;
399 if (Badging
!= NULL
) {
400 Status
= Badging
->GetImage (
410 if (EFI_ERROR (Status
)) {
415 // Currently only support BMP format
417 if (Format
!= EfiBadgingFormatBMP
) {
418 gBS
->FreePool (ImageData
);
422 Status
= GetGraphicsBitMapFromFV (LogoFile
, (VOID
**) &ImageData
, &ImageSize
);
423 if (EFI_ERROR (Status
)) {
424 return EFI_UNSUPPORTED
;
429 Attribute
= EfiBadgingDisplayAttributeCenter
;
434 Status
= ConvertBmpToGopBlt (
442 if (EFI_ERROR (Status
)) {
443 gBS
->FreePool (ImageData
);
444 if (Badging
== NULL
) {
452 case EfiBadgingDisplayAttributeLeftTop
:
457 case EfiBadgingDisplayAttributeCenterTop
:
458 DestX
= (SizeOfX
- Width
) / 2;
462 case EfiBadgingDisplayAttributeRightTop
:
463 DestX
= (SizeOfX
- Width
- CoordinateX
);
464 DestY
= CoordinateY
;;
467 case EfiBadgingDisplayAttributeCenterRight
:
468 DestX
= (SizeOfX
- Width
- CoordinateX
);
469 DestY
= (SizeOfY
- Height
) / 2;
472 case EfiBadgingDisplayAttributeRightBottom
:
473 DestX
= (SizeOfX
- Width
- CoordinateX
);
474 DestY
= (SizeOfY
- Height
- CoordinateY
);
477 case EfiBadgingDisplayAttributeCenterBottom
:
478 DestX
= (SizeOfX
- Width
) / 2;
479 DestY
= (SizeOfY
- Height
- CoordinateY
);
482 case EfiBadgingDisplayAttributeLeftBottom
:
484 DestY
= (SizeOfY
- Height
- CoordinateY
);
487 case EfiBadgingDisplayAttributeCenterLeft
:
489 DestY
= (SizeOfY
- Height
) / 2;
492 case EfiBadgingDisplayAttributeCenter
:
493 DestX
= (SizeOfX
- Width
) / 2;
494 DestY
= (SizeOfY
- Height
) / 2;
503 if ((DestX
>= 0) && (DestY
>= 0)) {
504 if (GraphicsOutput
!= NULL
) {
505 Status
= GraphicsOutput
->Blt (
515 Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
517 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
518 Status
= UgaDraw
->Blt (
520 (EFI_UGA_PIXEL
*) Blt
,
521 EfiUgaBltBufferToVideo
,
528 Width
* sizeof (EFI_UGA_PIXEL
)
531 Status
= EFI_UNSUPPORTED
;
535 gBS
->FreePool (ImageData
);
538 if (Badging
== NULL
) {
547 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
548 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
550 @retval EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
551 @retval EFI_UNSUPPORTED - Logo not found
560 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
562 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, (VOID
**) &ConsoleControl
);
563 if (EFI_ERROR (Status
)) {
564 return EFI_UNSUPPORTED
;
567 return ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);
570 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
571 { 0x00, 0x00, 0x00, 0x00 },
572 { 0x98, 0x00, 0x00, 0x00 },
573 { 0x00, 0x98, 0x00, 0x00 },
574 { 0x98, 0x98, 0x00, 0x00 },
575 { 0x00, 0x00, 0x98, 0x00 },
576 { 0x98, 0x00, 0x98, 0x00 },
577 { 0x00, 0x98, 0x98, 0x00 },
578 { 0x98, 0x98, 0x98, 0x00 },
579 { 0x10, 0x10, 0x10, 0x00 },
580 { 0xff, 0x10, 0x10, 0x00 },
581 { 0x10, 0xff, 0x10, 0x00 },
582 { 0xff, 0xff, 0x10, 0x00 },
583 { 0x10, 0x10, 0xff, 0x00 },
584 { 0xf0, 0x10, 0xff, 0x00 },
585 { 0x10, 0xff, 0xff, 0x00 },
586 { 0xff, 0xff, 0xff, 0x00 }
590 Display string worker for: Print, PrintAt, IPrint, IPrintAt
592 @param GraphicsOutput - Graphics output protocol interface
594 @param UgaDraw - UGA draw protocol interface
596 @param Sto - Simple text out protocol interface
598 @param X - X coordinate to start printing
600 @param Y - Y coordinate to start printing
602 @param Foreground - Foreground color
604 @param Background - Background color
606 @param fmt - Format string
608 @param args - Print arguments
611 @retval EFI_SUCCESS - success
612 @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
;
651 // For now, allocate an arbitrarily long buffer
653 Buffer
= AllocateZeroPool (0x10000);
654 if (Buffer
== NULL
) {
655 return EFI_OUT_OF_RESOURCES
;
658 if (GraphicsOutput
!= NULL
) {
659 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
660 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
661 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
663 // Get the current mode information from the UGA Draw Protocol
665 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
667 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
669 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
670 LineBuffer
= AllocatePool (LineBufferLen
);
671 if (LineBuffer
== NULL
) {
672 gBS
->FreePool (Buffer
);
673 return EFI_OUT_OF_RESOURCES
;
676 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**) &Hii
);
677 if (EFI_ERROR (Status
)) {
681 UnicodeVSPrint (Buffer
, 0x10000, fmt
, args
);
683 UnicodeWeight
= (CHAR16
*) Buffer
;
685 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
686 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
687 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
688 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
689 UnicodeWeight
[Index
] = 0;
693 BufferLen
= StrLen (Buffer
);
695 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
696 Status
= EFI_INVALID_PARAMETER
;
700 for (Index
= 0; Index
< BufferLen
; Index
++) {
701 StringIndex
= (UINT16
) Index
;
702 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
703 if (EFI_ERROR (Status
)) {
707 if (Foreground
== NULL
|| Background
== NULL
) {
708 Status
= Hii
->GlyphToBlt (
711 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
712 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
716 &LineBuffer
[Index
* GLYPH_WIDTH
]
719 Status
= Hii
->GlyphToBlt (
727 &LineBuffer
[Index
* GLYPH_WIDTH
]
733 // Blt a character to the screen
735 BufferGlyphWidth
= GLYPH_WIDTH
* BufferLen
;
736 if (GraphicsOutput
!= NULL
) {
737 Status
= GraphicsOutput
->Blt (
747 BufferGlyphWidth
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
749 } else if (FeaturePcdGet (PcdUgaConsumeSupport
)) {
750 Status
= UgaDraw
->Blt (
752 (EFI_UGA_PIXEL
*) (UINTN
) LineBuffer
,
753 EfiUgaBltBufferToVideo
,
760 BufferGlyphWidth
* sizeof (EFI_UGA_PIXEL
)
763 Status
= EFI_UNSUPPORTED
;
767 gBS
->FreePool (LineBuffer
);
768 gBS
->FreePool (Buffer
);
773 Prints a formatted unicode string to the default console
775 @param X - X coordinate to start printing
777 @param Y - Y coordinate to start printing
779 @param ForeGround - Foreground color
781 @param BackGround - Background color
783 @param Fmt - Format string
785 @param ... - Print arguments
788 @retval Length of string printed to the console
795 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
796 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
803 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
804 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
805 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Sto
;
809 VA_START (Args
, Fmt
);
813 Handle
= gST
->ConsoleOutHandle
;
815 Status
= gBS
->HandleProtocol (
817 &gEfiGraphicsOutputProtocolGuid
,
818 (VOID
**) &GraphicsOutput
821 if (EFI_ERROR (Status
) && FeaturePcdGet (PcdUgaConsumeSupport
)) {
822 GraphicsOutput
= NULL
;
824 Status
= gBS
->HandleProtocol (
826 &gEfiUgaDrawProtocolGuid
,
831 if (EFI_ERROR (Status
)) {
835 Status
= gBS
->HandleProtocol (
837 &gEfiSimpleTextOutProtocolGuid
,
841 if (EFI_ERROR (Status
)) {
845 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);