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