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