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