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