]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/GraphicsLib/Graphics.c
ea8c7d5157fb883f13ae43929850495c41ea2d88
[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 } else {
419 return EFI_UNSUPPORTED;
420 }
421
422 Instance = 0;
423 while (1) {
424 ImageData = NULL;
425 ImageSize = 0;
426
427 if (Badging != NULL) {
428 Status = Badging->GetImage (
429 Badging,
430 &Instance,
431 &Format,
432 &ImageData,
433 &ImageSize,
434 &Attribute,
435 &CoordinateX,
436 &CoordinateY
437 );
438 if (EFI_ERROR (Status)) {
439 return Status;
440 }
441
442 //
443 // Currently only support BMP format
444 //
445 if (Format != EfiBadgingFormatBMP) {
446 gBS->FreePool (ImageData);
447 continue;
448 }
449 } else {
450 Status = GetGraphicsBitMapFromFV (LogoFile, (VOID **) &ImageData, &ImageSize);
451 if (EFI_ERROR (Status)) {
452 return EFI_UNSUPPORTED;
453 }
454
455 CoordinateX = 0;
456 CoordinateY = 0;
457 Attribute = EfiBadgingDisplayAttributeCenter;
458 }
459
460 Blt = NULL;
461 BltSize = 0;
462 Status = ConvertBmpToGopBlt (
463 ImageData,
464 ImageSize,
465 (VOID**)&Blt,
466 &BltSize,
467 &Height,
468 &Width
469 );
470 if (EFI_ERROR (Status)) {
471 gBS->FreePool (ImageData);
472 if (Badging == NULL) {
473 return Status;
474 } else {
475 continue;
476 }
477 }
478
479 switch (Attribute) {
480 case EfiBadgingDisplayAttributeLeftTop:
481 DestX = CoordinateX;
482 DestY = CoordinateY;
483 break;
484
485 case EfiBadgingDisplayAttributeCenterTop:
486 DestX = (SizeOfX - Width) / 2;
487 DestY = CoordinateY;
488 break;
489
490 case EfiBadgingDisplayAttributeRightTop:
491 DestX = (SizeOfX - Width - CoordinateX);
492 DestY = CoordinateY;;
493 break;
494
495 case EfiBadgingDisplayAttributeCenterRight:
496 DestX = (SizeOfX - Width - CoordinateX);
497 DestY = (SizeOfY - Height) / 2;
498 break;
499
500 case EfiBadgingDisplayAttributeRightBottom:
501 DestX = (SizeOfX - Width - CoordinateX);
502 DestY = (SizeOfY - Height - CoordinateY);
503 break;
504
505 case EfiBadgingDisplayAttributeCenterBottom:
506 DestX = (SizeOfX - Width) / 2;
507 DestY = (SizeOfY - Height - CoordinateY);
508 break;
509
510 case EfiBadgingDisplayAttributeLeftBottom:
511 DestX = CoordinateX;
512 DestY = (SizeOfY - Height - CoordinateY);
513 break;
514
515 case EfiBadgingDisplayAttributeCenterLeft:
516 DestX = CoordinateX;
517 DestY = (SizeOfY - Height) / 2;
518 break;
519
520 case EfiBadgingDisplayAttributeCenter:
521 DestX = (SizeOfX - Width) / 2;
522 DestY = (SizeOfY - Height) / 2;
523 break;
524
525 default:
526 DestX = CoordinateX;
527 DestY = CoordinateY;
528 break;
529 }
530
531 if ((DestX >= 0) && (DestY >= 0)) {
532 if (GraphicsOutput != NULL) {
533 Status = GraphicsOutput->Blt (
534 GraphicsOutput,
535 Blt,
536 EfiBltBufferToVideo,
537 0,
538 0,
539 (UINTN) DestX,
540 (UINTN) DestY,
541 Width,
542 Height,
543 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
544 );
545 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
546 Status = UgaDraw->Blt (
547 UgaDraw,
548 (EFI_UGA_PIXEL *) Blt,
549 EfiUgaBltBufferToVideo,
550 0,
551 0,
552 (UINTN) DestX,
553 (UINTN) DestY,
554 Width,
555 Height,
556 Width * sizeof (EFI_UGA_PIXEL)
557 );
558 } else {
559 Status = EFI_UNSUPPORTED;
560 }
561 }
562
563 gBS->FreePool (ImageData);
564 gBS->FreePool (Blt);
565
566 if (Badging == NULL) {
567 break;
568 }
569 }
570
571 return Status;
572 }
573
574
575 EFI_STATUS
576 DisableQuietBoot (
577 VOID
578 )
579 /*++
580
581 Routine Description:
582
583 Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
584 Simple Text Out screens will now be synced up with all non GOP/UGA output devices
585
586 Arguments:
587
588 NONE
589
590 Returns:
591
592 EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
593 EFI_UNSUPPORTED - Logo not found
594
595 --*/
596 {
597 EFI_STATUS Status;
598 EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
599
600 Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
601 if (EFI_ERROR (Status)) {
602 return EFI_UNSUPPORTED;
603 }
604
605 return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
606 }
607
608 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {
609 { 0x00, 0x00, 0x00, 0x00 },
610 { 0x98, 0x00, 0x00, 0x00 },
611 { 0x00, 0x98, 0x00, 0x00 },
612 { 0x98, 0x98, 0x00, 0x00 },
613 { 0x00, 0x00, 0x98, 0x00 },
614 { 0x98, 0x00, 0x98, 0x00 },
615 { 0x00, 0x98, 0x98, 0x00 },
616 { 0x98, 0x98, 0x98, 0x00 },
617 { 0x10, 0x10, 0x10, 0x00 },
618 { 0xff, 0x10, 0x10, 0x00 },
619 { 0x10, 0xff, 0x10, 0x00 },
620 { 0xff, 0xff, 0x10, 0x00 },
621 { 0x10, 0x10, 0xff, 0x00 },
622 { 0xf0, 0x10, 0xff, 0x00 },
623 { 0x10, 0xff, 0xff, 0x00 },
624 { 0xff, 0xff, 0xff, 0x00 }
625 };
626
627 STATIC
628 UINTN
629 _IPrint (
630 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
631 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,
632 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto,
633 IN UINTN X,
634 IN UINTN Y,
635 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
636 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,
637 IN CHAR16 *fmt,
638 IN VA_LIST args
639 )
640 /*++
641
642 Routine Description:
643
644 Display string worker for: Print, PrintAt, IPrint, IPrintAt
645
646 Arguments:
647
648 GraphicsOutput - Graphics output protocol interface
649
650 UgaDraw - UGA draw protocol interface
651
652 Sto - Simple text out protocol interface
653
654 X - X coordinate to start printing
655
656 Y - Y coordinate to start printing
657
658 Foreground - Foreground color
659
660 Background - Background color
661
662 fmt - Format string
663
664 args - Print arguments
665
666 Returns:
667
668 EFI_SUCCESS - success
669 EFI_OUT_OF_RESOURCES - out of resources
670
671 --*/
672 {
673 VOID *Buffer;
674 EFI_STATUS Status;
675 UINT16 GlyphWidth;
676 UINT32 GlyphStatus;
677 UINT16 StringIndex;
678 UINTN Index;
679 CHAR16 *UnicodeWeight;
680 EFI_NARROW_GLYPH *Glyph;
681 EFI_HII_PROTOCOL *Hii;
682 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LineBuffer;
683 UINT32 HorizontalResolution;
684 UINT32 VerticalResolution;
685 UINT32 ColorDepth;
686 UINT32 RefreshRate;
687 UINTN BufferLen;
688 UINTN LineBufferLen;
689 UINTN BufferGlyphWidth;
690
691 GlyphStatus = 0;
692
693 //
694 // For now, allocate an arbitrarily long buffer
695 //
696 Buffer = AllocateZeroPool (0x10000);
697 if (Buffer == NULL) {
698 return EFI_OUT_OF_RESOURCES;
699 }
700
701 if (GraphicsOutput != NULL) {
702 HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
703 VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
704 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
705 //
706 // Get the current mode information from the UGA Draw Protocol
707 //
708 UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);
709 }
710 ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0));
711
712 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * GLYPH_HEIGHT;
713 LineBuffer = AllocatePool (LineBufferLen);
714 if (LineBuffer == NULL) {
715 gBS->FreePool (Buffer);
716 return EFI_OUT_OF_RESOURCES;
717 }
718
719 Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **) &Hii);
720 if (EFI_ERROR (Status)) {
721 goto Error;
722 }
723
724 UnicodeVSPrint (Buffer, 0x10000, fmt, args);
725
726 UnicodeWeight = (CHAR16 *) Buffer;
727
728 for (Index = 0; UnicodeWeight[Index] != 0; Index++) {
729 if (UnicodeWeight[Index] == CHAR_BACKSPACE ||
730 UnicodeWeight[Index] == CHAR_LINEFEED ||
731 UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {
732 UnicodeWeight[Index] = 0;
733 }
734 }
735
736 BufferLen = StrLen (Buffer);
737
738 if (GLYPH_WIDTH * GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {
739 Status = EFI_INVALID_PARAMETER;
740 goto Error;
741 }
742
743 for (Index = 0; Index < BufferLen; Index++) {
744 StringIndex = (UINT16) Index;
745 Status = Hii->GetGlyph (Hii, UnicodeWeight, &StringIndex, (UINT8 **) &Glyph, &GlyphWidth, &GlyphStatus);
746 if (EFI_ERROR (Status)) {
747 goto Error;
748 }
749
750 if (Foreground == NULL || Background == NULL) {
751 Status = Hii->GlyphToBlt (
752 Hii,
753 (UINT8 *) Glyph,
754 mEfiColors[Sto->Mode->Attribute & 0x0f],
755 mEfiColors[Sto->Mode->Attribute >> 4],
756 BufferLen,
757 GlyphWidth,
758 GLYPH_HEIGHT,
759 &LineBuffer[Index * GLYPH_WIDTH]
760 );
761 } else {
762 Status = Hii->GlyphToBlt (
763 Hii,
764 (UINT8 *) Glyph,
765 *Foreground,
766 *Background,
767 BufferLen,
768 GlyphWidth,
769 GLYPH_HEIGHT,
770 &LineBuffer[Index * GLYPH_WIDTH]
771 );
772 }
773 }
774
775 //
776 // Blt a character to the screen
777 //
778 BufferGlyphWidth = GLYPH_WIDTH * BufferLen;
779 if (GraphicsOutput != NULL) {
780 Status = GraphicsOutput->Blt (
781 GraphicsOutput,
782 LineBuffer,
783 EfiBltBufferToVideo,
784 0,
785 0,
786 X,
787 Y,
788 BufferGlyphWidth,
789 GLYPH_HEIGHT,
790 BufferGlyphWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
791 );
792 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
793 Status = UgaDraw->Blt (
794 UgaDraw,
795 (EFI_UGA_PIXEL *) (UINTN) LineBuffer,
796 EfiUgaBltBufferToVideo,
797 0,
798 0,
799 X,
800 Y,
801 BufferGlyphWidth,
802 GLYPH_HEIGHT,
803 BufferGlyphWidth * sizeof (EFI_UGA_PIXEL)
804 );
805 } else {
806 Status = EFI_UNSUPPORTED;
807 }
808
809 Error:
810 gBS->FreePool (LineBuffer);
811 gBS->FreePool (Buffer);
812 return Status;
813 }
814
815
816 UINTN
817 PrintXY (
818 IN UINTN X,
819 IN UINTN Y,
820 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL
821 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL
822 IN CHAR16 *Fmt,
823 ...
824 )
825 /*++
826
827 Routine Description:
828
829 Prints a formatted unicode string to the default console
830
831 Arguments:
832
833 X - X coordinate to start printing
834
835 Y - Y coordinate to start printing
836
837 ForeGround - Foreground color
838
839 BackGround - Background color
840
841 Fmt - Format string
842
843 ... - Print arguments
844
845 Returns:
846
847 Length of string printed to the console
848
849 --*/
850 {
851 EFI_HANDLE Handle;
852
853 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
854 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
855 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
856 EFI_STATUS Status;
857 VA_LIST Args;
858
859 VA_START (Args, Fmt);
860
861 UgaDraw = NULL;
862
863 Handle = gST->ConsoleOutHandle;
864
865 Status = gBS->HandleProtocol (
866 Handle,
867 &gEfiGraphicsOutputProtocolGuid,
868 (VOID **) &GraphicsOutput
869 );
870
871 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
872 GraphicsOutput = NULL;
873
874 Status = gBS->HandleProtocol (
875 Handle,
876 &gEfiUgaDrawProtocolGuid,
877 (VOID **) &UgaDraw
878 );
879 }
880
881 if (EFI_ERROR (Status)) {
882 return Status;
883 }
884
885 Status = gBS->HandleProtocol (
886 Handle,
887 &gEfiSimpleTextOutProtocolGuid,
888 (VOID **) &Sto
889 );
890
891 if (EFI_ERROR (Status)) {
892 return Status;
893 }
894
895 return _IPrint (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);
896 }