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