1.Removed PrintXY from Graphics Library.
[edk2.git] / MdeModulePkg / Library / GraphicsLib / Graphics.c
blob63e0696cf4f553fb6873b8dbe28fa96816b70c5f
1 /** @file
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 Copyright (c) 2006 - 2008, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 **/
19 #include <PiDxe.h>
21 #include <Protocol/SimpleTextOut.h>
22 #include <Protocol/OEMBadging.h>
23 #include <Protocol/ConsoleControl.h>
24 #include <Protocol/GraphicsOutput.h>
25 #include <Protocol/UgaDraw.h>
26 #include <Protocol/HiiFont.h>
27 #include <Protocol/HiiImage.h>
29 #include <Guid/Bmp.h>
31 #include <Library/GraphicsLib.h>
32 #include <Library/PrintLib.h>
33 #include <Library/BaseLib.h>
34 #include <Library/MemoryAllocationLib.h>
35 #include <Library/UefiBootServicesTableLib.h>
36 #include <Library/DebugLib.h>
37 #include <Library/BaseMemoryLib.h>
38 #include <Library/DxeServicesLib.h>
39 #include <Library/PcdLib.h>
42 /**
43 Return the graphics image file named FileNameGuid into Image and return it's
44 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
45 file name.
47 @param FileNameGuid File Name of graphics file in the FV(s).
48 @param Image Pointer to pointer to return graphics image. If NULL, a
49 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
56 **/
57 EFI_STATUS
58 EFIAPI
59 GetGraphicsBitMapFromFV (
60 IN EFI_GUID *FileNameGuid,
61 OUT VOID **Image,
62 OUT UINTN *ImageSize
65 return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);
68 /**
69 Return the graphics image file named FileNameGuid into Image and return it's
70 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
71 file name.
73 @param ImageHandle The driver image handle of the caller. The parameter is used to
74 optimize the loading of the image file so that the FV from which
75 the driver image is loaded will be tried first.
76 @param FileNameGuid File Name of graphics file in the FV(s).
77 @param Image Pointer to pointer to return graphics image. If NULL, a
78 buffer will be allocated.
79 @param ImageSize Size of the graphics Image in bytes. Zero if no image found.
81 @retval EFI_SUCCESS Image and ImageSize are valid.
82 @retval EFI_BUFFER_TOO_SMALL Image not big enough. ImageSize has required size
83 @retval EFI_NOT_FOUND FileNameGuid not found
85 **/
86 EFI_STATUS
87 EFIAPI
88 GetGraphicsBitMapFromFVEx (
89 IN EFI_HANDLE ImageHandle,
90 IN EFI_GUID *FileNameGuid,
91 OUT VOID **Image,
92 OUT UINTN *ImageSize
95 return GetSectionFromAnyFv (
96 FileNameGuid,
97 EFI_SECTION_RAW,
99 Image,
100 ImageSize
105 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
106 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
107 buffer is passed in it will be used if it is big enough.
109 @param BmpImage Pointer to BMP file
110 @param BmpImageSize Number of bytes in BmpImage
111 @param GopBlt Buffer containing GOP version of BmpImage.
112 @param GopBltSize Size of GopBlt in bytes.
113 @param PixelHeight Height of GopBlt/BmpImage in pixels
114 @param PixelWidth Width of GopBlt/BmpImage in pixels
116 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
117 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
118 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
119 GopBltSize will contain the required size.
120 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
123 EFI_STATUS
124 EFIAPI
125 ConvertBmpToGopBlt (
126 IN VOID *BmpImage,
127 IN UINTN BmpImageSize,
128 IN OUT VOID **GopBlt,
129 IN OUT UINTN *GopBltSize,
130 OUT UINTN *PixelHeight,
131 OUT UINTN *PixelWidth
134 UINT8 *Image;
135 UINT8 *ImageHeader;
136 BMP_IMAGE_HEADER *BmpHeader;
137 BMP_COLOR_MAP *BmpColorMap;
138 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
139 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
140 UINTN BltBufferSize;
141 UINTN Index;
142 UINTN Height;
143 UINTN Width;
144 UINTN ImageIndex;
145 BOOLEAN IsAllocated;
147 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
149 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
150 return EFI_UNSUPPORTED;
154 // Doesn't support compress.
156 if (BmpHeader->CompressionType != 0) {
157 return EFI_UNSUPPORTED;
161 // Calculate Color Map offset in the image.
163 Image = BmpImage;
164 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
167 // Calculate graphics image data address in the image
169 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
170 ImageHeader = Image;
173 // Calculate the BltBuffer needed size.
175 BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
176 IsAllocated = FALSE;
177 if (*GopBlt == NULL) {
179 // GopBlt is not allocated by caller.
181 *GopBltSize = BltBufferSize;
182 *GopBlt = AllocatePool (*GopBltSize);
183 IsAllocated = TRUE;
184 if (*GopBlt == NULL) {
185 return EFI_OUT_OF_RESOURCES;
187 } else {
189 // GopBlt has been allocated by caller.
191 if (*GopBltSize < BltBufferSize) {
192 *GopBltSize = BltBufferSize;
193 return EFI_BUFFER_TOO_SMALL;
197 *PixelWidth = BmpHeader->PixelWidth;
198 *PixelHeight = BmpHeader->PixelHeight;
201 // Convert image from BMP to Blt buffer format
203 BltBuffer = *GopBlt;
204 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
205 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
206 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
207 switch (BmpHeader->BitPerPixel) {
208 case 1:
210 // Convert 1-bit (2 colors) BMP to 24-bit color
212 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
213 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
214 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
215 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
216 Blt++;
217 Width++;
220 Blt --;
221 Width --;
222 break;
224 case 4:
226 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
228 Index = (*Image) >> 4;
229 Blt->Red = BmpColorMap[Index].Red;
230 Blt->Green = BmpColorMap[Index].Green;
231 Blt->Blue = BmpColorMap[Index].Blue;
232 if (Width < (BmpHeader->PixelWidth - 1)) {
233 Blt++;
234 Width++;
235 Index = (*Image) & 0x0f;
236 Blt->Red = BmpColorMap[Index].Red;
237 Blt->Green = BmpColorMap[Index].Green;
238 Blt->Blue = BmpColorMap[Index].Blue;
240 break;
242 case 8:
244 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
246 Blt->Red = BmpColorMap[*Image].Red;
247 Blt->Green = BmpColorMap[*Image].Green;
248 Blt->Blue = BmpColorMap[*Image].Blue;
249 break;
251 case 24:
253 // It is 24-bit BMP.
255 Blt->Blue = *Image++;
256 Blt->Green = *Image++;
257 Blt->Red = *Image;
258 break;
260 default:
262 // Other bit format BMP is not supported.
264 if (IsAllocated) {
265 FreePool (*GopBlt);
266 *GopBlt = NULL;
268 return EFI_UNSUPPORTED;
269 break;
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));
283 return EFI_SUCCESS;
288 Use Console Control Protocol to lock the Console In Spliter virtual handle.
289 This is the ConInHandle and ConIn handle in the EFI system table. All key
290 presses will be ignored until the Password is typed in. The only way to
291 disable the password is to type it in to a ConIn device.
293 @param Password Password used to lock ConIn device.
295 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
296 @retval EFI_UNSUPPORTED Password not found.
299 EFI_STATUS
300 EFIAPI
301 LockKeyboards (
302 IN CHAR16 *Password
305 EFI_STATUS Status;
306 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
308 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
309 if (EFI_ERROR (Status)) {
310 return EFI_UNSUPPORTED;
313 Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
314 return Status;
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 displayed.
325 @retval EFI_UNSUPPORTED Logo not found.
328 EFI_STATUS
329 EFIAPI
330 EnableQuietBoot (
331 IN EFI_GUID *LogoFile
334 return EnableQuietBootEx (LogoFile, NULL);
338 Use Console Control to turn off UGA based Simple Text Out consoles from going
339 to the UGA device. Put up LogoFile on every UGA device that is a console
341 @param LogoFile File name of logo to display on the center of the screen.
342 @param ImageHandle The driver image handle of the caller. The parameter is used to
343 optimize the loading of the logo file so that the FV from which
344 the driver image is loaded will be tried first.
346 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
347 @retval EFI_UNSUPPORTED Logo not found.
350 EFI_STATUS
351 EFIAPI
352 EnableQuietBootEx (
353 IN EFI_GUID *LogoFile,
354 IN EFI_HANDLE ImageHandle
357 EFI_STATUS Status;
358 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
359 EFI_OEM_BADGING_PROTOCOL *Badging;
360 UINT32 SizeOfX;
361 UINT32 SizeOfY;
362 INTN DestX;
363 INTN DestY;
364 UINT8 *ImageData;
365 UINTN ImageSize;
366 UINTN BltSize;
367 UINT32 Instance;
368 EFI_BADGING_FORMAT Format;
369 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
370 UINTN CoordinateX;
371 UINTN CoordinateY;
372 UINTN Height;
373 UINTN Width;
374 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
375 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
376 UINT32 ColorDepth;
377 UINT32 RefreshRate;
378 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
380 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
381 if (EFI_ERROR (Status)) {
382 return EFI_UNSUPPORTED;
385 UgaDraw = NULL;
387 // Try to open GOP first
389 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
390 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
391 GraphicsOutput = NULL;
393 // Open GOP failed, try to open UGA
395 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
397 if (EFI_ERROR (Status)) {
398 return EFI_UNSUPPORTED;
401 Badging = NULL;
402 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
405 // Set console control to graphics mode.
407 Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
408 if (EFI_ERROR (Status)) {
409 return EFI_UNSUPPORTED;
412 if (GraphicsOutput != NULL) {
413 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
414 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
415 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
416 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
417 if (EFI_ERROR (Status)) {
418 return EFI_UNSUPPORTED;
420 } else {
421 return EFI_UNSUPPORTED;
424 Instance = 0;
425 while (1) {
426 ImageData = NULL;
427 ImageSize = 0;
429 if (Badging != NULL) {
431 // Get image from OEMBadging protocol.
433 Status = Badging->GetImage (
434 Badging,
435 &Instance,
436 &Format,
437 &ImageData,
438 &ImageSize,
439 &Attribute,
440 &CoordinateX,
441 &CoordinateY
443 if (EFI_ERROR (Status)) {
444 return Status;
448 // Currently only support BMP format.
450 if (Format != EfiBadgingFormatBMP) {
451 if (ImageData != NULL) {
452 FreePool (ImageData);
454 continue;
456 } else {
458 // Get the specified image from FV.
460 Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
461 if (EFI_ERROR (Status)) {
462 return EFI_UNSUPPORTED;
465 CoordinateX = 0;
466 CoordinateY = 0;
467 Attribute = EfiBadgingDisplayAttributeCenter;
470 Blt = NULL;
471 Status = ConvertBmpToGopBlt (
472 ImageData,
473 ImageSize,
474 (VOID **) &Blt,
475 &BltSize,
476 &Height,
477 &Width
479 if (EFI_ERROR (Status)) {
480 if (ImageData != NULL) {
481 FreePool (ImageData);
483 if (Badging == NULL) {
484 return Status;
485 } else {
486 continue;
491 // Caculate the display position according to Attribute.
493 switch (Attribute) {
494 case EfiBadgingDisplayAttributeLeftTop:
495 DestX = CoordinateX;
496 DestY = CoordinateY;
497 break;
499 case EfiBadgingDisplayAttributeCenterTop:
500 DestX = (SizeOfX - Width) / 2;
501 DestY = CoordinateY;
502 break;
504 case EfiBadgingDisplayAttributeRightTop:
505 DestX = (SizeOfX - Width - CoordinateX);
506 DestY = CoordinateY;;
507 break;
509 case EfiBadgingDisplayAttributeCenterRight:
510 DestX = (SizeOfX - Width - CoordinateX);
511 DestY = (SizeOfY - Height) / 2;
512 break;
514 case EfiBadgingDisplayAttributeRightBottom:
515 DestX = (SizeOfX - Width - CoordinateX);
516 DestY = (SizeOfY - Height - CoordinateY);
517 break;
519 case EfiBadgingDisplayAttributeCenterBottom:
520 DestX = (SizeOfX - Width) / 2;
521 DestY = (SizeOfY - Height - CoordinateY);
522 break;
524 case EfiBadgingDisplayAttributeLeftBottom:
525 DestX = CoordinateX;
526 DestY = (SizeOfY - Height - CoordinateY);
527 break;
529 case EfiBadgingDisplayAttributeCenterLeft:
530 DestX = CoordinateX;
531 DestY = (SizeOfY - Height) / 2;
532 break;
534 case EfiBadgingDisplayAttributeCenter:
535 DestX = (SizeOfX - Width) / 2;
536 DestY = (SizeOfY - Height) / 2;
537 break;
539 default:
540 DestX = CoordinateX;
541 DestY = CoordinateY;
542 break;
545 if ((DestX >= 0) && (DestY >= 0)) {
546 if (GraphicsOutput != NULL) {
547 Status = GraphicsOutput->Blt (
548 GraphicsOutput,
549 Blt,
550 EfiBltBufferToVideo,
553 (UINTN) DestX,
554 (UINTN) DestY,
555 Width,
556 Height,
557 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
559 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
560 Status = UgaDraw->Blt (
561 UgaDraw,
562 (EFI_UGA_PIXEL *) Blt,
563 EfiUgaBltBufferToVideo,
566 (UINTN) DestX,
567 (UINTN) DestY,
568 Width,
569 Height,
570 Width * sizeof (EFI_UGA_PIXEL)
572 } else {
573 Status = EFI_UNSUPPORTED;
577 if (ImageData != NULL) {
578 FreePool (ImageData);
580 if (Blt != NULL) {
581 FreePool (Blt);
584 if (Badging == NULL) {
585 break;
589 return Status;
593 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA
594 Simple Text Out screens will now be synced up with all non UGA output devices
596 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
597 @retval EFI_UNSUPPORTED Logo not found
600 EFI_STATUS
601 EFIAPI
602 DisableQuietBoot (
603 VOID
606 EFI_STATUS Status;
607 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
609 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
610 if (EFI_ERROR (Status)) {
611 return EFI_UNSUPPORTED;
615 // Set console control to text mode.
617 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);