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