]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/GraphicsLib/Graphics.c
cdddfb6c500b99868dcbf07b30842bece1d42f0a
[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 ConsoleControl has been flipped to graphics and logo
316 displayed.
317 @retval EFI_UNSUPPORTED Password not found.
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 LockKeyboards (
323 IN CHAR16 *Password
324 )
325 {
326 EFI_STATUS Status;
327 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
328
329 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
330 if (EFI_ERROR (Status)) {
331 return EFI_UNSUPPORTED;
332 }
333
334 Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
335 return Status;
336 }
337
338
339 /**
340 Use Console Control to turn off UGA based Simple Text Out consoles from going
341 to the UGA device. Put up LogoFile on every UGA device that is a console.
342
343 @param LogoFile File name of logo to display on the center of the screen.
344
345 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
346 @retval EFI_UNSUPPORTED Logo not found.
347
348 **/
349 EFI_STATUS
350 EFIAPI
351 EnableQuietBoot (
352 IN EFI_GUID *LogoFile
353 )
354 {
355 return EnableQuietBootEx (LogoFile, NULL);
356 }
357
358 /**
359 Use Console Control to turn off UGA based Simple Text Out consoles from going
360 to the UGA device. Put up LogoFile on every UGA device that is a console
361
362 @param LogoFile File name of logo to display on the center of the screen.
363 @param ImageHandle The driver image handle of the caller. The parameter is used to
364 optimize the loading of the logo file so that the FV from which
365 the driver image is loaded will be tried first.
366
367 @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
368 @retval EFI_UNSUPPORTED Logo not found.
369
370 **/
371 EFI_STATUS
372 EFIAPI
373 EnableQuietBootEx (
374 IN EFI_GUID *LogoFile,
375 IN EFI_HANDLE ImageHandle
376 )
377 {
378 EFI_STATUS Status;
379 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
380 EFI_OEM_BADGING_PROTOCOL *Badging;
381 UINT32 SizeOfX;
382 UINT32 SizeOfY;
383 INTN DestX;
384 INTN DestY;
385 UINT8 *ImageData;
386 UINTN ImageSize;
387 UINTN BltSize;
388 UINT32 Instance;
389 EFI_BADGING_FORMAT Format;
390 EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
391 UINTN CoordinateX;
392 UINTN CoordinateY;
393 UINTN Height;
394 UINTN Width;
395 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
396 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
397 UINT32 ColorDepth;
398 UINT32 RefreshRate;
399 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
400
401 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
402 if (EFI_ERROR (Status)) {
403 return EFI_UNSUPPORTED;
404 }
405
406 UgaDraw = NULL;
407 //
408 // Try to open GOP first
409 //
410 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
411 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
412 GraphicsOutput = NULL;
413 //
414 // Open GOP failed, try to open UGA
415 //
416 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
417 }
418 if (EFI_ERROR (Status)) {
419 return EFI_UNSUPPORTED;
420 }
421
422 Badging = NULL;
423 Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);
424
425 //
426 // Set console control to graphics mode.
427 //
428 Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
429 if (EFI_ERROR (Status)) {
430 return EFI_UNSUPPORTED;
431 }
432
433 if (GraphicsOutput != NULL) {
434 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
435 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
436 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
437 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
438 if (EFI_ERROR (Status)) {
439 return EFI_UNSUPPORTED;
440 }
441 } else {
442 return EFI_UNSUPPORTED;
443 }
444
445 Instance = 0;
446 while (1) {
447 ImageData = NULL;
448 ImageSize = 0;
449
450 if (Badging != NULL) {
451 //
452 // Get image from OEMBadging protocol.
453 //
454 Status = Badging->GetImage (
455 Badging,
456 &Instance,
457 &Format,
458 &ImageData,
459 &ImageSize,
460 &Attribute,
461 &CoordinateX,
462 &CoordinateY
463 );
464 if (EFI_ERROR (Status)) {
465 return Status;
466 }
467
468 //
469 // Currently only support BMP format.
470 //
471 if (Format != EfiBadgingFormatBMP) {
472 SafeFreePool (ImageData);
473 continue;
474 }
475 } else {
476 //
477 // Get the specified image from FV.
478 //
479 Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
480 if (EFI_ERROR (Status)) {
481 return EFI_UNSUPPORTED;
482 }
483
484 CoordinateX = 0;
485 CoordinateY = 0;
486 Attribute = EfiBadgingDisplayAttributeCenter;
487 }
488
489 Blt = NULL;
490 Status = ConvertBmpToGopBlt (
491 ImageData,
492 ImageSize,
493 (VOID **) &Blt,
494 &BltSize,
495 &Height,
496 &Width
497 );
498 if (EFI_ERROR (Status)) {
499 SafeFreePool (ImageData);
500 if (Badging == NULL) {
501 return Status;
502 } else {
503 continue;
504 }
505 }
506
507 //
508 // Caculate the display position according to Attribute.
509 //
510 switch (Attribute) {
511 case EfiBadgingDisplayAttributeLeftTop:
512 DestX = CoordinateX;
513 DestY = CoordinateY;
514 break;
515
516 case EfiBadgingDisplayAttributeCenterTop:
517 DestX = (SizeOfX - Width) / 2;
518 DestY = CoordinateY;
519 break;
520
521 case EfiBadgingDisplayAttributeRightTop:
522 DestX = (SizeOfX - Width - CoordinateX);
523 DestY = CoordinateY;;
524 break;
525
526 case EfiBadgingDisplayAttributeCenterRight:
527 DestX = (SizeOfX - Width - CoordinateX);
528 DestY = (SizeOfY - Height) / 2;
529 break;
530
531 case EfiBadgingDisplayAttributeRightBottom:
532 DestX = (SizeOfX - Width - CoordinateX);
533 DestY = (SizeOfY - Height - CoordinateY);
534 break;
535
536 case EfiBadgingDisplayAttributeCenterBottom:
537 DestX = (SizeOfX - Width) / 2;
538 DestY = (SizeOfY - Height - CoordinateY);
539 break;
540
541 case EfiBadgingDisplayAttributeLeftBottom:
542 DestX = CoordinateX;
543 DestY = (SizeOfY - Height - CoordinateY);
544 break;
545
546 case EfiBadgingDisplayAttributeCenterLeft:
547 DestX = CoordinateX;
548 DestY = (SizeOfY - Height) / 2;
549 break;
550
551 case EfiBadgingDisplayAttributeCenter:
552 DestX = (SizeOfX - Width) / 2;
553 DestY = (SizeOfY - Height) / 2;
554 break;
555
556 default:
557 DestX = CoordinateX;
558 DestY = CoordinateY;
559 break;
560 }
561
562 if ((DestX >= 0) && (DestY >= 0)) {
563 if (GraphicsOutput != NULL) {
564 Status = GraphicsOutput->Blt (
565 GraphicsOutput,
566 Blt,
567 EfiBltBufferToVideo,
568 0,
569 0,
570 (UINTN) DestX,
571 (UINTN) DestY,
572 Width,
573 Height,
574 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
575 );
576 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
577 Status = UgaDraw->Blt (
578 UgaDraw,
579 (EFI_UGA_PIXEL *) Blt,
580 EfiUgaBltBufferToVideo,
581 0,
582 0,
583 (UINTN) DestX,
584 (UINTN) DestY,
585 Width,
586 Height,
587 Width * sizeof (EFI_UGA_PIXEL)
588 );
589 } else {
590 Status = EFI_UNSUPPORTED;
591 }
592 }
593
594 SafeFreePool (ImageData);
595 SafeFreePool (Blt);
596
597 if (Badging == NULL) {
598 break;
599 }
600 }
601
602 return Status;
603 }
604
605 /**
606 Use Console Control to turn on UGA based Simple Text Out consoles. The UGA
607 Simple Text Out screens will now be synced up with all non UGA output devices
608
609 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
610 @retval EFI_UNSUPPORTED Logo not found
611
612 **/
613 EFI_STATUS
614 EFIAPI
615 DisableQuietBoot (
616 VOID
617 )
618 {
619 EFI_STATUS Status;
620 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
621
622 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
623 if (EFI_ERROR (Status)) {
624 return EFI_UNSUPPORTED;
625 }
626
627 //
628 // Set console control to text mode.
629 //
630 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
631 }
632
633 /**
634 Internal display string worker function.
635
636 @param GraphicsOutput Graphics output protocol interface.
637 @param UgaDraw UGA draw protocol interface.
638 @param Sto Simple text out protocol interface.
639 @param X X coordinate to start printing.
640 @param Y Y coordinate to start printing.
641 @param Foreground Foreground color.
642 @param Background Background color.
643 @param fmt Format string.
644 @param args Print arguments.
645
646 @return Number of Characters printed. Zero means no any character
647 displayed successfully.
648
649 **/
650 UINTN
651 Print (
652 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
653 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,
654 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto,
655 IN UINTN X,
656 IN UINTN Y,
657 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
658 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,
659 IN CHAR16 *fmt,
660 IN VA_LIST args
661 )
662 {
663 VOID *Buffer;
664 EFI_STATUS Status;
665 UINTN Index;
666 CHAR16 *UnicodeWeight;
667 UINT32 HorizontalResolution;
668 UINT32 VerticalResolution;
669 UINT32 ColorDepth;
670 UINT32 RefreshRate;
671 UINTN BufferLen;
672 UINTN LineBufferLen;
673 EFI_HII_FONT_PROTOCOL *HiiFont;
674 EFI_IMAGE_OUTPUT *Blt;
675 EFI_FONT_DISPLAY_INFO *FontInfo;
676 EFI_HII_ROW_INFO *RowInfoArray;
677 UINTN RowInfoArraySize;
678 UINTN PrintNum;
679
680 //
681 // For now, allocate an arbitrarily long buffer
682 //
683 Buffer = AllocateZeroPool (0x10000);
684 if (Buffer == NULL) {
685 return 0;
686 }
687
688 HorizontalResolution = 0;
689 VerticalResolution = 0;
690 Blt = NULL;
691 FontInfo = NULL;
692 PrintNum = 0;
693
694 if (GraphicsOutput != NULL) {
695 HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
696 VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
697 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
698 UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);
699 } else {
700 Status = EFI_UNSUPPORTED;
701 goto Error;
702 }
703
704 ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0));
705
706 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);
707 if (EFI_ERROR (Status)) {
708 goto Error;
709 }
710
711 PrintNum = UnicodeVSPrint (Buffer, 0x10000, fmt, args);
712
713 UnicodeWeight = (CHAR16 *) Buffer;
714
715 for (Index = 0; UnicodeWeight[Index] != 0; Index++) {
716 if (UnicodeWeight[Index] == CHAR_BACKSPACE ||
717 UnicodeWeight[Index] == CHAR_LINEFEED ||
718 UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {
719 UnicodeWeight[Index] = 0;
720 }
721 }
722
723 BufferLen = StrLen (Buffer);
724
725 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;
726 if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {
727 Status = EFI_INVALID_PARAMETER;
728 goto Error;
729 }
730
731 Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
732 if (Blt == NULL) {
733 Status = EFI_OUT_OF_RESOURCES;
734 goto Error;
735 }
736
737 Blt->Width = (UINT16) (HorizontalResolution);
738 Blt->Height = (UINT16) (VerticalResolution);
739
740 FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
741 if (FontInfo == NULL) {
742 Status = EFI_OUT_OF_RESOURCES;
743 goto Error;
744 }
745 if (Foreground != NULL) {
746 CopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
747 } else {
748 CopyMem (
749 &FontInfo->ForegroundColor,
750 &mEfiColors[Sto->Mode->Attribute & 0x0f],
751 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
752 );
753 }
754 if (Background != NULL) {
755 CopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
756 } else {
757 CopyMem (
758 &FontInfo->BackgroundColor,
759 &mEfiColors[Sto->Mode->Attribute >> 4],
760 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
761 );
762 }
763
764 if (GraphicsOutput != NULL) {
765 Blt->Image.Screen = GraphicsOutput;
766
767 Status = HiiFont->StringToImage (
768 HiiFont,
769 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
770 Buffer,
771 FontInfo,
772 &Blt,
773 X,
774 Y,
775 NULL,
776 NULL,
777 NULL
778 );
779
780 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
781 ASSERT (UgaDraw!= NULL);
782
783 Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
784 if (Blt->Image.Bitmap == NULL) {
785 SafeFreePool (Blt);
786 SafeFreePool (Buffer);
787 return EFI_OUT_OF_RESOURCES;
788 }
789
790 RowInfoArray = NULL;
791 //
792 // StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
793 // we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
794 //
795 Status = HiiFont->StringToImage (
796 HiiFont,
797 EFI_HII_IGNORE_IF_NO_GLYPH,
798 Buffer,
799 FontInfo,
800 &Blt,
801 X,
802 Y,
803 &RowInfoArray,
804 &RowInfoArraySize,
805 NULL
806 );
807
808 if (!EFI_ERROR (Status)) {
809 //
810 // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
811 // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.
812 //
813 ASSERT (RowInfoArraySize <= 1);
814
815 Status = UgaDraw->Blt (
816 UgaDraw,
817 (EFI_UGA_PIXEL *) Blt->Image.Bitmap,
818 EfiUgaBltBufferToVideo,
819 X,
820 Y,
821 X,
822 Y,
823 RowInfoArray[0].LineWidth,
824 RowInfoArray[0].LineHeight,
825 Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
826 );
827 }
828
829 SafeFreePool (RowInfoArray);
830 SafeFreePool (Blt->Image.Bitmap);
831 } else {
832 Status = EFI_UNSUPPORTED;
833 }
834
835 Error:
836 SafeFreePool (Blt);
837 SafeFreePool (FontInfo);
838 FreePool (Buffer);
839
840 if (EFI_ERROR (Status)) {
841 return PrintNum;
842 } else {
843 return 0;
844 }
845 }
846
847 /**
848 Print to graphics screen at the given X,Y coordinates of the graphics screen.
849 see definition of Print to find rules for constructing Fmt.
850
851 @param X Row to start printing at.
852 @param Y Column to start printing at.
853 @param ForeGround Foreground color.
854 @param BackGround background color.
855 @param Fmt Print format sting. See definition of Print.
856 @param ... Argumnet stream defined by Fmt string.
857
858 @return Number of Characters printed. Zero means no any character
859 displayed successfully.
860
861 **/
862 UINTN
863 EFIAPI
864 PrintXY (
865 IN UINTN X,
866 IN UINTN Y,
867 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL
868 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL
869 IN CHAR16 *Fmt,
870 ...
871 )
872 {
873 EFI_HANDLE Handle;
874 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
875 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
876 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
877 EFI_STATUS Status;
878 VA_LIST Args;
879
880 VA_START (Args, Fmt);
881
882 Handle = gST->ConsoleOutHandle;
883
884 Status = gBS->HandleProtocol (
885 Handle,
886 &gEfiGraphicsOutputProtocolGuid,
887 (VOID **) &GraphicsOutput
888 );
889
890 UgaDraw = NULL;
891 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
892 //
893 // If no GOP available, try to open UGA Draw protocol if supported.
894 //
895 GraphicsOutput = NULL;
896
897 Status = gBS->HandleProtocol (
898 Handle,
899 &gEfiUgaDrawProtocolGuid,
900 (VOID **) &UgaDraw
901 );
902 }
903 if (EFI_ERROR (Status)) {
904 return 0;
905 }
906
907 Status = gBS->HandleProtocol (
908 Handle,
909 &gEfiSimpleTextOutProtocolGuid,
910 (VOID **) &Sto
911 );
912
913 if (EFI_ERROR (Status)) {
914 return 0;
915 }
916
917 return Print (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);
918 }
919