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