605a240bf2b57fe166e4cabe1790eb1253173145
[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 common header file for this module.\r
21 //\r
22 #include "CommonHeader.h"\r
23 \r
24 EFI_STATUS\r
25 GetGraphicsBitMapFromFV (\r
26   IN  EFI_GUID      *FileNameGuid,\r
27   OUT VOID          **Image,\r
28   OUT UINTN         *ImageSize\r
29   )\r
30 /*++\r
31 \r
32 Routine 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
38 Arguments:\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
48 Returns: \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
59   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
60   UINTN                         Index;\r
61   UINT32                        AuthenticationStatus;\r
62 \r
63 \r
64   Status = gBS->LocateHandleBuffer (\r
65                   ByProtocol,\r
66                   &gEfiFirmwareVolume2ProtocolGuid,\r
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
78                     &gEfiFirmwareVolume2ProtocolGuid,\r
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
107 STATIC\r
108 EFI_STATUS\r
109 ConvertBmpToGopBlt (\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
119 Routine 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
125 Arguments:\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
140 Returns: \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
284 EFI_STATUS\r
285 LockKeyboards (\r
286   IN  CHAR16    *Password\r
287   )\r
288 /*++\r
289 \r
290 Routine 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
296 Arguments:\r
297   Password - Password used to lock ConIn device\r
298 \r
299 \r
300 Returns: \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
321 EFI_STATUS\r
322 EnableQuietBoot (\r
323   IN  EFI_GUID  *LogoFile\r
324   )\r
325 /*++\r
326 \r
327 Routine 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
332 Arguments:\r
333 \r
334   LogoFile - File name of logo to display on the center of the screen.\r
335 \r
336 \r
337 Returns: \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
555 EFI_STATUS\r
556 DisableQuietBoot (\r
557   VOID\r
558   )\r
559 /*++\r
560 \r
561 Routine 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
566 Arguments:\r
567 \r
568   NONE\r
569 \r
570 Returns: \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
588 static 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
607 STATIC\r
608 UINTN\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
622 Routine Description:\r
623 \r
624   Display string worker for: Print, PrintAt, IPrint, IPrintAt\r
625 \r
626 Arguments:\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
646 Returns: \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
776 Error:\r
777   gBS->FreePool (LineBuffer);\r
778   gBS->FreePool (Buffer);\r
779   return Status;\r
780 }\r
781 \r
782 \r
783 UINTN\r
784 PrintXY (\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
794 Routine Description:\r
795 \r
796     Prints a formatted unicode string to the default console\r
797 \r
798 Arguments:\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
812 Returns:\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