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