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