]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/GraphicsLib/Graphics.c
check list clean.
[mirror_edk2.git] / MdeModulePkg / Library / GraphicsLib / Graphics.c
1 /** @file
2 Basic Graphics operations based on UEFI HII, Graphics Output protocol or UGA
3 Draw protocol.
4
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <PiDxe.h>
18
19 #include <Protocol/SimpleTextOut.h>
20 #include <Protocol/OEMBadging.h>
21 #include <Protocol/ConsoleControl.h>
22 #include <Protocol/GraphicsOutput.h>
23 #include <Protocol/FirmwareVolume2.h>
24 #include <Protocol/UgaDraw.h>
25 #include <Protocol/HiiFont.h>
26 #include <Protocol/HiiImage.h>
27
28 #include <Guid/Bmp.h>
29
30 #include <Library/GraphicsLib.h>
31 #include <Library/PrintLib.h>
32 #include <Library/BaseLib.h>
33 #include <Library/MemoryAllocationLib.h>
34 #include <Library/UefiBootServicesTableLib.h>
35 #include <Library/DebugLib.h>
36 #include <Library/BaseMemoryLib.h>
37 #include <Library/DxePiLib.h>
38 #include <Library/PcdLib.h>
39
40 STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {
41 { 0x00, 0x00, 0x00, 0x00 },
42 { 0x98, 0x00, 0x00, 0x00 },
43 { 0x00, 0x98, 0x00, 0x00 },
44 { 0x98, 0x98, 0x00, 0x00 },
45 { 0x00, 0x00, 0x98, 0x00 },
46 { 0x98, 0x00, 0x98, 0x00 },
47 { 0x00, 0x98, 0x98, 0x00 },
48 { 0x98, 0x98, 0x98, 0x00 },
49 { 0x10, 0x10, 0x10, 0x00 },
50 { 0xff, 0x10, 0x10, 0x00 },
51 { 0x10, 0xff, 0x10, 0x00 },
52 { 0xff, 0xff, 0x10, 0x00 },
53 { 0x10, 0x10, 0xff, 0x00 },
54 { 0xf0, 0x10, 0xff, 0x00 },
55 { 0x10, 0xff, 0xff, 0x00 },
56 { 0xff, 0xff, 0xff, 0x00 }
57 };
58
59
60 /**
61 Return the graphics image file named FileNameGuid into Image and return it's
62 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
63 file name.
64
65 @param FileNameGuid File Name of graphics file in the FV(s).
66 @param Image Pointer to pointer to return graphics image. If NULL, a
67 buffer will be allocated.
68 @param ImageSize Size of the graphics Image in bytes. Zero if no image found.
69
70 @retval EFI_SUCCESS Image and ImageSize are valid.
71 @retval EFI_BUFFER_TOO_SMALL Image not big enough. ImageSize has required size
72 @retval EFI_NOT_FOUND FileNameGuid not found
73
74 **/
75 EFI_STATUS
76 EFIAPI
77 GetGraphicsBitMapFromFV (
78 IN EFI_GUID *FileNameGuid,
79 OUT VOID **Image,
80 OUT UINTN *ImageSize
81 )
82 {
83 return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);
84 }
85
86 /**
87 Return the graphics image file named FileNameGuid into Image and return it's
88 size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
89 file name.
90
91 @param ImageHandle The driver image handle of the caller. The parameter is used to
92 optimize the loading of the image file so that the FV from which
93 the driver image is loaded will be tried first.
94 @param FileNameGuid File Name of graphics file in the FV(s).
95 @param Image Pointer to pointer to return graphics image. If NULL, a
96 buffer will be allocated.
97 @param ImageSize Size of the graphics Image in bytes. Zero if no image found.
98
99 @retval EFI_SUCCESS Image and ImageSize are valid.
100 @retval EFI_BUFFER_TOO_SMALL Image not big enough. ImageSize has required size
101 @retval EFI_NOT_FOUND FileNameGuid not found
102
103 **/
104 EFI_STATUS
105 EFIAPI
106 GetGraphicsBitMapFromFVEx (
107 IN EFI_HANDLE ImageHandle,
108 IN EFI_GUID *FileNameGuid,
109 OUT VOID **Image,
110 OUT UINTN *ImageSize
111 )
112 {
113 return PiLibGetSectionFromAnyFv (
114 FileNameGuid,
115 EFI_SECTION_RAW,
116 0,
117 Image,
118 ImageSize
119 );
120 }
121
122 /**
123 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
124 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
125 buffer is passed in it will be used if it is big enough.
126
127 @param BmpImage Pointer to BMP file
128 @param BmpImageSize Number of bytes in BmpImage
129 @param GopBlt Buffer containing GOP version of BmpImage.
130 @param GopBltSize Size of GopBlt in bytes.
131 @param PixelHeight Height of GopBlt/BmpImage in pixels
132 @param PixelWidth Width of GopBlt/BmpImage in pixels
133
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.
139
140 **/
141 EFI_STATUS
142 EFIAPI
143 ConvertBmpToGopBlt (
144 IN VOID *BmpImage,
145 IN UINTN BmpImageSize,
146 IN OUT VOID **GopBlt,
147 IN OUT UINTN *GopBltSize,
148 OUT UINTN *PixelHeight,
149 OUT UINTN *PixelWidth
150 )
151 {
152 UINT8 *Image;
153 UINT8 *ImageHeader;
154 BMP_IMAGE_HEADER *BmpHeader;
155 BMP_COLOR_MAP *BmpColorMap;
156 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
157 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
158 UINTN BltBufferSize;
159 UINTN Index;
160 UINTN Height;
161 UINTN Width;
162 UINTN ImageIndex;
163 BOOLEAN IsAllocated;
164
165 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
166
167 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
168 return EFI_UNSUPPORTED;
169 }
170
171 //
172 // Doesn't support compress.
173 //
174 if (BmpHeader->CompressionType != 0) {
175 return EFI_UNSUPPORTED;
176 }
177
178 //
179 // Calculate Color Map offset in the image.
180 //
181 Image = BmpImage;
182 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
183
184 //
185 // Calculate graphics image data address in the image
186 //
187 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
188 ImageHeader = Image;
189
190 //
191 // Calculate the BltBuffer needed size.
192 //
193 BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
194 IsAllocated = FALSE;
195 if (*GopBlt == NULL) {
196 //
197 // GopBlt is not allocated by caller.
198 //
199 *GopBltSize = BltBufferSize;
200 *GopBlt = AllocatePool (*GopBltSize);
201 IsAllocated = TRUE;
202 if (*GopBlt == NULL) {
203 return EFI_OUT_OF_RESOURCES;
204 }
205 } else {
206 //
207 // GopBlt has been allocated by caller.
208 //
209 if (*GopBltSize < BltBufferSize) {
210 *GopBltSize = BltBufferSize;
211 return EFI_BUFFER_TOO_SMALL;
212 }
213 }
214
215 *PixelWidth = BmpHeader->PixelWidth;
216 *PixelHeight = BmpHeader->PixelHeight;
217
218 //
219 // Convert image from BMP to Blt buffer format
220 //
221 BltBuffer = *GopBlt;
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) {
226 case 1:
227 //
228 // Convert 1-bit (2 colors) BMP to 24-bit color
229 //
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;
234 Blt++;
235 Width++;
236 }
237
238 Blt --;
239 Width --;
240 break;
241
242 case 4:
243 //
244 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
245 //
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)) {
251 Blt++;
252 Width++;
253 Index = (*Image) & 0x0f;
254 Blt->Red = BmpColorMap[Index].Red;
255 Blt->Green = BmpColorMap[Index].Green;
256 Blt->Blue = BmpColorMap[Index].Blue;
257 }
258 break;
259
260 case 8:
261 //
262 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
263 //
264 Blt->Red = BmpColorMap[*Image].Red;
265 Blt->Green = BmpColorMap[*Image].Green;
266 Blt->Blue = BmpColorMap[*Image].Blue;
267 break;
268
269 case 24:
270 //
271 // It is 24-bit BMP.
272 //
273 Blt->Blue = *Image++;
274 Blt->Green = *Image++;
275 Blt->Red = *Image;
276 break;
277
278 default:
279 //
280 // Other bit format BMP is not supported.
281 //
282 if (IsAllocated) {
283 FreePool (*GopBlt);
284 *GopBlt = NULL;
285 }
286 return EFI_UNSUPPORTED;
287 break;
288 };
289
290 }
291
292 ImageIndex = (UINTN) (Image - ImageHeader);
293 if ((ImageIndex % 4) != 0) {
294 //
295 // Bmp Image starts each row on a 32-bit boundary!
296 //
297 Image = Image + (4 - (ImageIndex % 4));
298 }
299 }
300
301 return EFI_SUCCESS;
302 }
303
304
305 /**
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.
310
311 @param Password Password used to lock ConIn device.
312
313 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo
314 displayed.
315 @retval EFI_UNSUPPORTED Password not found.
316
317 **/
318 EFI_STATUS
319 EFIAPI
320 LockKeyboards (
321 IN CHAR16 *Password
322 )
323 {
324 EFI_STATUS Status;
325 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
326
327 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
328 if (EFI_ERROR (Status)) {
329 return EFI_UNSUPPORTED;
330 }
331
332 Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
333 return Status;
334 }
335
336
337 /**
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.
340
341 @param LogoFile File name of logo to display on the center of the screen.
342
343 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
344 @retval EFI_UNSUPPORTED Logo not found.
345
346 **/
347 EFI_STATUS
348 EFIAPI
349 EnableQuietBoot (
350 IN EFI_GUID *LogoFile
351 )
352 {
353 return EnableQuietBootEx (LogoFile, NULL);
354 }
355
356 /**
357 Use Console Control to turn off UGA based Simple Text Out consoles from going
358 to the UGA device. Put up LogoFile on every UGA device that is a console
359
360 @param LogoFile File name of logo to display on the center of the screen.
361 @param ImageHandle The driver image handle of the caller. The parameter is used to
362 optimize the loading of the logo file so that the FV from which
363 the driver image is loaded will be tried first.
364
365 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
366 @retval EFI_UNSUPPORTED Logo not found.
367
368 **/
369 EFI_STATUS
370 EFIAPI
371 EnableQuietBootEx (
372 IN EFI_GUID *LogoFile,
373 IN EFI_HANDLE ImageHandle
374 )
375 {
376 EFI_STATUS Status;
377 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
378 EFI_OEM_BADGING_PROTOCOL *Badging;
379 UINT32 SizeOfX;
380 UINT32 SizeOfY;
381 INTN DestX;
382 INTN DestY;
383 UINT8 *ImageData;
384 UINTN ImageSize;
385 UINTN BltSize;
386 UINT32 Instance;
387 EFI_BADGING_FORMAT Format;
388 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
389 UINTN CoordinateX;
390 UINTN CoordinateY;
391 UINTN Height;
392 UINTN Width;
393 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
394 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
395 UINT32 ColorDepth;
396 UINT32 RefreshRate;
397 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
398
399 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
400 if (EFI_ERROR (Status)) {
401 return EFI_UNSUPPORTED;
402 }
403
404 UgaDraw = NULL;
405 //
406 // Try to open GOP first
407 //
408 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
409 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
410 GraphicsOutput = NULL;
411 //
412 // Open GOP failed, try to open UGA
413 //
414 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
415 }
416 if (EFI_ERROR (Status)) {
417 return EFI_UNSUPPORTED;
418 }
419
420 Badging = NULL;
421 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
422
423 //
424 // Set console control to graphics mode.
425 //
426 Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
427 if (EFI_ERROR (Status)) {
428 return EFI_UNSUPPORTED;
429 }
430
431 if (GraphicsOutput != NULL) {
432 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
433 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
434 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
435 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
436 if (EFI_ERROR (Status)) {
437 return EFI_UNSUPPORTED;
438 }
439 } else {
440 return EFI_UNSUPPORTED;
441 }
442
443 Instance = 0;
444 while (1) {
445 ImageData = NULL;
446 ImageSize = 0;
447
448 if (Badging != NULL) {
449 //
450 // Get image from OEMBadging protocol.
451 //
452 Status = Badging->GetImage (
453 Badging,
454 &Instance,
455 &Format,
456 &ImageData,
457 &ImageSize,
458 &Attribute,
459 &CoordinateX,
460 &CoordinateY
461 );
462 if (EFI_ERROR (Status)) {
463 return Status;
464 }
465
466 //
467 // Currently only support BMP format.
468 //
469 if (Format != EfiBadgingFormatBMP) {
470 SafeFreePool (ImageData);
471 continue;
472 }
473 } else {
474 //
475 // Get the specified image from FV.
476 //
477 Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
478 if (EFI_ERROR (Status)) {
479 return EFI_UNSUPPORTED;
480 }
481
482 CoordinateX = 0;
483 CoordinateY = 0;
484 Attribute = EfiBadgingDisplayAttributeCenter;
485 }
486
487 Blt = NULL;
488 Status = ConvertBmpToGopBlt (
489 ImageData,
490 ImageSize,
491 (VOID **) &Blt,
492 &BltSize,
493 &Height,
494 &Width
495 );
496 if (EFI_ERROR (Status)) {
497 SafeFreePool (ImageData);
498 if (Badging == NULL) {
499 return Status;
500 } else {
501 continue;
502 }
503 }
504
505 //
506 // Caculate the display position according to Attribute.
507 //
508 switch (Attribute) {
509 case EfiBadgingDisplayAttributeLeftTop:
510 DestX = CoordinateX;
511 DestY = CoordinateY;
512 break;
513
514 case EfiBadgingDisplayAttributeCenterTop:
515 DestX = (SizeOfX - Width) / 2;
516 DestY = CoordinateY;
517 break;
518
519 case EfiBadgingDisplayAttributeRightTop:
520 DestX = (SizeOfX - Width - CoordinateX);
521 DestY = CoordinateY;;
522 break;
523
524 case EfiBadgingDisplayAttributeCenterRight:
525 DestX = (SizeOfX - Width - CoordinateX);
526 DestY = (SizeOfY - Height) / 2;
527 break;
528
529 case EfiBadgingDisplayAttributeRightBottom:
530 DestX = (SizeOfX - Width - CoordinateX);
531 DestY = (SizeOfY - Height - CoordinateY);
532 break;
533
534 case EfiBadgingDisplayAttributeCenterBottom:
535 DestX = (SizeOfX - Width) / 2;
536 DestY = (SizeOfY - Height - CoordinateY);
537 break;
538
539 case EfiBadgingDisplayAttributeLeftBottom:
540 DestX = CoordinateX;
541 DestY = (SizeOfY - Height - CoordinateY);
542 break;
543
544 case EfiBadgingDisplayAttributeCenterLeft:
545 DestX = CoordinateX;
546 DestY = (SizeOfY - Height) / 2;
547 break;
548
549 case EfiBadgingDisplayAttributeCenter:
550 DestX = (SizeOfX - Width) / 2;
551 DestY = (SizeOfY - Height) / 2;
552 break;
553
554 default:
555 DestX = CoordinateX;
556 DestY = CoordinateY;
557 break;
558 }
559
560 if ((DestX >= 0) && (DestY >= 0)) {
561 if (GraphicsOutput != NULL) {
562 Status = GraphicsOutput->Blt (
563 GraphicsOutput,
564 Blt,
565 EfiBltBufferToVideo,
566 0,
567 0,
568 (UINTN) DestX,
569 (UINTN) DestY,
570 Width,
571 Height,
572 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
573 );
574 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
575 Status = UgaDraw->Blt (
576 UgaDraw,
577 (EFI_UGA_PIXEL *) Blt,
578 EfiUgaBltBufferToVideo,
579 0,
580 0,
581 (UINTN) DestX,
582 (UINTN) DestY,
583 Width,
584 Height,
585 Width * sizeof (EFI_UGA_PIXEL)
586 );
587 } else {
588 Status = EFI_UNSUPPORTED;
589 }
590 }
591
592 SafeFreePool (ImageData);
593 SafeFreePool (Blt);
594
595 if (Badging == NULL) {
596 break;
597 }
598 }
599
600 return Status;
601 }
602
603 /**
604 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA
605 Simple Text Out screens will now be synced up with all non UGA output devices
606
607 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
608 @retval EFI_UNSUPPORTED Logo not found
609
610 **/
611 EFI_STATUS
612 EFIAPI
613 DisableQuietBoot (
614 VOID
615 )
616 {
617 EFI_STATUS Status;
618 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
619
620 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
621 if (EFI_ERROR (Status)) {
622 return EFI_UNSUPPORTED;
623 }
624
625 //
626 // Set console control to text mode.
627 //
628 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
629 }
630
631 /**
632 Internal display string worker function.
633
634 @param GraphicsOutput Graphics output protocol interface.
635 @param UgaDraw UGA draw protocol interface.
636 @param Sto Simple text out protocol interface.
637 @param X X coordinate to start printing.
638 @param Y Y coordinate to start printing.
639 @param Foreground Foreground color.
640 @param Background Background color.
641 @param fmt Format string.
642 @param args Print arguments.
643
644 @return Number of Characters printed. Zero means no any character
645 displayed successfully.
646
647 **/
648 UINTN
649 Print (
650 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
651 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,
652 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto,
653 IN UINTN X,
654 IN UINTN Y,
655 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
656 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,
657 IN CHAR16 *fmt,
658 IN VA_LIST args
659 )
660 {
661 VOID *Buffer;
662 EFI_STATUS Status;
663 UINTN Index;
664 CHAR16 *UnicodeWeight;
665 UINT32 HorizontalResolution;
666 UINT32 VerticalResolution;
667 UINT32 ColorDepth;
668 UINT32 RefreshRate;
669 UINTN BufferLen;
670 UINTN LineBufferLen;
671 EFI_HII_FONT_PROTOCOL *HiiFont;
672 EFI_IMAGE_OUTPUT *Blt;
673 EFI_FONT_DISPLAY_INFO *FontInfo;
674 EFI_HII_ROW_INFO *RowInfoArray;
675 UINTN RowInfoArraySize;
676 UINTN PrintNum;
677
678 //
679 // For now, allocate an arbitrarily long buffer
680 //
681 Buffer = AllocateZeroPool (0x10000);
682 if (Buffer == NULL) {
683 return 0;
684 }
685
686 HorizontalResolution = 0;
687 VerticalResolution = 0;
688 Blt = NULL;
689 FontInfo = NULL;
690
691 if (GraphicsOutput != NULL) {
692 HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
693 VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
694 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
695 UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);
696 } else {
697 Status = EFI_UNSUPPORTED;
698 goto Error;
699 }
700
701 ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0));
702
703 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);
704 if (EFI_ERROR (Status)) {
705 goto Error;
706 }
707
708 PrintNum = UnicodeVSPrint (Buffer, 0x10000, fmt, args);
709
710 UnicodeWeight = (CHAR16 *) Buffer;
711
712 for (Index = 0; UnicodeWeight[Index] != 0; Index++) {
713 if (UnicodeWeight[Index] == CHAR_BACKSPACE ||
714 UnicodeWeight[Index] == CHAR_LINEFEED ||
715 UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {
716 UnicodeWeight[Index] = 0;
717 }
718 }
719
720 BufferLen = StrLen (Buffer);
721
722 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;
723 if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {
724 Status = EFI_INVALID_PARAMETER;
725 goto Error;
726 }
727
728 Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
729 if (Blt == NULL) {
730 Status = EFI_OUT_OF_RESOURCES;
731 goto Error;
732 }
733
734 Blt->Width = (UINT16) (HorizontalResolution);
735 Blt->Height = (UINT16) (VerticalResolution);
736
737 FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
738 if (FontInfo == NULL) {
739 Status = EFI_OUT_OF_RESOURCES;
740 goto Error;
741 }
742 if (Foreground != NULL) {
743 CopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
744 } else {
745 CopyMem (
746 &FontInfo->ForegroundColor,
747 &mEfiColors[Sto->Mode->Attribute & 0x0f],
748 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
749 );
750 }
751 if (Background != NULL) {
752 CopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
753 } else {
754 CopyMem (
755 &FontInfo->BackgroundColor,
756 &mEfiColors[Sto->Mode->Attribute >> 4],
757 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
758 );
759 }
760
761 if (GraphicsOutput != NULL) {
762 Blt->Image.Screen = GraphicsOutput;
763
764 Status = HiiFont->StringToImage (
765 HiiFont,
766 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
767 Buffer,
768 FontInfo,
769 &Blt,
770 X,
771 Y,
772 NULL,
773 NULL,
774 NULL
775 );
776
777 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
778 ASSERT (UgaDraw!= NULL);
779
780 Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
781 if (Blt->Image.Bitmap == NULL) {
782 SafeFreePool (Blt);
783 SafeFreePool (Buffer);
784 return EFI_OUT_OF_RESOURCES;
785 }
786
787 RowInfoArray = NULL;
788 //
789 // StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
790 // we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
791 //
792 Status = HiiFont->StringToImage (
793 HiiFont,
794 EFI_HII_IGNORE_IF_NO_GLYPH,
795 Buffer,
796 FontInfo,
797 &Blt,
798 X,
799 Y,
800 &RowInfoArray,
801 &RowInfoArraySize,
802 NULL
803 );
804
805 if (!EFI_ERROR (Status)) {
806 //
807 // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
808 // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.
809 //
810 ASSERT (RowInfoArraySize <= 1);
811
812 Status = UgaDraw->Blt (
813 UgaDraw,
814 (EFI_UGA_PIXEL *) Blt->Image.Bitmap,
815 EfiUgaBltBufferToVideo,
816 X,
817 Y,
818 X,
819 Y,
820 RowInfoArray[0].LineWidth,
821 RowInfoArray[0].LineHeight,
822 Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
823 );
824 }
825
826 SafeFreePool (RowInfoArray);
827 SafeFreePool (Blt->Image.Bitmap);
828 } else {
829 Status = EFI_UNSUPPORTED;
830 }
831
832 Error:
833 SafeFreePool (Blt);
834 SafeFreePool (FontInfo);
835 FreePool (Buffer);
836
837 if (EFI_ERROR(Status)) {
838 return PrintNum;
839 } else {
840 return 0;
841 }
842 }
843
844 /**
845 Print to graphics screen at the given X,Y coordinates of the graphics screen.
846 see definition of Print to find rules for constructing Fmt.
847
848 @param X Row to start printing at.
849 @param Y Column to start printing at.
850 @param ForeGround Foreground color.
851 @param BackGround background color.
852 @param Fmt Print format sting. See definition of Print.
853 @param ... Argumnet stream defined by Fmt string.
854
855 @return Number of Characters printed. Zero means no any character
856 displayed successfully.
857
858 **/
859 UINTN
860 EFIAPI
861 PrintXY (
862 IN UINTN X,
863 IN UINTN Y,
864 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL
865 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL
866 IN CHAR16 *Fmt,
867 ...
868 )
869 {
870 EFI_HANDLE Handle;
871 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
872 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
873 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
874 EFI_STATUS Status;
875 VA_LIST Args;
876
877 VA_START (Args, Fmt);
878
879 Handle = gST->ConsoleOutHandle;
880
881 Status = gBS->HandleProtocol (
882 Handle,
883 &gEfiGraphicsOutputProtocolGuid,
884 (VOID **) &GraphicsOutput
885 );
886
887 UgaDraw = NULL;
888 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
889 //
890 // If no GOP available, try to open UGA Draw protocol if supported.
891 //
892 GraphicsOutput = NULL;
893
894 Status = gBS->HandleProtocol (
895 Handle,
896 &gEfiUgaDrawProtocolGuid,
897 (VOID **) &UgaDraw
898 );
899 }
900 if (EFI_ERROR (Status)) {
901 return 0;
902 }
903
904 Status = gBS->HandleProtocol (
905 Handle,
906 &gEfiSimpleTextOutProtocolGuid,
907 (VOID **) &Sto
908 );
909
910 if (EFI_ERROR (Status)) {
911 return 0;
912 }
913
914 return Print (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);
915 }
916