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