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