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